diff --git a/.gitignore b/.gitignore index f3e4def..dce9578 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -#Added by cargo - -/target +.DS_Store +FeedTheMonkey.pro.user* +build diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..fcc6e8d --- /dev/null +++ b/.travis.yml @@ -0,0 +1,33 @@ +language: cpp +compiler: gcc +sudo: require +dist: trusty +before_install: +- sudo add-apt-repository ppa:beineri/opt-qt58-trusty -y +- sudo apt-get update -qq +install: +- sudo apt-get -y install qt58base qt58webengine qt58quickcontrols +- source /opt/qt58/bin/qt58-env.sh +script: +- qmake PREFIX=/usr +- make -j4 +- sudo make INSTALL_ROOT=appdir install ; sudo chown -R $USER appdir ; find appdir/ +- wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" +- chmod a+x linuxdeployqt*.AppImage +- unset QTDIR; unset QT_PLUGIN_PATH ; unset LD_LIBRARY_PATH +- "./linuxdeployqt*.AppImage ./appdir/usr/share/applications/*.desktop -qmldir=./qml/ + -bundle-non-qt-libs" +- "./linuxdeployqt*.AppImage ./appdir/usr/share/applications/*.desktop -qmldir=./qml/ + -appimage" +- find ./appdir -executable -type f -exec ldd {} \; | grep " => /usr" | cut -d " " + -f 2-3 | sort | uniq +- mv FeedTheMonkey*.AppImage FeedTheMonkey.AppImage +deploy: + provider: releases + api_key: + secure: d+hHwOnmeLPVvuue6VDCs2LwLS+BFzJF/BB5iObtkCYBwQ8ybnVzUcgnjJKOt37SHI0T9kLegI+Lq/843ECYiGiDjQg4PvCF69V8ODgHv3v1qiN5oG/eroBXd83a0+xhi4BuJt0SwcV9mcv4uD9bCPhj944rmMLH+3qD4ysgImBmbYSbbLecE9+QAs7bfrCwQRfdCePBORX3FHa/p12NEtln7xv6ZRyku9LdJSzAcdgm4zc95ggTAVC1+aQB6J0q2QzWPlQcOkLx+ZYmOqClhbSMFpIyPXP8UpXjYyvUlTAd0+wH8BGf0O3lpOqACc7IKIbj9d5oPmghVZo55SyW+RR77G+az+IbGJ7iXZsMfQZsMvtB7hNYhNvUUxQrAau7Y/ve+6sMQmvA7aMHV8kDUvnNW/c2r2jAWwk+N8QzGcP/rclDCKeOWZqZABmrzTViXZVAeXh4hJ8r6mbq8iwagBUPCsVYhVuerQt/KIoWxyn6/1GmMfKGi3dA/v3u1qU61vzrz3yLlJBmUAVPxZdVmqfRweh4BXjImxFMFmf5PYm5FnDg1gmw8rWsgii7+IPYw7DjTAHpjYbtXvDwDgG1nRXiRp2TGtPPgKW1/Uk8r/j5vfB5WcEZ7exLUgsPPjny5MGvzjqOxeLvwK1Pg9jFBFXIx7l1tNMJQxQU0r3DmBg= + file: FeedTheMonkey.AppImage + on: + repo: jeena/FeedTheMonkey + skip_cleanup: true + draft: true diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 0fe0de3..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "lldb", - "request": "launch", - "name": "Debug executable 'feedthemonkey'", - "cargo": { - "args": [ - "build", - "--bin=feedthemonkey", - "--package=feedthemonkey" - ], - "filter": { - "name": "feedthemonkey", - "kind": "bin" - } - }, - "args": [], - "cwd": "${workspaceFolder}" - }, - { - "type": "lldb", - "request": "launch", - "name": "Debug unit tests in executable 'feedthemonkey'", - "cargo": { - "args": [ - "test", - "--no-run", - "--bin=feedthemonkey", - "--package=feedthemonkey" - ], - "filter": { - "name": "feedthemonkey", - "kind": "bin" - } - }, - "args": [], - "cwd": "${workspaceFolder}" - } - ] -} \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 4b72dc6..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,815 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "anyhow" -version = "1.0.32" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "atk" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "atk-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "glib 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "glib-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gobject-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "atk-sys" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "glib-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gobject-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", - "system-deps 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cairo-rs" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cairo-sys-rs 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "glib 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "glib-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gobject-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", - "thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cairo-sys-rs" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "glib-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", - "system-deps 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cc" -version = "1.0.58" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "confy" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "directories 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.115 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "directories" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "either" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "feedthemonkey" -version = "3.0.0" -dependencies = [ - "confy 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "gio 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gtk 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.115 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-executor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-channel" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-core" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures-executor" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-io" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures-macro" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-sink" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures-task" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "once_cell 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-util" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-macro 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-nested 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gdk" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cairo-rs 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cairo-sys-rs 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gdk-pixbuf 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gdk-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gio 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gio-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "glib 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "glib-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gobject-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", - "pango 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gdk-pixbuf" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gdk-pixbuf-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gio 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gio-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "glib 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "glib-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gobject-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gdk-pixbuf-sys" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gio-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "glib-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gobject-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", - "system-deps 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gdk-sys" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cairo-sys-rs 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gdk-pixbuf-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gio-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "glib-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gobject-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", - "pango-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", - "system-deps 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gio" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "gio-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "glib 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "glib-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gobject-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gio-sys" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "glib-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gobject-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", - "system-deps 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "glib" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-executor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "glib-macros 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "glib-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gobject-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "glib-macros" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "anyhow 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-crate 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-error 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "glib-sys" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", - "system-deps 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gobject-sys" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "glib-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", - "system-deps 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gtk" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "atk 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cairo-rs 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cairo-sys-rs 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)", - "gdk 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "gdk-pixbuf 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gdk-pixbuf-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gdk-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gio 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gio-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "glib 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "glib-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gobject-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gtk-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pango 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pango-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gtk-sys" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "atk-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cairo-sys-rs 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gdk-pixbuf-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gdk-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gio-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "glib-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gobject-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", - "pango-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "system-deps 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "heck" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "idna" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "idna" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "itertools" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "either 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libc" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "matches" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memchr" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "once_cell" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "pango" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "glib 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "glib-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gobject-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pango-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pango-sys" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "glib-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gobject-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", - "system-deps 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "percent-encoding" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "pin-project" -version = "0.4.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "pin-project-internal 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pin-project-internal" -version = "0.4.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "pkg-config" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-error-attr 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "proc-macro-nested" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "proc-macro2" -version = "1.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quote" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde" -version = "1.0.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde_derive 1.0.115 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_derive" -version = "1.0.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "slab" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "strum" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "strum_macros" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "1.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "system-deps" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", - "strum 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "strum_macros 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "version-compare 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thiserror" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "thiserror-impl 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tinyvec" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "toml" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.115 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "toml" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.115 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-normalization" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "tinyvec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-segmentation" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-xid" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "url" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "url" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.115 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "url_serde" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.115 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "version-compare" -version = "0.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "version_check" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum anyhow 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b" -"checksum atk 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "812b4911e210bd51b24596244523c856ca749e6223c50a7fbbba3f89ee37c426" -"checksum atk-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f530e4af131d94cc4fa15c5c9d0348f0ef28bac64ba660b6b2a1cf2605dedfce" -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum cairo-rs 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c5c0f2e047e8ca53d0ff249c54ae047931d7a6ebe05d00af73e0ffeb6e34bdb8" -"checksum cairo-sys-rs 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2ed2639b9ad5f1d6efa76de95558e11339e7318426d84ac4890b86c03e828ca7" -"checksum cc 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518" -"checksum confy 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4b1400cd0dae7f27d2c7ced9492e1398d2e2df614570092a4936c73b416dedea" -"checksum directories 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc2561db021b6f1321d0f16b67ed28ce843ef4610dfaa432e3ffa2e8a3050ebf" -"checksum either 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd56b59865bce947ac5958779cfa508f6c3b9497cc762b7e24a12d11ccde2c4f" -"checksum futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613" -"checksum futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5" -"checksum futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399" -"checksum futures-executor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314" -"checksum futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789" -"checksum futures-macro 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39" -"checksum futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc" -"checksum futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626" -"checksum futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6" -"checksum gdk 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5726681d558da88e07e4bffee21d4e7e5b02b4eb2de0b7d995a8b25813a7ed99" -"checksum gdk-pixbuf 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f6dae3cb99dd49b758b88f0132f8d401108e63ae8edd45f432d42cdff99998a" -"checksum gdk-pixbuf-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bfe468a7f43e97b8d193a762b6c5cf67a7d36cacbc0b9291dbcae24bfea1e8f" -"checksum gdk-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a9653cfc500fd268015b1ac055ddbc3df7a5c9ea3f4ccef147b3957bd140d69" -"checksum gio 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c5492e80b45e6c56214894a9a0cbe1340ab5066eb44a2dbe151393b6d7942c0" -"checksum gio-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35993626299fbcaa73c0a19be8fdd01c950f9f3d3ac9cb4fb5532b924ab1a5d7" -"checksum glib 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a5e0533f48640d86e8e2f3cee778a9f97588d4a0bec8be065ee51ea52346d6c1" -"checksum glib-macros 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "41486a26d1366a8032b160b59065a59fb528530a46a49f627e7048fb8c064039" -"checksum glib-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6cda4af5c2f4507b7a3535b798dca2135293f4bc3a17f399ce244ef15841c4c" -"checksum gobject-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "952133b60c318a62bf82ee75b93acc7e84028a093e06b9e27981c2b6fe68218c" -"checksum gtk 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8dfefe08ae2c0e3a8a221a5440a891a5e3402ba7c01078182f700c38ef345" -"checksum gtk-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "89acda6f084863307d948ba64a4b1ef674e8527dddab147ee4cdcc194c880457" -"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -"checksum itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" -"checksum libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10" -"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" -"checksum once_cell 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d" -"checksum pango 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9937068580bebd8ced19975938573803273ccbcbd598c58d4906efd4ac87c438" -"checksum pango-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24d2650c8b62d116c020abd0cea26a4ed96526afda89b1c4ea567131fdefc890" -"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" -"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" -"checksum pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)" = "ca4433fff2ae79342e497d9f8ee990d174071408f28f726d6d83af93e58e48aa" -"checksum pin-project-internal 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)" = "2c0e815c3ee9a031fdf5af21c10aa17c573c9c6a566328d99e3936c34e36461f" -"checksum pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -"checksum pkg-config 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33" -"checksum proc-macro-crate 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -"checksum proc-macro-error 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -"checksum proc-macro-error-attr 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -"checksum proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)" = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598" -"checksum proc-macro-nested 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a" -"checksum proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" -"checksum quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" -"checksum serde 1.0.115 (registry+https://github.com/rust-lang/crates.io-index)" = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5" -"checksum serde_derive 1.0.115 (registry+https://github.com/rust-lang/crates.io-index)" = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48" -"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum strum 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b" -"checksum strum_macros 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" -"checksum syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "e69abc24912995b3038597a7a593be5053eb0fb44f3cc5beec0deb421790c1f4" -"checksum system-deps 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b" -"checksum thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08" -"checksum thiserror-impl 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" -"checksum tinyvec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" -"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" -"checksum toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" -"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977" -"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" -"checksum unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" -"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" -"checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea" -"checksum version-compare 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1" -"checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" -"checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index 67a3e39..0000000 --- a/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -name = "feedthemonkey" -version = "3.0.0" -authors = ["Jeena "] -edition = "2018" -readme = "README.md" -repository = "https://github.com/jeena/feedthemonkey" -description = "Desktop client for the TinyTinyRSS feed reader" -license = "GPL-3.0-or-later" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -url = { version = "2.1.1", features = ["serde"] } -url_serde = "0.2.0" -confy = "0.3.1" -serde = { version = "1.0", features = ["derive"] } - -[dependencies.gtk] -version = "0.9.0" -features = ["v3_16"] - -[dependencies.gio] -version = "" -features = ["v2_44"] diff --git a/FeedTheMonkey.pro b/FeedTheMonkey.pro new file mode 100644 index 0000000..91d3739 --- /dev/null +++ b/FeedTheMonkey.pro @@ -0,0 +1,66 @@ +requires(contains(QT_CONFIG, accessibility)) + +qtHaveModule(widgets) { + QT += widgets # QApplication is required to get native styling with QtQuickControls +} + +TARGET = feedthemonkey + +TEMPLATE = app +QT += qml quick webenginewidgets webengine +CONFIG += c++11 +CONFIG += qtquickcompiler + +SOURCES += \ + src/main.cpp \ + src/post.cpp \ + src/tinytinyrss.cpp \ + src/tinytinyrsslogin.cpp + +RESOURCES += \ + html/html.qrc \ + qml/qml.qrc \ + +mac { + RC_FILE = misc/Icon.icns + TARGET = FeedTheMonkey +} + +unix { + isEmpty(PREFIX) { + PREFIX = /usr/local + } + + target.path = $$PREFIX/bin + + shortcutfiles.files = misc/feedthemonkey.desktop + shortcutfiles.path = $$PREFIX/share/applications/ + data.files += misc/feedthemonkey.xpm + data.path = $$PREFIX/share/pixmaps/ + + INSTALLS += shortcutfiles + INSTALLS += data +} + +INSTALLS += target + + +# Needed for bringing browser from background to foreground using QDesktopServices: http://bugreports.qt-project.org/browse/QTBUG-8336 +TARGET.CAPABILITY += SwEvent + +# Additional import path used to resolve QML modules in Qt Creator's code model +QML_IMPORT_PATH = + +OTHER_FILES += + +HEADERS += \ + src/post.h \ + src/tinytinyrss.h \ + src/tinytinyrsslogin.h + +DISTFILES += \ + misc/feedthemonkey.desktop \ + misc/feedthemonkey.xpm \ + misc/Icon.icns \ + README.md \ + LICENSE.txt diff --git a/README.md b/README.md index 5454f06..155358a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ - # FeedTheMonkey Icon @@ -7,11 +6,17 @@ FeedTheMonkey is a desktop client for [TinyTinyRSS](http://tt-rss.org). That mea it doesn't work as a standalone feed reader but only as a client for the TinyTinyRSS API which it uses to get the normalized feeds and to synchronize the "article read" marks. -It is written in Rust and GTK. You need to have an account on a TinyTinyRSS server. +It is written in C++ with Qt and QML, it also uses Blink to show the contents. You need +to have Qt 5.6 installed to be able to compile and have a account on a TinyTinyRSS server. ## Installation -TBD +If you run Linux then there is an AppImage on the [Latest release](https://github.com/jeena/FeedTheMonkey/releases/latest) page. You download it, make executable and are able to run, it should work on most of the distributions out there. + +For ArchLinux I package it and it's available on https://aur.archlinux.org/packages/feedthemonkey/ + +You can compile and install it everywhere Qt is suported, this means on macOS, Windows +and Linux. ## Keyboard shortcuts @@ -28,11 +33,13 @@ The keyboard shortcuts are inspired by other feed readers which are inspired by `Ctrl -` zoom out `Ctrl 0` reset zoom +On macOS use `Cmd` instead of `Ctrl`. + ## Trivia -This is version 3 of FeedTheMonkey, you can find version 1 which was written -in PyQt in the v1 branch of this repo and version 2 which was written in C++ -and Qt/QML in the v2 branch. +This is version 2 of FeedTheMonkey, you can find version 1 which was written in PyQt in the v1 branch +of this repo. My goal is to make this usable on many different targets, for now it is only for +the use on a desktop computer but I'd like to see it on a mobile device too. ## Screenshot @@ -42,7 +49,7 @@ and Qt/QML in the v2 branch. This file is part of FeedTheMonkey. -Copyright 2020 Jeena +Copyright 2015-2017 Jeena FeedTheMonkey is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/html/html.qrc b/html/html.qrc new file mode 100644 index 0000000..c6cf166 --- /dev/null +++ b/html/html.qrc @@ -0,0 +1,6 @@ + + + content.css + content.html + + diff --git a/misc/misc.qrc b/misc/misc.qrc new file mode 100644 index 0000000..615a2a0 --- /dev/null +++ b/misc/misc.qrc @@ -0,0 +1,7 @@ + + + feedthemonkey.xpm + Icon.icns + feedthemonkey.desktop + + diff --git a/ports/arch/PKGBUILD b/ports/arch/PKGBUILD new file mode 100644 index 0000000..07c344b --- /dev/null +++ b/ports/arch/PKGBUILD @@ -0,0 +1,25 @@ +# Maintainer: Jeena + +pkgname=feedthemonkey +_name=FeedTheMonkey +pkgver=2.2.0 +pkgrel=1 +pkgdesc="Desktop client for the TinyTinyRSS reader" +arch=('i686' 'x86_64') +url="http://jabs.nu/feedthemonkey" +license=('GPL3') +depends=('qt5-declarative' 'qt5-quick1' 'qt5-quickcontrols' 'qt5-webengine') +source=("https://github.com/jeena/${_name}/archive/v${pkgver}.tar.gz") +md5sums=('SKIP') + +build() { + cd "${_name}-$pkgver" + qmake-qt5 PREFIX=${pkgdir}/usr + make +} + +package() { + cd "${_name}-$pkgver" + make install + install -D -m644 COPYING "${pkgdir}/usr/share/licenses/${pkgname}/COPYING" +} diff --git a/ports/osx/deploy.sh b/ports/osx/deploy.sh new file mode 100755 index 0000000..369e2ec --- /dev/null +++ b/ports/osx/deploy.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +# The macdeployqt app you get while installing Qt is broken for newer Qt +# versions like 5.4 which we use, we will have to replace it. +# +# Download and compile https://github.com/MaximAlien/macdeployqt do not +# use the .dmg which is too old. Move the new macdeployqt so it is in +# $QTDIR/bin/macdeployqt. +# +# Use fixqtlibspath.sh to fix your Qt installation, you need to change the +# path in this script, you don't have to run the Predator part. +# +# Build FeedTheMonkey.app in QtCreator as Release. + +if [[ "" == "$QTDIR" ]]; then + QTDIR=~/Qt/5.4/clang_64/ +fi + +BUILDDIR=$1 +APPDIR=$BUILDDIR/FeedTheMonkey.app +CONTENTSDIR=$APPDIR/Contents +ABSPATH=$(cd "$(dirname "$0")"; pwd) + +if [[ "" == "$BUILDDIR" ]]; then + echo "Usage: $0 path/to/build/" + exit 1 +fi + +# libexec +mkdir -p $APPDIR/Contents/libexec +cp $QTDIR/libexec/QtWebProcess $CONTENTSDIR/libexec +cat > $CONTENTSDIR/libexec/qt.conf << EOF +[Paths] +Plugins = ../PlugIns +Qml2Imports = ../Imports/qtquick2 +EOF + +# lab settings +mkdir -p $CONTENTSDIR/Imports/qtquick2/Qt/labs +cp -R $QTDIR/qml/Qt/labs/settings $CONTENTSDIR/Imports/qtquick2/Qt/labs +cat > $CONTENTSDIR/Resources/qt.conf << EOF +[Paths] +Plugins = PlugIns +Qml2Imports = Imports/qtquick2 +EOF + +# deploy +$QTDIR/bin/macdeployqt $APPDIR -no-strip -qmldir=$ABSPATH/../../qml -executable=$CONTENTSDIR/libexec/QtWebProcess + +open $BUILDDIR + diff --git a/qml/Content.qml b/qml/Content.qml new file mode 100644 index 0000000..07440be --- /dev/null +++ b/qml/Content.qml @@ -0,0 +1,116 @@ +/* + * This file is part of FeedTheMonkey. + * + * Copyright 2015 Jeena + * + * FeedTheMonkey is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FeedTheMonkey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FeedTheMonkey. If not, see . + */ + +import QtWebEngine 1.8 +import QtQuick 2.0 +import QtQuick.Controls 1.3 +import QtQuick.Layouts 1.1 +import QtQuick.Controls.Styles 1.3 +import TTRSS 1.0 + +Item { + id: content + property Post post + property ApplicationWindow app + + property int textFontSize: 14 + property bool nightmode + property int scrollJump: 48 + property int pageJump: parent.height + Layout.minimumWidth: 400 + onTextFontSizeChanged: webView.setDefaults() + onNightmodeChanged: webView.setDefaults() + + function scrollDown(jump) { + if(!jump) { + webView.runJavaScript("window.scrollTo(0, document.body.scrollHeight - " + height + ");") + } else { + webView.runJavaScript("window.scrollBy(0, " + jump + ");") + } + } + + function scrollUp(jump) { + if(!jump) { + webView.runJavaScript("window.scrollTo(0, 0);") + } else { + webView.runJavaScript("window.scrollBy(0, -" + jump + ");") + } + } + + function loggedOut() { + post = null + } + + Label { id: fontLabel } + + WebEngineView { + id: webView + anchors.fill: parent + url: "../html/content.html" + + property Post post: content.post + + function setPost() { + if(post) { + webView.runJavaScript("setArticle(" + post.jsonString + ")") + } else { + webView.runJavaScript("setArticle('logout')") + } + } + + function setDefaults() { + // font name needs to be enclosed in single quotes + // and this is needed for El Capitain because ".SF NS Text" won't work + var defFont = ", system, -apple-system, '.SFNSDisplay-Regular', 'Helvetica Neue', 'Lucida Grande'"; + var font = "'" + fontLabel.font.family + "'" + defFont; + webView.runJavaScript("document.body.style.fontFamily = \"" + font + "\";"); + webView.runJavaScript("document.body.style.fontSize = '" + content.textFontSize + "pt';"); + webView.runJavaScript("if(typeof setNightmode == \"function\") setNightmode(" + (content.nightmode ? "true" : "false") + ")") + } + + onNavigationRequested: { + if (request.url == "feedthemonkey:previous") { + request.action = WebEngineView.IgnoreRequest; + app.showPreviousPost(); + } else if (request.url == "feedthemonkey:next") { + request.action = WebEngineView.IgnoreRequest; + app.showNextPost(); + } else if (request.url == "feedthemonkey:open") { + request.action = WebEngineView.IgnoreRequest; + Qt.openUrlExternally(post.link) + } else if (request.navigationType !== WebEngineNavigationRequest.LinkClickedNavigation) { + request.action = WebEngineView.AcceptRequest; + } else { + request.action = WebEngineView.IgnoreRequest; + Qt.openUrlExternally(request.url); + } + } + + onLoadingChanged: { + if(!loading) { + setPost() + setDefaults() + } + } + + onPostChanged: setPost() + Keys.onPressed: app.keyPressed(event) + } +} + diff --git a/qml/Login.qml b/qml/Login.qml new file mode 100644 index 0000000..5948a12 --- /dev/null +++ b/qml/Login.qml @@ -0,0 +1,84 @@ +/* + * This file is part of FeedTheMonkey. + * + * Copyright 2015 Jeena + * + * FeedTheMonkey is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FeedTheMonkey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FeedTheMonkey. If not, see . + */ + +import QtQuick 2.0 +import QtQuick.Controls 1.2 + +Rectangle { + color: "transparent" + anchors.fill: parent + + property string serverUrl: serverUrl.text + property string userName: userName.text + property string password: password.text + + Column { + anchors.centerIn: parent + width: parent.width / 2 + anchors.margins: parent.width / 4 + spacing: 10 + + Text { + text: qsTr("Please specify a server url, a username and a password.") + wrapMode: Text.WordWrap + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: 20 + font.pointSize: 20 + } + + TextField { + id: serverUrl + placeholderText: "http://example.com/ttrss/" + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: 20 + validator: RegExpValidator { regExp: /https?:\/\/.+/ } + onAccepted: login() + } + + TextField { + id: userName + placeholderText: qsTr("username") + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: 20 + onAccepted: login() + } + + TextField { + id: password + placeholderText: qsTr("password") + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: 20 + echoMode: TextInput.Password + onAccepted: login() + } + + Button { + id: loginButton + text: "Ok" + anchors.right: parent.right + anchors.margins: 20 + onClicked: login() + } + } + +} diff --git a/qml/PostListItem.qml b/qml/PostListItem.qml new file mode 100644 index 0000000..63bf813 --- /dev/null +++ b/qml/PostListItem.qml @@ -0,0 +1,123 @@ +/* + * This file is part of FeedTheMonkey. + * + * Copyright 2015 Jeena + * + * FeedTheMonkey is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FeedTheMonkey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FeedTheMonkey. If not, see . + */ + +import QtQuick 2.0 +import QtQuick.Controls 1.3 + +Item { + property int textFontSize: 14 + property int smallfontSize: 11 + property bool nightmode + + Component.onCompleted: fixFontSize() + onTextFontSizeChanged: fixFontSize() + + function fixFontSize() { + smallfontSize = textFontSize * 0.8 + } + + id: item + height: d.height + t.height + e.height + 2 + + Item { + anchors.fill: parent + + Item { + anchors.fill: parent + anchors.leftMargin: 15 + anchors.rightMargin: 15 + anchors.topMargin: 10 + anchors.bottomMargin: 10 + + Column { + id: column + width: parent.width + + Item { + width: parent.width + height: d.height + + Label { + text: feedTitle + font.pointSize: smallfontSize + textFormat: Text.PlainText + color: nightmode ? "#888" : "gray" + wrapMode: Text.WrapAnywhere + renderType: Text.NativeRendering + elide: Text.ElideLeft + anchors.top: parent.top + anchors.left: parent.left + anchors.right: d.left + maximumLineCount: 1 + } + Label { + id: d + text: date.toLocaleString(Qt.locale(), Locale.ShortFormat) + font.pointSize: smallfontSize + textFormat: Text.PlainText + color: nightmode ? "#888" : "gray" + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + renderType: Text.NativeRendering + anchors.right: parent.right + anchors.top: parent.top + } + } + Label { + id: t + text: title + color: nightmode ? (read ? "#888" : "#ddd") : (read ? "gray" : "black") + font.pointSize: textFontSize + textFormat: Text.PlainText + wrapMode: Text.WrapAnywhere + renderType: Text.NativeRendering + width: parent.width + elide: Text.ElideRight + maximumLineCount: 1 + + } + Label { + id: e + text: excerpt + font.pointSize: smallfontSize + //textFormat: Text.RichText + color: nightmode ? "#888" : "gray" + wrapMode: Text.WrapAnywhere + renderType: Text.NativeRendering + width: parent.width + elide: Text.ElideRight + maximumLineCount: 1 + } + } + } + + Rectangle { + anchors.top: parent.bottom + width: parent.width + height: 1 + color: nightmode ? "#222" : "lightgray" + } + } + + MouseArea { + anchors.fill: parent + onClicked: { + parent.parent.parent.currentIndex = index + } + } +} diff --git a/qml/Sidebar.qml b/qml/Sidebar.qml new file mode 100644 index 0000000..84de4cb --- /dev/null +++ b/qml/Sidebar.qml @@ -0,0 +1,106 @@ +/* + * This file is part of FeedTheMonkey. + * + * Copyright 2015 Jeena + * + * FeedTheMonkey is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FeedTheMonkey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FeedTheMonkey. If not, see . + */ + +import QtQuick 2.0 +import TTRSS 1.0 +import QtQuick.Controls 1.3 +import QtQuick.Layouts 1.1 +import QtQuick.Controls.Styles 1.3 + +ScrollView { + id: item + + property Server server + property Content content + property Post previousPost + property int textFontSize: 14 + property bool nightmode + + style: ScrollViewStyle { + transientScrollBars: true + } + + function next() { + if(listView.count > listView.currentIndex) { + listView.currentIndex++; + } + } + + function previous() { + if(listView.currentIndex > 0) { + listView.currentIndex--; + } + } + + onWidthChanged: { + // Hide sidebar if smaller than 200px wide + if(width < 200) { + width = 0; + } + } + + Rectangle { + width: 1 + color: app.nightmode ? "#111" : "lightgray" + anchors.right: parent.right + anchors.top: parent.top + height: parent.height + } + + ListView { + id: listView + + focus: true + anchors.fill: parent + spacing: 1 + model: item.server.posts + + delegate: Component { + PostListItem { + textFontSize: item.textFontSize + nightmode: app.nightmode + width: listView.width + } + } + + highlightFollowsCurrentItem: false + highlight: Component { + Rectangle { + width: listView.currentItem.width -1 + height: listView.currentItem.height + color: nightmode ? "#15539e" : "lightblue" + y: listView.currentItem.y + } + + } + + onCurrentItemChanged: { + if(previousPost) { + if(!previousPost.dontChangeRead) { + previousPost.read = true; + } else { + previousPost.dontChangeRead = false; + } + } + + item.content.post = server.posts[currentIndex] + previousPost = item.content.post + } + } +} diff --git a/qml/TheMenuBar.qml b/qml/TheMenuBar.qml new file mode 100644 index 0000000..34c0310 --- /dev/null +++ b/qml/TheMenuBar.qml @@ -0,0 +1,144 @@ +/* + * This file is part of FeedTheMonkey. + * + * Copyright 2015 Jeena + * + * FeedTheMonkey is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FeedTheMonkey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FeedTheMonkey. If not, see . + */ + +import QtQuick.Controls 1.2 +import QtQuick.Window 2.0 +import QtQuick 2.0 +import TTRSS 1.0 + +MenuBar { + id: menuBar + property bool loggedIn: false + property ServerLogin serverLogin + property Server server + property Sidebar sidebar + property Content content + property bool visible: true + property var oldVisibility + + Menu { + visible: menuBar.visible + title: qsTr("File") + MenuItem { + text: qsTr("Close &Window") + shortcut: "Ctrl+W" + onTriggered: Qt.quit() + } + MenuItem { + text: qsTr("Exit") + shortcut: "Ctrl+Q" + onTriggered: Qt.quit() + } + } + + Menu { + visible: menuBar.visible + title: qsTr("Action") + MenuItem { + text: qsTr("Reload") + shortcut: "R" + enabled: loggedIn + onTriggered: server.reload() + } + MenuItem { + text: qsTr("Set &Unread") + shortcut: "U" + enabled: loggedIn + onTriggered: { + content.post.dontChangeRead = true + content.post.read = false + } + } + MenuItem { + text: qsTr("Next") + shortcut: "J" + enabled: loggedIn + onTriggered: sidebar.next() + } + MenuItem { + text: qsTr("Previous") + shortcut: "K" + enabled: loggedIn + onTriggered: sidebar.previous() + } + MenuItem { + text: qsTr("Open in Browser") + shortcut: "N" + enabled: loggedIn + onTriggered: Qt.openUrlExternally(content.post.link) + } + MenuItem { + text: qsTr("Log Out") + enabled: loggedIn + onTriggered: serverLogin.logout() + } + } + + Menu { + visible: menuBar.visible + title: qsTr("View") + MenuItem { + text: qsTr("Night mode") + shortcut: "1" + onTriggered: app.toggleNightmode() + } + MenuItem { + text: qsTr("Zoom In") + shortcut: "Ctrl++" + enabled: loggedIn + onTriggered: app.zoomIn() + } + MenuItem { + text: qsTr("Zoom Out") + shortcut: "Ctrl+-" + enabled: loggedIn + onTriggered: app.zoomOut() + } + MenuItem { + text: qsTr("Reset") + shortcut: "Ctrl+0" + enabled: loggedIn + onTriggered: app.zoomReset() + } + MenuItem { + text: qsTr("Fullscreen") + shortcut: "F11" + enabled: loggedIn + onTriggered: { + if(app.visibility == Window.FullScreen) { + app.visibility = oldVisibility + } else { + oldVisibility = app.visibility + app.showFullScreen() + } + + } + } + } + + Menu { + visible: menuBar.visible + title: qsTr("Help") + MenuItem { + text: qsTr("About") + onTriggered: Qt.openUrlExternally("http://jeena.net/feedthemonkey/index.html"); + } + } + +} diff --git a/qml/main.qml b/qml/main.qml new file mode 100644 index 0000000..0b6074b --- /dev/null +++ b/qml/main.qml @@ -0,0 +1,254 @@ +/* + * This file is part of FeedTheMonkey. + * + * Copyright 2015 Jeena + * + * FeedTheMonkey is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FeedTheMonkey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FeedTheMonkey. If not, see . + */ + +import QtQuick 2.3 +import QtQuick.Controls 1.3 +import QtQuick.Window 2.0 +import QtQuick.Layouts 1.1 +import QtQuick.Dialogs 1.1 +import Qt.labs.settings 1.0 +import TTRSS 1.0 + +ApplicationWindow { + id: app + title: "FeedTheMonkey" + visible: true + color: nightmode ? "#2d2d2d" : "#eee" + + minimumWidth: 480 + minimumHeight: 320 + + width: 800 + height: 640 + x: 200 + y: 200 + + property Server server: server + property Sidebar sidebar: sidebar + property Content content: content + + property variant fontSizes: [7,9,11,13,15,17,19,21,23,25,27,29,31] + property int defaultTextFontSizeIndex: 3 + property int textFontSizeIndex: defaultTextFontSizeIndex + property int textFontSize: fontSizes[textFontSizeIndex] + property bool nightmode: false + property bool showMenuBar: false + + menuBar: TheMenuBar { + id: menu + serverLogin: serverLogin + server: server + sidebar: sidebar + content: content + visible: app.showMenuBar + __contentItem.visible: visible + } + + Settings { + id: settings + category: "window" + property alias x: app.x + property alias y: app.y + property alias width: app.width + property alias height: app.height + property alias sidebarWidth: sidebar.width + property alias textFontSizeIndex: app.textFontSizeIndex + property alias nightmode: app.nightmode + } + + function loggedIn() { + if(serverLogin.loggedIn()) { + menu.loggedIn = true; + contentView.visible = true + login.visible = false; + server.initialize(serverLogin.serverUrl, serverLogin.sessionId); + } else { + menu.loggedIn = false + contentView.visible = false + login.visible = true + server.loggedOut() + content.loggedOut() + } + } + + function toggleNightmode() { + app.nightmode = !app.nightmode + } + + function zoomIn() { + if(textFontSizeIndex + 1 < fontSizes.length) { + textFontSize = fontSizes[++textFontSizeIndex] + } + } + + function zoomOut() { + if(textFontSizeIndex - 1 > 0) { + textFontSize = fontSizes[--textFontSizeIndex] + } + } + + function zoomReset() { + textFontSizeIndex = defaultTextFontSizeIndex + textFontSize = fontSizes[textFontSizeIndex] + } + + function removeHTML(str) { + forEscapingHTML.text = str + return forEscapingHTML.getText(0, forEscapingHTML.length) + } + + function showNextPost() { + sidebar.next() + } + + function showPreviousPost() { + sidebar.previous() + } + + function keyPressed(event) { + switch (event.key) { + case Qt.Key_Right: + case Qt.Key_J: + case Qt.Key_j: + sidebar.next() + break + case Qt.Key_Left: + case Qt.Key_K: + case Qt.Key_k: + sidebar.previous() + break + case Qt.Key_1: + toggleNightmode() + break + case Qt.Key_Home: + content.scrollUp() + break + case Qt.Key_End: + content.scrollDown() + break + case Qt.Key_PageUp: + content.scrollUp(content.pageJump) + break + case Qt.Key_PageDown: + case Qt.Key_Space: + content.scrollDown(content.pageJump) + break + case Qt.Key_Down: + content.scrollDown(content.scrollJump) + break + case Qt.Key_Up: + content.scrollUp(content.scrollJump) + break + case Qt.Key_Enter: + case Qt.Key_Return: + Qt.openUrlExternally(content.post.link) + break + default: + break + } + } + + SplitView { + id: contentView + anchors.fill: parent + orientation: Qt.Horizontal + visible: serverLogin.loggedIn() + focus: true + handleDelegate: Rectangle { + width: 1 + color: app.nightmode ? "#333" : "#aaa" + } + + Sidebar { + id: sidebar + content: content + server: server + + implicitWidth: 300 + textFontSize: app.textFontSize + nightmode: app.nightmode + } + + Content { + id: content + app: app + + Layout.minimumWidth: 200 + implicitWidth: 624 + textFontSize: app.textFontSize + nightmode: app.nightmode + } + + Keys.onPressed: keyPressed(event) + Keys.onReleased: { + switch (event.key) { + case Qt.Key_Alt: + app.showMenuBar = !app.showMenuBar + break + default: + break + } + } + } + + Login { + id: login + anchors.fill: parent + visible: !serverLogin.loggedIn() + + function login() { + serverLogin.login(serverUrl, userName, password) + } + + } + + MessageDialog { + id: loginErrorAlert + title: "A login error occured" + text: serverLogin.loginError + onAccepted: visible = false + } + + ServerLogin { + id: serverLogin + onSessionIdChanged: app.loggedIn() + onLoginErrorChanged: { + console.log("loginError:", loginError) + if(loginError.length > 0) { + loginErrorAlert.visible = true + } + } + } + + Server { + id: server + } + + TextArea { + id: forEscapingHTML + visible: false + textFormat: TextEdit.RichText + } + + Component.onCompleted: { + if(serverLogin.loggedIn()) { + loggedIn(); + } + } +} diff --git a/qml/qml.qrc b/qml/qml.qrc new file mode 100644 index 0000000..c0ff3c6 --- /dev/null +++ b/qml/qml.qrc @@ -0,0 +1,10 @@ + + + main.qml + TheMenuBar.qml + Content.qml + Login.qml + PostListItem.qml + Sidebar.qml + + diff --git a/src/app.rs b/src/app.rs deleted file mode 100644 index e36f740..0000000 --- a/src/app.rs +++ /dev/null @@ -1,63 +0,0 @@ -extern crate gio; -extern crate gtk; -extern crate confy; - -use gio::prelude::*; -use gtk::prelude::*; -use std::string::String; -use crate::settings::Settings; - -const APP_ID: &str = "net.jeena.feedthemonkey"; - -#[derive(Debug)] -pub struct App { - uiapp: gtk::Application, - settings: Option, -} - -impl App { - pub fn new() -> Self { - let app = gtk::Application::new( - Some(&APP_ID), - gio::ApplicationFlags::FLAGS_NONE, - ) - .expect("Application::new failed"); - - app.connect_activate(|app| { - // We create the main window. - let win = gtk::ApplicationWindow::new(app); - - // Then we set its size and a title. - win.set_default_size(320, 200); - win.set_title("FeedTheMonkey"); - - // Don't forget to make all widgets visible. - win.show_all(); - }); - - let conf: Result = confy::load(&APP_ID); - - match conf { - Ok(s) => Self { uiapp: app, settings: Some(s) }, - Err(_) => Self { uiapp: app, settings: None }, - } - } - - pub fn run(&self, argv: &[String]) { -/* - match self.settings { - Some(_) => self.show_content(), - None => match confy::store(&APP_ID, Settings::default()) { // TODO: Replace default data with login form data - Ok(_) => println!("New settings stored"), - Err(e) => eprint!("Error while storing settings: {}", e) - } - } -*/ - self.uiapp.run(&argv); - } - - pub fn show_content(&self) { - println!("Show content") - } - -} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..95f351e --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,50 @@ +/* + * This file is part of FeedTheMonkey. + * + * Copyright 2015 Jeena + * + * FeedTheMonkey is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FeedTheMonkey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FeedTheMonkey. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "tinytinyrsslogin.h" +#include "tinytinyrss.h" +#include "post.h" + +int main(int argc, char *argv[]) +{ + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QGuiApplication app(argc, argv); + app.setOrganizationName("Jeena"); + app.setOrganizationDomain("jeena.net"); + app.setApplicationName("FeedTheMonkey"); + + QtWebEngine::initialize(); + + qmlRegisterType("TTRSS", 1, 0, "ServerLogin"); + qmlRegisterType("TTRSS", 1, 0, "Server"); + qmlRegisterType("TTRSS", 1, 0, "Post"); + + QQmlApplicationEngine engine; + engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml"))); + + return app.exec(); +} diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index 78bee0b..0000000 --- a/src/main.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod app; -mod settings; - -fn main() { - let app = app::App::new(); - app.run(&std::env::args().collect::>()); -} \ No newline at end of file diff --git a/src/post.cpp b/src/post.cpp new file mode 100644 index 0000000..2d3179b --- /dev/null +++ b/src/post.cpp @@ -0,0 +1,79 @@ +/* + * This file is part of FeedTheMonkey. + * + * Copyright 2015 Jeena + * + * FeedTheMonkey is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FeedTheMonkey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FeedTheMonkey. If not, see . + */ + +#include "post.h" +#include +#include +#include + +Post::Post(QObject *parent) : QObject(parent) +{ + +} + +Post::Post(QJsonObject post, QObject *parent) : QObject(parent) +{ + mTitle = html2text(post.value("title").toString().trimmed()); + mFeedTitle = html2text(post.value("feed_title").toString().trimmed()); + mId = post.value("id").toInt(); + mFeedId = post.value("feed_id").toString().trimmed(); + mAuthor = post.value("author").toString().trimmed(); + QUrl url(post.value("link").toString().trimmed()); + mLink = url; + QDateTime timestamp; + timestamp.setTime_t(post.value("updated").toInt()); + mDate = timestamp; + mContent = post.value("content").toString().trimmed(); + mExcerpt = html2text(post.value("excerpt").toString().remove(QRegExp("<[^>]*>")).replace("…", " ...").trimmed().replace("(\\s+)", " ").replace("\n", "")); + mStarred = post.value("marked").toBool(); + mRead = !post.value("unread").toBool(); + mDontChangeRead = false; + + QJsonDocument doc(post); + QString result(doc.toJson(QJsonDocument::Indented)); + mJsonString = result; +} + +Post::~Post() +{ + +} + +void Post::setRead(bool r) +{ + if(mRead == r) return; + + mRead = r; + emit readChanged(mRead); +} + +void Post::setDontChangeRead(bool r) +{ + if(mDontChangeRead == r) return; + + mDontChangeRead = r; + emit dontChangeReadChanged(mDontChangeRead); +} + +QString Post::html2text(const QString htmlString) +{ + QTextDocument doc; + doc.setHtml(htmlString); + return doc.toPlainText(); +} diff --git a/src/post.h b/src/post.h new file mode 100644 index 0000000..56ab9ff --- /dev/null +++ b/src/post.h @@ -0,0 +1,89 @@ +/* + * This file is part of FeedTheMonkey. + * + * Copyright 2015 Jeena + * + * FeedTheMonkey is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FeedTheMonkey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FeedTheMonkey. If not, see . + */ + +#ifndef POST_H +#define POST_H + +#include +#include +#include +#include + +class Post : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString title READ title CONSTANT) + Q_PROPERTY(QString feedTitle READ feedTitle CONSTANT) + Q_PROPERTY(int id READ id CONSTANT) + Q_PROPERTY(QString feedId READ feedId CONSTANT) + Q_PROPERTY(QString author READ author CONSTANT) + Q_PROPERTY(QUrl link READ link CONSTANT) + Q_PROPERTY(QDateTime date READ date CONSTANT) + Q_PROPERTY(QString content READ content CONSTANT) + Q_PROPERTY(QString excerpt READ excerpt CONSTANT) + Q_PROPERTY(bool starred READ starred NOTIFY starredChanged) + Q_PROPERTY(bool read READ read WRITE setRead NOTIFY readChanged) + Q_PROPERTY(bool dontChangeRead READ dontChangeRead WRITE setDontChangeRead NOTIFY dontChangeReadChanged) + Q_PROPERTY(QString jsonString READ jsonString CONSTANT) + +public: + Post(QObject *parent = 0); + Post(QJsonObject post, QObject *parent = 0); + ~Post(); + QString title() const { return mTitle; } + QString feedTitle() const { return mFeedTitle; } + int id() const { return mId; } + QString feedId() const { return mFeedId; } + QString author() const { return mAuthor; } + QUrl link() const { return mLink; } + QDateTime date() const { return mDate; } + QString content() const { return mContent; } + QString excerpt() const { return mExcerpt; } + bool starred() const { return mStarred; } + bool read() { return mRead; } + void setRead(bool r); + bool dontChangeRead() const { return mDontChangeRead; } + void setDontChangeRead(bool r); + QString jsonString() const { return mJsonString; } + +signals: + void starredChanged(bool); + void readChanged(bool); + void dontChangeReadChanged(bool); + +public slots: + +private: + QString mTitle; + QString mFeedTitle; + int mId; + QString mFeedId; + QString mAuthor; + QUrl mLink; + QDateTime mDate; + QString mContent; + QString mExcerpt; + bool mStarred; + bool mRead; + bool mDontChangeRead; + QString mJsonString; + QString html2text(const QString htmlString); +}; + +#endif // POST_H diff --git a/src/settings.rs b/src/settings.rs deleted file mode 100644 index 6f29238..0000000 --- a/src/settings.rs +++ /dev/null @@ -1,20 +0,0 @@ -extern crate confy; - -use std::string::String; -use url::Url; -use serde::{Serialize, Deserialize}; - -#[derive(Debug, Serialize, Deserialize)] -pub struct Settings { - pub session_id: String, - pub server_url: Url, -} - -impl ::std::default::Default for Settings { - fn default() -> Self { - Self { - session_id: String::from("abcdefg"), - server_url: Url::parse("https://example.com").expect("Not a URL"), - } - } -} \ No newline at end of file diff --git a/src/tinytinyrss.cpp b/src/tinytinyrss.cpp new file mode 100644 index 0000000..4806c04 --- /dev/null +++ b/src/tinytinyrss.cpp @@ -0,0 +1,150 @@ +/* + * This file is part of FeedTheMonkey. + * + * Copyright 2015 Jeena + * + * FeedTheMonkey is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FeedTheMonkey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FeedTheMonkey. If not, see . + */ + +#include "tinytinyrss.h" +#include +#include +#include +#include + +TinyTinyRSS::TinyTinyRSS(QObject *parent) : + QObject(parent) +{ + qRegisterMetaType >(); + + mNetworkManager = new QNetworkAccessManager(this); + mPosts = QList(); +} + +TinyTinyRSS::~TinyTinyRSS() +{ + mPosts.clear(); + delete mNetworkManager; +} + +void TinyTinyRSS::initialize(const QString serverUrl, const QString sessionId) +{ + mServerUrl = serverUrl; + mSessionId = sessionId; + reload(); +} + +void TinyTinyRSS::reload() +{ + QVariantMap opts; + opts.insert("show_excerpt", false); + opts.insert("view_mode", "unread"); + opts.insert("show_content", true); + opts.insert("feed_id", -4); + opts.insert("skip", 0); + + doOperation("getHeadlines", opts, [this] (const QJsonObject &json) { + + mPosts.clear(); + + QJsonArray posts = json.value("content").toArray(); + for(int i = 0; i < posts.count(); i++) + { + QJsonObject postJson = posts.at(i).toObject(); + Post *post = new Post(postJson, this); + connect(post, SIGNAL(readChanged(bool)), this, SLOT(onPostReadChanged(bool))); + mPosts.append(post); + } + + emit postsChanged(mPosts); + }); +} + +void TinyTinyRSS::loggedOut() +{ + mServerUrl = nullptr; + mSessionId = nullptr; + mPosts.clear(); + emit postsChanged(mPosts); +} + +void TinyTinyRSS::doOperation(QString operation, QVariantMap opts, std::function callback) +{ + QVariantMap options; + options.insert("sid", mSessionId); + options.insert("op", operation); + + QMapIterator i(opts); + while (i.hasNext()) { + i.next(); + options.insert(i.key(), i.value()); + } + + QJsonObject jsonobj = QJsonObject::fromVariantMap(options); + QJsonDocument json = QJsonDocument(jsonobj); + + QNetworkRequest request(mServerUrl); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QNetworkReply *reply = mNetworkManager->post(request, json.toJson()); + + connect(reply, &QNetworkReply::finished, [callback, reply] () { + if (reply) { + if (reply->error() == QNetworkReply::NoError) { + QString jsonString = QString(reply->readAll()); + QJsonDocument json = QJsonDocument::fromJson(jsonString.toUtf8()); + callback(json.object()); + } else { + int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + //do some error management + qWarning() << "HTTP error: " << httpStatus; + } + reply->deleteLater(); + } + }); +} + +void TinyTinyRSS::onPostReadChanged(bool r) +{ + Post *post = (Post *)sender(); + + updateArticle(post->id(), 2, !r, [post] (const QJsonObject &) { + // not doing anything with this yet. + }); +} + +void TinyTinyRSS::updateArticle(int articleId, int field, bool trueFalse, std::function callback) +{ + QVariantMap opts; + opts.insert("article_ids", articleId); + opts.insert("field", field); + opts.insert("mode", trueFalse ? 1 : 0); + + doOperation("updateArticle", opts, callback); +} + +QQmlListProperty TinyTinyRSS::posts() +{ + return QQmlListProperty(this, mPosts); +} + +int TinyTinyRSS::postsCount() const +{ + return mPosts.count(); +} + +Post *TinyTinyRSS::post(int index) const +{ + return mPosts.at(index); +} diff --git a/src/tinytinyrss.h b/src/tinytinyrss.h new file mode 100644 index 0000000..2e85464 --- /dev/null +++ b/src/tinytinyrss.h @@ -0,0 +1,68 @@ +/* + * This file is part of FeedTheMonkey. + * + * Copyright 2015 Jeena + * + * FeedTheMonkey is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FeedTheMonkey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FeedTheMonkey. If not, see . + */ + +#ifndef TINYTINYRSS_H +#define TINYTINYRSS_H + +#include +#include +#include +#include +#include +#include + +#include + +#include "post.h" + +class TinyTinyRSS : public QObject +{ + Q_OBJECT + Q_PROPERTY(QQmlListProperty posts READ posts NOTIFY postsChanged) + +public: + TinyTinyRSS(QObject *parent = 0); + ~TinyTinyRSS(); + + Q_INVOKABLE void initialize(const QString serverUrl, const QString sessionId); + Q_INVOKABLE void reload(); + Q_INVOKABLE void loggedOut(); + + + QQmlListProperty posts(); + int postsCount() const; + Post *post(int) const; + +signals: + void postsChanged(QList); + +private slots: + void onPostReadChanged(bool); + +private: + void doOperation(QString operation, QVariantMap opts, std::function callback); + void updateArticle(int articleId, int field, bool trueFalse, std::function callback); + + QString mServerUrl; + QString mSessionId; + QList mPosts; + QNetworkAccessManager *mNetworkManager; +}; + +#endif // TINYTINYRSS_H diff --git a/src/tinytinyrsslogin.cpp b/src/tinytinyrsslogin.cpp new file mode 100644 index 0000000..2648e7a --- /dev/null +++ b/src/tinytinyrsslogin.cpp @@ -0,0 +1,135 @@ +/* + * This file is part of FeedTheMonkey. + * + * Copyright 2015 Jeena + * + * FeedTheMonkey is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FeedTheMonkey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FeedTheMonkey. If not, see . + */ + +#include "tinytinyrsslogin.h" +#include +#include +#include +#include + +#define APP_URL "net.jeena" +#define APP_NAME "FeedTheMonkey" + +TinyTinyRSSLogin::TinyTinyRSSLogin(QObject *parent) : + QObject(parent) +{ + mNetworkManager = new QNetworkAccessManager(this); + + QSettings settings; + mSessionId = settings.value("sessionId").toString(); + mServerUrl = settings.value("serverUrl").toString(); +} + +TinyTinyRSSLogin::~TinyTinyRSSLogin() +{ + delete mNetworkManager; +} + +bool TinyTinyRSSLogin::loggedIn() +{ + return !mSessionId.isEmpty(); +} + +void TinyTinyRSSLogin::login(const QString serverUrl, const QString user, const QString password) +{ + mServerUrl = QUrl(serverUrl + "/api/"); + + QVariantMap options; + options.insert("op", "login"); + options.insert("user", user); + options.insert("password", password); + + QJsonObject jsonobj = QJsonObject::fromVariantMap(options); + QJsonDocument json = QJsonDocument(jsonobj); + + QNetworkRequest request(mServerUrl); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QNetworkReply *reply = mNetworkManager->post(request, json.toJson()); + connect(reply, SIGNAL(finished()), this, SLOT(reply())); +} + +void TinyTinyRSSLogin::logout() +{ + if(mSessionId.length() > 0 && mServerUrl.toString().length() > 0) { + QVariantMap options; + options.insert("op", "logout"); + options.insert("sid", mSessionId); + + QJsonObject jsonobj = QJsonObject::fromVariantMap(options); + QJsonDocument json = QJsonDocument(jsonobj); + + QNetworkRequest request(mServerUrl); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QNetworkReply *reply = mNetworkManager->post(request, json.toJson()); + connect(reply, SIGNAL(finished()), this, SLOT(reply())); + } +} + +void TinyTinyRSSLogin::reply() +{ + QNetworkReply *reply = qobject_cast(sender()); + + if (reply) { + + if (reply->error() == QNetworkReply::NoError) { + + QString jsonString = QString(reply->readAll()); + QJsonDocument json = QJsonDocument::fromJson(jsonString.toUtf8()); + if(json.object().value("content").toObject().value("error").toString().length() > 0) { + + mLoginError = json.object().value("content").toObject().value("error").toString(); + qWarning() << mLoginError; + emit loginErrorChanged(mLoginError); + + if(mLoginError == "NOT_LOGGED_IN") { + mSessionId = nullptr; + mServerUrl = nullptr; + + QSettings settings; + settings.remove("sessionId"); + settings.remove("serverUrl"); + settings.sync(); + + emit sessionIdChanged(mSessionId); + } + + } else { + mSessionId = json.object().value("content").toObject().value("session_id").toString(); + + emit sessionIdChanged(mSessionId); + + QSettings settings; + settings.setValue("sessionId", mSessionId); + settings.setValue("serverUrl", mServerUrl); + settings.sync(); + } + } else { + mLoginError = "HTTP error: " + + reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toString() + + " :: " + + reply->errorString(); + qWarning() << mLoginError; + + emit loginErrorChanged(mLoginError); + } + reply->deleteLater(); + } +} diff --git a/src/tinytinyrsslogin.h b/src/tinytinyrsslogin.h new file mode 100644 index 0000000..5c21887 --- /dev/null +++ b/src/tinytinyrsslogin.h @@ -0,0 +1,60 @@ +/* + * This file is part of FeedTheMonkey. + * + * Copyright 2015 Jeena + * + * FeedTheMonkey is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * FeedTheMonkey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FeedTheMonkey. If not, see . + */ + +#ifndef TINYTINYRSSLOGIN_H +#define TINYTINYRSSLOGIN_H + +#include +#include +#include +#include + +class TinyTinyRSSLogin : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString sessionId READ sessionId NOTIFY sessionIdChanged) + Q_PROPERTY(QUrl serverUrl READ serverUrl) + Q_PROPERTY(QString loginError READ loginError NOTIFY loginErrorChanged) + +public: + TinyTinyRSSLogin(QObject *parent = 0); + ~TinyTinyRSSLogin(); + QString sessionId() const { return mSessionId; } + QUrl serverUrl() const { return mServerUrl; } + QString loginError() const { return mLoginError; } + + Q_INVOKABLE bool loggedIn(); + Q_INVOKABLE void login(const QString serverUrl, const QString user, const QString password); + Q_INVOKABLE void logout(); + +signals: + void sessionIdChanged(QString); + void loginErrorChanged(QString); + +private slots: + void reply(); + +private: + QString mSessionId; + QUrl mServerUrl; + QString mLoginError; + QNetworkAccessManager *mNetworkManager; +}; + +#endif // TINYTINYRSSLOGIN_H