Compare commits
No commits in common. "master" and "osx-fixes" have entirely different histories.
4
.github/FUNDING.yml
vendored
4
.github/FUNDING.yml
vendored
@ -1,4 +0,0 @@
|
|||||||
# These are supported funding model platforms
|
|
||||||
|
|
||||||
patreon: swordfish90
|
|
||||||
custom: ['https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=flscogna%40gmail.com&item_name=Support+CRT¤cy_code=EUR&source=url']
|
|
98
.github/workflows/appimage.yml
vendored
98
.github/workflows/appimage.yml
vendored
@ -1,98 +0,0 @@
|
|||||||
name: "ci"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags: "**"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
appimage:
|
|
||||||
runs-on: ubuntu-18.04
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo add-apt-repository -y ppa:beineri/opt-qt-5.15.2-bionic
|
|
||||||
sudo apt-get update -qq
|
|
||||||
sudo apt-get install -y \
|
|
||||||
build-essential make wget libgl1-mesa-dev \
|
|
||||||
qt515declarative qt515graphicaleffects \
|
|
||||||
qt515quickcontrols qt515quickcontrols2
|
|
||||||
|
|
||||||
- name: Download QT appimage builder
|
|
||||||
run: |
|
|
||||||
wget -c -O linuxdeployqt.AppImage \
|
|
||||||
https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage
|
|
||||||
chmod a+x linuxdeployqt.AppImage
|
|
||||||
|
|
||||||
- name: Build project
|
|
||||||
run: |
|
|
||||||
source /opt/qt*/bin/qt*-env.sh && \
|
|
||||||
qmake -v && \
|
|
||||||
qmake CONFIG+=release PREFIX=/usr && \
|
|
||||||
make -j$(nproc)
|
|
||||||
|
|
||||||
- name: Install to appdir
|
|
||||||
run: |
|
|
||||||
source /opt/qt*/bin/qt*-env.sh && \
|
|
||||||
make INSTALL_ROOT=appdir -j$(nproc) install
|
|
||||||
|
|
||||||
- name: Extract version number
|
|
||||||
run: |
|
|
||||||
# Extract version for linuxdeployqt to name the file. Use the tag as
|
|
||||||
# release name but remove prefix.
|
|
||||||
echo "VERSION=$(echo '${{ github.ref }}' | sed 's;.*/;;')" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Build appimage directory
|
|
||||||
run: |
|
|
||||||
mkdir -p \
|
|
||||||
appdir/usr/bin \
|
|
||||||
appdir/usr/lib \
|
|
||||||
appdir/usr/share/applications \
|
|
||||||
appdir/usr/share/metainfo \
|
|
||||||
appdir/usr/share/icons/hicolor/128x128/apps
|
|
||||||
|
|
||||||
cp cool-retro-term appdir/usr/bin/
|
|
||||||
cp cool-retro-term.desktop appdir/usr/share/applications/
|
|
||||||
cp packaging/appdata/cool-retro-term.appdata.xml appdir/usr/share/metainfo/
|
|
||||||
cp app/icons/128x128/cool-retro-term.png appdir/usr/share/icons/hicolor/128x128/apps/
|
|
||||||
cp -r ./app/qml appdir/usr/
|
|
||||||
# Workaround for https://github.com/probonopd/linuxdeployqt/issues/78
|
|
||||||
cp -r ./qmltermwidget/QMLTermWidget appdir/usr/qml/
|
|
||||||
|
|
||||||
find appdir | sort
|
|
||||||
|
|
||||||
- name: Build appimage
|
|
||||||
run: |
|
|
||||||
source /opt/qt*/bin/qt*-env.sh && \
|
|
||||||
./linuxdeployqt.AppImage appdir/usr/share/applications/cool-retro-term.desktop \
|
|
||||||
-verbose=1 -appimage \
|
|
||||||
-qmldir=./app/qml/ \
|
|
||||||
-qmldir=./qmltermwidget/
|
|
||||||
env:
|
|
||||||
# Unset environment variables
|
|
||||||
QTDIR:
|
|
||||||
QT_PLUGIN_PATH:
|
|
||||||
LD_LIBRARY_PATH:
|
|
||||||
|
|
||||||
- name: Upload release
|
|
||||||
uses: softprops/action-gh-release@v1
|
|
||||||
with:
|
|
||||||
body: appimage release
|
|
||||||
files: ./**/Cool_Retro_Term-*-x86_64.AppImage
|
|
||||||
|
|
||||||
- name: Clean up
|
|
||||||
if: always()
|
|
||||||
run: |
|
|
||||||
find appdir -executable -type f -exec ldd {} \; | grep " => /usr" | cut -d " " -f 2-3 | sort | uniq
|
|
||||||
make clean
|
|
||||||
rm -rf appdir
|
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -48,6 +48,3 @@ cool-retro-term
|
|||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*.app
|
*.app
|
||||||
|
|
||||||
# IntelliJ
|
|
||||||
.idea
|
|
||||||
|
197
README.md
197
README.md
@ -8,9 +8,9 @@
|
|||||||
cool-retro-term is a terminal emulator which mimics the look and feel of the old cathode tube screens.
|
cool-retro-term is a terminal emulator which mimics the look and feel of the old cathode tube screens.
|
||||||
It has been designed to be eye-candy, customizable, and reasonably lightweight.
|
It has been designed to be eye-candy, customizable, and reasonably lightweight.
|
||||||
|
|
||||||
It uses the QML port of qtermwidget (Konsole): https://github.com/Swordfish90/qmltermwidget.
|
It uses the QML port of qtermwidget (Konsole) developed by me: https://github.com/Swordfish90/qmltermwidget.
|
||||||
|
|
||||||
This terminal emulator works under Linux and macOS and requires Qt5. It's suggested that you stick to the latest LTS version.
|
This terminal emulator works under Linux and macOS and requires Qt 5.2 or higher.
|
||||||
|
|
||||||
Settings such as colors, fonts, and effects can be accessed via context menu.
|
Settings such as colors, fonts, and effects can be accessed via context menu.
|
||||||
|
|
||||||
@ -20,11 +20,196 @@ Settings such as colors, fonts, and effects can be accessed via context menu.
|
|||||||

|

|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
Walk the easy way and install cool-retro-term using one of these convenient packages:
|
||||||
|
|
||||||
If you want to get a hold of the latest version, just go to the Releases page and grab the latest AppImage (Linux) or dmg (macOS).
|
Just grab the latest AppImage from the release page and make it executable and run it:
|
||||||
|
|
||||||
Alternatively, most distributions such as Ubuntu, Fedora or Arch already package cool-retro-term in their official repositories.
|
wget https://github.com/Swordfish90/cool-retro-term/releases/download/1.1.1/Cool-Retro-Term-1.1.1-x86_64.AppImage
|
||||||
|
chmod a+x Cool-Retro-Term-1.1.1-x86_64.AppImage
|
||||||
|
./Cool-Retro-Term-1.1.1-x86_64.AppImage
|
||||||
|
|
||||||
## Building
|
**Fedora** has the `cool-retro-term` in the official repositories. All you have to do is `sudo dnf install cool-retro-term`.
|
||||||
|
|
||||||
Check out the wiki and follow the instructions on how to build it on [Linux](https://github.com/Swordfish90/cool-retro-term/wiki/Build-Instructions-(Linux)) and [macOS](https://github.com/Swordfish90/cool-retro-term/wiki/Build-Instructions-(macOS)).
|
Users of **openSUSE** can grab a package from [Open Build Service](http://software.opensuse.org/package/cool-retro-term).
|
||||||
|
|
||||||
|
**Arch** users can install this [package](https://aur.archlinux.org/packages/cool-retro-term-git/) directly via the [AUR](https://aur.archlinux.org):
|
||||||
|
|
||||||
|
trizen -S aur/cool-retro-term-git
|
||||||
|
|
||||||
|
or use:
|
||||||
|
|
||||||
|
pacman -S cool-retro-term
|
||||||
|
|
||||||
|
to install precompiled from community repository.
|
||||||
|
|
||||||
|
Users of **Ubuntu 14.04 LTS (Trusty) up to 15.10 (Wily)** can use [this PPA](https://launchpad.net/~bugs-launchpad-net-falkensweb).
|
||||||
|
|
||||||
|
**Ubuntu 17.10** can use [this PPA](https://launchpad.net/%7Evantuz/+archive/ubuntu/cool-retro-term)
|
||||||
|
|
||||||
|
**Solus** users can install using `eopg`:
|
||||||
|
```
|
||||||
|
eopkg it cool-retro-term
|
||||||
|
```
|
||||||
|
|
||||||
|
**macOS** users can grab the latest dmg from the [release page](https://github.com/Swordfish90/cool-retro-term/releases) or install via Homebrew or MacPorts:
|
||||||
|
```
|
||||||
|
brew install cool-retro-term --cask
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```
|
||||||
|
port install cool-retro-term
|
||||||
|
```
|
||||||
|
|
||||||
|
**FreeBSD** users can install cool-retro-term with `pkg`:
|
||||||
|
|
||||||
|
pkg install cool-retro-term
|
||||||
|
|
||||||
|
## Build instructions (FreeBSD)
|
||||||
|
|
||||||
|
Grab a copy of [the FreeBSD Ports Collection](https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/ports-using.html), modify [`/usr/ports/x11/cool-retro-term/Makefile`](https://svnweb.freebsd.org/ports/head/x11/cool-retro-term/Makefile?view=markup) as you like, and then run `make install` to build and install the emulator:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd /usr/ports/x11/cool-retro-term
|
||||||
|
make install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build instructions (Linux)
|
||||||
|
|
||||||
|
Build cool-retro-term yourself, you know, the retro way.
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
Make sure to install these first.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Ubuntu 14.04**
|
||||||
|
|
||||||
|
sudo apt-get install build-essential qmlscene qt5-qmake qt5-default qtdeclarative5-dev qtdeclarative5-controls-plugin qtdeclarative5-qtquick2-plugin libqt5qml-graphicaleffects qtdeclarative5-dialogs-plugin qtdeclarative5-localstorage-plugin qtdeclarative5-window-plugin
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Ubuntu 16.10**
|
||||||
|
|
||||||
|
sudo apt-get install build-essential qmlscene qt5-qmake qt5-default qtdeclarative5-dev qml-module-qtquick-controls qtdeclarative5-qtquick2-plugin libqt5qml-graphicaleffects qml-module-qtquick-dialogs qtdeclarative5-localstorage-plugin qtdeclarative5-window-plugin
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Ubuntu 17.04**
|
||||||
|
|
||||||
|
sudo apt install build-essential libqt5qml-graphicaleffects qml-module-qt-labs-folderlistmodel qml-module-qt-labs-settings qml-module-qtquick-controls qml-module-qtquick-dialogs qmlscene qt5-default qt5-qmake qtdeclarative5-dev qtdeclarative5-localstorage-plugin qtdeclarative5-qtquick2-plugin qtdeclarative5-window-plugin
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Ubuntu 17.10**
|
||||||
|
|
||||||
|
sudo apt-get install build-essential qml-module-qtgraphicaleffects qml-module-qt-labs-folderlistmodel qml-module-qt-labs-settings qml-module-qtquick-controls qml-module-qtquick-dialogs qmlscene qt5-default qt5-qmake qtdeclarative5-dev qtdeclarative5-localstorage-plugin qtdeclarative5-qtquick2-plugin qtdeclarative5-window-plugin
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**snapcraft (most of distros)**
|
||||||
|
|
||||||
|
sudo snap install cool-retro-term --classic
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Debian Jessie and above**
|
||||||
|
|
||||||
|
sudo apt install build-essential qmlscene qt5-qmake qt5-default qtdeclarative5-dev qml-module-qtquick-controls qml-module-qtgraphicaleffects qml-module-qtquick-dialogs qml-module-qtquick-localstorage qml-module-qtquick-window2 qml-module-qt-labs-settings qml-module-qt-labs-folderlistmodel
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Fedora**
|
||||||
|
This command should install the known fedora dependencies:
|
||||||
|
|
||||||
|
sudo yum -y install qt5-qtbase qt5-qtbase-devel qt5-qtdeclarative qt5-qtdeclarative-devel qt5-qtgraphicaleffects qt5-qtquickcontrols redhat-rpm-config
|
||||||
|
|
||||||
|
or:
|
||||||
|
|
||||||
|
sudo dnf -y install qt5-qtbase qt5-qtbase-devel qt5-qtdeclarative qt5-qtdeclarative-devel qt5-qtgraphicaleffects qt5-qtquickcontrols redhat-rpm-config
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Arch Linux**
|
||||||
|
|
||||||
|
sudo pacman -S qt5-base qt5-declarative qt5-quickcontrols qt5-graphicaleffects
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**openSUSE**
|
||||||
|
|
||||||
|
Add repository with latest Qt 5 (this is only needed on openSUSE 13.1, Factory already has it):
|
||||||
|
|
||||||
|
sudo zypper ar http://download.opensuse.org/repositories/KDE:/Qt5/openSUSE_13.1/ KDE:Qt5
|
||||||
|
|
||||||
|
Install dependencies:
|
||||||
|
|
||||||
|
sudo zypper install libqt5-qtbase-devel libqt5-qtdeclarative-devel libqt5-qtquickcontrols libqt5-qtgraphicaleffects
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Anyone else**
|
||||||
|
|
||||||
|
Install Qt directly from here http://qt-project.org/downloads . Once done export them in you path (replace "_/opt/Qt5.3.1/5.3/gcc_64/bin_" with your correct folder):
|
||||||
|
|
||||||
|
export PATH=/opt/Qt5.3.1/5.3/gcc_64/bin/:$PATH
|
||||||
|
---
|
||||||
|
|
||||||
|
### Compile
|
||||||
|
Once you installed all dependencies (Qt is installed and in your path) you need to compile and run the application:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Get it from GitHub
|
||||||
|
git clone --recursive https://github.com/Swordfish90/cool-retro-term.git
|
||||||
|
|
||||||
|
# Build it
|
||||||
|
cd cool-retro-term
|
||||||
|
|
||||||
|
# Compile (Fedora and OpenSUSE user should use qmake-qt5 instead of qmake)
|
||||||
|
qmake && make
|
||||||
|
|
||||||
|
# Have fun!
|
||||||
|
./cool-retro-term
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build instructions (macOS)
|
||||||
|
|
||||||
|
1. Install [Xcode](https://developer.apple.com/xcode/) and agree to the licence agreement
|
||||||
|
2. Enter the following commands into the terminal:
|
||||||
|
|
||||||
|
**Brew**
|
||||||
|
|
||||||
|
```sh
|
||||||
|
brew install qt5
|
||||||
|
git clone --recursive https://github.com/Swordfish90/cool-retro-term.git
|
||||||
|
export CPPFLAGS="-I/usr/local/opt/qt5/include"
|
||||||
|
export LDFLAGS="-L/usr/local/opt/qt5/lib"
|
||||||
|
export PATH=/usr/local/opt/qt5/bin:$PATH
|
||||||
|
cd cool-retro-term
|
||||||
|
qmake && make
|
||||||
|
mkdir cool-retro-term.app/Contents/PlugIns
|
||||||
|
cp -r qmltermwidget/QMLTermWidget cool-retro-term.app/Contents/PlugIns
|
||||||
|
open cool-retro-term.app
|
||||||
|
```
|
||||||
|
|
||||||
|
**MacPorts**
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo port install qt5
|
||||||
|
git clone --recursive https://github.com/Swordfish90/cool-retro-term.git
|
||||||
|
cd cool-retro-term
|
||||||
|
/opt/local/libexec/qt5/bin/qmake && make
|
||||||
|
mkdir cool-retro-term.app/Contents/PlugIns
|
||||||
|
cp -r qmltermwidget/QMLTermWidget cool-retro-term.app/Contents/PlugIns
|
||||||
|
open cool-retro-term.app
|
||||||
|
```
|
||||||
|
|
||||||
|
**Homebrew**
|
||||||
|
|
||||||
|
```sh
|
||||||
|
brew install cool-retro-term --cask
|
||||||
|
```
|
||||||
|
|
||||||
|
## Donations
|
||||||
|
I made this project in my spare time because I love what I'm doing. If you are enjoying it, and you want to buy me a beer click [here](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=flscogna%40gmail%2ecom&lc=IT&item_name=Filippo%20Scognamiglio¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted).
|
||||||
|
|
||||||
|
You can also add "bounties" on your favourite issues. More information on the [Bountysource](https://www.bountysource.com/teams/crt/issues) page.
|
||||||
|
@ -16,7 +16,7 @@ macx:ICON = icons/crt.icns
|
|||||||
RESOURCES += qml/resources.qrc
|
RESOURCES += qml/resources.qrc
|
||||||
|
|
||||||
#########################################
|
#########################################
|
||||||
## INSTALLS
|
## INTALLS
|
||||||
#########################################
|
#########################################
|
||||||
|
|
||||||
target.path += /usr/bin/
|
target.path += /usr/bin/
|
||||||
|
28
app/main.cpp
28
app/main.cpp
@ -47,27 +47,29 @@ int main(int argc, char *argv[])
|
|||||||
setenv("LC_CTYPE", "UTF-8", 1);
|
setenv("LC_CTYPE", "UTF-8", 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Force fusion style on every platform
|
||||||
|
QQuickStyle::setStyle("Fusion");
|
||||||
|
|
||||||
if (argc>1 && (!strcmp(argv[1],"-h") || !strcmp(argv[1],"--help"))) {
|
if (argc>1 && (!strcmp(argv[1],"-h") || !strcmp(argv[1],"--help"))) {
|
||||||
QTextStream cout(stdout, QIODevice::WriteOnly);
|
QTextStream cout(stdout, QIODevice::WriteOnly);
|
||||||
cout << "Usage: " << argv[0] << " [--default-settings] [--workdir <dir>] [--program <prog>] [-p|--profile <prof>] [--fullscreen] [-h|--help]" << '\n';
|
cout << "Usage: " << argv[0] << " [--default-settings] [--workdir <dir>] [--program <prog>] [-p|--profile <prof>] [--fullscreen] [-h|--help]" << endl;
|
||||||
cout << " --default-settings Run cool-retro-term with the default settings" << '\n';
|
cout << " --default-settings Run cool-retro-term with the default settings" << endl;
|
||||||
cout << " --workdir <dir> Change working directory to 'dir'" << '\n';
|
cout << " --workdir <dir> Change working directory to 'dir'" << endl;
|
||||||
cout << " -e <cmd> Command to execute. This option will catch all following arguments, so use it as the last option." << '\n';
|
cout << " -e <cmd> Command to execute. This option will catch all following arguments, so use it as the last option." << endl;
|
||||||
cout << " -T <title> Set window title to 'title'." << '\n';
|
cout << " -T <title> Set window title to 'title'." << endl;
|
||||||
cout << " --fullscreen Run cool-retro-term in fullscreen." << '\n';
|
cout << " --fullscreen Run cool-retro-term in fullscreen." << endl;
|
||||||
cout << " -p|--profile <prof> Run cool-retro-term with the given profile." << '\n';
|
cout << " -p|--profile <prof> Run cool-retro-term with the given profile." << endl;
|
||||||
cout << " -h|--help Print this help." << '\n';
|
cout << " -h|--help Print this help." << endl;
|
||||||
cout << " --verbose Print additional information such as profiles and settings." << '\n';
|
cout << " --verbose Print additional information such as profiles and settings." << endl;
|
||||||
cout << " -v|--version Print the program name and version." << '\n';
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString appVersion("1.2.0");
|
QString appVersion("1.1.1");
|
||||||
|
|
||||||
if (argc>1 && (!strcmp(argv[1],"-v") || !strcmp(argv[1],"--version"))) {
|
if (argc>1 && (!strcmp(argv[1],"-v") || !strcmp(argv[1],"--version"))) {
|
||||||
QTextStream cout(stdout, QIODevice::WriteOnly);
|
QTextStream cout(stdout, QIODevice::WriteOnly);
|
||||||
cout << "cool-retro-term " << appVersion << '\n';
|
cout << "cool-retro-term " << appVersion << endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
@ -71,7 +71,6 @@ QtObject {
|
|||||||
|
|
||||||
property string _backgroundColor: "#000000"
|
property string _backgroundColor: "#000000"
|
||||||
property string _fontColor: "#ff8100"
|
property string _fontColor: "#ff8100"
|
||||||
property string _frameColor: "#ffffff"
|
|
||||||
property string saturatedColor: Utils.mix(Utils.strToColor("#FFFFFF"),
|
property string saturatedColor: Utils.mix(Utils.strToColor("#FFFFFF"),
|
||||||
Utils.strToColor(_fontColor),
|
Utils.strToColor(_fontColor),
|
||||||
saturationColor * 0.5)
|
saturationColor * 0.5)
|
||||||
@ -82,7 +81,6 @@ QtObject {
|
|||||||
_backgroundColor),
|
_backgroundColor),
|
||||||
Utils.strToColor(saturatedColor),
|
Utils.strToColor(saturatedColor),
|
||||||
0.7 + (contrast * 0.3))
|
0.7 + (contrast * 0.3))
|
||||||
property color frameColor: Utils.strToColor(_frameColor)
|
|
||||||
|
|
||||||
property real staticNoise: 0.12
|
property real staticNoise: 0.12
|
||||||
property real screenCurvature: 0.3
|
property real screenCurvature: 0.3
|
||||||
@ -92,7 +90,6 @@ QtObject {
|
|||||||
|
|
||||||
property real chromaColor: 0.25
|
property real chromaColor: 0.25
|
||||||
property real saturationColor: 0.25
|
property real saturationColor: 0.25
|
||||||
property real frameGloss: 0
|
|
||||||
|
|
||||||
property real jitter: 0.2
|
property real jitter: 0.2
|
||||||
|
|
||||||
@ -254,13 +251,11 @@ QtObject {
|
|||||||
var settings = {
|
var settings = {
|
||||||
"backgroundColor": _backgroundColor,
|
"backgroundColor": _backgroundColor,
|
||||||
"fontColor": _fontColor,
|
"fontColor": _fontColor,
|
||||||
"frameColor": _frameColor,
|
|
||||||
"flickering": flickering,
|
"flickering": flickering,
|
||||||
"horizontalSync": horizontalSync,
|
"horizontalSync": horizontalSync,
|
||||||
"staticNoise": staticNoise,
|
"staticNoise": staticNoise,
|
||||||
"chromaColor": chromaColor,
|
"chromaColor": chromaColor,
|
||||||
"saturationColor": saturationColor,
|
"saturationColor": saturationColor,
|
||||||
"frameGloss": frameGloss,
|
|
||||||
"screenCurvature": screenCurvature,
|
"screenCurvature": screenCurvature,
|
||||||
"glowingLine": glowingLine,
|
"glowingLine": glowingLine,
|
||||||
"burnIn": burnIn,
|
"burnIn": burnIn,
|
||||||
@ -350,7 +345,6 @@ QtObject {
|
|||||||
_backgroundColor = settings.backgroundColor
|
_backgroundColor = settings.backgroundColor
|
||||||
!== undefined ? settings.backgroundColor : _backgroundColor
|
!== undefined ? settings.backgroundColor : _backgroundColor
|
||||||
_fontColor = settings.fontColor !== undefined ? settings.fontColor : _fontColor
|
_fontColor = settings.fontColor !== undefined ? settings.fontColor : _fontColor
|
||||||
_frameColor = settings.frameColor !== undefined ? settings.frameColor : _frameColor
|
|
||||||
|
|
||||||
horizontalSync = settings.horizontalSync
|
horizontalSync = settings.horizontalSync
|
||||||
!== undefined ? settings.horizontalSync : horizontalSync
|
!== undefined ? settings.horizontalSync : horizontalSync
|
||||||
@ -359,7 +353,6 @@ QtObject {
|
|||||||
chromaColor = settings.chromaColor !== undefined ? settings.chromaColor : chromaColor
|
chromaColor = settings.chromaColor !== undefined ? settings.chromaColor : chromaColor
|
||||||
saturationColor = settings.saturationColor
|
saturationColor = settings.saturationColor
|
||||||
!== undefined ? settings.saturationColor : saturationColor
|
!== undefined ? settings.saturationColor : saturationColor
|
||||||
frameGloss = settings.frameGloss !== undefined ? settings.frameGloss : frameGloss
|
|
||||||
screenCurvature = settings.screenCurvature
|
screenCurvature = settings.screenCurvature
|
||||||
!== undefined ? settings.screenCurvature : screenCurvature
|
!== undefined ? settings.screenCurvature : screenCurvature
|
||||||
glowingLine = settings.glowingLine !== undefined ? settings.glowingLine : glowingLine
|
glowingLine = settings.glowingLine !== undefined ? settings.glowingLine : glowingLine
|
||||||
@ -466,8 +459,6 @@ QtObject {
|
|||||||
"rbgShift": 0,
|
"rbgShift": 0,
|
||||||
"saturationColor": 0.2483,
|
"saturationColor": 0.2483,
|
||||||
"screenCurvature": 0.3,
|
"screenCurvature": 0.3,
|
||||||
"frameColor": "#ffffff",
|
|
||||||
"frameGloss": 0,
|
|
||||||
"staticNoise": 0.1198,
|
"staticNoise": 0.1198,
|
||||||
"windowOpacity": 1,
|
"windowOpacity": 1,
|
||||||
"margin": 0.5,
|
"margin": 0.5,
|
||||||
@ -497,8 +488,6 @@ QtObject {
|
|||||||
"rbgShift": 0,
|
"rbgShift": 0,
|
||||||
"saturationColor": 0.0,
|
"saturationColor": 0.0,
|
||||||
"screenCurvature": 0.3,
|
"screenCurvature": 0.3,
|
||||||
"frameColor": "#ffffff",
|
|
||||||
"frameGloss": 0,
|
|
||||||
"staticNoise": 0.1198,
|
"staticNoise": 0.1198,
|
||||||
"windowOpacity": 1,
|
"windowOpacity": 1,
|
||||||
"margin": 0.5,
|
"margin": 0.5,
|
||||||
@ -528,8 +517,6 @@ QtObject {
|
|||||||
"rbgShift": 0,
|
"rbgShift": 0,
|
||||||
"saturationColor": 0.5,
|
"saturationColor": 0.5,
|
||||||
"screenCurvature": 0.3,
|
"screenCurvature": 0.3,
|
||||||
"frameColor": "#ffffff",
|
|
||||||
"frameGloss": 0,
|
|
||||||
"staticNoise": 0.15,
|
"staticNoise": 0.15,
|
||||||
"windowOpacity": 1,
|
"windowOpacity": 1,
|
||||||
"margin": 0.5,
|
"margin": 0.5,
|
||||||
@ -559,8 +546,6 @@ QtObject {
|
|||||||
"rbgShift": 0,
|
"rbgShift": 0,
|
||||||
"saturationColor": 0,
|
"saturationColor": 0,
|
||||||
"screenCurvature": 0,
|
"screenCurvature": 0,
|
||||||
"frameColor": "#ffffff",
|
|
||||||
"frameGloss": 0,
|
|
||||||
"staticNoise": 0.15,
|
"staticNoise": 0.15,
|
||||||
"windowOpacity": 1,
|
"windowOpacity": 1,
|
||||||
"margin": 0.5,
|
"margin": 0.5,
|
||||||
@ -590,8 +575,6 @@ QtObject {
|
|||||||
"rbgShift": 0,
|
"rbgShift": 0,
|
||||||
"saturationColor": 0,
|
"saturationColor": 0,
|
||||||
"screenCurvature": 0.5,
|
"screenCurvature": 0.5,
|
||||||
"frameColor": "#ffffff",
|
|
||||||
"frameGloss": 0,
|
|
||||||
"staticNoise": 0.099,
|
"staticNoise": 0.099,
|
||||||
"windowOpacity": 1,
|
"windowOpacity": 1,
|
||||||
"margin": 0.5,
|
"margin": 0.5,
|
||||||
@ -621,8 +604,6 @@ QtObject {
|
|||||||
"rbgShift": 0.2969,
|
"rbgShift": 0.2969,
|
||||||
"saturationColor": 0,
|
"saturationColor": 0,
|
||||||
"screenCurvature": 0.5,
|
"screenCurvature": 0.5,
|
||||||
"frameColor": "#ffffff",
|
|
||||||
"frameGloss": 0,
|
|
||||||
"staticNoise": 0.2969,
|
"staticNoise": 0.2969,
|
||||||
"windowOpacity": 1,
|
"windowOpacity": 1,
|
||||||
"margin": 0.5,
|
"margin": 0.5,
|
||||||
@ -632,7 +613,7 @@ QtObject {
|
|||||||
builtin: true
|
builtin: true
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
text: "IBM DOS"
|
text: "IBM Dos"
|
||||||
obj_string: '{
|
obj_string: '{
|
||||||
"ambientLight": 0.151,
|
"ambientLight": 0.151,
|
||||||
"backgroundColor": "#000000",
|
"backgroundColor": "#000000",
|
||||||
@ -652,8 +633,6 @@ QtObject {
|
|||||||
"rbgShift": 0.3524,
|
"rbgShift": 0.3524,
|
||||||
"saturationColor": 0,
|
"saturationColor": 0,
|
||||||
"screenCurvature": 0.4,
|
"screenCurvature": 0.4,
|
||||||
"frameColor": "#ffffff",
|
|
||||||
"frameGloss": 0,
|
|
||||||
"staticNoise": 0.0503,
|
"staticNoise": 0.0503,
|
||||||
"windowOpacity": 1,
|
"windowOpacity": 1,
|
||||||
"margin": 0.5,
|
"margin": 0.5,
|
||||||
@ -683,8 +662,6 @@ QtObject {
|
|||||||
"rbgShift": 0,
|
"rbgShift": 0,
|
||||||
"saturationColor": 0,
|
"saturationColor": 0,
|
||||||
"screenCurvature": 0.2,
|
"screenCurvature": 0.2,
|
||||||
"frameColor": "#ffffff",
|
|
||||||
"frameGloss": 0,
|
|
||||||
"staticNoise": 0,
|
"staticNoise": 0,
|
||||||
"windowOpacity": 1,
|
"windowOpacity": 1,
|
||||||
"margin": 0.5,
|
"margin": 0.5,
|
||||||
@ -714,8 +691,6 @@ QtObject {
|
|||||||
"rbgShift": 0,
|
"rbgShift": 0,
|
||||||
"saturationColor": 0.4983,
|
"saturationColor": 0.4983,
|
||||||
"screenCurvature": 0,
|
"screenCurvature": 0,
|
||||||
"frameColor": "#ffffff",
|
|
||||||
"frameGloss": 0,
|
|
||||||
"staticNoise": 0.0955,
|
"staticNoise": 0.0955,
|
||||||
"windowOpacity": 0.7,
|
"windowOpacity": 0.7,
|
||||||
"margin": 0.1,
|
"margin": 0.1,
|
||||||
|
@ -76,7 +76,7 @@ Loader {
|
|||||||
Connections {
|
Connections {
|
||||||
target: kterminal
|
target: kterminal
|
||||||
|
|
||||||
onImagePainted: {
|
function onImagePainted() {
|
||||||
completelyUpdate()
|
completelyUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,19 +84,19 @@ Loader {
|
|||||||
Connections {
|
Connections {
|
||||||
target: appSettings
|
target: appSettings
|
||||||
|
|
||||||
onBurnInChanged: {
|
function onBurnInChanged() {
|
||||||
burnInEffect.restartBlurSource()
|
burnInEffect.restartBlurSource()
|
||||||
}
|
}
|
||||||
|
|
||||||
onTerminalFontChanged: {
|
function onTerminalFontChanged() {
|
||||||
burnInEffect.restartBlurSource()
|
burnInEffect.restartBlurSource()
|
||||||
}
|
}
|
||||||
|
|
||||||
onRasterizationChanged: {
|
function onRasterizationChanged() {
|
||||||
burnInEffect.restartBlurSource()
|
burnInEffect.restartBlurSource()
|
||||||
}
|
}
|
||||||
|
|
||||||
onBurnInQualityChanged: {
|
function onBurnInQualityChanged() {
|
||||||
burnInEffect.restartBlurSource()
|
burnInEffect.restartBlurSource()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,52 +47,45 @@ Item{
|
|||||||
Connections {
|
Connections {
|
||||||
target: copyAction
|
target: copyAction
|
||||||
|
|
||||||
onTriggered: {
|
function onTriggered() {
|
||||||
kterminal.copyClipboard()
|
kterminal.copyClipboard()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Connections {
|
Connections {
|
||||||
target: pasteAction
|
target: pasteAction
|
||||||
|
|
||||||
onTriggered: {
|
function onTriggered() {
|
||||||
kterminal.pasteClipboard()
|
kterminal.pasteClipboard()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Connections {
|
|
||||||
target: pasteActionAlt
|
|
||||||
|
|
||||||
onTriggered: {
|
|
||||||
kterminal.pasteSelection()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//When settings are updated sources need to be redrawn.
|
//When settings are updated sources need to be redrawn.
|
||||||
Connections {
|
Connections {
|
||||||
target: appSettings
|
target: appSettings
|
||||||
|
|
||||||
onFontScalingChanged: {
|
function onFontScalingChanged() {
|
||||||
terminalContainer.updateSources()
|
terminalContainer.updateSources()
|
||||||
}
|
}
|
||||||
|
|
||||||
onFontWidthChanged: {
|
function onFontWidthChanged() {
|
||||||
terminalContainer.updateSources()
|
terminalContainer.updateSources()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Connections {
|
Connections {
|
||||||
target: terminalContainer
|
target: terminalContainer
|
||||||
|
|
||||||
onWidthChanged: {
|
function onWidthChanged() {
|
||||||
terminalContainer.updateSources()
|
terminalContainer.updateSources()
|
||||||
}
|
}
|
||||||
|
|
||||||
onHeightChanged: {
|
function onHeightChanged() {
|
||||||
terminalContainer.updateSources()
|
terminalContainer.updateSources()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Connections {
|
Connections {
|
||||||
target: terminalWindow
|
target: terminalWindow
|
||||||
|
|
||||||
onActiveChanged: {
|
function onActiveChanged() {
|
||||||
kterminal.forceActiveFocus()
|
kterminal.forceActiveFocus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ ColumnLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SizedLabel {
|
Label {
|
||||||
text: appSettings.fps !== 0 ? appSettings.fps : qsTr("Max")
|
text: appSettings.fps !== 0 ? appSettings.fps : qsTr("Max")
|
||||||
}
|
}
|
||||||
Label {
|
Label {
|
||||||
@ -109,7 +109,7 @@ ColumnLayout {
|
|||||||
enabled = true
|
enabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SizedLabel {
|
Label {
|
||||||
text: Math.round(txtslider.value * 100) + "%"
|
text: Math.round(txtslider.value * 100) + "%"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ ColumnLayout {
|
|||||||
enabled = true
|
enabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SizedLabel {
|
Label {
|
||||||
text: Math.round(bloomSlider.value * 100) + "%"
|
text: Math.round(bloomSlider.value * 100) + "%"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ ColumnLayout {
|
|||||||
enabled = true
|
enabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SizedLabel {
|
Label {
|
||||||
text: Math.round(burnInSlider.value * 100) + "%"
|
text: Math.round(burnInSlider.value * 100) + "%"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ ColumnLayout {
|
|||||||
Connections {
|
Connections {
|
||||||
target: appSettings
|
target: appSettings
|
||||||
|
|
||||||
onTerminalFontChanged: {
|
function onTerminalFontChanged() {
|
||||||
fontChanger.updateIndex()
|
fontChanger.updateIndex()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,11 +149,6 @@ ColumnLayout {
|
|||||||
value: appSettings.saturationColor
|
value: appSettings.saturationColor
|
||||||
enabled: appSettings.chromaColor !== 0
|
enabled: appSettings.chromaColor !== 0
|
||||||
}
|
}
|
||||||
CheckableSlider {
|
|
||||||
name: qsTr("Frame Gloss")
|
|
||||||
onNewValue: appSettings.frameGloss = newValue
|
|
||||||
value: appSettings.frameGloss
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@ -171,13 +166,6 @@ ColumnLayout {
|
|||||||
onColorSelected: appSettings._backgroundColor = color
|
onColorSelected: appSettings._backgroundColor = color
|
||||||
color: appSettings._backgroundColor
|
color: appSettings._backgroundColor
|
||||||
}
|
}
|
||||||
ColorButton {
|
|
||||||
name: qsTr("Frame")
|
|
||||||
height: 50
|
|
||||||
Layout.fillWidth: true
|
|
||||||
onColorSelected: appSettings._frameColor = color
|
|
||||||
color: appSettings._frameColor
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,8 @@ import QtQuick.Dialogs 1.1
|
|||||||
Window {
|
Window {
|
||||||
id: settings_window
|
id: settings_window
|
||||||
title: qsTr("Settings")
|
title: qsTr("Settings")
|
||||||
width: 640
|
width: 600
|
||||||
height: 640
|
height: 480
|
||||||
|
|
||||||
property int tabmargins: 15
|
property int tabmargins: 15
|
||||||
|
|
||||||
|
@ -37,8 +37,6 @@ Item {
|
|||||||
|
|
||||||
property real ambientLight: appSettings.ambientLight * 0.2
|
property real ambientLight: appSettings.ambientLight * 0.2
|
||||||
|
|
||||||
property real frameGloss: appSettings.frameGloss
|
|
||||||
|
|
||||||
property size virtualResolution
|
property size virtualResolution
|
||||||
property size screenResolution
|
property size screenResolution
|
||||||
|
|
||||||
@ -61,7 +59,6 @@ Item {
|
|||||||
property real screenCurvature: parent.screenCurvature
|
property real screenCurvature: parent.screenCurvature
|
||||||
property real chromaColor: parent.chromaColor
|
property real chromaColor: parent.chromaColor
|
||||||
property real ambientLight: parent.ambientLight
|
property real ambientLight: parent.ambientLight
|
||||||
property real frameGloss: parent.frameGloss
|
|
||||||
|
|
||||||
property real flickering: appSettings.flickering
|
property real flickering: appSettings.flickering
|
||||||
property real horizontalSync: appSettings.horizontalSync
|
property real horizontalSync: appSettings.horizontalSync
|
||||||
@ -175,7 +172,6 @@ Item {
|
|||||||
uniform highp vec4 fontColor;
|
uniform highp vec4 fontColor;
|
||||||
uniform highp vec4 backgroundColor;
|
uniform highp vec4 backgroundColor;
|
||||||
uniform lowp float shadowLength;
|
uniform lowp float shadowLength;
|
||||||
uniform lowp float frameGloss;
|
|
||||||
|
|
||||||
uniform highp vec2 virtualResolution;
|
uniform highp vec2 virtualResolution;
|
||||||
uniform lowp float rasterizationIntensity;\n" +
|
uniform lowp float rasterizationIntensity;\n" +
|
||||||
@ -247,17 +243,6 @@ Item {
|
|||||||
" return outColor;
|
" return outColor;
|
||||||
}" +
|
}" +
|
||||||
|
|
||||||
//pseudo-random vector
|
|
||||||
//https://stackoverflow.com/a/10625698
|
|
||||||
"float random( vec2 p )
|
|
||||||
{
|
|
||||||
vec2 K1 = vec2(
|
|
||||||
23.14069263277926, // e^pi (Gelfond's constant)
|
|
||||||
2.665144142690225 // 2^sqrt(2) (Gelfond-Schneider constant)
|
|
||||||
);
|
|
||||||
return fract( cos( dot(p,K1) ) * 12345.6789 );
|
|
||||||
}" +
|
|
||||||
|
|
||||||
"void main() {" +
|
"void main() {" +
|
||||||
"vec2 cc = vec2(0.5) - qt_TexCoord0;" +
|
"vec2 cc = vec2(0.5) - qt_TexCoord0;" +
|
||||||
"float distance = length(cc);" +
|
"float distance = length(cc);" +
|
||||||
@ -296,11 +281,7 @@ Item {
|
|||||||
: "") +
|
: "") +
|
||||||
|
|
||||||
(jitter !== 0 || staticNoise !== 0 ?
|
(jitter !== 0 || staticNoise !== 0 ?
|
||||||
"vec4 noiseTexel = texture2D(
|
"vec4 noiseTexel = texture2D(noiseSource, scaleNoiseSize * coords + vec2(fract(time / 51.0), fract(time / 237.0)));"
|
||||||
noiseSource, scaleNoiseSize * coords
|
|
||||||
+ vec2(0.0, random(vec2(fract(time / 237.0), 822.9582)))
|
|
||||||
+ vec2(fract(time / 31.0), fract(time / 177.0))
|
|
||||||
);"
|
|
||||||
: "") +
|
: "") +
|
||||||
|
|
||||||
(jitter !== 0 ? "
|
(jitter !== 0 ? "
|
||||||
@ -340,7 +321,7 @@ Item {
|
|||||||
|
|
||||||
(displayTerminalFrame ?
|
(displayTerminalFrame ?
|
||||||
"vec4 frameColor = texture2D(frameSource, qt_TexCoord0);
|
"vec4 frameColor = texture2D(frameSource, qt_TexCoord0);
|
||||||
finalColor = mix(finalColor, frameColor.rgb + (finalColor*frameGloss), frameColor.a);"
|
finalColor = mix(finalColor, frameColor.rgb, frameColor.a);"
|
||||||
: "") +
|
: "") +
|
||||||
|
|
||||||
"gl_FragColor = vec4(finalColor, qt_Opacity);" +
|
"gl_FragColor = vec4(finalColor, qt_Opacity);" +
|
||||||
|
@ -22,13 +22,13 @@ import QtQuick 2.0
|
|||||||
import "utils.js" as Utils
|
import "utils.js" as Utils
|
||||||
|
|
||||||
ShaderEffect {
|
ShaderEffect {
|
||||||
property color _frameColor: appSettings.frameColor
|
property color _staticFrameColor: "#fff"
|
||||||
property color _backgroundColor: appSettings.backgroundColor
|
property color _backgroundColor: appSettings.backgroundColor
|
||||||
property color _fontColor: appSettings.fontColor
|
property color _fontColor: appSettings.fontColor
|
||||||
property color _lightColor: Utils.mix(_fontColor, _backgroundColor, 0.2)
|
property color _lightColor: Utils.mix(_fontColor, _backgroundColor, 0.2)
|
||||||
property real _ambientLight: Utils.lint(0.2, 0.8, appSettings.ambientLight)
|
property real _ambientLight: Utils.lint(0.2, 0.8, appSettings.ambientLight)
|
||||||
|
|
||||||
property color frameColor: Utils.mix(_frameColor, _lightColor, _ambientLight)
|
property color frameColor: Utils.mix(_staticFrameColor, _lightColor, _ambientLight)
|
||||||
property real screenCurvature: appSettings.screenCurvature * appSettings.screenCurvatureSize
|
property real screenCurvature: appSettings.screenCurvature * appSettings.screenCurvatureSize
|
||||||
|
|
||||||
// Coefficient of the log curve used to approximate shadowing
|
// Coefficient of the log curve used to approximate shadowing
|
||||||
@ -87,7 +87,7 @@ ShaderEffect {
|
|||||||
float alpha = 0.0;
|
float alpha = 0.0;
|
||||||
|
|
||||||
float frameShadow = max2(positiveLog(-coords * frameShadowCoeff + vec2(1.0)) + positiveLog(coords * frameShadowCoeff - (vec2(frameShadowCoeff) - vec2(1.0))));
|
float frameShadow = max2(positiveLog(-coords * frameShadowCoeff + vec2(1.0)) + positiveLog(coords * frameShadowCoeff - (vec2(frameShadowCoeff) - vec2(1.0))));
|
||||||
frameShadow = clamp(sqrt(frameShadow), 0.0, 1.0);
|
frameShadow = max(sqrt(frameShadow), 0.0);
|
||||||
color *= frameShadow;
|
color *= frameShadow;
|
||||||
alpha = sum2(1.0 - step(vec2(0.0), coords) + step(vec2(1.0), coords));
|
alpha = sum2(1.0 - step(vec2(0.0), coords) + step(vec2(1.0), coords));
|
||||||
alpha = clamp(alpha, 0.0, 1.0);
|
alpha = clamp(alpha, 0.0, 1.0);
|
||||||
|
@ -116,11 +116,6 @@ ApplicationWindow {
|
|||||||
text: qsTr("Paste")
|
text: qsTr("Paste")
|
||||||
shortcut: "Ctrl+Shift+V"
|
shortcut: "Ctrl+Shift+V"
|
||||||
}
|
}
|
||||||
Action {
|
|
||||||
id: pasteActionAlt
|
|
||||||
text: qsTr("Paste selection")
|
|
||||||
shortcut: "Shift+Insert"
|
|
||||||
}
|
|
||||||
Action {
|
Action {
|
||||||
id: zoomIn
|
id: zoomIn
|
||||||
text: qsTr("Zoom In")
|
text: qsTr("Zoom In")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user