Compare commits

..

No commits in common. "master" and "0.12.1" have entirely different histories.

23 changed files with 1358 additions and 1328 deletions

View File

@ -1,223 +1,188 @@
kind: pipeline pipeline:
name: build x86_64 gcc6:
image: ubuntu:xenial
pull: true
environment:
- LANG=C.utf8
- CXX=g++-6
- CXXFLAGS=-pipe -O2
commands:
- rm /etc/apt/apt.conf.d/docker-clean
- echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu xenial main" >> /etc/apt/sources.list.d/ubuntu-toolchain-r.list
# - echo "deb http://ppa.launchpad.net/george-edison55/cmake-3.x/ubuntu xenial main" >> /etc/apt/sources.list.d/cmake-3.x.list
- gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 0x60c317803a41ba51845e371a1e9377a2ba9ef27f
# - gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 0xb118cd3c377df930edd06c67084ecfc5828ab726
- gpg --armor --export 0x60c317803a41ba51845e371a1e9377a2ba9ef27f | apt-key add -
# - gpg --armor --export 0xb118cd3c377df930edd06c67084ecfc5828ab726 | apt-key add -
- apt-get update -q
- apt-get install -qy g++-6 cmake pkg-config
- apt-get install -qy libvsqlitepp-dev libboost-dev libxdg-basedir-dev qt5-default qttools5-dev-tools qttools5-dev libconfig++-dev
- apt-get install -qy dpkg-dev rpm file wget
- gpg --import /var/autosign_gpg.key
- rm -rf build && mkdir -p build && cd build
- cmake -DCMAKE_INSTALL_PREFIX=/usr ..
- make VERBOSE=1
- make install DESTDIR=install
- make package
- cmake -DWITH_DEB=ON ..
- make package
- cmake -DWITH_DEB=OFF -DWITH_RPM=ON ..
- make package
- gpg --verbose --detach-sign *.tar.gz
- gpg --verbose --detach-sign *.deb
- gpg --verbose --detach-sign *.rpm
volumes:
- /var/cache/debian-package-cache:/var/cache/apt/archives
- /home/tastytea/misc/autosign_gpg.key:/var/autosign_gpg.key
volumes: gcc7:
- name: debian-package-cache image: debian:stretch-slim
host: pull: true
path: /var/cache/debian-package-cache when:
event: [push, pull_request]
environment:
- LANG=C.utf8
- CXX=g++-7
- CXXFLAGS=-pipe -O2
commands:
- rm /etc/apt/apt.conf.d/docker-clean
- apt-get update -q
- echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
- echo "deb http://deb.debian.org/debian stretch-backports main" >> /etc/apt/sources.list.d/backports.list
- echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu xenial main" >> /etc/apt/sources.list.d/ubuntu-toolchain-r.list
- apt-get install -qy gnupg
- gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 0x60c317803a41ba51845e371a1e9377a2ba9ef27f
- gpg --armor --export 0x60c317803a41ba51845e371a1e9377a2ba9ef27f | apt-key add -
- apt-get update -q
- apt-get install -qy -t xenial g++-7
- apt-get install -qy cmake pkg-config
- apt-get install -qy libvsqlitepp-dev libboost-dev libxdg-basedir-dev qt5-default qttools5-dev-tools qttools5-dev libconfig++-dev
- rm -rf build && mkdir -p build && cd build
- cmake ..
- make VERBOSE=1
- make install DESTDIR=install
volumes:
- /var/cache/debian-package-cache:/var/cache/apt/archives
trigger: gcc8:
event: image: debian:stretch-slim
exclude: pull: true
- tag when:
event: [push, pull_request]
environment:
- LANG=C.utf8
- CXX=g++-8
- CXXFLAGS=-pipe -O2
commands:
- rm /etc/apt/apt.conf.d/docker-clean
- apt-get update -q
- echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
- echo "deb http://deb.debian.org/debian stretch-backports main" >> /etc/apt/sources.list.d/backports.list
- echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu xenial main" >> /etc/apt/sources.list.d/ubuntu-toolchain-r.list
- apt-get install -qy gnupg
- gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 0x60c317803a41ba51845e371a1e9377a2ba9ef27f
- gpg --armor --export 0x60c317803a41ba51845e371a1e9377a2ba9ef27f | apt-key add -
- apt-get update -q
- apt-get install -qy -t xenial g++-8
- apt-get install -qy cmake pkg-config
- apt-get install -qy libvsqlitepp-dev libboost-dev libxdg-basedir-dev qt5-default qttools5-dev-tools qttools5-dev libconfig++-dev
- rm -rf build && mkdir -p build && cd build
- cmake ..
- make VERBOSE=1
- make install DESTDIR=install
volumes:
- /var/cache/debian-package-cache:/var/cache/apt/archives
steps: clang3:
- name: submodules image: debian:stretch-slim
image: docker:git pull: true
commands: when:
- git submodule init event: [push, pull_request]
- git submodule update --recursive environment:
- LANG=C.utf8
- CXX=clang++
- CXXFLAGS=-pipe -O2
commands:
- rm /etc/apt/apt.conf.d/docker-clean
- echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
- echo "deb http://deb.debian.org/debian stretch-backports main" >> /etc/apt/sources.list.d/backports.list
- apt-get update -q
- apt-get install -qy clang cmake pkg-config
- apt-get install -qy libvsqlitepp-dev libboost-dev libxdg-basedir-dev qt5-default qttools5-dev-tools qttools5-dev libconfig++-dev
- rm -rf build && mkdir -p build && cd build
- cmake ..
- make VERBOSE=1
- make install DESTDIR=install
volumes:
- /var/cache/debian-package-cache:/var/cache/apt/archives
- name: gcc6 clang5:
image: ubuntu:xenial image: debian:stretch-slim
pull: always pull: true
environment: when:
CXX: g++-6 event: [push, pull_request]
CXXFLAGS: -pipe -O2 environment:
commands: - LANG=C.utf8
- rm /etc/apt/apt.conf.d/docker-clean - CXX=clang++-5.0
- echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu xenial main" >> /etc/apt/sources.list.d/ubuntu-toolchain-r.list - CXXFLAGS=-pipe -O2
- gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 0x60c317803a41ba51845e371a1e9377a2ba9ef27f commands:
- gpg --armor --export 0x60c317803a41ba51845e371a1e9377a2ba9ef27f | apt-key add - - rm /etc/apt/apt.conf.d/docker-clean
- rm -f /var/cache/apt/archives/lock - echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
- apt-get update -q - echo "deb http://deb.debian.org/debian stretch-backports main" >> /etc/apt/sources.list.d/stretch.list
- rm -f /var/cache/apt/archives/lock - apt-get update -q
- apt-get install -qy g++-6 cmake pkg-config - apt-get install -qy -t stretch-backports clang-5.0
- rm -f /var/cache/apt/archives/lock - apt-get install -qy cmake pkg-config
- apt-get install -qy libvsqlitepp-dev libboost-dev libxdg-basedir-dev qt5-default qttools5-dev-tools qttools5-dev libconfig++-dev asciidoc - apt-get install -qy libvsqlitepp-dev libboost-dev libxdg-basedir-dev qt5-default qttools5-dev-tools qttools5-dev libconfig++-dev
- rm -rf build && mkdir -p build && cd build - rm -rf build && mkdir -p build && cd build
- cmake -DCMAKE_INSTALL_PREFIX=/usr .. - cmake ..
- make VERBOSE=1 - make VERBOSE=1
- make install DESTDIR=install - make install DESTDIR=install
volumes: volumes:
- name: debian-package-cache - /var/cache/debian-package-cache:/var/cache/apt/archives
path: /var/cache/apt/archives
- name: gcc9 clang6:
image: debian:stretch-slim image: debian:stretch-slim
pull: always pull: true
environment: when:
CXX: g++-9 event: [push, pull_request]
CXXFLAGS: -pipe -O2 environment:
commands: - LANG=C.utf8
- rm /etc/apt/apt.conf.d/docker-clean - CXX=clang++-6.0
- rm -f /var/cache/apt/archives/lock - CXXFLAGS=-pipe -O2
- apt-get update -q commands:
- echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release - rm /etc/apt/apt.conf.d/docker-clean
- echo "deb http://deb.debian.org/debian stretch-backports main" >> /etc/apt/sources.list.d/backports.list - echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
- echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu xenial main" >> /etc/apt/sources.list.d/ubuntu-toolchain-r.list - echo "deb http://deb.debian.org/debian stretch-backports main" >> /etc/apt/sources.list.d/stretch.list
- rm -f /var/cache/apt/archives/lock - apt-get update -q
- apt-get install -qy gnupg - apt-get install -qy -t stretch-backports clang-6.0
- gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 0x60c317803a41ba51845e371a1e9377a2ba9ef27f - apt-get install -qy cmake pkg-config
- gpg --armor --export 0x60c317803a41ba51845e371a1e9377a2ba9ef27f | apt-key add - - apt-get install -qy libvsqlitepp-dev libboost-dev libxdg-basedir-dev qt5-default qttools5-dev-tools qttools5-dev libconfig++-dev
- rm -f /var/cache/apt/archives/lock - rm -rf build && mkdir -p build && cd build
- apt-get update -q - cmake ..
- rm -f /var/cache/apt/archives/lock - make VERBOSE=1
- apt-get install -qy -t xenial g++-9 - make install DESTDIR=install
- rm -f /var/cache/apt/archives/lock volumes:
- apt-get install -qy cmake pkg-config - /var/cache/debian-package-cache:/var/cache/apt/archives
- rm -f /var/cache/apt/archives/lock
- apt-get install -qy libvsqlitepp-dev libboost-dev libxdg-basedir-dev qt5-default qttools5-dev-tools qttools5-dev libconfig++-dev asciidoc
- rm -rf build && mkdir -p build && cd build
- cmake ..
- make VERBOSE=1
- make install DESTDIR=install
volumes:
- name: debian-package-cache
path: /var/cache/apt/archives
- name: clang3 prepare_release:
image: debian:stretch-slim image: ubuntu:xenial
pull: always pull: true
environment: when:
CXX: clang++ event: tag
CXXFLAGS: -pipe -O2 commands:
commands: - cp -v build/whyblocked-${DRONE_TAG}_x86_64.tar.gz .
- rm /etc/apt/apt.conf.d/docker-clean - cp -v build/whyblocked-${DRONE_TAG}_x86_64.tar.gz.sig .
- echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release - cp -v build/whyblocked_${DRONE_TAG}-0_amd64.deb .
- echo "deb http://deb.debian.org/debian stretch-backports main" >> /etc/apt/sources.list.d/backports.list - cp -v build/whyblocked_${DRONE_TAG}-0_amd64.deb.sig .
- rm -f /var/cache/apt/archives/lock - cp -v build/whyblocked-${DRONE_TAG}-0.x86_64.rpm .
- apt-get update -q - cp -v build/whyblocked-${DRONE_TAG}-0.x86_64.rpm.sig .
- rm -f /var/cache/apt/archives/lock gitea_release:
- apt-get install -qy clang cmake pkg-config image: plugins/gitea-release
- rm -f /var/cache/apt/archives/lock pull: true
- apt-get install -qy libvsqlitepp-dev libboost-dev libxdg-basedir-dev qt5-default qttools5-dev-tools qttools5-dev libconfig++-dev asciidoc when:
- rm -rf build && mkdir -p build && cd build event: tag
- cmake ..
- make VERBOSE=1
- make install DESTDIR=install
volumes:
- name: debian-package-cache
path: /var/cache/apt/archives
- name: clang6
image: debian:stretch-slim
pull: always
environment:
CXX: clang++-6.0
CXXFLAGS: -pipe -O2
commands:
- rm /etc/apt/apt.conf.d/docker-clean
- echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
- echo "deb http://deb.debian.org/debian stretch-backports main" >> /etc/apt/sources.list.d/stretch.list
- rm -f /var/cache/apt/archives/lock
- apt-get update -q
- rm -f /var/cache/apt/archives/lock
- apt-get install -qy -t stretch-backports clang-6.0
- rm -f /var/cache/apt/archives/lock
- apt-get install -qy cmake pkg-config
- rm -f /var/cache/apt/archives/lock
- apt-get install -qy libvsqlitepp-dev libboost-dev libxdg-basedir-dev qt5-default qttools5-dev-tools qttools5-dev libconfig++-dev asciidoc
- rm -rf build && mkdir -p build && cd build
- cmake ..
- make VERBOSE=1
- make install DESTDIR=install
volumes:
- name: debian-package-cache
path: /var/cache/apt/archives
- name: notify
image: drillster/drone-email
pull: always
settings:
host: cryptoparty-celle.de
username:
from_secret: email_username
password:
from_secret: email_password
from: drone@tzend.de
when:
status: [ changed, failure ]
---
kind: pipeline
name: packages x86_64
volumes:
- name: debian-package-cache
host:
path: /var/cache/debian-package-cache
- name: gpg-key
host:
path: /var/autosign_gpg.key
trigger:
event:
- tag
steps:
- name: submodules
image: docker:git
commands:
- git submodule init
- git submodule update --recursive
- name: gcc6
image: ubuntu:xenial
pull: always
environment:
CXX: g++-6
CXXFLAGS: -pipe -O2
commands:
- rm /etc/apt/apt.conf.d/docker-clean
- echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu xenial main" >> /etc/apt/sources.list.d/ubuntu-toolchain-r.list
- gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 0x60c317803a41ba51845e371a1e9377a2ba9ef27f
- gpg --armor --export 0x60c317803a41ba51845e371a1e9377a2ba9ef27f | apt-key add -
- rm -f /var/cache/apt/archives/lock
- apt-get update -q
- rm -f /var/cache/apt/archives/lock
- apt-get install -qy g++-6 cmake pkg-config
- rm -f /var/cache/apt/archives/lock
- apt-get install -qy libvsqlitepp-dev libboost-dev libxdg-basedir-dev qt5-default qttools5-dev-tools qttools5-dev libconfig++-dev asciidoc
- rm -f /var/cache/apt/archives/lock
- apt-get install -qy dpkg-dev rpm file wget
- gpg --import /var/autosign_gpg.key
- rm -rf build && mkdir -p build && cd build
- cmake -DCMAKE_INSTALL_PREFIX=/usr ..
- make VERBOSE=1
- make install DESTDIR=install
- make package
- cmake -DWITH_DEB=ON ..
- make package
- cmake -DWITH_DEB=OFF -DWITH_RPM=ON ..
- make package
- gpg --verbose --detach-sign *.tar.gz
- gpg --verbose --detach-sign *.deb
- gpg --verbose --detach-sign *.rpm
volumes:
- name: debian-package-cache
path: /var/cache/apt/archives
- name: gpg-key
path: /var/autosign_gpg.key
- name: prepare_release
image: ubuntu:xenial
pull: always
commands:
- cp -v build/whyblocked-${DRONE_TAG}_x86_64.tar.gz .
- cp -v build/whyblocked-${DRONE_TAG}_x86_64.tar.gz.sig .
- cp -v build/whyblocked_${DRONE_TAG}-0_amd64.deb .
- cp -v build/whyblocked_${DRONE_TAG}-0_amd64.deb.sig .
- cp -v build/whyblocked-${DRONE_TAG}-0.x86_64.rpm .
- cp -v build/whyblocked-${DRONE_TAG}-0.x86_64.rpm.sig .
- name: release
image: plugins/gitea-release
pull: always
settings:
base_url: https://schlomp.space base_url: https://schlomp.space
api_key: secrets: [ gitea_token ]
from_secret: gitea_token
title: ${DRONE_TAG} title: ${DRONE_TAG}
prerelease: true prerelease: true
files: files:
@ -231,15 +196,11 @@ steps:
- sha256 - sha256
- sha512 - sha512
- name: notify notify:
image: drillster/drone-email image: drillster/drone-email
pull: always pull: true
settings:
host: cryptoparty-celle.de host: cryptoparty-celle.de
username: secrets: [ email_username, email_password ]
from_secret: email_username
password:
from_secret: email_password
from: drone@tzend.de from: drone@tzend.de
when: when:
status: [ changed, failure ] status: [ changed, failure ]

View File

@ -1,6 +1,6 @@
cmake_minimum_required (VERSION 3.2) cmake_minimum_required (VERSION 3.2)
project (whyblocked project (whyblocked
VERSION 0.15.0 VERSION 0.12.1
LANGUAGES CXX LANGUAGES CXX
) )
@ -13,15 +13,16 @@ pkg_check_modules(LIBXDG_BASEDIR REQUIRED libxdg-basedir)
# because the sqlite3 in Debian jessie doesn't come with a pkg-config module. # because the sqlite3 in Debian jessie doesn't come with a pkg-config module.
pkg_check_modules(SQLITE3 sqlite3) pkg_check_modules(SQLITE3 sqlite3)
find_package(Qt5Core CONFIG REQUIRED) find_package(Qt5Core CONFIG REQUIRED)
find_package(Qt5Widgets CONFIG REQUIRED) if(NOT WITHOUT_GUI)
pkg_check_modules(LIBCONFIG REQUIRED libconfig++) find_package(Qt5Widgets CONFIG REQUIRED)
pkg_check_modules(LIBCONFIG REQUIRED libconfig++)
endif()
set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_FLAGS_DEBUG set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -g -Og")
"${CMAKE_CXX_FLAGS_DEBUG} -Wpedantic -Wall -Wextra -g -Og -fno-omit-frame-pointer")
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOUIC ON)
@ -41,46 +42,31 @@ configure_file (
"${PROJECT_BINARY_DIR}/version.hpp" "${PROJECT_BINARY_DIR}/version.hpp"
) )
add_executable(${CMAKE_PROJECT_NAME} set(COMMON_LIBRARIES
src/qt/main.cpp src/qt/mainwindow.cpp src/qt/dialog_add.cpp ${LIBXDG_BASEDIR_LIBRARIES} vsqlitepp stdc++fs)
src/whyblocked.cpp src/xdgcfg.cpp)
target_link_libraries(${CMAKE_PROJECT_NAME}
${LIBXDG_BASEDIR_LIBRARIES} vsqlitepp Qt5::Widgets
${LIBCONFIG_LIBRARIES} stdc++fs)
set(WITH_MAN "YES" CACHE STRING "WITH_MAN defaults to \"YES\"")
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
WORKING_DIRECTORY "${PROJECT_BINARY_DIR}"
COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_PROJECT_NAME} whyblocked-gui)
if(WITH_MAN) add_executable(whyblocked
add_custom_command( src/interface_text.cpp src/whyblocked.cpp)
OUTPUT "${PROJECT_BINARY_DIR}/whyblocked.1" target_link_libraries(whyblocked ${COMMON_LIBRARIES} Qt5::Core)
WORKING_DIRECTORY "${PROJECT_BINARY_DIR}" install(TARGETS whyblocked DESTINATION ${CMAKE_INSTALL_BINDIR})
DEPENDS "${CMAKE_SOURCE_DIR}/whyblocked.1.adoc"
COMMAND ${CMAKE_SOURCE_DIR}/build_manpage.sh if(NOT WITHOUT_GUI)
ARGS ${PROJECT_VERSION}) add_executable(whyblocked-gui
add_custom_target(run ALL src/interface_qt.cpp src/whyblocked.cpp src/xdgcfg.cpp)
DEPENDS "${PROJECT_BINARY_DIR}/whyblocked.1" target_link_libraries(whyblocked-gui
) ${COMMON_LIBRARIES} Qt5::Widgets
${LIBCONFIG_LIBRARIES} stdc++fs)
install(TARGETS whyblocked-gui DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES de.tastytea.Whyblocked.desktop DESTINATION
${CMAKE_INSTALL_DATAROOTDIR}/applications)
install(FILES de.tastytea.Whyblocked.appdata.xml DESTINATION
${CMAKE_INSTALL_DATAROOTDIR}/metainfo)
install(FILES de.tastytea.Whyblocked.svg DESTINATION
${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/apps)
endif() endif()
install(TARGETS ${CMAKE_PROJECT_NAME} if(NOT WITHOUT_TRANSLATIONS)
DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES "${PROJECT_BINARY_DIR}/whyblocked-gui"
DESTINATION "${CMAKE_INSTALL_BINDIR}")
install(FILES de.tastytea.Whyblocked.desktop
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
install(FILES de.tastytea.Whyblocked.appdata.xml
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/metainfo)
install(FILES de.tastytea.Whyblocked.svg
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/apps)
if(WITH_MAN)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/whyblocked.1
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
endif()
set(WITH_TRANSLATIONS "YES" CACHE STRING "WITH_TRANSLATIONS defaults to \"YES\"")
if(WITH_TRANSLATIONS)
add_subdirectory(translations) add_subdirectory(translations)
endif() endif()

View File

@ -1,13 +1,14 @@
**Whyblocked** allows you to store the reason why you blocked someone, along **Whyblocked** allows you to store the reason why you blocked someone, along with
with “receipts”, URLs to the posts that led you to block them. "receipts", URLs to the posts that led you to block them.
It has a Qt-interface and uses an SQLite-database. It has a text- and a Qt-interface and uses an SQLite-database.
![Screenshot](https://doc.schlomp.space/whyblocked/whyblocked_screenshot.png) ![Screenshot Qt interface](https://doc.schlomp.space/whyblocked/whyblocked_screenshot.png)
## Usage ## Usage
Run `whyblocked`. You can also start it from the menu of your desktop For the text interface start `whyblocked`, for the Qt interface
`whyblocked-gui`. You can also start it from the menu of your desktop
environment. environment.
## Install ## Install
@ -16,12 +17,9 @@ environment.
Every [release](https://schlomp.space/tastytea/whyblocked/releases) includes Every [release](https://schlomp.space/tastytea/whyblocked/releases) includes
a .deb-package, an .rpm-package and a .tar.gz-package with precompiled binaries a .deb-package, an .rpm-package and a .tar.gz-package with precompiled binaries
for x86_64(amd64) for x86_64(amd64). These are automatically built and not tested. You can install
([more info](https://schlomp.space/tastytea/whyblocked/wiki/Binary-Packages)). them with `dpkg -i` or `rpm -i`, respectively. The packages are signed with the
These are automatically built and not tested. You can install them with PGP key [242E5AC4DA587BF9](https://tastytea.de/tastytea_autosign.asc)
`apt install ./whyblocked*.deb` or `yum install ./whyblocked*.rpm`,
respectively. The packages are signed with the PGP key
[242E5AC4DA587BF9](https://tastytea.de/tastytea_autosign.asc)
(Fingerprint: `F730 1ADF C9ED 2624 48C4 2B64 242E 5AC4 DA58 7BF9`). (Fingerprint: `F730 1ADF C9ED 2624 48C4 2B64 242E 5AC4 DA58 7BF9`).
Gentoo ebuilds are available via my Gentoo ebuilds are available via my
@ -31,26 +29,31 @@ Gentoo ebuilds are available via my
#### Dependencies #### Dependencies
* C++ compiler (tested: [gcc](https://gcc.gnu.org/) 6/8/9, * C++ compiler (tested: [gcc](https://gcc.gnu.org/) 6/7/8,
[clang](https://llvm.org/) 3/6) [clang](https://llvm.org/) 3/5/6)
* [cmake](https://cmake.org/) (at least 3.2) * [cmake](https://cmake.org/) (at least 3.2)
* [vsqlite++](http://vsqlite.virtuosic-bytes.com/) (tested: 0.3) * [vsqlite++](http://vsqlite.virtuosic-bytes.com/) (tested: 0.3)
* [libxdg-basedir](http://repo.or.cz/w/libxdg-basedir.git) (tested: 1.2) * [libxdg-basedir](http://repo.or.cz/w/libxdg-basedir.git) (tested: 1.2)
* [qtcore](https://www.qt.io/) (tested: 5.12/5.5) * [qtcore](https://www.qt.io/) (tested: 5.11/5.2)
* [qtwidgets](https://www.qt.io/) (tested: 5.12/5.5)
* [libconfig++](https://github.com/hyperrealm/libconfig) (tested: 1.5)
* Optional * Optional
* Translations: [lupdate & lrelease](http://doc.qt.io/qt-5/linguist-manager.html) (tested: 5.12/5.5) * GUI: [qtwidgets](https://www.qt.io/) (tested: 5.11/5.2)
* Manpage: [asciidoc](http://asciidoc.org/) (tested: 8.6) * GUI: [libconfig++](https://github.com/hyperrealm/libconfig) (tested: 1.5 / 1.4)
* Translations: [lupdate & lrelease](http://doc.qt.io/qt-5/linguist-manager.html) (tested: 5.11/5.2)
#### Get sourcecode #### Get sourcecode
Download the current Download the current
[release](https://schlomp.space/tastytea/whyblocked/releases). [release](https://schlomp.space/tastytea/whyblocked/releases) and copy
[xdgcfg](https://schlomp.space/tastytea/xdgcfg) into `xdgcfg/`.
If you clone from git, be sure to `git submodule init` and
`git submodule update` afterwards. See the [submodules article in the git book]
(https://git-scm.com/book/en/v2/Git-Tools-Submodules#_cloning_submodules) for
further info.
#### Compile #### Compile
``` zsh ```SH
mkdir build mkdir build
cd build cd build
cmake .. cmake ..
@ -60,8 +63,8 @@ make install
cmake options: cmake options:
* `-DCMAKE_BUILD_TYPE=Debug` for a debug build * `-DCMAKE_BUILD_TYPE=Debug` for a debug build
* `-DWITH_TRANSLATIONS=NO` to not compile translations * `-DWITHOUT_GUI=YES` to not build GUI
* `-DWITH_MAN=NO` to not compile the manpage * `-DWITHOUT_TRANSLATIONS=YES` to not compile translations
* One of: * One of:
* `-DWITH_DEB=YES` if you want to be able to generate a deb-package * `-DWITH_DEB=YES` if you want to be able to generate a deb-package
* `-DWITH_RPM=YES` if you want to be able to generate an rpm-package * `-DWITH_RPM=YES` if you want to be able to generate an rpm-package
@ -89,14 +92,14 @@ Please report them on the
## Licence & Copyright ## Licence & Copyright
``` plain ```PLAIN
Copyright © 2018 tastytea <tastytea@tastytea.de>. Copyright © 2018 tastytea <tastytea@tastytea.de>.
License GPLv3: GNU GPL version 3 <https://www.gnu.org/licenses/gpl-3.0.html>. License GPLv3: GNU GPL version 3 <https://www.gnu.org/licenses/gpl-3.0.html>.
This program comes with ABSOLUTELY NO WARRANTY. This is free software, This program comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions. and you are welcome to redistribute it under certain conditions.
``` ```
The icon is derived from the icons *“messagebox critical”* and *“help”* of the The icon is derived from the icons `messagebox critical` and `help` of the
[Gartoon icon theme](https://commons.wikimedia.org/wiki/Gartoon_icons). The [Gartoon icon theme](https://commons.wikimedia.org/wiki/Gartoon_icons). The
original authors were Zeus, Patrick Yavitz and La Mula Francis, who released original authors were Zeus, Patrick Yavitz and La Mula Francis, who released
them under the terms of the them under the terms of the

View File

@ -1,10 +0,0 @@
#!/bin/sh
if [ -n "${1}" ]; then
dir="$(dirname ${0})"
cp -vf ${dir}/whyblocked.1.adoc .
sed -Ei "s/(Revision: +)[0-9]+\.[0-9]\.[0-9]/\1${1}/" whyblocked.1.adoc
a2x --doctype manpage --format manpage --no-xmllint whyblocked.1.adoc
else
echo "usage: ${0} VERSION" >&2
fi

View File

@ -5,7 +5,7 @@ Name=Whyblocked
Comment=Reminds you why you blocked someone Comment=Reminds you why you blocked someone
Comment[de]=Erinnert dich, warum du jemanden blockiertest Comment[de]=Erinnert dich, warum du jemanden blockiertest
Icon=de.tastytea.Whyblocked Icon=de.tastytea.Whyblocked
Exec=whyblocked Exec=whyblocked-gui
Terminal=false Terminal=false
Categories=Utility; Categories=Utility;
Keywords=blocklist;social-network; Keywords=blocklist;social-network;

View File

@ -1,8 +1,8 @@
# Packages # Packages
set(CPACK_PACKAGE_NAME ${CMAKE_PROJECT_NAME}) set(CPACK_PACKAGE_NAME ${CMAKE_PROJECT_NAME})
set(CPACK_PACKAGE_VERSION_MAJOR ${${CMAKE_PROJECT_NAME}_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MAJOR ${mastodon-cpp_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${${CMAKE_PROJECT_NAME}_VERSION_MINOR}) set(CPACK_PACKAGE_VERSION_MINOR ${mastodon-cpp_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${${CMAKE_PROJECT_NAME}_VERSION_PATCH}) set(CPACK_PACKAGE_VERSION_PATCH ${mastodon-cpp_VERSION_PATCH})
set(CPACK_PACKAGE_VERSION ${whyblocked_VERSION}) set(CPACK_PACKAGE_VERSION ${whyblocked_VERSION})
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Whyblocked reminds you why you blocked someone.") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Whyblocked reminds you why you blocked someone.")
set(CPACK_PACKAGE_CONTACT "tastytea <tastytea@tastytea.de>") set(CPACK_PACKAGE_CONTACT "tastytea <tastytea@tastytea.de>")

View File

@ -1,5 +1,5 @@
/* This file is part of whyblocked. /* This file is part of whyblocked.
* Copyright © 2018, 2019 tastytea <tastytea@tastytea.de> * Copyright © 2018 tastytea <tastytea@tastytea.de>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -16,27 +16,22 @@
#include <regex> #include <regex>
#include <array> #include <array>
#include <locale>
#include <codecvt>
#include <algorithm>
#include <QMessageBox> #include <QMessageBox>
#include <QDebug>
#include <iostream>
#include <QTranslator>
#include <QLibraryInfo>
#include <QtCore/qmimedata.h> #include <QtCore/qmimedata.h>
#include <libconfig.h++> #include <libconfig.h++>
#include "version.hpp" #include "version.hpp"
#include "mainwindow.hpp" #include "whyblocked.hpp"
#include "dialog_add.hpp" #include "interface_qt.hpp"
using std::wstring;
MainWindow::MainWindow(QMainWindow *parent) MainWindow::MainWindow(QMainWindow *parent)
: QMainWindow(parent) : QMainWindow(parent)
, _config("whyblocked.cfg") , _config("whyblocked.cfg")
, _headersize({ 250, 125, 125 }) , _headersize({ 250, 125, 125 })
, _database()
, _dbdata(_database.get_data())
{ {
std::locale::global(std::locale(""));
setupUi(this); setupUi(this);
_model = new QStandardItemModel; _model = new QStandardItemModel;
@ -91,23 +86,9 @@ MainWindow::MainWindow(QMainWindow *parent)
const libconfig::Setting &value = root[key.c_str()]; const libconfig::Setting &value = root[key.c_str()];
_headersize = { value[0], value[1], value[2] }; _headersize = { value[0], value[1], value[2] };
} }
key = "find_in";
if (root.exists(key) && root[key.c_str()].isGroup())
{
const libconfig::Setting &value = root[key.c_str()];
check_user->setChecked(value["user"]);
check_reason->setChecked(value["reason"]);
}
} }
widget_find->hide(); populate_tableview();
reload();
statusBar()->showMessage(tr("Try dragging an account from your webbrowser "
"into this window."));
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()
@ -115,8 +96,7 @@ MainWindow::~MainWindow()
libconfig::Setting &root = _config.get_cfg().getRoot(); libconfig::Setting &root = _config.get_cfg().getRoot();
// We can't add an element that already exists, so we delete it beforehand. // We can't add an element that already exists, so we delete it beforehand.
for (const string &key : for (const string &key :
{ "size", "toolbar_position", "toolbar_visible", "table_headers", { "size", "toolbar_position", "toolbar_visible", "table_headers" })
"find_in" })
{ {
if (root.exists(key)) if (root.exists(key))
{ {
@ -162,18 +142,39 @@ MainWindow::~MainWindow()
tableview->horizontalHeader()->sectionSize(0); tableview->horizontalHeader()->sectionSize(0);
headers.add(libconfig::Setting::TypeInt) = headers.add(libconfig::Setting::TypeInt) =
tableview->horizontalHeader()->sectionSize(1); tableview->horizontalHeader()->sectionSize(1);
headers.add(libconfig::Setting::TypeInt) = 125; headers.add(libconfig::Setting::TypeInt) =
tableview->horizontalHeader()->sectionSize(2);
libconfig::Setting &find_in = root.add("find_in",
libconfig::Setting::TypeGroup);
find_in.add("user", libconfig::Setting::TypeBoolean) =
check_user->isChecked();
find_in.add("reason", libconfig::Setting::TypeBoolean) =
check_reason->isChecked();
_config.write(); _config.write();
} }
void MainWindow::populate_tableview()
{
_model->clear();
_model->setHorizontalHeaderLabels(
{
tr("User/Instance"),
tr("Blocked/Silenced"),
tr("Reason")
});
tableview->horizontalHeader()->resizeSection(0, _headersize[0]);
tableview->horizontalHeader()->resizeSection(1, _headersize[1]);
tableview->horizontalHeader()->resizeSection(2, _headersize[2]);
result_view result;
if (database::view(result))
{
for (const std::tuple<string, int, string> &line : result)
{
add_row(QString::fromStdString(std::get<0>(line)),
std::get<1>(line),
QString::fromStdString(std::get<2>(line)));
}
}
statusBar()->showMessage(tr("Database loaded."));
}
void MainWindow::add_row(const QString &user, const int &blocked, void MainWindow::add_row(const QString &user, const int &blocked,
const QString &reason) const QString &reason)
{ {
@ -191,26 +192,100 @@ void MainWindow::add_row(const QString &user, const int &blocked,
_model->appendRow(items); _model->appendRow(items);
} }
void MainWindow::add()
{
DialogAdd *dialog = new DialogAdd(this);
dialog->show();
}
void MainWindow::edit()
{
if (tableview->selectionModel()->selectedRows().count() != 1)
{
QMessageBox::warning(this, tr("Invalid selection"),
tr("Please select only 1 entry to edit."));
return;
}
DialogAdd *dialog = new DialogAdd(this);
dialog->setWindowTitle(tr("Edit entry"));
Dialogdata data;
QModelIndex index = tableview->selectionModel()->selectedRows().first();
data.user = index.sibling(index.row(), 0).data().toString().toStdString();
result_details details;
database::details(data.user, details);
if (std::get<0>(details) == true)
{
data.blocked = 1;
}
else
{
data.blocked = 0;
}
data.reason = std::get<1>(details);
data.receipts = std::get<2>(details);
dialog->set_data(data);
dialog->setProperty("edit", true);
dialog->show();
}
void MainWindow::remove() void MainWindow::remove()
{ {
QItemSelectionModel *selection = tableview->selectionModel(); QItemSelectionModel *selection = tableview->selectionModel();
if (selection->hasSelection()) if (selection->hasSelection())
{ {
// I use this construct here because the number of selected rows for (auto &row : selection->selectedRows())
// decrease by 1 each iteration.
for (; selection->selectedRows().count() > 0;)
{ {
const QModelIndex row = selection->selectedRows().front();
const string user = row.data().toString().toStdString(); const string user = row.data().toString().toStdString();
_database.remove(user); database::remove(user);
statusBar()->showMessage(tr("Removed %1 from database.")
.arg(QString::fromStdString(user)));
_model->removeRow(row.row()); _model->removeRow(row.row());
} }
label_receipts->clear(); label_receipts->clear();
} }
else else
{ {
QMessageBox::warning(this, tr("Nothing selected"), statusBar()->showMessage(tr("Select data to remove."));
tr("Please select entries to remove.")); }
}
void MainWindow::about()
{
QMessageBox::about(this, tr("About Whyblocked"),
tr("<p><b>Whyblocked</b> %1</p>"
"<p>Reminds you why you blocked someone.</p>"
"<p>Sourcecode: <a href=\"https://schlomp.space/tastytea/whyblocked\">"
"https://schlomp.space/tastytea/whyblocked</a></p>"
"<p><small>Copyright © 2018 <a href=\"mailto:tastytea@tastytea.de\">tastytea</a>.<br>"
"Licence GPLv3: <a href=\"https://www.gnu.org/licenses/gpl-3.0.html\">"
"GNU GPL version 3</a>.<br>"
"This program comes with ABSOLUTELY NO WARRANTY. This is free software, "
"and you are welcome to redistribute it under certain conditions.</small></p>")
.arg(global::version));
}
void MainWindow::show_details(QModelIndex index)
{
const string user = index.sibling(index.row(), 0).data()
.toString().toStdString();
result_details result;
string text = "";
if (database::details(user, result))
{
if (!std::get<2>(result).empty())
{
text += string("<b>") + tr("Receipts:").toStdString() + "</b>";
for (const string &url : std::get<2>(result))
{
text += "<br>" + url;
}
text = urls_to_hyperlinks(text);
}
label_receipts->setText(QString::fromStdString((text)));
} }
} }
@ -252,148 +327,127 @@ void MainWindow::dropEvent(QDropEvent *event)
} }
} }
DialogAdd *dialog = new DialogAdd(_database, this); DialogAdd *dialog = new DialogAdd(this);
Database::data data; Dialogdata data;
data.user = text; data.user = text;
data.blocked = true;
dialog->set_data(data); dialog->set_data(data);
dialog->show(); dialog->show();
} }
void MainWindow::add() DialogAdd::DialogAdd(QMainWindow *parent)
: QDialog(parent)
, _parent(static_cast<MainWindow*>(parent))
{ {
DialogAdd *dialog = new DialogAdd(_database, this); setupUi(this);
dialog->show();
} }
void MainWindow::edit() const Dialogdata DialogAdd::get_data() const
{ {
if (tableview->selectionModel()->selectedRows().count() != 1) std::vector<string> receipts;
for (int row = 0; row <= list_receipts->count() - 1; ++row)
{
receipts.push_back(list_receipts->item(row)->text().toStdString());
}
Dialogdata data;
data.user = text_user->text().toStdString();
data.blocked = radio_blocked->isChecked();
data.reason = text_reason->text().toStdString();
data.receipts = receipts;
return data;
}
const void DialogAdd::set_data(const Dialogdata &data)
{
text_user->setText(QString::fromStdString(data.user));
radio_blocked->setChecked(data.blocked);
radio_silcenced->setChecked(!data.blocked);
text_reason->setText(QString::fromStdString(data.reason));
for (const string &receipt : data.receipts)
{
QListWidgetItem *item =
new QListWidgetItem(QString::fromStdString(receipt));
item->setFlags(item->flags() | Qt::ItemIsEditable);
list_receipts->insertItem(list_receipts->count(), item);
}
}
void DialogAdd::add_receipt()
{
QListWidgetItem *item = new QListWidgetItem(tr("Insert receipt here."));
item->setFlags(item->flags() | Qt::ItemIsEditable);
list_receipts->insertItem(list_receipts->count(), item);
list_receipts->editItem(item);
}
void DialogAdd::remove_receipt()
{
for (auto item :list_receipts->selectedItems())
{
delete item;
}
}
void DialogAdd::accept()
{
if (property("edit").toBool())
{
_parent->remove();
}
Dialogdata data = get_data();
if (data.user.empty())
{ {
QMessageBox::warning(this, tr("Invalid selection"),
tr("Please select only 1 entry to edit."));
return; return;
} }
database::add_block(data.user, data.blocked, data.reason);
DialogAdd *dialog = new DialogAdd(_database, this); _parent->add_row(QString::fromStdString(data.user),
dialog->setWindowTitle(tr("Edit entry")); data.blocked,
QString::fromStdString(data.reason));
QModelIndex index = tableview->selectionModel()->selectedRows().first(); for (const string &receipt : data.receipts)
const string user = index.sibling(index.row(), 0).data()
.toString().toStdString();
dialog->set_data(_database.get_user(user));
dialog->setProperty("edit", true);
dialog->show();
}
void MainWindow::about()
{
QMessageBox::about(this, tr("About Whyblocked"),
tr("<p><b>Whyblocked</b> %1</p>"
"<p>Reminds you why you blocked someone.</p>"
"<p>Sourcecode: <a href=\"https://schlomp.space/tastytea/whyblocked\">"
"https://schlomp.space/tastytea/whyblocked</a></p>"
"<p><small>Copyright © 2018 <a href=\"mailto:tastytea@tastytea.de\">tastytea</a>.<br>"
"Licence GPLv3: <a href=\"https://www.gnu.org/licenses/gpl-3.0.html\">"
"GNU GPL version 3</a>.<br>"
"This program comes with ABSOLUTELY NO WARRANTY. This is free software, "
"and you are welcome to redistribute it under certain conditions.</small></p>")
.arg(global::version));
}
void MainWindow::show_details(QModelIndex index)
{
const string user = index.sibling(index.row(), 0).data()
.toString().toStdString();
Database::data data = _database.get_user(user);
string text = "";
if (!data.receipts.empty())
{ {
text += string("<b>") + tr("Receipts:").toStdString() + "</b>"; database::add_receipt(data.user, receipt);
for (const string &url : data.receipts)
{
text += "<br>" + url;
}
text = urls_to_hyperlinks(text);
} }
label_receipts->setText(QString::fromStdString((text)));
_parent->statusBar()->showMessage(tr("Added %1 to database.")
.arg(QString::fromStdString(data.user)));
delete this;
} }
void MainWindow::populate_tableview(const vector<Database::data> &entries) void DialogAdd::dragEnterEvent(QDragEnterEvent *event)
{ {
_model->clear(); if (event->mimeData()->hasFormat("text/plain"))
_model->setHorizontalHeaderLabels(
{ {
tr("User/Instance"), event->acceptProposedAction();
tr("Blocked/Silenced"),
tr("Reason")
});
tableview->horizontalHeader()->resizeSection(0, _headersize[0]);
tableview->horizontalHeader()->resizeSection(1, _headersize[1]);
tableview->horizontalHeader()->resizeSection(2, _headersize[2]);
for (const Database::data &entry : entries)
{
add_row(QString::fromStdString(entry.user),
entry.blocked,
QString::fromStdString(entry.reason));
} }
} }
void MainWindow::reload() void DialogAdd::dropEvent(QDropEvent *event)
{ {
_database.reload(); const QString text = event->mimeData()->text();
populate_tableview(_dbdata); QListWidgetItem *item = new QListWidgetItem(text);
item->setFlags(item->flags() | Qt::ItemIsEditable);
list_receipts->insertItem(list_receipts->count(), item);
} }
void MainWindow::find() int main(int argc, char *argv[])
{ {
if (widget_find->isVisible()) QApplication app(argc, argv);
{ QCoreApplication::setApplicationName("Whyblocked");
widget_find->hide();
} QTranslator qtTranslator;
else qtTranslator.load("qt_" + QLocale::system().name(),
{ QLibraryInfo::location(QLibraryInfo::TranslationsPath));
widget_find->show(); app.installTranslator(&qtTranslator);
text_find->setFocus(); QTranslator appTranslator;
} appTranslator.load("whyblocked_" + QLocale::system().name(),
} QLibraryInfo::location(QLibraryInfo::TranslationsPath));
app.installTranslator(&appTranslator);
void MainWindow::update_search(const QString &text)
{ MainWindow win;
const wstring searchfor = text.toLower().toStdWString(); win.show();
vector<Database::data> filtered_entries; return app.exec();
if (!_dbdata.empty())
{
for (const Database::data &entry : _dbdata)
{
wstring searchstring;
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;
if (check_user->isChecked())
{
searchstring += convert.from_bytes(entry.user);
}
if (check_reason->isChecked())
{
searchstring += convert.from_bytes(entry.reason);
}
std::transform(searchstring.begin(), searchstring.end(),
searchstring.begin(), ::towlower);
if (searchstring.find(searchfor) != std::string::npos)
{
filtered_entries.push_back(entry);
}
}
}
populate_tableview(filtered_entries);
}
void MainWindow::update_search()
{
update_search(text_find->text());
} }

View File

@ -1,5 +1,5 @@
/* This file is part of whyblocked. /* This file is part of whyblocked.
* Copyright © 2018, 2019 tastytea <tastytea@tastytea.de> * Copyright © 2018 tastytea <tastytea@tastytea.de>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -14,23 +14,29 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef MAINWINDOW_HPP #ifndef INTERFACE_QT_HPP
#define MAINWINDOW_HPP #define INTERFACE_QT_HPP
#include <string> #include <string>
#include <memory> #include <memory>
#include <array> #include <array>
#include <vector>
#include <QMainWindow> #include <QMainWindow>
#include <QStandardItemModel> #include <QStandardItemModel>
#include <QDialog> #include <QDialog>
#include <QtGui/qevent.h> #include <QtGui/qevent.h>
#include "../xdgcfg.hpp" #include "xdgcfg.hpp"
#include "../whyblocked.hpp"
#include "ui_whyblocked.h" #include "ui_whyblocked.h"
#include "ui_whyblocked_add.h"
using std::string; using std::string;
using std::vector;
struct Dialogdata
{
string user = "";
bool blocked = true;
string reason = "";
std::vector<string> receipts = {};
};
class MainWindow : public QMainWindow, private Ui::MainWindow class MainWindow : public QMainWindow, private Ui::MainWindow
{ {
@ -53,20 +59,36 @@ private:
QStandardItemModel *_model; QStandardItemModel *_model;
xdgcfg _config; xdgcfg _config;
std::array<int, 3> _headersize; std::array<int, 3> _headersize;
Database _database;
std::vector<Database::data> &_dbdata;
private slots: private slots:
void add(); void add();
void edit(); void edit();
void about(); void about();
void show_details(QModelIndex index); void show_details(QModelIndex index);
void populate_tableview(const vector<Database::data> &entries); void populate_tableview();
void reload();
void find();
void update_search(const QString &text);
void update_search();
}; };
#endif // MAINWINDOW_HPP class DialogAdd : public QDialog, private Ui::DialogAdd
{
Q_OBJECT
public:
explicit DialogAdd(QMainWindow *parent = nullptr);
const void set_data(const Dialogdata &data);
private:
const Dialogdata get_data() const;
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);
MainWindow *_parent;
private slots:
void add_receipt();
void remove_receipt();
void accept();
};
#endif // INTERFACE_QT_HPP

322
src/interface_text.cpp Normal file
View File

@ -0,0 +1,322 @@
/* This file is part of whyblocked.
* Copyright © 2018 tastytea <tastytea@tastytea.de>
*
* This program 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, version 3.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <QCoreApplication>
#include <QTranslator>
#include <QLocale>
#include <QLibraryInfo>
#include "version.hpp"
#include "whyblocked.hpp"
#include "interface_text.hpp"
using std::cout;
using std::cerr;
using std::cin;
// Allow cout to output QStrings
std::ostream &operator <<(std::ostream &stream, const QString &str)
{
stream << str.toStdString();
return stream;
}
const string Text::get_answer(const QString &question)
{
string answer;
cout << question << ": ";
std::getline(cin, answer, '\n');
return answer;
}
const bool Text::askblocked()
{
while (true)
{
const string blocked = get_answer(tr("Blocked or silenced?") +
" [b/s]");
if (blocked[0] == 'b' || blocked[0] == 'B')
{
return true;
}
else if (blocked[0] == 's' || blocked[0] == 'S')
{
return false;
}
}
}
const void Text::askrecipes(const string &user)
{
while (true)
{
const string receipt_yn = get_answer(tr("Add receipt? [y/n]"));
if (receipt_yn[0] == tr("y")[0] || receipt_yn[0] == tr("Y")[0])
{
const string receipt = get_answer(tr("Receipt"));
if (database::add_receipt(user, receipt))
{
cout << tr("Receipt added.") << '\n';
}
}
else if (receipt_yn[0] == tr("n")[0] || receipt_yn[0] == tr("N")[0])
{
break;
}
else
{
continue;
}
}
}
const void Text::add()
{
const string user = get_answer(tr("User or instance"));
int blocked;
if (askblocked())
{
blocked = 1;
}
else
{
blocked = 0;
}
const string reason = get_answer(tr("Reason"));
if (database::add_block(user, blocked, reason))
{
cout << user << " " << tr("added.") << '\n';
}
askrecipes(user);
}
const void Text::edit()
{
result_details olddata;
const string olduser = get_answer(tr("User or instance"));
if (database::details(olduser, olddata))
{
cout << tr("A blank line keeps the former value.") << '\n';
string newuser = get_answer(tr("Change user or instance to"));
if (newuser.empty())
{
newuser = olduser;
}
int blocked;
if (askblocked())
{
blocked = 1;
}
else
{
blocked = 0;
}
cout << tr("Old reason was:") << " " << std::get<1>(olddata) << '\n';
string newreason = get_answer(tr("Change reason to"));
if (newreason.empty())
{
newreason = std::get<1>(olddata);
}
std::vector<string> newreceipts;
for (const string &oldreceipt : std::get<2>(olddata))
{
cout << tr("Old receipt was:") << " " << oldreceipt << '\n';
string newreceipt = get_answer(tr("Change receipt to"));
if (newreceipt.empty())
{
newreceipt = oldreceipt;
}
newreceipts.push_back(newreceipt);
}
if (database::remove(olduser))
{
database::add_block(newuser, blocked, newreason);
if (!newreceipts.empty())
{
for (const string &newreceipt : newreceipts)
{
database::add_receipt(newuser, newreceipt);
}
}
askrecipes(newuser);
}
else
{
cerr << tr("Could not remove") << " " << olduser << ".\n";
}
}
}
const void Text::remove()
{
const string user = get_answer(tr("User or instance"));
if (database::remove(user))
{
cout << user << " " << tr("removed.") << '\n';
}
}
const void Text::view()
{
result_view result;
if (database::view(result))
{
for (const std::tuple<string, int, string> &line : result)
{
if (std::get<1>(line) == 1)
{
cout << tr(" Blocked:") << " ";
}
else
{
cout << tr("Silenced:") << " ";
}
cout << std::get<0>(line) << " " << tr("because:") << " ";
cout << std::get<2>(line) << '\n';
}
}
}
const void Text::details()
{
const string user = get_answer(tr("User or instance"));
{
result_details result;
if (database::details(user, result))
{
cout << user << " " << tr("is") << " ";
if (std::get<0>(result) == 1)
{
cout << tr("blocked, because:") << " ";
}
else if (std::get<0>(result) == 0)
{
cout << tr("silenced, because:") << " ";
}
cout << std::get<1>(result) << '\n';
if (!std::get<2>(result).empty())
{
cout << tr("Receipts:") << '\n';
for (const string &url : std::get<2>(result))
{
cout << " " << url << '\n';
}
}
}
}
}
const void Text::help()
{
cout << tr(
"Type add, edit, remove, view or details. Or just the first letter.")
<< '\n';
cout << tr(
"Type help or h to show this help. Type quit or q to quit the program.")
<< '\n';
}
Text::Text(QObject *parent) : QObject(parent)
{
bool keeprunning = true;
cout << tr("This is Whyblocked") << " " << global::version << ".\n";
help();
while (keeprunning)
{
string answer = get_answer("");
switch (answer[0])
{
case 'a':
case 'A':
{
add();
break;
}
case 'e':
case 'E':
{
edit();
break;
}
case 'r':
case 'R':
{
remove();
break;
}
case 'v':
case 'V':
{
view();
break;
}
case 'd':
case 'D':
{
details();
break;
}
case 'h':
case 'H':
{
help();
break;
}
case 'q':
case 'Q':
{
keeprunning = false;
break;
}
default:
{
cout << tr("Response not understood.") << '\n';
}
}
}
}
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QCoreApplication::setApplicationName("Whyblocked");
QTranslator qtTranslator;
qtTranslator.load("qt_" + QLocale::system().name(),
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
app.installTranslator(&qtTranslator);
QTranslator appTranslator;
appTranslator.load("whyblocked_" + QLocale::system().name(),
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
app.installTranslator(&appTranslator);
Text t(&app);
return 0;
}

View File

@ -1,5 +1,5 @@
/* This file is part of whyblocked. /* This file is part of whyblocked.
* Copyright © 2019 tastytea <tastytea@tastytea.de> * Copyright © 2018 tastytea <tastytea@tastytea.de>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -14,33 +14,31 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef DIALOG_ADD_HPP #ifndef INTERFACE_TEXT_HPP
#define DIALOG_ADD_HPP #define INTERFACE_TEXT_HPP
#include "mainwindow.hpp" #include <string>
#include "ui_whyblocked_add.h" #include <QtCore>
class DialogAdd : public QDialog, private Ui::DialogAdd using std::string;
class Text : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit DialogAdd(Database &database, QMainWindow *parent = nullptr); explicit Text(QObject *parent = nullptr);
void set_data(const Database::data &data);
private: private:
const Database::data get_data() const; const string get_answer(const QString &question);
void dragEnterEvent(QDragEnterEvent *event); const bool askblocked();
void dropEvent(QDropEvent *event); const void askrecipes(const string &user);
const void add();
MainWindow *_parent; const void edit();
Database &_database; const void remove();
const void view();
private slots: const void details();
void add_receipt(); const void help();
void remove_receipt();
void accept();
}; };
#endif // DIALOG_ADD_HPP #endif // INTERFACE_TEXT_HPP

View File

@ -1,112 +0,0 @@
/* This file is part of whyblocked.
* Copyright © 2019 tastytea <tastytea@tastytea.de>
*
* This program 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, version 3.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QtCore/qmimedata.h>
#include "dialog_add.hpp"
DialogAdd::DialogAdd(Database &database, QMainWindow *parent)
: QDialog(parent)
, _parent(static_cast<MainWindow*>(parent))
, _database(database)
{
setupUi(this);
}
void DialogAdd::set_data(const Database::data &data)
{
text_user->setText(QString::fromStdString(data.user));
radio_blocked->setChecked(data.blocked);
radio_silcenced->setChecked(!data.blocked);
text_reason->setText(QString::fromStdString(data.reason));
for (const string &receipt : data.receipts)
{
QListWidgetItem *item =
new QListWidgetItem(QString::fromStdString(receipt));
item->setFlags(item->flags() | Qt::ItemIsEditable);
list_receipts->insertItem(list_receipts->count(), item);
}
}
const Database::data DialogAdd::get_data() const
{
std::vector<string> receipts;
for (int row = 0; row <= list_receipts->count() - 1; ++row)
{
receipts.push_back(list_receipts->item(row)->text().toStdString());
}
Database::data data;
data.user = text_user->text().toStdString();
data.blocked = radio_blocked->isChecked();
data.reason = text_reason->text().toStdString();
data.receipts = receipts;
return data;
}
void DialogAdd::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat("text/plain"))
{
event->acceptProposedAction();
}
}
void DialogAdd::dropEvent(QDropEvent *event)
{
const QString text = event->mimeData()->text();
QListWidgetItem *item = new QListWidgetItem(text);
item->setFlags(item->flags() | Qt::ItemIsEditable);
list_receipts->insertItem(list_receipts->count(), item);
}
void DialogAdd::add_receipt()
{
QListWidgetItem *item = new QListWidgetItem(tr("Insert receipt here."));
item->setFlags(item->flags() | Qt::ItemIsEditable);
list_receipts->insertItem(list_receipts->count(), item);
list_receipts->editItem(item);
}
void DialogAdd::remove_receipt()
{
for (auto item :list_receipts->selectedItems())
{
delete item;
}
}
void DialogAdd::accept()
{
if (property("edit").toBool())
{
_parent->remove();
}
Database::data data = get_data();
if (!data)
{
return;
}
_database.add_user(data);
_parent->add_row(QString::fromStdString(data.user),
data.blocked,
QString::fromStdString(data.reason));
delete this;
}

View File

@ -1,42 +0,0 @@
/* This file is part of whyblocked.
* Copyright © 2019, 2020 tastytea <tastytea@tastytea.de>
*
* This program 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, version 3.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "mainwindow.hpp"
#include <QLibraryInfo>
#include <QLocale>
#include <QTranslator>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QCoreApplication::setApplicationName("Whyblocked");
QTranslator qtTranslator;
qtTranslator.load(QLocale(), "qt", "_",
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
app.installTranslator(&qtTranslator);
QTranslator appTranslator;
appTranslator.load(QLocale(), "whyblocked", "_",
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
app.installTranslator(&appTranslator);
MainWindow win;
win.show();
return app.exec();
}

View File

@ -1,5 +1,5 @@
/* This file is part of whyblocked. /* This file is part of whyblocked.
* Copyright © 2018, 2019 tastytea <tastytea@tastytea.de> * Copyright © 2018 tastytea <tastytea@tastytea.de>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -17,7 +17,7 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <vector> #include <vector>
#include <iterator> #include <tuple>
#include <experimental/filesystem> #include <experimental/filesystem>
#include <basedir.h> #include <basedir.h>
#include <sqlite/connection.hpp> #include <sqlite/connection.hpp>
@ -28,25 +28,20 @@
using std::cerr; using std::cerr;
namespace fs = std::experimental::filesystem; namespace fs = std::experimental::filesystem;
Database::data::operator bool() const const string get_filepath()
{ {
return !user.empty(); string filepath;
}
const string Database::get_filepath() const
{
fs::path filepath;
xdgHandle xdg; xdgHandle xdg;
xdgInitHandle(&xdg); xdgInitHandle(&xdg);
filepath = xdgDataHome(&xdg); filepath = xdgDataHome(&xdg);
xdgWipeHandle(&xdg); xdgWipeHandle(&xdg);
filepath /= "whyblocked"; filepath += "/whyblocked";
if (!fs::exists(filepath)) if (!fs::exists(filepath))
{ {
fs::create_directories(filepath); fs::create_directories(filepath);
} }
filepath /= "database.sqlite"; filepath += "/database.sqlite";
if (!fs::exists(filepath)) if (!fs::exists(filepath))
{ {
sqlite::connection con(filepath); sqlite::connection con(filepath);
@ -58,30 +53,15 @@ const string Database::get_filepath() const
return filepath; return filepath;
} }
bool Database::add_user(const Database::data &userdata) const bool database::add_block(const string &user, const int blocked,
const string &reason)
{ {
try try
{ {
int blocked_int = 0;
if (userdata.blocked)
{
blocked_int = 1;
}
sqlite::connection con(get_filepath()); sqlite::connection con(get_filepath());
{ sqlite::execute ins(con, "INSERT INTO blocks VALUES(?, ?, ?);");
sqlite::execute ins(con, "INSERT INTO blocks VALUES(?, ?, ?);"); ins % user % blocked % reason;
ins % userdata.user % blocked_int % userdata.reason; ins();
ins();
}
{
for (const string &receipt : userdata.receipts)
{
sqlite::execute ins(con, "INSERT INTO urls VALUES(?, ?);");
ins % userdata.user % receipt;
ins();
}
}
_data.push_back(userdata);
} }
catch (const std::exception &e) catch (const std::exception &e)
{ {
@ -92,7 +72,25 @@ bool Database::add_user(const Database::data &userdata)
return true; return true;
} }
bool Database::remove(const string &user) const bool database::add_receipt(const string &user, const string &receipt)
{
try
{
sqlite::connection con(get_filepath());
sqlite::execute ins(con, "INSERT INTO urls VALUES(?, ?);");
ins % user % receipt;
ins();
}
catch (const std::exception &e)
{
cerr << "An error occurred: " << e.what() << std::endl;
return false;
}
return true;
}
const bool database::remove(const string &user)
{ {
try try
{ {
@ -103,7 +101,6 @@ bool Database::remove(const string &user)
rm_urls % user; rm_urls % user;
rm_blocks(); rm_blocks();
rm_urls(); rm_urls();
reload();
} }
catch (const std::exception &e) catch (const std::exception &e)
{ {
@ -114,80 +111,69 @@ bool Database::remove(const string &user)
return true; return true;
} }
const vector<Database::data> Database::query(const string &sql_query) const const bool database::view(result_view &result)
{ {
try try
{ {
sqlite::connection con(get_filepath()); sqlite::connection con(get_filepath());
sqlite::query q_blocks(con, sql_query); sqlite::query q(con, "SELECT * FROM blocks;");
sqlite::result_type res_blocks = q_blocks.get_result(); sqlite::result_type res = q.get_result();
std::vector<data> result; while(res->next_row())
while(res_blocks->next_row())
{ {
const string user = res_blocks->get_string(0);
const int blocked = res_blocks->get_int(1);
const string reason = res_blocks->get_string(2);
bool blocked_bool = false;
if (blocked == 1)
{
blocked_bool = true;
}
sqlite::query q_urls(con,
"SELECT * FROM urls WHERE user = \'" + user + "\';");
sqlite::result_type res_urls = q_urls.get_result();
vector<string> receipts;
while(res_urls->next_row())
{
receipts.push_back(res_urls->get_string(1));
}
result.push_back( result.push_back(
{ {
user, res->get_string(0),
blocked_bool, res->get_int(1),
reason, res->get_string(2)
receipts
}); });
} }
return result;
} }
catch (const std::exception &e) catch (const std::exception &e)
{ {
cerr << "An error occurred: " << e.what() << std::endl; cerr << "An error occurred: " << e.what() << std::endl;
return {};
}
}
bool Database::reload()
{
auto buffer = query();
if (buffer.empty())
{
return false; return false;
} }
else
{ return true;
_data = std::move(buffer);
return true;
}
} }
std::vector<Database::data> &Database::get_data() const bool database::details(const string &user, result_details &result)
{ {
return _data; try
}
const Database::data Database::get_user(const string &user) const
{
for (const Database::data &entry : _data)
{ {
if (entry.user == user) sqlite::connection con(get_filepath());
sqlite::query q_blocks(con,
"SELECT * FROM blocks WHERE user = \'" + user + "\';");
sqlite::result_type res_blocks = q_blocks.get_result();
sqlite::query q_urls(con,
"SELECT * FROM urls WHERE user = \'" + user + "\';");
sqlite::result_type res_urls = q_urls.get_result();
if (!res_blocks->next_row())
{ {
return entry; cerr << user << " is not in the database.\n";
return false;
} }
std::vector<string> urls;
while (res_urls->next_row())
{
urls.push_back(res_urls->get_string(1));
}
result =
{
res_blocks->get_int(1),
res_blocks->get_string(2),
urls
};
} }
return {}; catch (const std::exception &e)
{
cerr << "An error occurred: " << e.what() << std::endl;
return false;
}
return true;
} }

View File

@ -1,5 +1,5 @@
/* This file is part of whyblocked. /* This file is part of whyblocked.
* Copyright © 2018, 2019 tastytea <tastytea@tastytea.de> * Copyright © 2018 tastytea <tastytea@tastytea.de>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -18,37 +18,22 @@
#define WHYBLOCKED_HPP #define WHYBLOCKED_HPP
#include <vector> #include <vector>
#include <tuple>
#include <string> #include <string>
using std::string; using std::string;
using std::vector; using result_view = std::vector<std::tuple<string, int, string>>;
using result_details = std::tuple<int, string, std::vector<string>>;
class Database const string get_filepath();
namespace database
{ {
public: const bool add_block(const string &user, const int blocked,
struct data const string &reason);
{ const bool add_receipt(const string &user, const string &receipt);
string user; const bool remove(const string &user);
bool blocked; const bool view(result_view &result);
string reason; const bool details(const string &user, result_details &result);
vector<string> receipts; }
explicit operator bool() const;
};
bool add_user(const data &userdata);
bool remove(const string &user);
const vector<data> query(const string &sql_query =
"SELECT * FROM blocks;") const;
bool reload();
std::vector<data> &get_data();
const data get_user(const string &user) const;
private:
std::vector<data> _data;
private:
const string get_filepath() const;
};
#endif // WHYBLOCKED_HPP #endif // WHYBLOCKED_HPP

View File

@ -25,60 +25,6 @@
</property> </property>
<widget class="QWidget" name="centralwidget"> <widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widget_find" native="true">
<layout class="QHBoxLayout" name="hbox_find">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="text_find">
<property name="enabled">
<bool>true</bool>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="check_user">
<property name="toolTip">
<string>Search for Users/Instances</string>
</property>
<property name="text">
<string>User/Instance</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="check_reason">
<property name="toolTip">
<string>Search for Reasons</string>
</property>
<property name="text">
<string>Reason</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QTableView" name="tableview"> <widget class="QTableView" name="tableview">
<property name="acceptDrops"> <property name="acceptDrops">
@ -167,7 +113,6 @@
<addaction name="action_edit"/> <addaction name="action_edit"/>
<addaction name="action_remove"/> <addaction name="action_remove"/>
<addaction name="action_reload"/> <addaction name="action_reload"/>
<addaction name="action_find"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="action_about"/> <addaction name="action_about"/>
<addaction name="action_quit"/> <addaction name="action_quit"/>
@ -189,7 +134,6 @@
<addaction name="action_edit"/> <addaction name="action_edit"/>
<addaction name="action_remove"/> <addaction name="action_remove"/>
<addaction name="action_reload"/> <addaction name="action_reload"/>
<addaction name="action_find"/>
<addaction name="action_quit"/> <addaction name="action_quit"/>
</widget> </widget>
<widget class="QMenu" name="menu_help"> <widget class="QMenu" name="menu_help">
@ -288,24 +232,6 @@
<string notr="true">Ctrl+E</string> <string notr="true">Ctrl+E</string>
</property> </property>
</action> </action>
<action name="action_find">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="edit-find">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Find</string>
</property>
<property name="toolTip">
<string>Find entries</string>
</property>
<property name="shortcut">
<string>Ctrl+F</string>
</property>
</action>
</widget> </widget>
<resources/> <resources/>
<connections> <connections>
@ -361,7 +287,7 @@
<sender>action_reload</sender> <sender>action_reload</sender>
<signal>triggered()</signal> <signal>triggered()</signal>
<receiver>MainWindow</receiver> <receiver>MainWindow</receiver>
<slot>reload()</slot> <slot>populate_tableview()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>-1</x> <x>-1</x>
@ -437,70 +363,6 @@
</hint> </hint>
</hints> </hints>
</connection> </connection>
<connection>
<sender>action_find</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>find()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>299</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>text_find</sender>
<signal>textChanged(QString)</signal>
<receiver>MainWindow</receiver>
<slot>update_search(QString)</slot>
<hints>
<hint type="sourcelabel">
<x>201</x>
<y>83</y>
</hint>
<hint type="destinationlabel">
<x>299</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>check_user</sender>
<signal>clicked()</signal>
<receiver>MainWindow</receiver>
<slot>update_search()</slot>
<hints>
<hint type="sourcelabel">
<x>455</x>
<y>82</y>
</hint>
<hint type="destinationlabel">
<x>299</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>check_reason</sender>
<signal>clicked()</signal>
<receiver>MainWindow</receiver>
<slot>update_search()</slot>
<hints>
<hint type="sourcelabel">
<x>553</x>
<y>82</y>
</hint>
<hint type="destinationlabel">
<x>299</x>
<y>299</y>
</hint>
</hints>
</connection>
</connections> </connections>
<slots> <slots>
<slot>add()</slot> <slot>add()</slot>
@ -509,11 +371,5 @@
<slot>about()</slot> <slot>about()</slot>
<slot>show_details(QModelIndex)</slot> <slot>show_details(QModelIndex)</slot>
<slot>edit()</slot> <slot>edit()</slot>
<slot>find()</slot>
<slot>reload()</slot>
<slot>check_user_changed(int)</slot>
<slot>check_reason_changed(int)</slot>
<slot>update_search(QString)</slot>
<slot>update_search()</slot>
</slots> </slots>
</ui> </ui>

View File

@ -167,9 +167,6 @@
</item> </item>
<item row="4" column="1" rowspan="3"> <item row="4" column="1" rowspan="3">
<widget class="QListWidget" name="list_receipts"> <widget class="QListWidget" name="list_receipts">
<property name="toolTip">
<string>You can drag URLs in here</string>
</property>
<property name="editTriggers"> <property name="editTriggers">
<set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked</set> <set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked</set>
</property> </property>

View File

@ -1,95 +0,0 @@
/* Copyright © 2019 tastytea <tastytea@tastytea.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the BSD-3-Clause license.
*/
#include <basedir.h>
#include "xdgcfg.hpp"
xdgcfg::xdgcfg(const string &filename, const string &subdir)
: _cfg()
, _verbose(false)
{
xdgHandle xdg;
xdgInitHandle(&xdg);
_filepath = xdgConfigHome(&xdg);
xdgWipeHandle(&xdg);
if (!subdir.empty())
{
_filepath /= subdir;
}
if (!fs::exists(_filepath))
{
fs::create_directories(_filepath);
}
_filepath /= filename;
}
uint8_t xdgcfg::read()
{
try
{
_cfg.readFile(_filepath.c_str());
}
catch (const libconfig::FileIOException &e)
{
if (_verbose)
{
cerr << "I/O error while reading " << _filepath
<< " - " << e.what() << endl;
}
return 1;
}
catch (const libconfig::ParseException &e)
{
if (_verbose)
{
cerr << "Parse error at " << e.getFile() << ":" << e.getLine()
<< " - " << e.getError() << endl;
}
return 2;
}
return 0;
}
bool xdgcfg::write()
{
try
{
_cfg.writeFile(_filepath.c_str());
}
catch (const libconfig::FileIOException &e)
{
if (_verbose)
{
cerr << "I/O error while writing " << _filepath
<< " - " << e.what() << endl;
}
return false;
}
return true;
}
libconfig::Config &xdgcfg::get_cfg()
{
return _cfg;
}
const fs::path xdgcfg::get_filepath() const
{
return _filepath;
}
void xdgcfg::set_verbose(bool verbose)
{
_verbose = verbose;
}
bool xdgcfg::get_verbose() const
{
return _verbose;
}

1
src/xdgcfg.cpp Symbolic link
View File

@ -0,0 +1 @@
../xdgcfg/src/xdgcfg.cpp

View File

@ -1,106 +0,0 @@
/* Copyright © 2019 tastytea <tastytea@tastytea.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the BSD-3-Clause license.
*/
#ifndef XDGCFG_HPP
#define XDGCFG_HPP
#if __cplusplus >= 201703L
#include <filesystem>
#else
#include <experimental/filesystem>
#endif
#include <string>
#include <iostream>
#include <cstdint>
#include <libconfig.h++>
#if __cplusplus >= 201703L
namespace fs = std::filesystem;
#else
namespace fs = std::experimental::filesystem;
#endif
using std::string;
using std::uint8_t;
using std::cerr;
using std::endl;
class xdgcfg
{
public:
/*!
* @brief Checks if subdir is present, creates it if necessary
*
* Example:
* @code
* xdgcfg config("test.cfg", "subdirectory");
* @endcode
*
* @param filename The name of the file, including extension
* @param subdir The subdir (optional)
*/
explicit xdgcfg(const string &filename, const string &subdir = "");
/*!
* @brief Read the file
*
* @return 0 on success, 1 on I/O error, 2 on parse error.
*/
uint8_t read();
/*!
* @brief Write the file
*
* @return `true` on success
*/
bool write();
/*!
* @brief Returns a reference to the config as libconfig::Config
*
* Example:
* @code
* libconfig::Config &cfg = config.get_cfg();
* @endcode
*/
libconfig::Config &get_cfg();
/*!
* @brief Returns the complete filepath
*/
const fs::path get_filepath() const;
/*!
* @brief Sets verbosity
*/
void set_verbose(bool verbose);
/*!
* @brief Returns verbosity
*/
bool get_verbose() const;
private:
/*!
* Holds the contents of the CFG file
*/
libconfig::Config _cfg;
/*!
* Complete filepath
*/
fs::path _filepath;
/*!
* Print out error messages if true
*/
bool _verbose;
};
/*!
* @example example.cpp
*/
#endif // XDGCFG_HPP

1
src/xdgcfg.hpp Symbolic link
View File

@ -0,0 +1 @@
../xdgcfg/src/xdgcfg.hpp

View File

@ -8,5 +8,6 @@ qt5_create_translation(QM_FILES ${TS_SRC_FILES} ${TS_FILES}
# qt5_add_translation(QM_FILES ${TS_FILES}) # qt5_add_translation(QM_FILES ${TS_FILES})
add_custom_target(translations ALL DEPENDS ${QM_FILES}) add_custom_target(translations ALL DEPENDS ${QM_FILES})
add_dependencies(${CMAKE_PROJECT_NAME} translations) add_dependencies(${CMAKE_PROJECT_NAME} translations)
add_dependencies(${CMAKE_PROJECT_NAME}-gui translations)
install(FILES ${QM_FILES} DESTINATION install(FILES ${QM_FILES} DESTINATION
${CMAKE_INSTALL_DATAROOTDIR}/qt5/translations) ${CMAKE_INSTALL_DATAROOTDIR}/qt5/translations)

View File

@ -4,285 +4,414 @@
<context> <context>
<name>DialogAdd</name> <name>DialogAdd</name>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="17"/> <location filename="../src/whyblocked_add.ui" line="17"/>
<source>Add entry</source> <source>Add entry</source>
<translation>Eintrag hinzufügen</translation> <translation>Eintrag hinzufügen</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="40"/> <location filename="../src/whyblocked_add.ui" line="40"/>
<source>Memory aids, proof</source> <source>Memory aids, proof</source>
<translation>Gedächtnisstützen, Beweise</translation> <translation>Gedächtnisstützen, Beweise</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="43"/> <location filename="../src/whyblocked_add.ui" line="43"/>
<source>Rece&amp;ipts</source> <source>Rece&amp;ipts</source>
<translation>Be&amp;lege</translation> <translation>Be&amp;lege</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="56"/> <location filename="../src/whyblocked_add.ui" line="56"/>
<source>Add receipt</source> <source>Add receipt</source>
<translation>Beleg hinzufügen</translation> <translation>Beleg hinzufügen</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="59"/> <location filename="../src/whyblocked_add.ui" line="59"/>
<source>&amp;Add</source> <source>&amp;Add</source>
<translation>&amp;Hinzufügen</translation> <translation>&amp;Hinzufügen</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="79"/> <location filename="../src/whyblocked_add.ui" line="79"/>
<source>&amp;Blocked</source> <source>&amp;Blocked</source>
<translation>&amp;Blockiert</translation> <translation>&amp;Blockiert</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="98"/> <location filename="../src/whyblocked_add.ui" line="98"/>
<source>&amp;Silenced</source> <source>&amp;Silenced</source>
<translation>&amp;Gedämpft</translation> <translation>&amp;Gedämpft</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="105"/> <location filename="../src/whyblocked_add.ui" line="105"/>
<source>R&amp;eason</source> <source>R&amp;eason</source>
<translation>B&amp;egründung</translation> <translation>B&amp;egründung</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="134"/> <location filename="../src/whyblocked_add.ui" line="134"/>
<source>Blocked/Silenced</source> <source>Blocked/Silenced</source>
<translation>Blockiert/Gedämpft</translation> <translation>Blockiert/Gedämpft</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="144"/> <location filename="../src/whyblocked_add.ui" line="144"/>
<source>&amp;User/Instance</source> <source>&amp;User/Instance</source>
<translation>Ben&amp;utzer/Instanz</translation> <translation>Ben&amp;utzer/Instanz</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="154"/> <location filename="../src/whyblocked_add.ui" line="154"/>
<source>Remove receipt</source> <source>Remove receipt</source>
<translation>Beleg entfernen</translation> <translation>Beleg entfernen</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="157"/> <location filename="../src/whyblocked_add.ui" line="157"/>
<source>Re&amp;move</source> <source>Re&amp;move</source>
<translation>Ent&amp;fernen</translation> <translation>Ent&amp;fernen</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="164"/> <location filename="../src/whyblocked_add.ui" line="164"/>
<source>Del</source> <source>Del</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="171"/> <location filename="../src/interface_qt.cpp" line="378"/>
<source>You can drag URLs in here</source>
<translation>Du kannst URLs hier hineinziehen</translation>
</message>
<message>
<location filename="../src/qt/dialog_add.cpp" line="79"/>
<source>Insert receipt here.</source> <source>Insert receipt here.</source>
<translation>Beleg hier einfügen.</translation> <translation>Beleg hier einfügen.</translation>
</message> </message>
<message>
<location filename="../src/interface_qt.cpp" line="413"/>
<source>Added %1 to database.</source>
<translation>%1 zur Datenbank hinzugefügt.</translation>
</message>
</context> </context>
<context> <context>
<name>MainWindow</name> <name>MainWindow</name>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="17"/> <location filename="../src/whyblocked.ui" line="17"/>
<source>Whyblocked</source> <source>Whyblocked</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="56"/> <location filename="../src/whyblocked.ui" line="34"/>
<source>Search for Users/Instances</source>
<translation>Suche nach Benutzern/Instanzen</translation>
</message>
<message>
<location filename="../src/qt/whyblocked.ui" line="69"/>
<source>Search for Reasons</source>
<translation>Suche nach Begründungen</translation>
</message>
<message>
<location filename="../src/qt/whyblocked.ui" line="88"/>
<source>Click or press enter to view receipts</source> <source>Click or press enter to view receipts</source>
<translation>Klicken oder Eingabe drücken, um Belege zu anzuzeigen</translation> <translation>Klicken oder Eingabe drücken, um Belege zu anzuzeigen</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="131"/> <location filename="../src/whyblocked.ui" line="77"/>
<source>Memory aids, proof</source> <source>Memory aids, proof</source>
<translation>Gedächtnisstützen, Beweise</translation> <translation>Gedächtnisstützen, Beweise</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="155"/> <location filename="../src/whyblocked.ui" line="101"/>
<source>Toolbar</source> <source>Toolbar</source>
<translation>Werkzeugleiste</translation> <translation>Werkzeugleiste</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="186"/> <location filename="../src/whyblocked.ui" line="131"/>
<source>&amp;Database</source> <source>&amp;Database</source>
<translation>&amp;Datenbank</translation> <translation>&amp;Datenbank</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="197"/> <location filename="../src/whyblocked.ui" line="141"/>
<source>&amp;Help</source> <source>&amp;Help</source>
<translation>&amp;Hilfe</translation> <translation>&amp;Hilfe</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="210"/> <location filename="../src/whyblocked.ui" line="154"/>
<source>&amp;Add</source> <source>&amp;Add</source>
<translation>&amp;Hinzufügen</translation> <translation>&amp;Hinzufügen</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="213"/> <location filename="../src/whyblocked.ui" line="157"/>
<source>Add user or instance</source> <source>Add user or instance</source>
<translation>Benutzer oder Instanz hinzufügen</translation> <translation>Benutzer oder Instanz hinzufügen</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="216"/> <location filename="../src/whyblocked.ui" line="160"/>
<source>Ctrl+N</source> <source>Ctrl+N</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="225"/> <location filename="../src/whyblocked.ui" line="169"/>
<source>Re&amp;move</source> <source>Re&amp;move</source>
<translation>Ent&amp;fernen</translation> <translation>Ent&amp;fernen</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="228"/> <location filename="../src/whyblocked.ui" line="172"/>
<source>Remove user or instance</source> <source>Remove user or instance</source>
<translation>Benutzer oder Instanz entfernen</translation> <translation>Benutzer oder Instanz entfernen</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="231"/> <location filename="../src/whyblocked.ui" line="175"/>
<source>Del</source> <source>Del</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="240"/> <location filename="../src/whyblocked.ui" line="184"/>
<source>&amp;About</source> <source>&amp;About</source>
<translation>&amp;Über</translation> <translation>&amp;Über</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="243"/> <location filename="../src/whyblocked.ui" line="187"/>
<source>About this application</source> <source>About this application</source>
<translation>Über dieses Programm</translation> <translation>Über dieses Programm</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="252"/> <location filename="../src/whyblocked.ui" line="196"/>
<source>&amp;Reload</source> <source>&amp;Reload</source>
<translation>Neu &amp;laden</translation> <translation>Neu &amp;laden</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="255"/> <location filename="../src/whyblocked.ui" line="199"/>
<source>Reload database</source> <source>Reload database</source>
<translation>Datenbank neu laden</translation> <translation>Datenbank neu laden</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="258"/> <location filename="../src/whyblocked.ui" line="202"/>
<source>Ctrl+R</source> <source>Ctrl+R</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="267"/> <location filename="../src/whyblocked.ui" line="211"/>
<source>&amp;Quit</source> <source>&amp;Quit</source>
<translation>&amp;Beenden</translation> <translation>&amp;Beenden</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="270"/> <location filename="../src/whyblocked.ui" line="214"/>
<source>Quit application</source> <source>Quit application</source>
<translation>Programm beenden</translation> <translation>Programm beenden</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="273"/> <location filename="../src/whyblocked.ui" line="217"/>
<source>Ctrl+Q</source> <source>Ctrl+Q</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="282"/> <location filename="../src/whyblocked.ui" line="226"/>
<source>&amp;Edit</source> <source>&amp;Edit</source>
<translation>B&amp;earbeiten</translation> <translation>B&amp;earbeiten</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="285"/> <location filename="../src/whyblocked.ui" line="229"/>
<location filename="../src/qt/mainwindow.cpp" line="279"/> <location filename="../src/interface_qt.cpp" line="211"/>
<source>Edit entry</source> <source>Edit entry</source>
<translation>Eintrag bearbeiten</translation> <translation>Eintrag bearbeiten</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="300"/> <location filename="../src/interface_qt.cpp" line="156"/>
<source>&amp;Find</source>
<translation>&amp;Finden</translation>
</message>
<message>
<location filename="../src/qt/whyblocked.ui" line="303"/>
<source>Find entries</source>
<translation>Finde Einträge</translation>
</message>
<message>
<location filename="../src/qt/whyblocked.ui" line="306"/>
<source>Ctrl+F</source>
<translation></translation>
</message>
<message>
<location filename="../src/qt/whyblocked.ui" line="59"/>
<location filename="../src/qt/mainwindow.cpp" line="329"/>
<source>User/Instance</source> <source>User/Instance</source>
<translation>Benutzer/Instanz</translation> <translation>Benutzer/Instanz</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="330"/> <location filename="../src/interface_qt.cpp" line="157"/>
<source>Blocked/Silenced</source> <source>Blocked/Silenced</source>
<translation>Blockiert/Gedämpft</translation> <translation>Blockiert/Gedämpft</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="72"/> <location filename="../src/interface_qt.cpp" line="158"/>
<location filename="../src/qt/mainwindow.cpp" line="331"/>
<source>Reason</source> <source>Reason</source>
<translation>Begründung</translation> <translation>Begründung</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="109"/> <location filename="../src/interface_qt.cpp" line="175"/>
<source>Try dragging an account from your webbrowser into this window.</source> <source>Database loaded.</source>
<translation>Versuche, einen Account von deinem Webbrowser in dieses Fenster zu ziehen.</translation> <translation>Datenbank geladen.</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="184"/> <location filename="../src/interface_qt.cpp" line="185"/>
<source>blocked</source> <source>blocked</source>
<translation>blockiert</translation> <translation>blockiert</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="188"/> <location filename="../src/interface_qt.cpp" line="189"/>
<source>silenced</source> <source>silenced</source>
<translation>gedämpft</translation> <translation>gedämpft</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="273"/> <location filename="../src/interface_qt.cpp" line="205"/>
<source>Invalid selection</source> <source>Invalid selection</source>
<translation>Ungültige Auswahl</translation> <translation>Ungültige Auswahl</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="274"/> <location filename="../src/interface_qt.cpp" line="206"/>
<source>Please select only 1 entry to edit.</source> <source>Please select only 1 entry to edit.</source>
<translation>Bitte nur 1 Eintrag zum bearbeiten auswählen.</translation> <translation>Bitte nur 1 Eintrag zum bearbeiten auswählen.</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="212"/> <location filename="../src/interface_qt.cpp" line="243"/>
<source>Nothing selected</source> <source>Removed %1 from database.</source>
<translation>Nichts ausgewählt</translation> <translation>%1 aus der Datenbank gelöscht.</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="213"/> <location filename="../src/interface_qt.cpp" line="251"/>
<source>Please select entries to remove.</source> <source>Select data to remove.</source>
<translation>Bitte wähle Einträge aus, die gelöscht werden sollen.</translation> <translation>Wähle Daten zum löschen aus.</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="292"/> <location filename="../src/interface_qt.cpp" line="257"/>
<source>About Whyblocked</source> <source>About Whyblocked</source>
<translation>Über Whyblocked</translation> <translation>Über Whyblocked</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="293"/> <location filename="../src/interface_qt.cpp" line="258"/>
<source>&lt;p&gt;&lt;b&gt;Whyblocked&lt;/b&gt; %1&lt;/p&gt;&lt;p&gt;Reminds you why you blocked someone.&lt;/p&gt;&lt;p&gt;Sourcecode: &lt;a href=&quot;https://schlomp.space/tastytea/whyblocked&quot;&gt;https://schlomp.space/tastytea/whyblocked&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;small&gt;Copyright © 2018 &lt;a href=&quot;mailto:tastytea@tastytea.de&quot;&gt;tastytea&lt;/a&gt;.&lt;br&gt;Licence GPLv3: &lt;a href=&quot;https://www.gnu.org/licenses/gpl-3.0.html&quot;&gt;GNU GPL version 3&lt;/a&gt;.&lt;br&gt;This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions.&lt;/small&gt;&lt;/p&gt;</source> <source>&lt;p&gt;&lt;b&gt;Whyblocked&lt;/b&gt; %1&lt;/p&gt;&lt;p&gt;Reminds you why you blocked someone.&lt;/p&gt;&lt;p&gt;Sourcecode: &lt;a href=&quot;https://schlomp.space/tastytea/whyblocked&quot;&gt;https://schlomp.space/tastytea/whyblocked&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;small&gt;Copyright © 2018 &lt;a href=&quot;mailto:tastytea@tastytea.de&quot;&gt;tastytea&lt;/a&gt;.&lt;br&gt;Licence GPLv3: &lt;a href=&quot;https://www.gnu.org/licenses/gpl-3.0.html&quot;&gt;GNU GPL version 3&lt;/a&gt;.&lt;br&gt;This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions.&lt;/small&gt;&lt;/p&gt;</source>
<translation>&lt;p&gt;&lt;b&gt;Whyblocked&lt;/b&gt; %1&lt;/p&gt;&lt;p&gt;Erinnert dich, warum du jemanden blockiertest.&lt;/p&gt;&lt;p&gt;Quelltext: &lt;a href=&quot;https://schlomp.space/tastytea/whyblocked&quot;&gt;https://schlomp.space/tastytea/whyblocked&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;small&gt;Copyright © 2018 &lt;a href=&quot;mailto:tastytea@tastytea.de&quot;&gt;tastytea&lt;/a&gt;.&lt;br&gt;Lizenz GPLv3: &lt;a href=&quot;https://www.gnu.org/licenses/gpl-3.0.html&quot;&gt;GNU GPL version 3&lt;/a&gt;.&lt;br&gt;Für dieses Programm besteht KEINERLEI GARANTIE. Dies ist freie Software, die Sie unter bestimmten Bedingungen weitergeben dürfen.&lt;/small&gt;&lt;/p&gt;</translation> <translation>&lt;p&gt;&lt;b&gt;Whyblocked&lt;/b&gt; %1&lt;/p&gt;&lt;p&gt;Erinnert dich, warum du jemanden blockiertest.&lt;/p&gt;&lt;p&gt;Quelltext: &lt;a href=&quot;https://schlomp.space/tastytea/whyblocked&quot;&gt;https://schlomp.space/tastytea/whyblocked&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;small&gt;Copyright © 2018 &lt;a href=&quot;mailto:tastytea@tastytea.de&quot;&gt;tastytea&lt;/a&gt;.&lt;br&gt;Lizenz GPLv3: &lt;a href=&quot;https://www.gnu.org/licenses/gpl-3.0.html&quot;&gt;GNU GPL version 3&lt;/a&gt;.&lt;br&gt;Für dieses Programm besteht KEINERLEI GARANTIE. Dies ist freie Software, die Sie unter bestimmten Bedingungen weitergeben dürfen.&lt;/small&gt;&lt;/p&gt;</translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="314"/> <location filename="../src/interface_qt.cpp" line="281"/>
<source>Receipts:</source> <source>Receipts:</source>
<translation>Belege:</translation> <translation>Belege:</translation>
</message> </message>
</context> </context>
<context>
<name>Text</name>
<message>
<location filename="../src/interface_text.cpp" line="51"/>
<source>Blocked or silenced?</source>
<translation>Blockiert oder gedämpft?</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="68"/>
<source>Add receipt? [y/n]</source>
<translation>Beleg hinzufügen? [j/n]</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="69"/>
<source>y</source>
<translation>j</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="69"/>
<source>Y</source>
<translation>J</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="71"/>
<source>Receipt</source>
<translation>Beleg</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="75"/>
<source>Receipt added.</source>
<translation>Beleg hinzugefügt.</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="78"/>
<source>n</source>
<translation>n</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="78"/>
<source>N</source>
<translation>N</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="91"/>
<location filename="../src/interface_text.cpp" line="115"/>
<location filename="../src/interface_text.cpp" line="175"/>
<location filename="../src/interface_text.cpp" line="206"/>
<source>User or instance</source>
<translation>Benutzer oder Instanz</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="102"/>
<source>Reason</source>
<translation>Begründung</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="106"/>
<source>added.</source>
<translation>hinzugefügt.</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="118"/>
<source>A blank line keeps the former value.</source>
<translation>Leere Zeile um den alten Wert zu erhalten.</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="119"/>
<source>Change user or instance to</source>
<translation>Ändere Benutzer oder Instanz zu</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="135"/>
<source>Old reason was:</source>
<translation>Alte Begründung war:</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="136"/>
<source>Change reason to</source>
<translation>Ändere Begründung zu</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="145"/>
<source>Old receipt was:</source>
<translation>Alter Beleg war:</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="146"/>
<source>Change receipt to</source>
<translation>Ändere beleg zu</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="168"/>
<source>Could not remove</source>
<translation>Konnte nicht entfernen:</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="179"/>
<source>removed.</source>
<translation>entfernt.</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="192"/>
<source> Blocked:</source>
<translation>Blockiert:</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="196"/>
<source>Silenced:</source>
<translation> Gedämpft:</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="198"/>
<source>because:</source>
<translation>weil:</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="211"/>
<source>is</source>
<translation>ist</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="214"/>
<source>blocked, because:</source>
<translation>blockiert, weil:</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="218"/>
<source>silenced, because:</source>
<translation>gedämpft, weil:</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="224"/>
<source>Receipts:</source>
<translation>Belege:</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="236"/>
<source>Type add, edit, remove, view or details. Or just the first letter.</source>
<translation>Schreibe a für hinzufügen, e für ändern, r für entfernen, v für anschauen oder d für Details.</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="239"/>
<source>Type help or h to show this help. Type quit or q to quit the program.</source>
<translation>Schreibe hilfe oder h, um die Hilfe anzuzeigen. Schreibe q um das Programm zu beenden.</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="248"/>
<source>This is Whyblocked</source>
<translation>Dies ist Whyblocked</translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="299"/>
<source>Response not understood.</source>
<translation>Antwort nicht verstanden.</translation>
</message>
</context>
</TS> </TS>

View File

@ -4,285 +4,414 @@
<context> <context>
<name>DialogAdd</name> <name>DialogAdd</name>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="17"/> <location filename="../src/whyblocked_add.ui" line="17"/>
<source>Add entry</source> <source>Add entry</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="40"/> <location filename="../src/whyblocked_add.ui" line="40"/>
<source>Memory aids, proof</source> <source>Memory aids, proof</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="43"/> <location filename="../src/whyblocked_add.ui" line="43"/>
<source>Rece&amp;ipts</source> <source>Rece&amp;ipts</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="56"/> <location filename="../src/whyblocked_add.ui" line="56"/>
<source>Add receipt</source> <source>Add receipt</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="59"/> <location filename="../src/whyblocked_add.ui" line="59"/>
<source>&amp;Add</source> <source>&amp;Add</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="79"/> <location filename="../src/whyblocked_add.ui" line="79"/>
<source>&amp;Blocked</source> <source>&amp;Blocked</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="98"/> <location filename="../src/whyblocked_add.ui" line="98"/>
<source>&amp;Silenced</source> <source>&amp;Silenced</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="105"/> <location filename="../src/whyblocked_add.ui" line="105"/>
<source>R&amp;eason</source> <source>R&amp;eason</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="134"/> <location filename="../src/whyblocked_add.ui" line="134"/>
<source>Blocked/Silenced</source> <source>Blocked/Silenced</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="144"/> <location filename="../src/whyblocked_add.ui" line="144"/>
<source>&amp;User/Instance</source> <source>&amp;User/Instance</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="154"/> <location filename="../src/whyblocked_add.ui" line="154"/>
<source>Remove receipt</source> <source>Remove receipt</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="157"/> <location filename="../src/whyblocked_add.ui" line="157"/>
<source>Re&amp;move</source> <source>Re&amp;move</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="164"/> <location filename="../src/whyblocked_add.ui" line="164"/>
<source>Del</source> <source>Del</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked_add.ui" line="171"/> <location filename="../src/interface_qt.cpp" line="378"/>
<source>You can drag URLs in here</source> <source>Insert receipt here.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/dialog_add.cpp" line="79"/> <location filename="../src/interface_qt.cpp" line="413"/>
<source>Insert receipt here.</source> <source>Added %1 to database.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context> <context>
<name>MainWindow</name> <name>MainWindow</name>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="17"/> <location filename="../src/whyblocked.ui" line="17"/>
<source>Whyblocked</source> <source>Whyblocked</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="56"/> <location filename="../src/whyblocked.ui" line="34"/>
<source>Search for Users/Instances</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/qt/whyblocked.ui" line="69"/>
<source>Search for Reasons</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/qt/whyblocked.ui" line="88"/>
<source>Click or press enter to view receipts</source> <source>Click or press enter to view receipts</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="131"/> <location filename="../src/whyblocked.ui" line="77"/>
<source>Memory aids, proof</source> <source>Memory aids, proof</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="155"/> <location filename="../src/whyblocked.ui" line="101"/>
<source>Toolbar</source> <source>Toolbar</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="186"/> <location filename="../src/whyblocked.ui" line="131"/>
<source>&amp;Database</source> <source>&amp;Database</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="197"/> <location filename="../src/whyblocked.ui" line="141"/>
<source>&amp;Help</source> <source>&amp;Help</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="210"/> <location filename="../src/whyblocked.ui" line="154"/>
<source>&amp;Add</source> <source>&amp;Add</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="213"/> <location filename="../src/whyblocked.ui" line="157"/>
<source>Add user or instance</source> <source>Add user or instance</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="216"/> <location filename="../src/whyblocked.ui" line="160"/>
<source>Ctrl+N</source> <source>Ctrl+N</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="225"/> <location filename="../src/whyblocked.ui" line="169"/>
<source>Re&amp;move</source> <source>Re&amp;move</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="228"/> <location filename="../src/whyblocked.ui" line="172"/>
<source>Remove user or instance</source> <source>Remove user or instance</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="231"/> <location filename="../src/whyblocked.ui" line="175"/>
<source>Del</source> <source>Del</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="240"/> <location filename="../src/whyblocked.ui" line="184"/>
<source>&amp;About</source> <source>&amp;About</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="243"/> <location filename="../src/whyblocked.ui" line="187"/>
<source>About this application</source> <source>About this application</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="252"/> <location filename="../src/whyblocked.ui" line="196"/>
<source>&amp;Reload</source> <source>&amp;Reload</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="255"/> <location filename="../src/whyblocked.ui" line="199"/>
<source>Reload database</source> <source>Reload database</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="258"/> <location filename="../src/whyblocked.ui" line="202"/>
<source>Ctrl+R</source> <source>Ctrl+R</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="267"/> <location filename="../src/whyblocked.ui" line="211"/>
<source>&amp;Quit</source> <source>&amp;Quit</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="270"/> <location filename="../src/whyblocked.ui" line="214"/>
<source>Quit application</source> <source>Quit application</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="273"/> <location filename="../src/whyblocked.ui" line="217"/>
<source>Ctrl+Q</source> <source>Ctrl+Q</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="282"/> <location filename="../src/whyblocked.ui" line="226"/>
<source>&amp;Edit</source> <source>&amp;Edit</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="285"/> <location filename="../src/whyblocked.ui" line="229"/>
<location filename="../src/qt/mainwindow.cpp" line="279"/> <location filename="../src/interface_qt.cpp" line="211"/>
<source>Edit entry</source> <source>Edit entry</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="300"/> <location filename="../src/interface_qt.cpp" line="156"/>
<source>&amp;Find</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/qt/whyblocked.ui" line="303"/>
<source>Find entries</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/qt/whyblocked.ui" line="306"/>
<source>Ctrl+F</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/qt/whyblocked.ui" line="59"/>
<location filename="../src/qt/mainwindow.cpp" line="329"/>
<source>User/Instance</source> <source>User/Instance</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="330"/> <location filename="../src/interface_qt.cpp" line="157"/>
<source>Blocked/Silenced</source> <source>Blocked/Silenced</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/whyblocked.ui" line="72"/> <location filename="../src/interface_qt.cpp" line="158"/>
<location filename="../src/qt/mainwindow.cpp" line="331"/>
<source>Reason</source> <source>Reason</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="109"/> <location filename="../src/interface_qt.cpp" line="175"/>
<source>Try dragging an account from your webbrowser into this window.</source> <source>Database loaded.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="184"/> <location filename="../src/interface_qt.cpp" line="185"/>
<source>blocked</source> <source>blocked</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="188"/> <location filename="../src/interface_qt.cpp" line="189"/>
<source>silenced</source> <source>silenced</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="273"/> <location filename="../src/interface_qt.cpp" line="205"/>
<source>Invalid selection</source> <source>Invalid selection</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="274"/> <location filename="../src/interface_qt.cpp" line="206"/>
<source>Please select only 1 entry to edit.</source> <source>Please select only 1 entry to edit.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="212"/> <location filename="../src/interface_qt.cpp" line="243"/>
<source>Nothing selected</source> <source>Removed %1 from database.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="213"/> <location filename="../src/interface_qt.cpp" line="251"/>
<source>Please select entries to remove.</source> <source>Select data to remove.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="292"/> <location filename="../src/interface_qt.cpp" line="257"/>
<source>About Whyblocked</source> <source>About Whyblocked</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="293"/> <location filename="../src/interface_qt.cpp" line="258"/>
<source>&lt;p&gt;&lt;b&gt;Whyblocked&lt;/b&gt; %1&lt;/p&gt;&lt;p&gt;Reminds you why you blocked someone.&lt;/p&gt;&lt;p&gt;Sourcecode: &lt;a href=&quot;https://schlomp.space/tastytea/whyblocked&quot;&gt;https://schlomp.space/tastytea/whyblocked&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;small&gt;Copyright © 2018 &lt;a href=&quot;mailto:tastytea@tastytea.de&quot;&gt;tastytea&lt;/a&gt;.&lt;br&gt;Licence GPLv3: &lt;a href=&quot;https://www.gnu.org/licenses/gpl-3.0.html&quot;&gt;GNU GPL version 3&lt;/a&gt;.&lt;br&gt;This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions.&lt;/small&gt;&lt;/p&gt;</source> <source>&lt;p&gt;&lt;b&gt;Whyblocked&lt;/b&gt; %1&lt;/p&gt;&lt;p&gt;Reminds you why you blocked someone.&lt;/p&gt;&lt;p&gt;Sourcecode: &lt;a href=&quot;https://schlomp.space/tastytea/whyblocked&quot;&gt;https://schlomp.space/tastytea/whyblocked&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;small&gt;Copyright © 2018 &lt;a href=&quot;mailto:tastytea@tastytea.de&quot;&gt;tastytea&lt;/a&gt;.&lt;br&gt;Licence GPLv3: &lt;a href=&quot;https://www.gnu.org/licenses/gpl-3.0.html&quot;&gt;GNU GPL version 3&lt;/a&gt;.&lt;br&gt;This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions.&lt;/small&gt;&lt;/p&gt;</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/qt/mainwindow.cpp" line="314"/> <location filename="../src/interface_qt.cpp" line="281"/>
<source>Receipts:</source> <source>Receipts:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context>
<name>Text</name>
<message>
<location filename="../src/interface_text.cpp" line="51"/>
<source>Blocked or silenced?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="68"/>
<source>Add receipt? [y/n]</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="69"/>
<source>y</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="69"/>
<source>Y</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="71"/>
<source>Receipt</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="75"/>
<source>Receipt added.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="78"/>
<source>n</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="78"/>
<source>N</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="91"/>
<location filename="../src/interface_text.cpp" line="115"/>
<location filename="../src/interface_text.cpp" line="175"/>
<location filename="../src/interface_text.cpp" line="206"/>
<source>User or instance</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="102"/>
<source>Reason</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="106"/>
<source>added.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="118"/>
<source>A blank line keeps the former value.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="119"/>
<source>Change user or instance to</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="135"/>
<source>Old reason was:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="136"/>
<source>Change reason to</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="145"/>
<source>Old receipt was:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="146"/>
<source>Change receipt to</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="168"/>
<source>Could not remove</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="179"/>
<source>removed.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="192"/>
<source> Blocked:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="196"/>
<source>Silenced:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="198"/>
<source>because:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="211"/>
<source>is</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="214"/>
<source>blocked, because:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="218"/>
<source>silenced, because:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="224"/>
<source>Receipts:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="236"/>
<source>Type add, edit, remove, view or details. Or just the first letter.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="239"/>
<source>Type help or h to show this help. Type quit or q to quit the program.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="248"/>
<source>This is Whyblocked</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/interface_text.cpp" line="299"/>
<source>Response not understood.</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS> </TS>

View File

@ -1,37 +0,0 @@
= whyblocked(1)
:Author: tastytea
:Email: tastytea@tastytea.de
:Date: 2019-04-12
:Revision: 0.0.0
:man source: Whyblocked
:man version: {revision}
:man manual: General Commands Manual
== NAME
whyblocked - reminds you why you blocked someone.
== SYNOPSIS
*whyblocked*
== DESCRIPTION
Whyblocked allows you to store the reason why you blocked someone, along with
"receipts", URLs to the posts that led you to block them.
Apart from the obvious method, you can add entries by dropping the link to a
profile into the main window. In the "Add entry" dialog, you can add receipts by
dropping links or text into the receipts list.
== FILES
- *Configuration file*: `${XDG_CONFIG_HOME}/whyblocked.cfg`
- *Database*: `${XDG_DATA_HOME}/whyblocked/database.sqlite`
`${XDG_CONFIG_HOME}` is usually `~/.config` and `${XDG_DATA_HOME}` is usually
`~/.local/share`
== REPORTING BUGS
Bugtracker: https://schlomp.space/tastytea/whyblocked/issues

1
xdgcfg Submodule

@ -0,0 +1 @@
Subproject commit 6c0976baa74f959ed3218af56e56ff58202a5a05