1
0
mirror of https://github.com/Swordfish90/cool-retro-term.git synced 2026-02-08 08:42:22 +00:00

13 Commits

Author SHA1 Message Date
Filippo Scognamiglio
77434e463e Fix github workflows. 2026-01-19 01:12:56 +01:00
Filippo Scognamiglio
6bcb54114d Update the readme to mention Qt6 instead of Qt5. 2026-01-19 00:50:13 +01:00
Filippo Scognamiglio
09f813a7e0 Fix terminal size not displayed when resizing. 2026-01-19 00:13:45 +01:00
Filippo Scognamiglio
a6a7768e42 Add version to build packages. 2026-01-19 00:13:15 +01:00
Filippo Scognamiglio
33878dae24 Bump QMLTermWidget version to 2.0. 2026-01-17 22:15:18 +01:00
Filippo Scognamiglio
0313a00b4f Move showMenuBar toggle inside advanced settings. 2026-01-17 22:09:29 +01:00
Filippo Scognamiglio
be4b1f366c Make version number dynamic. 2026-01-17 21:44:40 +01:00
Filippo Scognamiglio
c54dcb1c1c Add build script for macos dmgs. 2026-01-17 18:53:38 +01:00
Filippo Scognamiglio
5795aeb6b7 Fix fullscreen not tied to multiple windows. 2026-01-17 18:35:05 +01:00
Filippo Scognamiglio
e70268bb73 Make actions between the different menus global. 2026-01-17 17:20:37 +01:00
Filippo Scognamiglio
e72faa1d2c Set up appimage build. 2026-01-17 13:53:12 +01:00
Filippo Scognamiglio
e1fc767431 Some improvements to default themes and small cleanups. 2026-01-17 13:51:27 +01:00
Filippo Scognamiglio
737d289a19 Allow enabling and disabling italic. 2026-01-15 23:57:10 +01:00
44 changed files with 429 additions and 338 deletions

View File

@@ -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

54
.github/workflows/build-appimage.yml vendored Normal file
View File

@@ -0,0 +1,54 @@
name: Build AppImage
on:
workflow_dispatch:
push:
branches:
- main
pull_request:
jobs:
build-appimage:
name: Build (Linux, AppImage)
runs-on: ubuntu-22.04
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install build deps
run: |
sudo apt update
sudo apt install -y build-essential rsync wget
- name: Install Qt
uses: jurplel/install-qt-action@v4
with:
version: 6.10.0
dir: ..
modules: qtshadertools
setup-python: false
cache: true
- name: Build AppImage
run: |
./scripts/build-appimage.sh
- name: Collect artifact
run: |
mkdir -p release
mv ./*.AppImage release/
- name: Attestation
uses: actions/attest-build-provenance@v1
with:
subject-path: ./release/*
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: cool-retro-term-appimage
path: ./release/*

50
.github/workflows/build-dmg.yml vendored Normal file
View File

@@ -0,0 +1,50 @@
name: Build DMG
on:
workflow_dispatch:
push:
branches:
- main
pull_request:
jobs:
build-dmg:
name: Build (macOS, DMG)
runs-on: macos-14
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Qt
uses: jurplel/install-qt-action@v4
with:
version: 6.10.*
modules: qtshadertools
setup-python: true
python-version: '3.11'
cache: true
- name: Build DMG
run: |
JOBS="$(sysctl -n hw.ncpu)"
./scripts/build-dmg.sh
- name: Collect artifact
run: |
mkdir -p release
mv ./*.dmg release/
- name: Attestation
uses: actions/attest-build-provenance@v1
with:
subject-path: ./release/*
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: cool-retro-term-dmg
path: ./release/*

6
.gitignore vendored
View File

@@ -41,11 +41,17 @@ Makefile*
*.json
# Excludes compiled files
imports
cool-retro-term
build
# Linux
*.AppImage
# Mac OSX
.DS_Store
*.app
*.dmg

View File

@@ -1,37 +0,0 @@
sudo: required
dist: trusty
language: c++
install:
- sudo add-apt-repository -y ppa:beineri/opt-qt58-trusty
- sudo apt-get update -qq
- sudo apt-get -y install build-essential qt58declarative qt58graphicaleffects qt58quickcontrols libgl1-mesa-dev
- source /opt/qt*/bin/qt*-env.sh
script:
- qmake CONFIG+=release PREFIX=/usr
- make -j$(nproc)
- mkdir -p appdir/usr/share/metainfo appdir/usr/bin
- cp packaging/appdata/cool-retro-term.appdata.xml appdir/usr/share/metainfo/
- cp cool-retro-term appdir/usr/bin/
- cp ./cool-retro-term.desktop appdir/
- cp ./app/icons/128x128/cool-retro-term.png appdir/
- cp -r ./app/qml appdir/usr/
- cp -r ./qmltermwidget/QMLTermWidget appdir/usr/qml/ # Workaround for https://github.com/probonopd/linuxdeployqt/issues/78
- wget -c https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage
- chmod a+x linuxdeployqt-*.AppImage
- unset QTDIR; unset QT_PLUGIN_PATH ; unset LD_LIBRARY_PATH
- export VERSION=$(git rev-parse --short HEAD) # linuxdeployqt uses this for naming the file
- ./linuxdeployqt-*.AppImage appdir/usr/bin/cool-retro-term -qmldir=./app/qml/ -qmldir=./qmltermwidget/ # -verbose=3 2>&1 | grep "path:" -C 3
- ./linuxdeployqt-*.AppImage appdir/usr/bin/cool-retro-term -qmldir=./app/qml/ -qmldir=./qmltermwidget/ -verbose=2 -appimage
after_success:
- find appdir -executable -type f -exec ldd {} \; | grep " => /usr" | cut -d " " -f 2-3 | sort | uniq
- # curl --upload-file Cool*.AppImage https://transfer.sh/Cool_Retro_Term-git.$(git rev-parse --short HEAD)-x86_64.AppImage
- wget -c https://github.com/probonopd/uploadtool/raw/master/upload.sh
- bash upload.sh Cool*.AppImage*
branches:
except:
- # Do not build tags that we create when we upload to GitHub Releases
- /^(?i:continuous)/

View File

@@ -10,7 +10,7 @@ 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.
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 Qt6.
Settings such as colors, fonts, and effects can be accessed via context menu.

View File

@@ -1,5 +1,8 @@
QT += qml quick widgets sql quickcontrols2
TARGET = cool-retro-term
APP_VERSION = $$system(git -C $$PWD/.. describe --tags --always --dirty=-dirty)
isEmpty(APP_VERSION): APP_VERSION = "unknown"
DEFINES += APP_VERSION=\\\"$$APP_VERSION\\\"
# TODO: When migrating to CMake, use KDSingleApplication's CMakeLists.txt instead of these manual sources.
INCLUDEPATH += $$PWD/../KDSingleApplication/src

View File

@@ -73,7 +73,7 @@ int main(int argc, char *argv[])
return 0;
}
QString appVersion("1.2.0");
QString appVersion(QStringLiteral(APP_VERSION));
if (argc>1 && (!strcmp(argv[1],"-v") || !strcmp(argv[1],"--version"))) {
QTextStream cout(stdout, QIODevice::WriteOnly);
@@ -86,6 +86,7 @@ int main(int argc, char *argv[])
app.setApplicationName(QStringLiteral("cool-retro-term"));
app.setOrganizationName(QStringLiteral("cool-retro-term"));
app.setOrganizationDomain(QStringLiteral("cool-retro-term"));
app.setApplicationVersion(appVersion);
KDSingleApplication singleApp(QStringLiteral("cool-retro-term"));

View File

@@ -40,7 +40,6 @@ QtObject {
property bool isMacOS: Qt.platform.os === "osx"
// GENERAL SETTINGS ///////////////////////////////////////////////////////
property bool fullscreen: false
property bool showMenubar: false
property bool showTerminalSize: true
@@ -86,7 +85,7 @@ QtObject {
property real horizontalSync: 0.08
property real flickering: 0.1
property real rbgShift: 0.0
property real rgbShift: 0.0
property real _frameShininess: 0.2
property real frameShininess: _frameShininess * 0.5
@@ -188,7 +187,7 @@ QtObject {
"bloom": bloom,
"rasterization": rasterization,
"jitter": jitter,
"rbgShift": rbgShift,
"rgbShift": rgbShift,
"brightness": brightness,
"contrast": contrast,
"ambientLight": ambientLight,
@@ -289,7 +288,7 @@ QtObject {
jitter = settings.jitter !== undefined ? settings.jitter : jitter
rbgShift = settings.rbgShift !== undefined ? settings.rbgShift : rbgShift
rgbShift = settings.rgbShift !== undefined ? settings.rgbShift : rgbShift
ambientLight = settings.ambientLight !== undefined ? settings.ambientLight : ambientLight
contrast = settings.contrast !== undefined ? settings.contrast : contrast
@@ -384,9 +383,9 @@ QtObject {
"horizontalSync": 0.1,
"jitter": 0.2,
"rasterization": 0,
"rbgShift": 0,
"rgbShift": 0,
"saturationColor": 0.2,
"screenCurvature": 0.4,
"screenCurvature": 0.2,
"screenRadius": 0.1,
"staticNoise": 0.1,
"windowOpacity": 1,
@@ -410,7 +409,7 @@ QtObject {
"contrast": 0.8,
"flickering": 0.1,
"fontColor": "#0ccc68",
"fontName": "EXCELSIOR_SCALED",
"fontName": "DEPARTURE_MONO_SCALED",
"fontSource": 0,
"fontWidth": 1,
"lineSpacing": 0.1,
@@ -418,9 +417,9 @@ QtObject {
"horizontalSync": 0.1,
"jitter": 0.2,
"rasterization": 0,
"rbgShift": 0,
"rgbShift": 0,
"saturationColor": 0.0,
"screenCurvature": 0.7,
"screenCurvature": 0.3,
"screenRadius": 0.2,
"staticNoise": 0.1,
"windowOpacity": 1,
@@ -444,7 +443,7 @@ QtObject {
"contrast": 0.8,
"flickering": 0.1,
"fontColor": "#7fb4ff",
"fontName": "COZETTE_SCALED",
"fontName": "BIGBLUE_TERMINAL_SCALED",
"fontSource": 0,
"fontWidth": 1,
"lineSpacing": 0.1,
@@ -452,9 +451,9 @@ QtObject {
"horizontalSync": 0.1,
"jitter": 0.2,
"rasterization": 0,
"rbgShift": 0,
"rgbShift": 0,
"saturationColor": 0.2,
"screenCurvature": 1.0,
"screenCurvature": 0.4,
"screenRadius": 0.1,
"staticNoise": 0.1,
"windowOpacity": 1,
@@ -486,7 +485,7 @@ QtObject {
"horizontalSync": 0.0,
"jitter": 0.0,
"rasterization": 1,
"rbgShift": 0,
"rgbShift": 0,
"saturationColor": 0,
"screenCurvature": 0.5,
"screenRadius": 0.1,
@@ -495,7 +494,7 @@ QtObject {
"margin": 0.3,
"blinkingCursor": false,
"frameSize": 0.5,
"frameColor": "#444444",
"frameColor": "#999999",
"frameShininess": 0.0
}'
builtin: true
@@ -520,15 +519,15 @@ QtObject {
"horizontalSync": 0.2,
"jitter": 0.15,
"rasterization": 1,
"rbgShift": 0.1,
"rgbShift": 0.0,
"saturationColor": 0,
"screenCurvature": 1.0,
"screenCurvature": 0.7,
"screenRadius": 0.3,
"staticNoise": 0.2,
"windowOpacity": 1,
"margin": 0.2,
"blinkingCursor": false,
"frameSize": 0.8,
"frameSize": 0.5,
"frameColor": "#000000",
"frameShininess": 0.6
}'
@@ -554,15 +553,15 @@ QtObject {
"horizontalSync": 0.2,
"jitter": 0.2,
"rasterization": 1,
"rbgShift": 0.1,
"rgbShift": 0.0,
"saturationColor": 0,
"screenCurvature": 1.0,
"screenCurvature": 0.5,
"screenRadius": 0.3,
"staticNoise": 0.2,
"windowOpacity": 1,
"margin": 0.0,
"blinkingCursor": false,
"frameSize": 0.5,
"frameSize": 0.2,
"frameColor": "#ffffff",
"frameShininess": 0.8
}'
@@ -588,9 +587,9 @@ QtObject {
"horizontalSync": 0.0,
"jitter": 0.0,
"rasterization": 1,
"rbgShift": 0.0,
"rgbShift": 0.0,
"saturationColor": 0,
"screenCurvature": 0.3,
"screenCurvature": 0.4,
"screenRadius": 0.2,
"staticNoise": 0.1,
"windowOpacity": 1,
@@ -622,7 +621,7 @@ QtObject {
"horizontalSync": 0.0,
"jitter": 0.0,
"rasterization": 1,
"rbgShift": 0.15,
"rgbShift": 0.1,
"saturationColor": 0,
"screenCurvature": 0.3,
"screenRadius": 0.1,
@@ -637,13 +636,13 @@ QtObject {
builtin: true
}
ListElement {
text: "IBM 3278"
text: "IBM 3278 Reborn"
obj_string: '{
"ambientLight": 0.2,
"backgroundColor": "#000000",
"bloom": 0.2,
"brightness": 0.5,
"burnIn": 0.7,
"burnIn": 0.5,
"chromaColor": 0,
"contrast": 0.8,
"flickering": 0,
@@ -656,7 +655,7 @@ QtObject {
"horizontalSync": 0,
"jitter": 0,
"rasterization": 4,
"rbgShift": 0,
"rgbShift": 0,
"saturationColor": 0,
"screenCurvature": 0,
"screenRadius": 0.0,
@@ -690,7 +689,7 @@ QtObject {
"horizontalSync": 0.0,
"jitter": 0.1,
"rasterization": 4,
"rbgShift": 0.0,
"rgbShift": 0.0,
"saturationColor": 0.6,
"screenCurvature": 0,
"screenRadius": 0.0,
@@ -724,7 +723,7 @@ QtObject {
"horizontalSync": 0.0,
"jitter": 0.0,
"rasterization": 4,
"rbgShift": 0.1,
"rgbShift": 0.0,
"saturationColor": 0.0,
"screenCurvature": 0,
"screenRadius": 0.0,
@@ -758,7 +757,7 @@ QtObject {
"horizontalSync": 0.0,
"jitter": 0.1,
"rasterization": 4,
"rbgShift": 0.1,
"rgbShift": 0.1,
"saturationColor": 0.8,
"screenCurvature": 0,
"screenRadius": 0.0,
@@ -792,7 +791,7 @@ QtObject {
"horizontalSync": 0,
"jitter": 0.0,
"rasterization": 4,
"rbgShift": 0,
"rgbShift": 0,
"saturationColor": 0.0,
"screenCurvature": 0,
"screenRadius": 0.0,
@@ -826,7 +825,7 @@ QtObject {
"horizontalSync": 0.0,
"jitter": 0.0,
"rasterization": 4,
"rbgShift": 0,
"rgbShift": 0,
"saturationColor": 0,
"screenCurvature": 0,
"screenRadius": 0.0,
@@ -864,17 +863,12 @@ QtObject {
var profileArgPosition = args.indexOf("--profile")
if (profileArgPosition !== -1) {
var profileIndex = getProfileIndexByName(
args[profileArgPosition + 1])
if (profileIndex !== -1)
var profileIndex = getProfileIndexByName(args[profileArgPosition + 1])
if (profileIndex !== -1) {
loadProfile(profileIndex)
else
} else {
console.log("Warning: selected profile is not valid; ignoring it")
}
if (args.indexOf("--fullscreen") !== -1) {
fullscreen = true
showMenubar = false
}
}
initializedSettings()

View File

@@ -20,14 +20,15 @@
import QtQuick 2.2
import QtQuick.Controls 2.0
import QtQml
import QMLTermWidget 1.0
import QMLTermWidget 2.0
import "menus"
import "utils.js" as Utils
Item{
id: terminalContainer
Item {
id: preprocessedTerminal
signal sessionFinished()
property size virtualResolution: Qt.size(kterminal.totalWidth, kterminal.totalHeight)
@@ -47,14 +48,14 @@ Item{
// Manage copy and paste
Connections {
target: copyAction
enabled: terminalContainer.hasFocus
onTriggered: {
kterminal.copyClipboard()
}
}
Connections {
target: pasteAction
enabled: terminalContainer.hasFocus
onTriggered: {
kterminal.pasteClipboard()
}
@@ -65,22 +66,22 @@ Item{
target: appSettings
onFontScalingChanged: {
terminalContainer.updateSources()
preprocessedTerminal.updateSources()
}
onFontWidthChanged: {
terminalContainer.updateSources()
preprocessedTerminal.updateSources()
}
}
Connections {
target: terminalContainer
target: preprocessedTerminal
onWidthChanged: {
terminalContainer.updateSources()
preprocessedTerminal.updateSources()
}
onHeightChanged: {
terminalContainer.updateSources()
preprocessedTerminal.updateSources()
}
}
@@ -118,7 +119,7 @@ Item{
id: ksession
onFinished: {
terminalContainer.sessionFinished()
preprocessedTerminal.sessionFinished()
}
}
@@ -141,14 +142,15 @@ Item{
kterminal.antialiasText = !lowResolutionFont;
kterminal.smooth = !lowResolutionFont;
kterminal.enableBold = !lowResolutionFont;
kterminal.enableItalic = !lowResolutionFont;
kterminal.font = Qt.font({
family: fontFamily,
pixelSize: pixelSize
});
terminalContainer.fontWidth = fontWidth;
terminalContainer.screenScaling = screenScaling;
preprocessedTerminal.fontWidth = fontWidth;
preprocessedTerminal.screenScaling = screenScaling;
scaleTexture = Math.max(1.0, Math.floor(screenScaling * appSettings.windowScaling));
}
@@ -156,7 +158,7 @@ Item{
target: appSettings
onWindowScalingChanged: {
scaleTexture = Math.max(1.0, Math.floor(terminalContainer.screenScaling * appSettings.windowScaling));
scaleTexture = Math.max(1.0, Math.floor(preprocessedTerminal.screenScaling * appSettings.windowScaling));
}
}
@@ -199,7 +201,7 @@ Item{
Loader {
id: menuLoader
sourceComponent: (appSettings.isMacOS || appSettings.showMenubar ? shortContextMenu : fullContextMenu)
sourceComponent: (appSettings.isMacOS || (appSettings.showMenubar && !terminalWindow.fullscreen) ? shortContextMenu : fullContextMenu)
}
property alias contextmenu: menuLoader.item
@@ -212,7 +214,7 @@ Item{
cursorShape: kterminal.terminalUsesMouse ? Qt.ArrowCursor : Qt.IBeamCursor
onWheel: function(wheel) {
if (wheel.modifiers & Qt.ControlModifier) {
wheel.angleDelta.y > 0 ? zoomIn.trigger() : zoomOut.trigger();
wheel.angleDelta.y > 0 ? zoomInAction.trigger() : zoomOutAction.trigger();
} else {
var coord = correctDistortion(wheel.x, wheel.y);
kterminal.simulateWheel(coord.x, coord.y, wheel.buttons, wheel.modifiers, wheel.angleDelta);

View File

@@ -28,7 +28,7 @@ ColumnLayout {
GroupBox {
Layout.fillWidth: true
Layout.fillHeight: true
title: qsTr("Command")
title: qsTr("Miscellaneous")
padding: appSettings.defaultMargin
ColumnLayout {
@@ -39,12 +39,6 @@ ColumnLayout {
checked: appSettings.useCustomCommand
onCheckedChanged: appSettings.useCustomCommand = checked
}
// Workaround for QTBUG-31627 for pre 5.3.0
Binding {
target: useCustomCommand
property: "checked"
value: appSettings.useCustomCommand
}
TextField {
id: customCommand
Layout.fillWidth: true
@@ -59,26 +53,18 @@ ColumnLayout {
Component.onCompleted: settings_window.closing.connect(
saveSetting)
}
}
}
GroupBox {
title: qsTr("Cursor")
Layout.fillWidth: true
Layout.fillHeight: true
padding: appSettings.defaultMargin
ColumnLayout {
anchors.fill: parent
CheckBox {
id: blinkingCursor
text: qsTr("Blinking Cursor")
checked: appSettings.blinkingCursor
onCheckedChanged: appSettings.blinkingCursor = checked
}
Binding {
target: blinkingCursor
property: "checked"
value: appSettings.blinkingCursor
CheckBox {
id: showMenubar
text: qsTr("Show Menubar")
enabled: !appSettings.isMacOS
checked: appSettings.showMenubar
onCheckedChanged: appSettings.showMenubar = checked
}
}
}

View File

@@ -83,8 +83,8 @@ ColumnLayout {
}
CheckableSlider {
name: qsTr("RGB Shift")
onNewValue: function(newValue) { appSettings.rbgShift = newValue }
value: appSettings.rbgShift
onNewValue: function(newValue) { appSettings.rgbShift = newValue }
value: appSettings.rgbShift
}
CheckableSlider {
name: qsTr("Frame Shininess")

View File

@@ -36,7 +36,7 @@ Item {
}
function staticFragmentPath() {
var rgbShiftOn = appSettings.rbgShift > 0 ? 1 : 0;
var rgbShiftOn = appSettings.rgbShift > 0 ? 1 : 0;
var bloomOn = appSettings.bloom > 0 ? 1 : 0;
var curvatureOn = (appSettings.screenCurvature > 0 || appSettings.frameSize > 0) ? 1 : 0;
var shineOn = appSettings.frameShininess > 0 ? 1 : 0;
@@ -176,7 +176,7 @@ Item {
property real chromaColor: appSettings.chromaColor;
property real rbgShift: (appSettings.rbgShift / width) * appSettings.totalFontScaling
property real rgbShift: appSettings.rgbShift * (4.0 / width) * appSettings.totalFontScaling
property real screen_brightness: Utils.lint(0.5, 1.5, appSettings.brightness)
property real frameShininess: appSettings.frameShininess

View File

@@ -21,15 +21,13 @@ import QtQuick 2.2
Rectangle {
property size terminalSize
property real topOpacity: 0.6
property real topOpacity: 0.5
width: textSize.width * 2
height: textSize.height * 2
radius: 5
border.width: 2
border.color: "white"
color: "black"
opacity: sizetimer.running ? 0.6 : 0.0
opacity: sizetimer.running ? 0.5 : 0.0
Behavior on opacity {
NumberAnimation {

View File

@@ -28,6 +28,13 @@ ShaderTerminal {
signal sessionFinished()
property bool loadBloomEffect: appSettings.bloom > 0 || appSettings._frameShininess > 0
property bool hasFocus
onHasFocusChanged: {
if (hasFocus) {
activate()
}
}
id: mainShader
opacity: appSettings.windowOpacity * 0.3 + 0.7

View File

@@ -20,16 +20,16 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQml.Models
Item {
id: tabsRoot
readonly property int innerPadding: 6
readonly property string currentTitle: tabsModel.get(currentIndex).title ?? "cool-retro-term"
readonly property size terminalSize: stack.currentItem ? stack.currentItem.terminalSize : Qt.size(0, 0)
property alias currentIndex: tabBar.currentIndex
readonly property int count: tabsModel.count
property var hostWindow
property size terminalSize: Qt.size(0, 0)
function normalizeTitle(rawTitle) {
if (rawTitle === undefined || rawTitle === null) {
@@ -45,7 +45,7 @@ Item {
function closeTab(index) {
if (tabsModel.count <= 1) {
hostWindow.close()
terminalWindow.close()
return
}
@@ -130,16 +130,22 @@ Item {
Repeater {
model: tabsModel
TerminalContainer {
property bool shouldHaveFocus: terminalWindow.active && StackLayout.isCurrentItem
onShouldHaveFocusChanged: {
if (shouldHaveFocus) {
activate()
}
}
id: terminalContainer
hasFocus: terminalWindow.active && StackLayout.isCurrentItem
onTerminalSizeChanged: updateTerminalSize()
onTitleChanged: tabsModel.setProperty(index, "title", normalizeTitle(title))
Layout.fillWidth: true
Layout.fillHeight: true
onSessionFinished: tabsRoot.closeTab(index)
function updateTerminalSize() {
// Every tab will have the same size so we can simply take the first one.
if (index == 0) {
tabsRoot.terminalSize = terminalSize
}
}
}
}
}

View File

@@ -20,6 +20,7 @@
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 2.3
import QtQml
import "menus"
@@ -39,21 +40,27 @@ ApplicationWindow {
visible: false
property bool fullscreen: appSettings.fullscreen
property bool fullscreen: false
onFullscreenChanged: visibility = (fullscreen ? Window.FullScreen : Window.Windowed)
menuBar: qtquickMenuLoader.item
Loader {
id: qtquickMenuLoader
active: !appSettings.isMacOS && appSettings.showMenubar
active: !appSettings.isMacOS && (appSettings.showMenubar && !fullscreen)
sourceComponent: WindowMenu { }
}
Loader {
id: globalMenuLoader
active: appSettings.isMacOS
sourceComponent: OSXMenu { }
Connections {
target: newTabAction
enabled: terminalWindow.active
onTriggered: terminalTabs.addTab()
}
Connections {
target: fullscreenAction
enabled: terminalWindow.active
onTriggered: terminalWindow.fullscreen = !terminalWindow.fullscreen
}
property real normalizedWindowScale: 1024 / ((0.5 * width + 0.5 * height))
@@ -62,86 +69,10 @@ ApplicationWindow {
title: terminalTabs.currentTitle
Action {
id: showMenubarAction
text: qsTr("Show Menubar")
enabled: !appSettings.isMacOS
shortcut: "Ctrl+Shift+M"
checkable: true
checked: appSettings.showMenubar
onTriggered: appSettings.showMenubar = !appSettings.showMenubar
}
Action {
id: fullscreenAction
text: qsTr("Fullscreen")
enabled: !appSettings.isMacOS
shortcut: "Alt+F11"
onTriggered: appSettings.fullscreen = !appSettings.fullscreen
checkable: true
checked: appSettings.fullscreen
}
Action {
id: newWindowAction
text: qsTr("New Window")
shortcut: "Ctrl+Shift+N"
onTriggered: appRoot.createWindow()
}
Action {
id: quitAction
text: qsTr("Quit")
shortcut: "Ctrl+Shift+Q"
onTriggered: appSettings.close()
}
Action {
id: showsettingsAction
text: qsTr("Settings")
onTriggered: {
settingsWindow.show()
settingsWindow.requestActivate()
settingsWindow.raise()
}
}
Action {
id: copyAction
text: qsTr("Copy")
shortcut: "Ctrl+Shift+C"
}
Action {
id: pasteAction
text: qsTr("Paste")
shortcut: "Ctrl+Shift+V"
}
Action {
id: zoomIn
text: qsTr("Zoom In")
shortcut: "Ctrl++"
onTriggered: appSettings.incrementScaling()
}
Action {
id: zoomOut
text: qsTr("Zoom Out")
shortcut: "Ctrl+-"
onTriggered: appSettings.decrementScaling()
}
Action {
id: showAboutAction
text: qsTr("About")
onTriggered: {
aboutDialog.show()
aboutDialog.requestActivate()
aboutDialog.raise()
}
}
Action {
id: newTabAction
text: qsTr("New Tab")
onTriggered: terminalTabs.addTab()
}
TerminalTabs {
id: terminalTabs
width: parent.width
height: (parent.height + Math.abs(y))
hostWindow: terminalWindow
}
Loader {
anchors.centerIn: parent

View File

@@ -18,6 +18,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
import QtQuick 2.2
import QtQuick.Controls 2.3
import "menus"
QtObject {
id: appRoot
@@ -34,7 +37,7 @@ QtObject {
visible: false
}
property AboutDialog aboutWindow: AboutDialog {
property AboutDialog aboutDialog: AboutDialog {
visible: false
}
@@ -44,12 +47,83 @@ QtObject {
property ListModel windowsModel: ListModel { }
property Loader globalMenuLoader: Loader {
active: appSettings.isMacOS
sourceComponent: OSXMenu { }
}
property Action fullscreenAction: Action {
text: qsTr("Fullscreen")
enabled: !appSettings.isMacOS
shortcut: "Alt+F11"
}
property bool initialFullscreenRequested: Qt.application.arguments.indexOf("--fullscreen") !== -1
property Action newWindowAction: Action {
text: qsTr("New Window")
shortcut: "Ctrl+Shift+N"
onTriggered: appRoot.createWindow()
}
property Action quitAction: Action {
text: qsTr("Quit")
shortcut: "Ctrl+Shift+Q"
onTriggered: appSettings.close()
}
property Action showsettingsAction: Action {
text: qsTr("Settings")
onTriggered: {
settingsWindow.show()
settingsWindow.requestActivate()
settingsWindow.raise()
}
}
property Action copyAction: Action {
text: qsTr("Copy")
shortcut: "Ctrl+Shift+C"
}
property Action pasteAction: Action {
text: qsTr("Paste")
shortcut: "Ctrl+Shift+V"
}
property Action zoomInAction: Action {
text: qsTr("Zoom In")
shortcut: "Ctrl++"
onTriggered: appSettings.incrementScaling()
}
property Action zoomOutAction: Action {
text: qsTr("Zoom Out")
shortcut: "Ctrl+-"
onTriggered: appSettings.decrementScaling()
}
property Action showAboutAction: Action {
text: qsTr("About")
onTriggered: {
aboutDialog.show()
aboutDialog.requestActivate()
aboutDialog.raise()
}
}
property Action newTabAction: Action {
text: qsTr("New Tab")
}
function createWindow() {
var window = windowComponent.createObject(null)
var useFullscreen = initialFullscreenRequested
var window = windowComponent.createObject(null, { fullscreen: useFullscreen })
if (!window)
return
windowsModel.append({ window: window })
initialFullscreenRequested = false
window.show()
window.requestActivate()
}
@@ -65,8 +139,6 @@ QtObject {
window.destroy()
if (windowsModel.count === 0) {
settingsWindow.close()
aboutWindow.close()
appSettings.close()
}
}

View File

@@ -65,14 +65,10 @@ Menu {
visible: fullscreenAction.enabled
}
MenuItem {
action: showMenubarAction
visible: showMenubarAction.enabled
action: zoomInAction
}
MenuItem {
action: zoomIn
}
MenuItem {
action: zoomOut
action: zoomOutAction
}
}
Menu {

View File

@@ -64,14 +64,14 @@ MenuBar {
Menu {
title: qsTr("View")
MenuItem {
text: zoomIn.text
text: zoomInAction.text
shortcut: "Meta++"
onTriggered: zoomIn.trigger()
onTriggered: zoomInAction.trigger()
}
MenuItem {
text: zoomOut.text
text: zoomOutAction.text
shortcut: "Meta+-"
onTriggered: zoomOut.trigger()
onTriggered: zoomOutAction.trigger()
}
}
Menu {

View File

@@ -57,14 +57,10 @@ MenuBar {
visible: fullscreenAction.enabled
}
MenuItem {
action: showMenubarAction
visible: showMenubarAction.enabled
action: zoomInAction
}
MenuItem {
action: zoomIn
}
MenuItem {
action: zoomOut
action: zoomOutAction
}
}
Menu {

View File

@@ -29,7 +29,7 @@ layout(std140, binding = 0) uniform ubuf {
vec2 scaleNoiseSize;
float screen_brightness;
float bloom;
float rbgShift;
float rgbShift;
float frameShadowCoeff;
float frameShininess;
vec4 frameColor;

View File

@@ -20,7 +20,7 @@ layout(std140, binding = 0) uniform ubuf {
mat4 qt_Matrix;
float qt_Opacity;
float screenCurvature;
float rbgShift;
float rgbShift;
float frameShininess;
float frameSize;
float screen_brightness;
@@ -59,7 +59,7 @@ void main() {
vec3 txt_color = texture(source, txt_coords).rgb;
#if CRT_RGB_SHIFT == 1
vec2 displacement = vec2(12.0, 0.0) * rbgShift;
vec2 displacement = vec2(rgbShift, 0.0);
vec3 rightColor = texture(source, txt_coords + displacement).rgb;
vec3 leftColor = texture(source, txt_coords - displacement).rgb;
txt_color.r = leftColor.r * 0.10 + rightColor.r * 0.30 + txt_color.r * 0.60;

View File

@@ -7,7 +7,7 @@ layout(std140, binding = 0) uniform ubuf {
mat4 qt_Matrix;
float qt_Opacity;
float screenCurvature;
float rbgShift;
float rgbShift;
float frameShininess;
float frameSize;
float screen_brightness;

Binary file not shown.

83
scripts/build-appimage.sh Executable file
View File

@@ -0,0 +1,83 @@
#!/usr/bin/env bash
set -euo pipefail
set -x
REPO_ROOT="$(readlink -f "$(dirname "$(dirname "$0")")")"
OLD_CWD="$(readlink -f .)"
BUILD_DIR="$REPO_ROOT/build/appimage"
TOOLS_DIR="$BUILD_DIR/tools"
VERSION="$(git -C "$REPO_ROOT" describe --tags --always --dirty=-dirty 2>/dev/null || true)"
if [ -z "$VERSION" ]; then
VERSION="unknown"
fi
if ! command -v qmake >/dev/null; then
echo "qmake not found in PATH." >&2
exit 1
fi
QTDIR="$(qmake -query QT_INSTALL_PREFIX)"
QT_INSTALL_QML="$(qmake -query QT_INSTALL_QML)"
APPDIR="$BUILD_DIR/AppDir"
mkdir -p "$BUILD_DIR"
rm -rf "$APPDIR"
pushd "$BUILD_DIR"
qmake "$REPO_ROOT/cool-retro-term.pro"
make -j"$(nproc)"
# Install targets from subprojects (the top-level install only installs the desktop file).
make -C app install INSTALL_ROOT="$APPDIR"
make -C qmltermwidget install INSTALL_ROOT="$APPDIR"
make install INSTALL_ROOT="$APPDIR"
popd
# Relocate QMLTermWidget into the standard AppDir QML import path.
QML_ROOT="$APPDIR$QT_INSTALL_QML"
if [ -d "$QML_ROOT" ]; then
mkdir -p "$APPDIR/usr/qml"
rsync -a "$QML_ROOT/" "$APPDIR/usr/qml/"
rm -rf "$QML_ROOT"
QML_PARENT="$(dirname "$QML_ROOT")"
while [ "$QML_PARENT" != "$APPDIR" ] && rmdir "$QML_PARENT" 2>/dev/null; do
QML_PARENT="$(dirname "$QML_PARENT")"
done
fi
# Build AppImage using linuxdeploy and linuxdeploy-plugin-qt.
mkdir -p "$TOOLS_DIR"
LINUXDEPLOY="$TOOLS_DIR/linuxdeploy-x86_64.AppImage"
LINUXDEPLOY_QT="$TOOLS_DIR/linuxdeploy-plugin-qt-x86_64.AppImage"
if [ ! -x "$LINUXDEPLOY" ]; then
wget -c -O "$LINUXDEPLOY" https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
chmod +x "$LINUXDEPLOY"
fi
if [ ! -x "$LINUXDEPLOY_QT" ]; then
wget -c -O "$LINUXDEPLOY_QT" https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage
chmod +x "$LINUXDEPLOY_QT"
fi
export QML_SOURCES_PATHS="$REPO_ROOT/app"
pushd "$BUILD_DIR"
export EXTRA_PLATFORM_PLUGINS="libqwayland.so;"
export EXTRA_QT_MODULES="sql;waylandcompositor;waylandclient"
export DEPLOY_PLATFORM_THEMES=true
export LINUXDEPLOY_EXCLUDED_LIBRARIES="libmysqlclient.so;libqsqlmimer.so;libqsqlmysql.so;libqsqlodbc.so;libqsqlpsql.so;libqsqloci.so;libqsqlibase.so"
"$LINUXDEPLOY" \
--appdir "$APPDIR" \
-e "$APPDIR/usr/bin/cool-retro-term" \
-i "$REPO_ROOT/app/icons/256x256/cool-retro-term.png" \
-d "$REPO_ROOT/cool-retro-term.desktop" \
--plugin qt \
--output appimage
APPIMAGE_PATH="$(ls -1 ./*.AppImage | head -n 1)"
APPIMAGE_OUT="cool-retro-term-${VERSION}.AppImage"
mv "$APPIMAGE_PATH" "$OLD_CWD/$APPIMAGE_OUT"
popd

41
scripts/build-dmg.sh Executable file
View File

@@ -0,0 +1,41 @@
#!/usr/bin/env bash
set -euo pipefail
set -x
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
OLD_CWD="$(pwd -P)"
BUILD_DIR="$REPO_ROOT/build/dmg"
APP="cool-retro-term.app"
QML_DIR="$REPO_ROOT/app/qml"
JOBS="${JOBS:-$(sysctl -n hw.ncpu 2>/dev/null || echo 4)}"
VERSION="$(git -C "$REPO_ROOT" describe --tags --always --dirty=-dirty 2>/dev/null || true)"
if [ -z "$VERSION" ]; then
VERSION="unknown"
fi
if ! command -v qmake >/dev/null; then
echo "qmake not found in PATH." >&2
exit 1
fi
QT_DIR="${QT_DIR:-$(qmake -query QT_INSTALL_PREFIX)}"
QT_BIN="${QT_DIR%/}/bin"
mkdir -p "$BUILD_DIR"
rm -f "$BUILD_DIR/${APP%.app}.dmg"
pushd "$BUILD_DIR"
"$QT_BIN/qmake" CONFIG+=release "$REPO_ROOT/cool-retro-term.pro"
make -j"$JOBS"
PLUGIN_DST="$APP/Contents/PlugIns/qmltermwidget"
rm -rf "$PLUGIN_DST"
mkdir -p "$APP/Contents/PlugIns"
cp -R qmltermwidget/QMLTermWidget "$PLUGIN_DST"
export QML_IMPORT_PATH="$PWD/$APP/Contents/PlugIns"
"$QT_BIN/macdeployqt" "$APP" -qmldir="$QML_DIR" -dmg
rm -f "$APP/Contents/PlugIns/sqldrivers/"libqsql{odbc,psql,mimer}.dylib 2>/dev/null || true
DMG_OUT="${APP%.app}-${VERSION}.dmg"
mv "$BUILD_DIR/${APP%.app}.dmg" "$OLD_CWD/$DMG_OUT"
popd