diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..340ec2d --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,4 @@ +# 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'] diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml new file mode 100644 index 0000000..2627318 --- /dev/null +++ b/.github/workflows/appimage.yml @@ -0,0 +1,98 @@ +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 diff --git a/.gitignore b/.gitignore index ba2c815..a6f396d 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ *.pro.user.* *.moc moc_*.cpp +moc_*.h qrc_*.cpp ui_*.h Makefile* diff --git a/README.md b/README.md index bbb2f6d..f263b9d 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,25 @@ # cool-cyber-term ## Description -this is a modified version of cool-retro-term, which enables you to add background images to crt. -You will have to specify a folder with all your background images you want to use, aswell as a opacity factor if you want to still see your desktop, and a scaling factor, in case you want the pictures to be pixellated. all this has to be done in the file background_selection.py. +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. -The used image will then be chosen randomly, each time you start a new terminal. +It uses the QML port of qtermwidget (Konsole): https://github.com/Swordfish90/qmltermwidget. -You may want to add a shortcut, which can be done as followed: -1. go to settings -> devices -> keyboard -2. change the "launch terminal" shortcut to anything but ctrl-alt-t -3. add a new shortcut and use as shortcut ctrl-alt-t and use as command '/opt/cool-cyber-term/start.sh' +This terminal emulator works under Linux and macOS and requires Qt5. It's suggested that you stick to the latest LTS version. -## Screenshot -![Imgur](https://i.imgur.com/q47kwHt.jpg) +Settings such as colors, fonts, and effects can be accessed via context menu. + +## Screenshots +![Image]() +![Image]() +![Image]() ## Install -This was tested on ubuntu 18.04. -### Install Dependencies +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). - 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 imagemagick python3 - -### Compile +Alternatively, most distributions such as Ubuntu, Fedora or Arch already package cool-retro-term in their official repositories. -```bash -# Get it! -git clone --recursive https://github.com/neurudan/cool-cyber-term.git +## Building -# Move it! -sudo mv cool-cyber-term /opt/ -sudo chmod -R a=rwx /opt/cool-cyber-term -cd /opt/cool-cyber-term -sudo cp cool-cyber-term.desktop /usr/share/applications - -# Build it! -qmake && make - -# Use it! -``` +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)). diff --git a/app/app.pro b/app/app.pro index 39bd4ec..1e42dcc 100644 --- a/app/app.pro +++ b/app/app.pro @@ -1,4 +1,4 @@ -QT += qml quick widgets sql +QT += qml quick widgets sql quickcontrols2 TARGET = cool-retro-term DESTDIR = $$OUT_PWD/../ diff --git a/app/main.cpp b/app/main.cpp index 1bccbd0..30cbf31 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -6,11 +6,13 @@ #include #include +#include #include #include #include +#include #include #include @@ -33,6 +35,9 @@ int main(int argc, char *argv[]) // This disables QT appmenu under Ubuntu, which is not working with QML apps. setenv("QT_QPA_PLATFORMTHEME", "", 1); + // Disable Connections slot warnings + QLoggingCategory::setFilterRules("qt.qml.connections.warning=false"); + #if defined (Q_OS_LINUX) setenv("QSG_RENDER_LOOP", "threaded", 0); #endif @@ -42,10 +47,30 @@ int main(int argc, char *argv[]) setenv("LC_CTYPE", "UTF-8", 1); #endif + if (argc>1 && (!strcmp(argv[1],"-h") || !strcmp(argv[1],"--help"))) { + QTextStream cout(stdout, QIODevice::WriteOnly); + cout << "Usage: " << argv[0] << " [--default-settings] [--workdir ] [--program ] [-p|--profile ] [--fullscreen] [-h|--help]" << endl; + cout << " --default-settings Run cool-retro-term with the default settings" << endl; + cout << " --workdir Change working directory to 'dir'" << endl; + cout << " -e Command to execute. This option will catch all following arguments, so use it as the last option." << endl; + cout << " -T Set window title to 'title'." << endl; + cout << " --fullscreen Run cool-retro-term in fullscreen." << endl; + cout << " -p|--profile <prof> Run cool-retro-term with the given profile." << endl; + cout << " -h|--help Print this help." << endl; + cout << " --verbose Print additional information such as profiles and settings." << endl; + return 0; + } + + QString appVersion("1.2.0"); + + if (argc>1 && (!strcmp(argv[1],"-v") || !strcmp(argv[1],"--version"))) { + QTextStream cout(stdout, QIODevice::WriteOnly); + cout << "cool-retro-term " << appVersion << endl; + return 0; + } + QApplication app(argc, argv); - // set application attributes - // Has no effects, see https://bugreports.qt.io/browse/QTBUG-51293 - // app.setAttribute(Qt::AA_MacDontSwapCtrlAndMeta, true); + app.setAttribute(Qt::AA_MacDontSwapCtrlAndMeta, true); QQmlApplicationEngine engine; FileIO fileIO; @@ -57,29 +82,11 @@ int main(int argc, char *argv[]) app.setWindowIcon(QIcon(":../icons/32x32/cool-retro-term.png")); #endif + app.setOrganizationName("cool-retro-term"); + app.setOrganizationDomain("cool-retro-term"); + // Manage command line arguments from the cpp side QStringList args = app.arguments(); - if (args.contains("-h") || args.contains("--help")) { - // BUG: This usage help text goes to stderr, should go to stdout. - // BUG: First line of output is surrounded by double quotes. - qDebug() << "Usage: " + args.at(0) + " [--default-settings] [--workdir <dir>] [--program <prog>] [-p|--profile <prof>] [--fullscreen] [-h|--help]"; - qDebug() << " --default-settings Run cool-retro-term with the default settings"; - qDebug() << " --workdir <dir> Change working directory to 'dir'"; - qDebug() << " -e <cmd> Command to execute. This option will catch all following arguments, so use it as the last option."; - qDebug() << " -T <title> Set window title to 'title'."; - qDebug() << " --fullscreen Run cool-retro-term in fullscreen."; - qDebug() << " -p|--profile <prof> Run cool-retro-term with the given profile."; - qDebug() << " -h|--help Print this help."; - qDebug() << " --verbose Print additional information such as profiles and settings."; - return 0; - } - - QString appVersion("1.1.1"); - - if (args.contains("-v") || args.contains("--version")) { - qDebug() << ("cool-retro-term " + appVersion).toStdString().c_str(); - return 0; - } // Manage default command QStringList cmdList; diff --git a/app/qml/AboutDialog.qml b/app/qml/AboutDialog.qml index 79d4936..22becce 100644 --- a/app/qml/AboutDialog.qml +++ b/app/qml/AboutDialog.qml @@ -1,9 +1,28 @@ +/******************************************************************************* +* Copyright (c) 2013-2021 "Filippo Scognamiglio" +* https://github.com/Swordfish90/cool-retro-term +* +* This file is part of cool-retro-term. +* +* cool-retro-term is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* 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/>. +*******************************************************************************/ import QtQuick 2.2 -import QtQuick.Controls 1.1 +import QtQuick.Controls 2.2 import QtQuick.Layouts 1.1 import QtQuick.Window 2.0 -Window{ +Window { id: dialogwindow title: qsTr("About") width: 600 @@ -11,16 +30,19 @@ Window{ modality: Qt.ApplicationModal - ColumnLayout{ + ColumnLayout { anchors.fill: parent anchors.margins: 15 spacing: 15 Text { Layout.alignment: Qt.AlignHCenter text: "cool-retro-term" - font {bold: true; pointSize: 18} + font { + bold: true + pointSize: 18 + } } - Loader{ + Loader { id: mainContent Layout.fillHeight: true Layout.fillWidth: true @@ -41,32 +63,33 @@ Window{ } } ] - Component.onCompleted: mainContent.state = "Default"; + Component.onCompleted: mainContent.state = "Default" } - Item{ + Item { Layout.fillWidth: true height: childrenRect.height - Button{ + Button { anchors.left: parent.left text: qsTr("License") onClicked: { - mainContent.state == "Default" ? mainContent.state = "License" : mainContent.state = "Default" + mainContent.state == "Default" ? mainContent.state + = "License" : mainContent.state = "Default" } } - Button{ + Button { anchors.right: parent.right text: qsTr("Close") - onClicked: dialogwindow.close(); + onClicked: dialogwindow.close() } } } // MAIN COMPONENTS //////////////////////////////////////////////////////// - Component{ + Component { id: defaultComponent - ColumnLayout{ + ColumnLayout { anchors.fill: parent spacing: 10 - Image{ + Image { Layout.fillWidth: true Layout.fillHeight: true Layout.alignment: Qt.AlignHCenter @@ -74,36 +97,37 @@ Window{ source: "images/crt256.png" smooth: true } - Text{ + Text { Layout.alignment: Qt.AlignCenter horizontalAlignment: Text.AlignHCenter - text: appSettings.version + "\n" + - qsTr("Author: ") + "Filippo Scognamiglio\n" + - qsTr("Email: ") + "flscogna@gmail.com\n" + - qsTr("Source: ") + "https://github.com/Swordfish90/cool-retro-term\n" + text: appSettings.version + "\n" + qsTr( + "Author: ") + "Filippo Scognamiglio\n" + qsTr( + "Email: ") + "flscogna@gmail.com\n" + qsTr( + "Source: ") + "https://github.com/Swordfish90/cool-retro-term\n" } } } - Component{ + Component { id: licenseComponent - TextArea{ + ScrollView { anchors.fill: parent - readOnly: true - text: "Copyright (c) 2013 Filippo Scognamiglio <flscogna@gmail.com>\n\n" + - "https://github.com/Swordfish90/cool-retro-term\n\n" + - - "cool-retro-term is free software: you can redistribute it and/or modify " + - "it under the terms of the GNU General Public License as published by " + - "the Free Software Foundation, either version 3 of the License, or " + - "(at your option) any later version.\n\n" + - - "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.\n\n" + - - "You should have received a copy of the GNU General Public License " + - "along with this program. If not, see <http://www.gnu.org/licenses/>." + clip: true + TextArea { + readOnly: true + wrapMode: TextEdit.Wrap + text: "Copyright (c) 2013-2021 Filippo Scognamiglio <flscogna@gmail.com>\n\n" + + "https://github.com/Swordfish90/cool-retro-term\n\n" + + "cool-retro-term is free software: you can redistribute it and/or modify " + + "it under the terms of the GNU General Public License as published by " + + "the Free Software Foundation, either version 3 of the License, or " + + "(at your option) any later version.\n\n" + + "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.\n\n" + + "You should have received a copy of the GNU General Public License " + + "along with this program. If not, see <http://www.gnu.org/licenses/>." + } } } } diff --git a/app/qml/ApplicationSettings.qml b/app/qml/ApplicationSettings.qml index 11d4330..424f0bd 100644 --- a/app/qml/ApplicationSettings.qml +++ b/app/qml/ApplicationSettings.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -17,18 +17,16 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ - import QtQuick 2.2 -import QtQuick.Controls 1.0 +import QtQuick.Controls 2.0 import "utils.js" as Utils -QtObject{ +QtObject { readonly property string version: appVersion readonly property int profileVersion: 2 // STATIC CONSTANTS //////////////////////////////////////////////////////// - readonly property real screenCurvatureSize: 0.4 readonly property real minimumFontScaling: 0.25 readonly property real maximumFontScaling: 2.50 @@ -36,15 +34,16 @@ QtObject{ readonly property real minBurnInFadeTime: 160 readonly property real maxBurnInFadeTime: 1600 - // GENERAL SETTINGS /////////////////////////////////////////////////////// + property bool isMacOS: Qt.platform.os === "osx" + // GENERAL SETTINGS /////////////////////////////////////////////////////// property int x: 100 property int y: 100 property int width: 1024 property int height: 768 property bool fullscreen: false - property bool showMenubar: Qt.platform.os === "osx" ? true : false + property bool showMenubar: false property string wintitle: "cool-retro-term" @@ -55,14 +54,13 @@ QtObject{ property bool verbose: false property real bloomQuality: 0.5 - property real burnInQuality: 0.5 - property bool useFastBurnIn: Qt.platform.os === "osx" ? false : true - onWindowScalingChanged: handleFontChanged(); + property bool blinkingCursor: false + + onWindowScalingChanged: handleFontChanged() // PROFILE SETTINGS /////////////////////////////////////////////////////// - property real windowOpacity: 1.0 property real ambientLight: 0.2 property real contrast: 0.80 @@ -73,9 +71,16 @@ QtObject{ property string _backgroundColor: "#000000" property string _fontColor: "#ff8100" - property string saturatedColor: Utils.mix(Utils.strToColor("#FFFFFF"), Utils.strToColor(_fontColor), saturationColor * 0.5) - property color fontColor: Utils.mix(Utils.strToColor(saturatedColor), Utils.strToColor(_backgroundColor), 0.7 + (contrast * 0.3)) - property color backgroundColor: Utils.mix(Utils.strToColor(_backgroundColor), Utils.strToColor(saturatedColor), 0.7 + (contrast * 0.3)) + property string saturatedColor: Utils.mix(Utils.strToColor("#FFFFFF"), + Utils.strToColor(_fontColor), + saturationColor * 0.5) + property color fontColor: Utils.mix(Utils.strToColor(saturatedColor), + Utils.strToColor(_backgroundColor), + 0.7 + (contrast * 0.3)) + property color backgroundColor: Utils.mix(Utils.strToColor( + _backgroundColor), + Utils.strToColor(saturatedColor), + 0.7 + (contrast * 0.3)) property real staticNoise: 0.12 property real screenCurvature: 0.3 @@ -94,16 +99,21 @@ QtObject{ property real rbgShift: 0.0 property real _margin: 0.5 + property real _frameMargin: 0.5 + property real margin: Utils.lint(1.0, 20.0, _margin) + property real frameMargin: Utils.lint(1.0, 50.0, _frameMargin) + + property real totalMargin: frameMargin + margin readonly property int no_rasterization: 0 readonly property int scanline_rasterization: 1 readonly property int pixel_rasterization: 2 + readonly property int subpixel_rasterization: 3 property int rasterization: no_rasterization // FONTS ////////////////////////////////////////////////////////////////// - readonly property real baseFontScaling: 0.75 property real fontScaling: 1.0 property real totalFontScaling: baseFontScaling * fontScaling @@ -117,167 +127,197 @@ QtObject{ signal terminalFontChanged(string fontFamily, int pixelSize, int lineSpacing, real screenScaling, real fontWidth) - signal initializedSettings() + signal initializedSettings - property Loader fontManager: Loader{ + property Loader fontManager: Loader { states: [ - State { when: rasterization == no_rasterization - PropertyChanges {target: fontManager; source: "Fonts.qml" } }, - State { when: rasterization == scanline_rasterization - PropertyChanges {target: fontManager; source: "FontScanlines.qml" } }, - State { when: rasterization == pixel_rasterization; - PropertyChanges {target: fontManager; source: "FontPixels.qml" } } + State { + when: rasterization == no_rasterization + PropertyChanges { + target: fontManager + source: "Fonts.qml" + } + }, + State { + when: rasterization == scanline_rasterization + PropertyChanges { + target: fontManager + source: "FontScanlines.qml" + } + }, + State { + when: rasterization == pixel_rasterization + PropertyChanges { + target: fontManager + source: "FontPixels.qml" + } + }, + State { + when: rasterization == subpixel_rasterization + PropertyChanges { + target: fontManager + source: "FontPixels.qml" + } + } ] onLoaded: handleFontChanged() } - property FontLoader fontLoader: FontLoader { } + property FontLoader fontLoader: FontLoader {} - onTotalFontScalingChanged: handleFontChanged(); - onFontWidthChanged: handleFontChanged(); + onTotalFontScalingChanged: handleFontChanged() + onFontWidthChanged: handleFontChanged() function getIndexByName(name) { for (var i = 0; i < fontlist.count; i++) { - var requestedName = fontlist.get(i).name; + var requestedName = fontlist.get(i).name if (name === requestedName) - return i; + return i } - return 0; // If the font is not available default to 0. + return 0 // If the font is not available default to 0. } - function incrementScaling(){ - fontScaling = Math.min(fontScaling + 0.05, maximumFontScaling); - handleFontChanged(); + function incrementScaling() { + fontScaling = Math.min(fontScaling + 0.05, maximumFontScaling) + handleFontChanged() } - function decrementScaling(){ - fontScaling = Math.max(fontScaling - 0.05, minimumFontScaling); - handleFontChanged(); + function decrementScaling() { + fontScaling = Math.max(fontScaling - 0.05, minimumFontScaling) + handleFontChanged() } - function handleFontChanged(){ - if (!fontManager.item) return; + function handleFontChanged() { + if (!fontManager.item) + return - var index = getIndexByName(fontNames[rasterization]); - if (index === undefined) return; + var index = getIndexByName(fontNames[rasterization]) + if (index === undefined) + return - fontManager.item.selectedFontIndex = index; - fontManager.item.scaling = totalFontScaling; + fontManager.item.selectedFontIndex = index + fontManager.item.scaling = totalFontScaling - var fontSource = fontManager.item.source; - var pixelSize = fontManager.item.pixelSize; - var lineSpacing = fontManager.item.lineSpacing; - var screenScaling = fontManager.item.screenScaling; - var fontWidth = fontManager.item.defaultFontWidth * appSettings.fontWidth; - var fontFamily = fontManager.item.family; - var isSystemFont = fontManager.item.isSystemFont; + var fontSource = fontManager.item.source + var pixelSize = fontManager.item.pixelSize + var lineSpacing = fontManager.item.lineSpacing + var screenScaling = fontManager.item.screenScaling + var fontWidth = fontManager.item.defaultFontWidth * appSettings.fontWidth + var fontFamily = fontManager.item.family + var isSystemFont = fontManager.item.isSystemFont - lowResolutionFont = fontManager.item.lowResolutionFont; + lowResolutionFont = fontManager.item.lowResolutionFont if (!isSystemFont) { - fontLoader.source = fontSource; - fontFamily = fontLoader.name; + fontLoader.source = fontSource + fontFamily = fontLoader.name } - terminalFontChanged(fontFamily, pixelSize, lineSpacing, screenScaling, fontWidth); + terminalFontChanged(fontFamily, pixelSize, lineSpacing, screenScaling, + fontWidth) } - property Storage storage: Storage{ } + property Storage storage: Storage {} function stringify(obj) { - var replacer = function(key, val) { - return val.toFixed ? Number(val.toFixed(4)) : val; + var replacer = function (key, val) { + return val.toFixed ? Number(val.toFixed(4)) : val } - return JSON.stringify(obj, replacer, 2); + return JSON.stringify(obj, replacer, 2) } - function composeSettingsString(){ + function composeSettingsString() { var settings = { - fps: fps, - x: x, - y: y, - width: width, - height: height, - windowScaling: windowScaling, - showTerminalSize: showTerminalSize, - fontScaling: fontScaling, - fontNames: fontNames, - showMenubar: showMenubar, - bloomQuality: bloomQuality, - burnInQuality: burnInQuality, - useCustomCommand: useCustomCommand, - customCommand: customCommand, - useFastBurnIn: useFastBurnIn + "fps": fps, + "x": x, + "y": y, + "width": width, + "height": height, + "windowScaling": windowScaling, + "showTerminalSize": showTerminalSize, + "fontScaling": fontScaling, + "fontNames": fontNames, + "showMenubar": showMenubar, + "bloomQuality": bloomQuality, + "burnInQuality": burnInQuality, + "useCustomCommand": useCustomCommand, + "customCommand": customCommand } - return stringify(settings); + return stringify(settings) } - function composeProfileObject(){ + function composeProfileObject() { var settings = { - backgroundColor: _backgroundColor, - fontColor: _fontColor, - flickering: flickering, - horizontalSync: horizontalSync, - staticNoise: staticNoise, - chromaColor: chromaColor, - saturationColor: saturationColor, - screenCurvature: screenCurvature, - glowingLine: glowingLine, - burnIn: burnIn, - bloom: bloom, - rasterization: rasterization, - jitter: jitter, - rbgShift: rbgShift, - brightness: brightness, - contrast: contrast, - ambientLight: ambientLight, - windowOpacity: windowOpacity, - fontName: fontNames[rasterization], - fontWidth: fontWidth, - margin: _margin + "backgroundColor": _backgroundColor, + "fontColor": _fontColor, + "flickering": flickering, + "horizontalSync": horizontalSync, + "staticNoise": staticNoise, + "chromaColor": chromaColor, + "saturationColor": saturationColor, + "screenCurvature": screenCurvature, + "glowingLine": glowingLine, + "burnIn": burnIn, + "bloom": bloom, + "rasterization": rasterization, + "jitter": jitter, + "rbgShift": rbgShift, + "brightness": brightness, + "contrast": contrast, + "ambientLight": ambientLight, + "windowOpacity": windowOpacity, + "fontName": fontNames[rasterization], + "fontWidth": fontWidth, + "margin": _margin, + "blinkingCursor": blinkingCursor, + "frameMargin": _frameMargin, } - return settings; + return settings } function composeProfileString() { - return stringify(composeProfileObject()); + return stringify(composeProfileObject()) } - function loadSettings(){ - var settingsString = storage.getSetting("_CURRENT_SETTINGS"); - var profileString = storage.getSetting("_CURRENT_PROFILE"); + function loadSettings() { + var settingsString = storage.getSetting("_CURRENT_SETTINGS") + var profileString = storage.getSetting("_CURRENT_PROFILE") - if(!settingsString) return; - if(!profileString) return; + if (!settingsString) + return + if (!profileString) + return - loadSettingsString(settingsString); - loadProfileString(profileString); + loadSettingsString(settingsString) + loadProfileString(profileString) if (verbose) - console.log("Loading settings: " + settingsString + profileString); + console.log("Loading settings: " + settingsString + profileString) } - function storeSettings(){ - var settingsString = composeSettingsString(); - var profileString = composeProfileString(); + function storeSettings() { + var settingsString = composeSettingsString() + var profileString = composeProfileString() - storage.setSetting("_CURRENT_SETTINGS", settingsString); - storage.setSetting("_CURRENT_PROFILE", profileString); + storage.setSetting("_CURRENT_SETTINGS", settingsString) + storage.setSetting("_CURRENT_PROFILE", profileString) if (verbose) { - console.log("Storing settings: " + settingsString); - console.log("Storing profile: " + profileString); + console.log("Storing settings: " + settingsString) + console.log("Storing profile: " + profileString) } } - function loadSettingsString(settingsString){ - var settings = JSON.parse(settingsString); + function loadSettingsString(settingsString) { + var settings = JSON.parse(settingsString) - showTerminalSize = settings.showTerminalSize !== undefined ? settings.showTerminalSize : showTerminalSize + showTerminalSize = settings.showTerminalSize + !== undefined ? settings.showTerminalSize : showTerminalSize - fps = settings.fps !== undefined ? settings.fps: fps - windowScaling = settings.windowScaling !== undefined ? settings.windowScaling : windowScaling + fps = settings.fps !== undefined ? settings.fps : fps + windowScaling = settings.windowScaling + !== undefined ? settings.windowScaling : windowScaling x = settings.x !== undefined ? settings.x : x y = settings.y !== undefined ? settings.y : y @@ -287,398 +327,428 @@ QtObject{ fontNames = settings.fontNames !== undefined ? settings.fontNames : fontNames fontScaling = settings.fontScaling !== undefined ? settings.fontScaling : fontScaling - showMenubar = settings.showMenubar !== undefined ? settings.showMenubar : showMenubar; + showMenubar = settings.showMenubar !== undefined ? settings.showMenubar : showMenubar - bloomQuality = settings.bloomQuality !== undefined ? settings.bloomQuality : bloomQuality; - burnInQuality = settings.burnInQuality !== undefined ? settings.burnInQuality : burnInQuality; + bloomQuality = settings.bloomQuality !== undefined ? settings.bloomQuality : bloomQuality + burnInQuality = settings.burnInQuality + !== undefined ? settings.burnInQuality : burnInQuality - useCustomCommand = settings.useCustomCommand !== undefined ? settings.useCustomCommand : useCustomCommand - customCommand = settings.customCommand !== undefined ? settings.customCommand : customCommand - - useFastBurnIn = settings.useFastBurnIn !== undefined ? settings.useFastBurnIn : useFastBurnIn; + useCustomCommand = settings.useCustomCommand + !== undefined ? settings.useCustomCommand : useCustomCommand + customCommand = settings.customCommand + !== undefined ? settings.customCommand : customCommand } - function loadProfileString(profileString){ - var settings = JSON.parse(profileString); + function loadProfileString(profileString) { + var settings = JSON.parse(profileString) - _backgroundColor = settings.backgroundColor !== undefined ? settings.backgroundColor : _backgroundColor; - _fontColor = settings.fontColor !== undefined ? settings.fontColor : _fontColor; + _backgroundColor = settings.backgroundColor + !== undefined ? settings.backgroundColor : _backgroundColor + _fontColor = settings.fontColor !== undefined ? settings.fontColor : _fontColor - horizontalSync = settings.horizontalSync !== undefined ? settings.horizontalSync : horizontalSync - flickering = settings.flickering !== undefined ? settings.flickering : flickering; - staticNoise = settings.staticNoise !== undefined ? settings.staticNoise : staticNoise; - chromaColor = settings.chromaColor !== undefined ? settings.chromaColor : chromaColor; - saturationColor = settings.saturationColor !== undefined ? settings.saturationColor : saturationColor; - screenCurvature = settings.screenCurvature !== undefined ? settings.screenCurvature : screenCurvature; - glowingLine = settings.glowingLine !== undefined ? settings.glowingLine : glowingLine; + horizontalSync = settings.horizontalSync + !== undefined ? settings.horizontalSync : horizontalSync + flickering = settings.flickering !== undefined ? settings.flickering : flickering + staticNoise = settings.staticNoise !== undefined ? settings.staticNoise : staticNoise + chromaColor = settings.chromaColor !== undefined ? settings.chromaColor : chromaColor + saturationColor = settings.saturationColor + !== undefined ? settings.saturationColor : saturationColor + screenCurvature = settings.screenCurvature + !== undefined ? settings.screenCurvature : screenCurvature + glowingLine = settings.glowingLine !== undefined ? settings.glowingLine : glowingLine burnIn = settings.burnIn !== undefined ? settings.burnIn : burnIn bloom = settings.bloom !== undefined ? settings.bloom : bloom - rasterization = settings.rasterization !== undefined ? settings.rasterization : rasterization; + rasterization = settings.rasterization + !== undefined ? settings.rasterization : rasterization - jitter = settings.jitter !== undefined ? settings.jitter : jitter; + jitter = settings.jitter !== undefined ? settings.jitter : jitter - rbgShift = settings.rbgShift !== undefined ? settings.rbgShift : rbgShift; + rbgShift = settings.rbgShift !== undefined ? settings.rbgShift : rbgShift - ambientLight = settings.ambientLight !== undefined ? settings.ambientLight : ambientLight; - contrast = settings.contrast !== undefined ? settings.contrast : contrast; - brightness = settings.brightness !== undefined ? settings.brightness : brightness; - windowOpacity = settings.windowOpacity !== undefined ? settings.windowOpacity : windowOpacity; + ambientLight = settings.ambientLight !== undefined ? settings.ambientLight : ambientLight + contrast = settings.contrast !== undefined ? settings.contrast : contrast + brightness = settings.brightness !== undefined ? settings.brightness : brightness + windowOpacity = settings.windowOpacity + !== undefined ? settings.windowOpacity : windowOpacity - fontNames[rasterization] = settings.fontName !== undefined ? settings.fontName : fontNames[rasterization]; - fontWidth = settings.fontWidth !== undefined ? settings.fontWidth : fontWidth; + fontNames[rasterization] = settings.fontName + !== undefined ? settings.fontName : fontNames[rasterization] + fontWidth = settings.fontWidth !== undefined ? settings.fontWidth : fontWidth - _margin = settings.margin !== undefined ? settings.margin : _margin; + _margin = settings.margin !== undefined ? settings.margin : _margin + _frameMargin = settings.frameMargin !== undefined ? settings.frameMargin : _frameMargin - handleFontChanged(); + blinkingCursor = settings.blinkingCursor !== undefined ? settings.blinkingCursor : blinkingCursor + + handleFontChanged() } - function storeCustomProfiles(){ - storage.setSetting("_CUSTOM_PROFILES", composeCustomProfilesString()); + function storeCustomProfiles() { + storage.setSetting("_CUSTOM_PROFILES", composeCustomProfilesString()) } - function loadCustomProfiles(){ - var customProfileString = storage.getSetting("_CUSTOM_PROFILES"); - if(customProfileString === undefined) customProfileString = "[]"; - loadCustomProfilesString(customProfileString); + function loadCustomProfiles() { + var customProfileString = storage.getSetting("_CUSTOM_PROFILES") + if (customProfileString === undefined) + customProfileString = "[]" + loadCustomProfilesString(customProfileString) } - function loadCustomProfilesString(customProfilesString){ - var customProfiles = JSON.parse(customProfilesString); - for (var i=0; i<customProfiles.length; i++) { - var profile = customProfiles[i]; + function loadCustomProfilesString(customProfilesString) { + var customProfiles = JSON.parse(customProfilesString) + for (var i = 0; i < customProfiles.length; i++) { + var profile = customProfiles[i] if (verbose) - console.log("Loading custom profile: " + stringify(profile)); + console.log("Loading custom profile: " + stringify(profile)) - profilesList.append(profile); + profilesList.append(profile) } } - function composeCustomProfilesString(){ + function composeCustomProfilesString() { var customProfiles = [] - for(var i=0; i<profilesList.count; i++){ - var profile = profilesList.get(i); - if(profile.builtin) continue; - customProfiles.push({text: profile.text, obj_string: profile.obj_string, builtin: false}) + for (var i = 0; i < profilesList.count; i++) { + var profile = profilesList.get(i) + if (profile.builtin) + continue + customProfiles.push({ + "text": profile.text, + "obj_string": profile.obj_string, + "builtin": false + }) } - return stringify(customProfiles); + return stringify(customProfiles) } - function loadProfile(index){ - var profile = profilesList.get(index); - loadProfileString(profile.obj_string); + function loadProfile(index) { + var profile = profilesList.get(index) + loadProfileString(profile.obj_string) } function appendCustomProfile(name, profileString) { - profilesList.append({text: name, obj_string: profileString, builtin: false}); + profilesList.append({ + "text": name, + "obj_string": profileString, + "builtin": false + }) } // PROFILES /////////////////////////////////////////////////////////////// - - property ListModel profilesList: ListModel{ - ListElement{ + property ListModel profilesList: ListModel { + ListElement { text: "Default Amber" obj_string: '{ - "ambientLight": 0.2, - "backgroundColor": "#000000", - "bloom": 0.5538, - "brightness": 0.5, - "burnIn": 0.2517, - "chromaColor": 0.2483, - "contrast": 0.7959, - "flickering": 0.1, - "fontColor": "#ff8100", - "fontName": "TERMINUS_SCALED", - "fontWidth": 1, - "glowingLine": 0.2, - "horizontalSync": 0.08, - "jitter": 0.1997, - "rasterization": 0, - "rbgShift": 0, - "saturationColor": 0.2483, - "screenCurvature": 0.3, - "staticNoise": 0.1198, - "windowOpacity": 1, - "margin": 0.5 - }' + "ambientLight": 0.2, + "backgroundColor": "#000000", + "bloom": 0.5538, + "brightness": 0.5, + "burnIn": 0.2517, + "chromaColor": 0.2483, + "contrast": 0.7959, + "flickering": 0.1, + "fontColor": "#ff8100", + "fontName": "TERMINUS_SCALED", + "fontWidth": 1, + "glowingLine": 0.2, + "horizontalSync": 0.08, + "jitter": 0.1997, + "rasterization": 0, + "rbgShift": 0, + "saturationColor": 0.2483, + "screenCurvature": 0.3, + "staticNoise": 0.1198, + "windowOpacity": 1, + "margin": 0.5, + "blinkingCursor": false, + "frameMargin": 0.1 + }' builtin: true } - ListElement{ + ListElement { text: "Monochrome Green" - obj_string: ' - { - "ambientLight": 0.2, - "backgroundColor": "#000000", - "bloom": 0.5538, - "brightness": 0.5, - "burnIn": 0.2517, - "chromaColor": 0.0, - "contrast": 0.7959, - "flickering": 0.1, - "fontColor": "#0ccc68", - "fontName": "TERMINUS_SCALED", - "fontWidth": 1, - "glowingLine": 0.2, - "horizontalSync": 0.08, - "jitter": 0.1997, - "rasterization": 0, - "rbgShift": 0, - "saturationColor": 0.0, - "screenCurvature": 0.3, - "staticNoise": 0.1198, - "windowOpacity": 1, - "margin": 0.5 - }' + obj_string: '{ + "ambientLight": 0.2, + "backgroundColor": "#000000", + "bloom": 0.5538, + "brightness": 0.5, + "burnIn": 0.2517, + "chromaColor": 0.0, + "contrast": 0.7959, + "flickering": 0.1, + "fontColor": "#0ccc68", + "fontName": "TERMINUS_SCALED", + "fontWidth": 1, + "glowingLine": 0.2, + "horizontalSync": 0.08, + "jitter": 0.1997, + "rasterization": 0, + "rbgShift": 0, + "saturationColor": 0.0, + "screenCurvature": 0.3, + "staticNoise": 0.1198, + "windowOpacity": 1, + "margin": 0.5, + "blinkingCursor": false, + "frameMargin": 0.1 + }' builtin: true } - ListElement{ + ListElement { text: "Green Scanlines" - obj_string: ' - { - "ambientLight": 0, - "backgroundColor": "#000000", - "bloom": 0.6, - "brightness": 0.5, - "burnIn": 0.3, - "chromaColor": 0.5, - "contrast": 0.6, - "flickering": 0.1, - "fontColor": "#7cff4f", - "fontName": "PRO_FONT_SCALED", - "fontWidth": 1, - "glowingLine": 0.2, - "horizontalSync": 0.151, - "jitter": 0.11, - "rasterization": 1, - "rbgShift": 0, - "saturationColor": 0.5, - "screenCurvature": 0.3, - "staticNoise": 0.15, - "windowOpacity": 1, - "margin": 0.5 - }' + obj_string: '{ + "ambientLight": 0, + "backgroundColor": "#000000", + "bloom": 0.6, + "brightness": 0.5, + "burnIn": 0.3, + "chromaColor": 0.5, + "contrast": 0.6, + "flickering": 0.1, + "fontColor": "#7cff4f", + "fontName": "PRO_FONT_SCALED", + "fontWidth": 1, + "glowingLine": 0.2, + "horizontalSync": 0.151, + "jitter": 0.11, + "rasterization": 1, + "rbgShift": 0, + "saturationColor": 0.5, + "screenCurvature": 0.3, + "staticNoise": 0.15, + "windowOpacity": 1, + "margin": 0.5, + "blinkingCursor": false, + "frameMargin": 0.1 + }' builtin: true } - ListElement{ + ListElement { text: "Default Pixelated" - obj_string: ' - { - "ambientLight": 0, - "backgroundColor": "#000000", - "bloom": 0.4045, - "brightness": 0.6041, - "burnIn": 0.1024, - "chromaColor": 0.7517, - "contrast": 0.7473, - "flickering": 0.1962, - "fontColor": "#ffffff", - "fontName": "COMMODORE_PET", - "fontWidth": 1, - "glowingLine": 0.2, - "horizontalSync": 0.151, - "jitter": 0, - "rasterization": 2, - "rbgShift": 0, - "saturationColor": 0, - "screenCurvature": 0, - "staticNoise": 0.15, - "windowOpacity": 1, - "margin": 0.5 - }' + obj_string: '{ + "ambientLight": 0, + "backgroundColor": "#000000", + "bloom": 0.4045, + "brightness": 0.6041, + "burnIn": 0.1024, + "chromaColor": 0.7517, + "contrast": 0.7473, + "flickering": 0.1962, + "fontColor": "#ffffff", + "fontName": "COMMODORE_PET", + "fontWidth": 1, + "glowingLine": 0.2, + "horizontalSync": 0.151, + "jitter": 0, + "rasterization": 2, + "rbgShift": 0, + "saturationColor": 0, + "screenCurvature": 0, + "staticNoise": 0.15, + "windowOpacity": 1, + "margin": 0.5, + "blinkingCursor": false, + "frameMargin": 0.1 + }' builtin: true } - ListElement{ + ListElement { text: "Apple ][" - obj_string: - '{ - "ambientLight": 0.3038, - "backgroundColor": "#000000", - "bloom": 0.5, - "brightness": 0.5, - "burnIn": 0.5017, - "chromaColor": 0, - "contrast": 0.85, - "flickering": 0.2, - "fontColor": "#00d56d", - "fontName": "APPLE_II", - "fontWidth": 1, - "glowingLine": 0.22, - "horizontalSync": 0.16, - "jitter": 0.1, - "rasterization": 1, - "rbgShift": 0, - "saturationColor": 0, - "screenCurvature": 0.5, - "staticNoise": 0.099, - "windowOpacity": 1, - "margin": 0.5 - }' + obj_string: '{ + "ambientLight": 0.3038, + "backgroundColor": "#000000", + "bloom": 0.5, + "brightness": 0.5, + "burnIn": 0.5017, + "chromaColor": 0, + "contrast": 0.85, + "flickering": 0.2, + "fontColor": "#00d56d", + "fontName": "APPLE_II", + "fontWidth": 1, + "glowingLine": 0.22, + "horizontalSync": 0.16, + "jitter": 0.1, + "rasterization": 1, + "rbgShift": 0, + "saturationColor": 0, + "screenCurvature": 0.5, + "staticNoise": 0.099, + "windowOpacity": 1, + "margin": 0.5, + "blinkingCursor": false, + "frameMargin": 0.2 + }' builtin: true } - ListElement{ + ListElement { text: "Vintage" - obj_string: ' - { - "ambientLight": 0.5, - "backgroundColor": "#000000", - "bloom": 0.4983, - "brightness": 0.5014, - "burnIn": 0.4983, - "chromaColor": 0, - "contrast": 0.7473, - "flickering": 0.9, - "fontColor": "#00ff3e", - "fontName": "COMMODORE_PET", - "fontWidth": 1, - "glowingLine": 0.3, - "horizontalSync": 0.42, - "jitter": 0.4, - "rasterization": 1, - "rbgShift": 0.2969, - "saturationColor": 0, - "screenCurvature": 0.5, - "staticNoise": 0.2969, - "windowOpacity": 1, - "margin": 0.5 - }' + obj_string: '{ + "ambientLight": 0.5, + "backgroundColor": "#000000", + "bloom": 0.4983, + "brightness": 0.5014, + "burnIn": 0.4983, + "chromaColor": 0, + "contrast": 0.7473, + "flickering": 0.9, + "fontColor": "#00ff3e", + "fontName": "COMMODORE_PET", + "fontWidth": 1, + "glowingLine": 0.3, + "horizontalSync": 0.42, + "jitter": 0.4, + "rasterization": 1, + "rbgShift": 0.2969, + "saturationColor": 0, + "screenCurvature": 0.5, + "staticNoise": 0.2969, + "windowOpacity": 1, + "margin": 0.5, + "blinkingCursor": false, + "frameMargin": 0.5 + }' builtin: true } - ListElement{ + ListElement { text: "IBM Dos" - obj_string: - '{ - "ambientLight": 0.151, - "backgroundColor": "#000000", - "bloom": 0.2969, - "brightness": 0.5, - "burnIn": 0.0469, - "chromaColor": 1, - "contrast": 0.85, - "flickering": 0.0955, - "fontColor": "#ffffff", - "fontName": "IBM_DOS", - "fontWidth": 1, - "glowingLine": 0.1545, - "horizontalSync": 0, - "jitter": 0.1545, - "rasterization": 0, - "rbgShift": 0.3524, - "saturationColor": 0, - "screenCurvature": 0.4, - "staticNoise": 0.0503, - "windowOpacity": 1, - "margin": 0.5 - }' + obj_string: '{ + "ambientLight": 0.151, + "backgroundColor": "#000000", + "bloom": 0.2969, + "brightness": 0.5, + "burnIn": 0.0469, + "chromaColor": 1, + "contrast": 0.85, + "flickering": 0.0955, + "fontColor": "#ffffff", + "fontName": "IBM_DOS", + "fontWidth": 1, + "glowingLine": 0.1545, + "horizontalSync": 0, + "jitter": 0.1545, + "rasterization": 0, + "rbgShift": 0.3524, + "saturationColor": 0, + "screenCurvature": 0.4, + "staticNoise": 0.0503, + "windowOpacity": 1, + "margin": 0.5, + "blinkingCursor": false, + "frameMargin": 0.2 + }' builtin: true } - ListElement{ + ListElement { text: "IBM 3278" - obj_string: - '{ - "ambientLight": 0.1, - "backgroundColor": "#000000", - "bloom": 0.2969, - "brightness": 0.5, - "burnIn": 0.6, - "chromaColor": 0, - "contrast": 0.85, - "flickering": 0, - "fontColor": "#0ccc68", - "fontName": "IBM_3278", - "fontWidth": 1, - "glowingLine": 0, - "horizontalSync": 0, - "jitter": 0, - "rasterization": 0, - "rbgShift": 0, - "saturationColor": 0, - "screenCurvature": 0.2, - "staticNoise": 0, - "windowOpacity": 1, - "margin": 0.5 - }' + obj_string: '{ + "ambientLight": 0.1, + "backgroundColor": "#000000", + "bloom": 0.2969, + "brightness": 0.5, + "burnIn": 0.6, + "chromaColor": 0, + "contrast": 0.85, + "flickering": 0, + "fontColor": "#0ccc68", + "fontName": "IBM_3278", + "fontWidth": 1, + "glowingLine": 0, + "horizontalSync": 0, + "jitter": 0, + "rasterization": 0, + "rbgShift": 0, + "saturationColor": 0, + "screenCurvature": 0.2, + "staticNoise": 0, + "windowOpacity": 1, + "margin": 0.5, + "blinkingCursor": false, + "frameMargin": 0.1 + }' builtin: true } - ListElement{ + ListElement { text: "Futuristic" - obj_string: - '{ - "ambientLight": 0, - "backgroundColor": "#000000", - "bloom": 0.5017, - "brightness": 0.5014, - "burnIn": 0.0955, - "chromaColor": 1, - "contrast": 0.85, - "flickering": 0.2, - "fontColor": "#729fcf", - "fontName": "TERMINUS", - "fontWidth": 1, - "glowingLine": 0.1476, - "horizontalSync": 0, - "jitter": 0.099, - "rasterization": 0, - "rbgShift": 0, - "saturationColor": 0.4983, - "screenCurvature": 0, - "staticNoise": 0.0955, - "windowOpacity": 0.7, - "margin": 0.1 - }' + obj_string: '{ + "ambientLight": 0, + "backgroundColor": "#000000", + "bloom": 0.5017, + "brightness": 0.5014, + "burnIn": 0.0955, + "chromaColor": 1, + "contrast": 0.85, + "flickering": 0.2, + "fontColor": "#729fcf", + "fontName": "TERMINUS", + "fontWidth": 1, + "glowingLine": 0.1476, + "horizontalSync": 0, + "jitter": 0.099, + "rasterization": 0, + "rbgShift": 0, + "saturationColor": 0.4983, + "screenCurvature": 0, + "staticNoise": 0.0955, + "windowOpacity": 0.7, + "margin": 0.1, + "blinkingCursor": false, + "frameMargin": 0 + }' builtin: true } } function getProfileIndexByName(name) { for (var i = 0; i < profilesList.count; i++) { - if(profilesList.get(i).text === name) - return i; + if (profilesList.get(i).text === name) + return i } - return -1; + return -1 } Component.onCompleted: { // Manage the arguments from the QML side. - var args = Qt.application.arguments; + var args = Qt.application.arguments if (args.indexOf("--verbose") !== -1) { - verbose = true; + verbose = true } if (args.indexOf("--default-settings") === -1) { - loadSettings(); + loadSettings() } - loadCustomProfiles(); + loadCustomProfiles() - var profileArgPosition = args.indexOf("--profile"); + var profileArgPosition = args.indexOf("--profile") if (profileArgPosition !== -1) { - var profileIndex = getProfileIndexByName(args[profileArgPosition + 1]); + var profileIndex = getProfileIndexByName( + args[profileArgPosition + 1]) if (profileIndex !== -1) - loadProfile(profileIndex); + loadProfile(profileIndex) else - console.log("Warning: selected profile is not valid; ignoring it"); + console.log("Warning: selected profile is not valid; ignoring it") } if (args.indexOf("--fullscreen") !== -1) { - fullscreen = true; - showMenubar = false; + fullscreen = true + showMenubar = false } if (args.indexOf("-T") !== -1) { wintitle = args[args.indexOf("-T") + 1] } - initializedSettings(); + initializedSettings() } Component.onDestruction: { - storeSettings(); - storeCustomProfiles(); -// storage.dropSettings(); //DROPS THE SETTINGS!.. REMEMBER TO DISABLE ONCE ENABLED!! + storeSettings() + storeCustomProfiles() + // storage.dropSettings(); //DROPS THE SETTINGS!.. REMEMBER TO DISABLE ONCE ENABLED!! } // VARS /////////////////////////////////////////////////////////////////// - property Label _sampleLabel: Label { text: "100%" } diff --git a/app/qml/BurnInEffect.qml b/app/qml/BurnInEffect.qml index 2d4f223..6016e25 100644 --- a/app/qml/BurnInEffect.qml +++ b/app/qml/BurnInEffect.qml @@ -1,3 +1,22 @@ +/******************************************************************************* +* Copyright (c) 2013-2021 "Filippo Scognamiglio" +* https://github.com/Swordfish90/cool-retro-term +* +* This file is part of cool-retro-term. +* +* cool-retro-term is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* 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/>. +*******************************************************************************/ import QtQuick 2.0 import "utils.js" as Utils @@ -10,26 +29,29 @@ Loader { property real lastUpdate: 0 property real prevLastUpdate: 0 - property real delay: (1.0 / appSettings.fps) * 1000 property real burnIn: appSettings.burnIn property real burnInFadeTime: 1 / Utils.lint(_minBurnInFadeTime, _maxBurnInFadeTime, burnIn) property real _minBurnInFadeTime: appSettings.minBurnInFadeTime property real _maxBurnInFadeTime: appSettings.maxBurnInFadeTime - active: appSettings.useFastBurnIn && appSettings.burnIn !== 0 + active: appSettings.burnIn !== 0 anchors.fill: parent function completelyUpdate() { - prevLastUpdate = lastUpdate; - lastUpdate = timeManager.time; - item.source.scheduleUpdate(); + let newTime = timeManager.time + if (newTime > lastUpdate) { + prevLastUpdate = lastUpdate + lastUpdate = newTime + } + + item.source.scheduleUpdate() } - function restartBlurSource(){ - prevLastUpdate = timeManager.time; - lastUpdate = prevLastUpdate; - completelyUpdate(); + function restartBlurSource() { + prevLastUpdate = timeManager.time + lastUpdate = prevLastUpdate + completelyUpdate() } sourceComponent: Item { @@ -53,23 +75,37 @@ Loader { Connections { target: kterminal - onImagePainted: completelyUpdate() + + onImagePainted: { + completelyUpdate() + } } // Restart blurred source settings change. - Connections{ - target: appSettings - onBurnInChanged: burnInEffect.restartBlurSource(); - onTerminalFontChanged: burnInEffect.restartBlurSource(); - onRasterizationChanged: burnInEffect.restartBlurSource(); - onBurnInQualityChanged: burnInEffect.restartBlurSource(); - } - Connections { - target: kterminalScrollbar - onOpacityChanged: completelyUpdate() + target: appSettings + + onBurnInChanged: { + burnInEffect.restartBlurSource() + } + + onTerminalFontChanged: { + burnInEffect.restartBlurSource() + } + + onRasterizationChanged: { + burnInEffect.restartBlurSource() + } + + onBurnInQualityChanged: { + burnInEffect.restartBlurSource() + } } } + ShaderLibrary { + id: shaderLibrary + } + ShaderEffect { id: burnInShaderEffect @@ -99,9 +135,7 @@ Loader { uniform highp float prevLastUpdate;" + - "float rgb2grey(vec3 v){ - return dot(v, vec3(0.21, 0.72, 0.04)); - }" + + shaderLibrary.rgb2grey + "void main() { vec2 coords = qt_TexCoord0; diff --git a/app/qml/CRTMainMenuBar.qml b/app/qml/CRTMainMenuBar.qml deleted file mode 100644 index be5423e..0000000 --- a/app/qml/CRTMainMenuBar.qml +++ /dev/null @@ -1,51 +0,0 @@ -import QtQuick 2.2 -import QtQuick.Controls 1.1 - -MenuBar { - id: defaultMenuBar - property bool visible: true - Menu { - title: qsTr("File") - visible: defaultMenuBar.visible - MenuItem {action: quitAction} - } - Menu { - title: qsTr("Edit") - visible: defaultMenuBar.visible && appSettings.showMenubar - MenuItem {action: copyAction} - MenuItem {action: pasteAction} - MenuSeparator{visible: Qt.platform.os !== "osx"} - MenuItem {action: showsettingsAction} - } - Menu{ - title: qsTr("View") - visible: defaultMenuBar.visible - MenuItem {action: fullscreenAction; visible: fullscreenAction.enabled} - MenuItem {action: showMenubarAction; visible: showMenubarAction.enabled} - MenuSeparator{visible: showMenubarAction.enabled} - MenuItem {action: zoomIn} - MenuItem {action: zoomOut} - } - Menu{ - id: profilesMenu - title: qsTr("Profiles") - visible: defaultMenuBar.visible - Instantiator{ - model: appSettings.profilesList - delegate: MenuItem { - text: model.text - onTriggered: { - appSettings.loadProfileString(obj_string); - appSettings.handleFontChanged(); - } - } - onObjectAdded: profilesMenu.insertItem(index, object) - onObjectRemoved: profilesMenu.removeItem(object) - } - } - Menu{ - title: qsTr("Help") - visible: defaultMenuBar.visible - MenuItem {action: showAboutAction} - } -} diff --git a/app/qml/CheckableSlider.qml b/app/qml/CheckableSlider.qml index 3548a9c..d81cd41 100644 --- a/app/qml/CheckableSlider.qml +++ b/app/qml/CheckableSlider.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -17,9 +17,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ - import QtQuick 2.2 -import QtQuick.Controls 1.1 +import QtQuick.Controls 2.0 import QtQuick.Layouts 1.1 import "Components" @@ -28,46 +27,46 @@ RowLayout { property alias name: check.text property double value - property alias min_value: slider.minimumValue - property alias max_value: slider.maximumValue + property alias min_value: slider.from + property alias max_value: slider.to property alias stepSize: slider.stepSize - signal newValue(real newValue); + signal newValue(real newValue) id: setting_component Layout.fillWidth: true onValueChanged: { - check.checked = !(value == 0); - if(check.checked) - slider.value = value; + check.checked = !(value == 0) + if (check.checked) + slider.value = value } - CheckBox{ + CheckBox { id: check implicitWidth: 160 onClicked: { - if(!checked){ - checked = false; - slider.enabled = false; - newValue(0); + if (!checked) { + checked = false + slider.enabled = false + newValue(0) } else { - checked = true; - newValue(slider.value); - slider.enabled = true; + checked = true + newValue(slider.value) + slider.enabled = true } } } - Slider{ + Slider { id: slider stepSize: parent.stepSize Layout.fillWidth: true onValueChanged: { - newValue(value); + newValue(value) } } SizedLabel { - Layout.fillHeight: true - text: Math.round(((value - min_value) / (max_value - min_value)) * 100) + "%" + text: Math.round( + ((value - min_value) / (max_value - min_value)) * 100) + "%" } } diff --git a/app/qml/ColorButton.qml b/app/qml/ColorButton.qml index 3b9e1b9..a2d97e3 100644 --- a/app/qml/ColorButton.qml +++ b/app/qml/ColorButton.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -17,14 +17,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ - import QtQuick 2.2 import QtQuick.Dialogs 1.1 Item { id: rootItem - signal colorSelected (color color) + signal colorSelected(color color) property color color property string name @@ -35,15 +34,14 @@ Item { visible: false //This is a workaround to a Qt 5.2 bug. - onColorChanged: if (Qt.platform.os !== "osx") colorSelected(color) - onAccepted: if (Qt.platform.os === "osx") colorSelected(color) + onColorChanged: if (!appSettings.isMacOS) colorSelected(color) + onAccepted: if (appSettings.isMacOS) colorSelected(color) } - Rectangle{ + Rectangle { anchors.fill: parent radius: 10 color: rootItem.color - border.color: "black" - Glossy {} + Rectangle { anchors.fill: parent anchors.margins: parent.height * 0.25 @@ -51,14 +49,14 @@ Item { color: "white" opacity: 0.5 } - Text{ + Text { anchors.centerIn: parent z: parent.z + 1 text: name + ": " + rootItem.color } } - MouseArea{ + MouseArea { anchors.fill: parent - onClicked: colorDialog.visible = true; + onClicked: colorDialog.visible = true } } diff --git a/app/qml/Components/SizedLabel.qml b/app/qml/Components/SizedLabel.qml index 23a38b6..5e0a9b5 100644 --- a/app/qml/Components/SizedLabel.qml +++ b/app/qml/Components/SizedLabel.qml @@ -1,5 +1,7 @@ + + /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -17,19 +19,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ - - import QtQuick 2.0 -import QtQuick.Controls 1.0 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.0 // This component is simply a label with a predefined size. // Used to improve alignment. - -Item { - property alias text: textfield.text +Label { + id: textfield + Layout.minimumWidth: appSettings.labelWidth width: appSettings.labelWidth - Label{ - id: textfield - anchors { right: parent.right; verticalCenter: parent.verticalCenter } - } } diff --git a/app/qml/FontPixels.qml b/app/qml/FontPixels.qml index 8b96190..0978480 100644 --- a/app/qml/FontPixels.qml +++ b/app/qml/FontPixels.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -17,10 +17,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ - import QtQuick 2.2 -QtObject{ +QtObject { property int selectedFontIndex property real scaling property var _font: fontlist.get(selectedFontIndex) @@ -31,8 +30,8 @@ QtObject{ property real defaultFontWidth: fontlist.get(selectedFontIndex).fontWidth property bool lowResolutionFont: true - property ListModel fontlist: ListModel{ - ListElement{ + property ListModel fontlist: ListModel { + ListElement { name: "COMMODORE_PET" text: "Commodore PET (1977)" source: "fonts/1977-commodore-pet/PetMe.ttf" @@ -41,7 +40,7 @@ QtObject{ baseScaling: 3.5 fontWidth: 0.8 } - ListElement{ + ListElement { name: "IBM_PC" text: "IBM PC (1981)" source: "fonts/1981-ibm-pc/PxPlus_IBM_BIOS.ttf" @@ -50,7 +49,7 @@ QtObject{ baseScaling: 3.5 fontWidth: 0.8 } - ListElement{ + ListElement { name: "PROGGY_TINY" text: "Proggy Tiny (Modern)" source: "fonts/modern-proggy-tiny/ProggyTiny.ttf" @@ -59,7 +58,7 @@ QtObject{ baseScaling: 3.3 fontWidth: 0.9 } - ListElement{ + ListElement { name: "TERMINUS_SCALED" text: "Terminus (Modern)" source: "fonts/modern-terminus/TerminusTTF-4.46.0.ttf" @@ -68,7 +67,7 @@ QtObject{ baseScaling: 3.0 fontWidth: 1.0 } - ListElement{ + ListElement { name: "PRO_FONT_SCALED" text: "Pro Font (Modern)" source: "fonts/modern-pro-font-win-tweaked/ProFontWindows.ttf" @@ -77,7 +76,7 @@ QtObject{ baseScaling: 3.0 fontWidth: 1.0 } - ListElement{ + ListElement { name: "APPLE_II" text: "Apple ][ (1977)" source: "fonts/1977-apple2/PrintChar21.ttf" @@ -86,7 +85,7 @@ QtObject{ baseScaling: 3.5 fontWidth: 0.9 } - ListElement{ + ListElement { name: "ATARI_400" text: "Atari 400-800 (1979)" source: "fonts/1979-atari-400-800/AtariClassic-Regular.ttf" @@ -95,7 +94,7 @@ QtObject{ baseScaling: 3.5 fontWidth: 0.8 } - ListElement{ + ListElement { name: "COMMODORE_64" text: "Commodore 64 (1982)" source: "fonts/1982-commodore64/C64_Pro_Mono-STYLE.ttf" diff --git a/app/qml/FontScanlines.qml b/app/qml/FontScanlines.qml index c618aed..37003ed 100644 --- a/app/qml/FontScanlines.qml +++ b/app/qml/FontScanlines.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -17,10 +17,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ - import QtQuick 2.2 -QtObject{ +QtObject { property int selectedFontIndex property real scaling property var _font: fontlist.get(selectedFontIndex) @@ -31,8 +30,8 @@ QtObject{ property real defaultFontWidth: fontlist.get(selectedFontIndex).fontWidth property bool lowResolutionFont: true - property ListModel fontlist: ListModel{ - ListElement{ + property ListModel fontlist: ListModel { + ListElement { name: "COMMODORE_PET" text: "Commodore PET (1977)" source: "fonts/1977-commodore-pet/PetMe.ttf" @@ -41,7 +40,7 @@ QtObject{ baseScaling: 3.5 fontWidth: 0.7 } - ListElement{ + ListElement { name: "IBM_PC" text: "IBM PC (1981)" source: "fonts/1981-ibm-pc/PxPlus_IBM_BIOS.ttf" @@ -50,7 +49,7 @@ QtObject{ baseScaling: 3.5 fontWidth: 0.8 } - ListElement{ + ListElement { name: "PROGGY_TINY" text: "Proggy Tiny (Modern)" source: "fonts/modern-proggy-tiny/ProggyTiny.ttf" @@ -59,7 +58,7 @@ QtObject{ baseScaling: 3.3 fontWidth: 0.9 } - ListElement{ + ListElement { name: "TERMINUS_SCALED" text: "Terminus (Modern)" source: "fonts/modern-terminus/TerminusTTF-4.46.0.ttf" @@ -68,7 +67,7 @@ QtObject{ baseScaling: 3.0 fontWidth: 1.0 } - ListElement{ + ListElement { name: "PRO_FONT_SCALED" text: "Pro Font (Modern)" source: "fonts/modern-pro-font-win-tweaked/ProFontWindows.ttf" @@ -77,7 +76,7 @@ QtObject{ baseScaling: 3.0 fontWidth: 1.0 } - ListElement{ + ListElement { name: "APPLE_II" text: "Apple ][ (1977)" source: "fonts/1977-apple2/PrintChar21.ttf" @@ -86,7 +85,7 @@ QtObject{ baseScaling: 3.5 fontWidth: 0.8 } - ListElement{ + ListElement { name: "ATARI_400" text: "Atari 400-800 (1979)" source: "fonts/1979-atari-400-800/AtariClassic-Regular.ttf" @@ -95,7 +94,7 @@ QtObject{ baseScaling: 3.5 fontWidth: 0.7 } - ListElement{ + ListElement { name: "COMMODORE_64" text: "Commodore 64 (1982)" source: "fonts/1982-commodore64/C64_Pro_Mono-STYLE.ttf" diff --git a/app/qml/Fonts.qml b/app/qml/Fonts.qml index 9f10c08..1dc15aa 100644 --- a/app/qml/Fonts.qml +++ b/app/qml/Fonts.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -17,27 +17,20 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ - import QtQuick 2.2 -QtObject{ +QtObject { property int selectedFontIndex property real scaling property var source: fontlist.get(selectedFontIndex).source property var _font: fontlist.get(selectedFontIndex) property bool lowResolutionFont: _font.lowResolutionFont - property int pixelSize: lowResolutionFont - ? _font.pixelSize - : _font.pixelSize * scaling + property int pixelSize: lowResolutionFont ? _font.pixelSize : _font.pixelSize * scaling - property int lineSpacing: lowResolutionFont - ? _font.lineSpacing - : pixelSize * _font.lineSpacing + property int lineSpacing: lowResolutionFont ? _font.lineSpacing : pixelSize * _font.lineSpacing - property real screenScaling: lowResolutionFont - ? _font.baseScaling * scaling - : 1.0 + property real screenScaling: lowResolutionFont ? _font.baseScaling * scaling : 1.0 property real defaultFontWidth: fontlist.get(selectedFontIndex).fontWidth @@ -52,9 +45,8 @@ QtObject{ // High resolution fonts are instead drawn on a texture which has the // size of the screen, and the scaling directly controls their pixels size. // Those are slower to render but are not pixelated. - property ListModel fontlist: ListModel { - ListElement{ + ListElement { name: "TERMINUS_SCALED" text: "Terminus (Modern)" source: "fonts/modern-terminus/TerminusTTF-4.46.0.ttf" @@ -66,7 +58,7 @@ QtObject{ isSystemFont: false family: "" } - ListElement{ + ListElement { name: "PRO_FONT_SCALED" text: "Pro Font (Modern)" source: "fonts/modern-pro-font-win-tweaked/ProFontWindows.ttf" @@ -78,7 +70,7 @@ QtObject{ isSystemFont: false family: "" } - ListElement{ + ListElement { name: "EXCELSIOR_SCALED" text: "Fixedsys Excelsior (Modern)" source: "fonts/modern-fixedsys-excelsior/FSEX301-L2.ttf" @@ -90,7 +82,7 @@ QtObject{ isSystemFont: false family: "" } - ListElement{ + ListElement { name: "COMMODORE_PET_SCALED" text: "Commodore PET (1977)" source: "fonts/1977-commodore-pet/PetMe.ttf" @@ -102,7 +94,7 @@ QtObject{ isSystemFont: false family: "" } - ListElement{ + ListElement { name: "PROGGY_TINY_SCALED" text: "Proggy Tiny (Modern)" source: "fonts/modern-proggy-tiny/ProggyTiny.ttf" @@ -114,7 +106,7 @@ QtObject{ isSystemFont: false family: "" } - ListElement{ + ListElement { name: "APPLE_II_SCALED" text: "Apple ][ (1977)" source: "fonts/1977-apple2/PrintChar21.ttf" @@ -126,7 +118,7 @@ QtObject{ isSystemFont: false family: "" } - ListElement{ + ListElement { name: "ATARI_400_SCALED" text: "Atari 400-800 (1979)" source: "fonts/1979-atari-400-800/AtariClassic-Regular.ttf" @@ -138,7 +130,7 @@ QtObject{ isSystemFont: false family: "" } - ListElement{ + ListElement { name: "IBM_PC_SCALED" text: "IBM PC (1981)" source: "fonts/1981-ibm-pc/PxPlus_IBM_BIOS.ttf" @@ -150,7 +142,7 @@ QtObject{ isSystemFont: false family: "" } - ListElement{ + ListElement { name: "COMMODORE_64_SCALED" text: "Commodore 64 (1982)" source: "fonts/1982-commodore64/C64_Pro_Mono-STYLE.ttf" @@ -162,7 +154,7 @@ QtObject{ isSystemFont: false family: "" } - ListElement{ + ListElement { name: "IBM_DOS" text: "IBM DOS (1985)" source: "fonts/1985-ibm-pc-vga/PxPlus_IBM_VGA8.ttf" @@ -174,7 +166,7 @@ QtObject{ isSystemFont: false family: "" } - ListElement{ + ListElement { name: "HERMIT" text: "HD: Hermit (Modern)" source: "fonts/modern-hermit/Hermit-medium.otf" @@ -185,7 +177,7 @@ QtObject{ isSystemFont: false family: "" } - ListElement{ + ListElement { name: "TERMINUS" text: "HD: Terminus (Modern)" source: "fonts/modern-terminus/TerminusTTF-4.46.0.ttf" @@ -196,7 +188,7 @@ QtObject{ isSystemFont: false family: "" } - ListElement{ + ListElement { name: "PRO_FONT" text: "HD: Pro Font (Modern)" source: "fonts/modern-pro-font-win-tweaked/ProFontWindows.ttf" @@ -207,7 +199,7 @@ QtObject{ isSystemFont: false family: "" } - ListElement{ + ListElement { name: "INCONSOLATA" text: "HD: Inconsolata (Modern)" source: "fonts/modern-inconsolata/Inconsolata.otf" @@ -218,10 +210,10 @@ QtObject{ isSystemFont: false family: "" } - ListElement{ + ListElement { name: "IBM_3278" text: "HD: IBM 3278 (1971)" - source: "fonts/1971-ibm-3278/3270Medium.ttf" + source: "fonts/1971-ibm-3278/3270-Regular.ttf" lineSpacing: 0.2 pixelSize: 32 fontWidth: 1.0 @@ -234,7 +226,7 @@ QtObject{ Component.onCompleted: addSystemFonts() function addSystemFonts() { - var families = monospaceSystemFonts; + var families = monospaceSystemFonts for (var i = 0; i < families.length; i++) { if (verbose) { console.log("Adding system font: ", families[i]) @@ -245,16 +237,16 @@ QtObject{ function convertToListElement(family) { return { - name: "System: " + family, - text: qsTr("System: ") + family, - source: "", - lineSpacing: 0.1, - pixelSize: 30, - fontWidth: 1.0, - baseScaling: 1.0, - lowResolutionFont: false, - isSystemFont: true, - family: family + "name": "System: " + family, + "text": qsTr("System: ") + family, + "source": "", + "lineSpacing": 0.1, + "pixelSize": 30, + "fontWidth": 1.0, + "baseScaling": 1.0, + "lowResolutionFont": false, + "isSystemFont": true, + "family": family } } } diff --git a/app/qml/Glossy.qml b/app/qml/Glossy.qml deleted file mode 100644 index 3ac9c14..0000000 --- a/app/qml/Glossy.qml +++ /dev/null @@ -1,21 +0,0 @@ -import QtQuick 2.2 - -Rectangle { - anchors.centerIn: parent - width: parent.width - parent.border.width - height: parent.height - parent.border.width - radius:parent.radius - parent.border.width/2 - smooth: true - - border.width: parent.border.width/2 - border.color: "#22FFFFFF" - - gradient: Gradient { - GradientStop { position: 0; color: "#88FFFFFF" } - GradientStop { position: .1; color: "#55FFFFFF" } - GradientStop { position: .5; color: "#33FFFFFF" } - GradientStop { position: .501; color: "#11000000" } - GradientStop { position: .8; color: "#11FFFFFF" } - GradientStop { position: 1; color: "#55FFFFFF" } - } -} diff --git a/app/qml/InsertNameDialog.qml b/app/qml/InsertNameDialog.qml index 22d31f7..fb4d7e9 100644 --- a/app/qml/InsertNameDialog.qml +++ b/app/qml/InsertNameDialog.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -17,14 +17,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ - import QtQuick 2.2 import QtQuick.Window 2.0 -import QtQuick.Controls 1.1 +import QtQuick.Controls 2.0 import QtQuick.Layouts 1.1 import QtQuick.Dialogs 1.1 -Window{ +Window { id: insertnamedialog width: 400 height: 100 @@ -39,50 +38,53 @@ Window{ title: qsTr("Error") visible: false - function showError(message){ - text = message; - open(); + function showError(message) { + text = message + open() } } - function validateName(name){ - var profile_list = appSettings.profilesList; + function validateName(name) { + var profile_list = appSettings.profilesList if (name === "") - return 1; - return 0; + return 1 + return 0 } - ColumnLayout{ + ColumnLayout { anchors.margins: 10 anchors.fill: parent - RowLayout{ - Label{text: qsTr("Name")} - TextField{ + RowLayout { + Label { + text: qsTr("Name") + } + TextField { id: namefield Layout.fillWidth: true Component.onCompleted: forceActiveFocus() onAccepted: okbutton.clickAction() } } - RowLayout{ + RowLayout { Layout.alignment: Qt.AlignBottom | Qt.AlignRight - Button{ + Button { id: okbutton text: qsTr("OK") onClicked: clickAction() - function clickAction(){ - var name = namefield.text; - switch(validateName(name)){ + function clickAction() { + var name = namefield.text + switch (validateName(name)) { case 1: - errorDialog.showError(qsTr("The name you inserted is empty. Please choose a different one.")); - break; + errorDialog.showError( + qsTr("The name you inserted is empty. Please choose a different one.")) + break default: - nameSelected(name); - close(); + nameSelected(name) + close() } } } - Button{ + Button { text: qsTr("Cancel") onClicked: close() } diff --git a/app/qml/NewTerminalFrame.qml b/app/qml/NewTerminalFrame.qml deleted file mode 100644 index f7b1669..0000000 --- a/app/qml/NewTerminalFrame.qml +++ /dev/null @@ -1,78 +0,0 @@ -import QtQuick 2.0 - -import "utils.js" as Utils - -ShaderEffect { - property color _staticFrameColor: "#ffffff" - property color _backgroundColor: appSettings.backgroundColor - property color _fontColor: appSettings.fontColor - property color _lightColor: Utils.mix(_fontColor, _backgroundColor, 0.2) - property real _ambientLight: Utils.lint(0.2, 0.8, appSettings.ambientLight) - - property color frameColor: Utils.mix(_staticFrameColor, _lightColor, _ambientLight) - property real screenCurvature: appSettings.screenCurvature * appSettings.screenCurvatureSize - property real shadowLength: 0.5 * screenCurvature * Utils.lint(0.50, 1.5, _ambientLight) - - property size aadelta: Qt.size(1.0 / width, 1.0 / height) - - fragmentShader: " - #ifdef GL_ES - precision mediump float; - #endif - - uniform lowp float screenCurvature; - uniform lowp float shadowLength; - uniform highp float qt_Opacity; - uniform lowp vec4 frameColor; - uniform mediump vec2 aadelta; - - varying highp vec2 qt_TexCoord0; - - vec2 distortCoordinates(vec2 coords){ - vec2 cc = (coords - vec2(0.5)); - float dist = dot(cc, cc) * screenCurvature; - return (coords + cc * (1.0 + dist) * dist); - } - - float max2(vec2 v) { - return max(v.x, v.y); - } - - float min2(vec2 v) { - return min(v.x, v.y); - } - - float prod2(vec2 v) { - return v.x * v.y; - } - - float sum2(vec2 v) { - return v.x + v.y; - } - - void main(){ - vec2 staticCoords = qt_TexCoord0; - vec2 coords = distortCoordinates(staticCoords); - - vec3 color = vec3(0.0); - float alpha = 0.0; - - float outShadowLength = shadowLength; - float inShadowLength = shadowLength * 0.5; - - float outShadow = max2(1.0 - smoothstep(vec2(-outShadowLength), vec2(0.0), coords) + smoothstep(vec2(1.0), vec2(1.0 + outShadowLength), coords)); - outShadow = clamp(sqrt(outShadow), 0.0, 1.0); - color += frameColor.rgb * outShadow; - alpha = sum2(1.0 - smoothstep(vec2(0.0), aadelta, coords) + smoothstep(vec2(1.0) - aadelta, vec2(1.0), coords)); - alpha = clamp(alpha, 0.0, 1.0) * mix(1.0, 0.9, outShadow); - - float inShadow = 1.0 - prod2(smoothstep(0.0, inShadowLength, coords) - smoothstep(1.0 - inShadowLength, 1.0, coords)); - inShadow = 0.5 * inShadow * inShadow; - alpha = max(alpha, inShadow); - - gl_FragColor = vec4(color * alpha, alpha); - } - " - - onStatusChanged: if (log) console.log(log) //Print warning messages -} diff --git a/app/qml/PreprocessedTerminal.qml b/app/qml/PreprocessedTerminal.qml index d0d9cee..916ae5b 100644 --- a/app/qml/PreprocessedTerminal.qml +++ b/app/qml/PreprocessedTerminal.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -19,10 +19,11 @@ *******************************************************************************/ import QtQuick 2.2 -import QtQuick.Controls 1.1 +import QtQuick.Controls 2.0 import QMLTermWidget 1.0 +import "menus" import "utils.js" as Utils Item{ @@ -33,7 +34,6 @@ Item{ property ShaderEffectSource mainSource: kterminalSource property BurnInEffect burnInEffect: burnInEffect - property SlowBurnIn slowBurnInEffect: slowBurnInEffect property real fontWidth: 1.0 property real screenScaling: 1.0 property real scaleTexture: 1.0 @@ -44,35 +44,61 @@ Item{ property size fontMetrics: kterminal.fontMetrics // Manage copy and paste - Connections{ + Connections { target: copyAction - onTriggered: kterminal.copyClipboard(); + + onTriggered: { + kterminal.copyClipboard() + } } - Connections{ + Connections { target: pasteAction - onTriggered: kterminal.pasteClipboard() + + onTriggered: { + kterminal.pasteClipboard() + } } //When settings are updated sources need to be redrawn. - Connections{ + Connections { target: appSettings - onFontScalingChanged: terminalContainer.updateSources(); - onFontWidthChanged: terminalContainer.updateSources(); + + onFontScalingChanged: { + terminalContainer.updateSources() + } + + onFontWidthChanged: { + terminalContainer.updateSources() + } } - Connections{ + Connections { target: terminalContainer - onWidthChanged: terminalContainer.updateSources(); - onHeightChanged: terminalContainer.updateSources(); + + onWidthChanged: { + terminalContainer.updateSources() + } + + onHeightChanged: { + terminalContainer.updateSources() + } } + Connections { + target: terminalWindow + + onActiveChanged: { + kterminal.forceActiveFocus() + } + } + function updateSources() { - kterminal.update(); + kterminal.update() } QMLTermWidget { id: kterminal property int textureResolutionScale: appSettings.lowResolutionFont ? devicePixelRatio : 1 - property int margin: appSettings.margin / screenScaling + property int margin: appSettings.totalMargin / screenScaling property int totalWidth: Math.floor(parent.width / (screenScaling * fontWidth)) property int totalHeight: Math.floor(parent.height / screenScaling) @@ -94,6 +120,7 @@ Item{ smooth: !appSettings.lowResolutionFont enableBold: false fullCursorHeight: true + blinkingCursor: appSettings.blinkingCursor session: QMLTermSession { id: ksession @@ -141,7 +168,7 @@ Item{ var args = Utils.tokenizeCommandLine(appSettings.customCommand); ksession.setShellProgram(args[0]); ksession.setArgs(args.slice(1)); - } else if (!defaultCmd && Qt.platform.os === "osx") { + } else if (!defaultCmd && appSettings.isMacOS) { // OSX Requires the following default parameters for auto login. ksession.setArgs(["-i", "-l"]); } @@ -155,36 +182,28 @@ Item{ Component.onCompleted: { appSettings.terminalFontChanged.connect(handleFontChanged); appSettings.initializedSettings.connect(startSession); + appSettings.handleFontChanged() } } + Component { - id: linuxContextMenu - Menu{ - id: contextmenu - MenuItem { action: copyAction } - MenuItem { action: pasteAction } - MenuSeparator { visible: !appSettings.showMenubar } - MenuItem { action: showsettingsAction ; visible: !appSettings.showMenubar} - MenuSeparator { visible: !appSettings.showMenubar } - CRTMainMenuBar { visible: !appSettings.showMenubar } - } + id: shortContextMenu + ShortContextMenu { } } + Component { - id: osxContextMenu - Menu{ - id: contextmenu - MenuItem{action: copyAction} - MenuItem{action: pasteAction} - } + id: fullContextMenu + FullContextMenu { } } + Loader { id: menuLoader - sourceComponent: (Qt.platform.os === "osx" ? osxContextMenu : linuxContextMenu) + sourceComponent: (appSettings.isMacOS || appSettings.showMenubar ? shortContextMenu : fullContextMenu) } property alias contextmenu: menuLoader.item - MouseArea{ - property real margin: appSettings.margin + MouseArea { + property real margin: appSettings.totalMargin acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton anchors.fill: parent @@ -225,8 +244,8 @@ Item{ var cc = Qt.size(0.5 - x, 0.5 - y); var distortion = (cc.height * cc.height + cc.width * cc.width) * appSettings.screenCurvature * appSettings.screenCurvatureSize; - return Qt.point((x - cc.width * (1+distortion) * distortion) * kterminal.totalWidth, - (y - cc.height * (1+distortion) * distortion) * kterminal.totalHeight) + return Qt.point((x - cc.width * (1+distortion) * distortion) * (kterminal.totalWidth), + (y - cc.height * (1+distortion) * distortion) * (kterminal.totalHeight)) } } ShaderEffectSource{ @@ -256,9 +275,5 @@ Item{ BurnInEffect { id: burnInEffect } - - SlowBurnIn { - id: slowBurnInEffect - } } } diff --git a/app/qml/SettingsAdvancedTab.qml b/app/qml/SettingsAdvancedTab.qml index c0d486a..0adf851 100644 --- a/app/qml/SettingsAdvancedTab.qml +++ b/app/qml/SettingsAdvancedTab.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -17,129 +17,143 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ - import QtQuick 2.2 -import QtQuick.Controls 1.1 +import QtQuick.Controls 2.0 import QtQuick.Layouts 1.1 +import QtQml 2.0 import "Components" -Tab{ - ColumnLayout{ - anchors.fill: parent +ColumnLayout { + GroupBox { + Layout.fillWidth: true + title: qsTr("Command") - GroupBox{ - Layout.fillWidth: true - title: qsTr("Command") - ColumnLayout { - anchors.fill: parent - CheckBox{ - id: useCustomCommand - text: qsTr("Use custom command instead of shell at startup") - 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 - text: appSettings.customCommand - enabled: useCustomCommand.checked - onEditingFinished: appSettings.customCommand = text + ColumnLayout { + anchors.fill: parent + CheckBox { + id: useCustomCommand + text: qsTr("Use custom command instead of shell at startup") + 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 + text: appSettings.customCommand + enabled: useCustomCommand.checked + onEditingFinished: appSettings.customCommand = text - // Save text even if user forgets to press enter or unfocus - function saveSetting() { - appSettings.customCommand = text; - } - Component.onCompleted: settings_window.closing.connect(saveSetting) + // Save text even if user forgets to press enter or unfocus + function saveSetting() { + appSettings.customCommand = text } + Component.onCompleted: settings_window.closing.connect( + saveSetting) } } + } - GroupBox{ - title: qsTr("Performance") - Layout.fillWidth: true - GridLayout{ - anchors.fill: parent - rows: 2 - columns: 3 + GroupBox { + title: qsTr("Performance") + Layout.fillWidth: true + GridLayout { + anchors.fill: parent + columns: 4 - Label{text: qsTr("Effects FPS")} - Slider{ - Layout.fillWidth: true - id: fpsSlider - onValueChanged: { - if (enabled) { - appSettings.fps = value !== 60 ? value + 1 : 0; - } - } - stepSize: 1 - enabled: false - Component.onCompleted: { - minimumValue = 0; - maximumValue = 60; - value = appSettings.fps !== 0 ? appSettings.fps - 1 : 60; - enabled = true; + Label { + text: qsTr("Effects FPS") + } + Slider { + Layout.fillWidth: true + Layout.columnSpan: 2 + id: fpsSlider + onValueChanged: { + if (enabled) { + appSettings.fps = value !== 60 ? value + 1 : 0 } } + stepSize: 1 + enabled: false + Component.onCompleted: { + from = 0 + to = 60 + value = appSettings.fps !== 0 ? appSettings.fps - 1 : 60 + enabled = true + } + } - SizedLabel{text: appSettings.fps !== 0 ? appSettings.fps : qsTr("Max")} - Label{text: qsTr("Texture Quality")} - Slider{ - Layout.fillWidth: true - id: txtslider - onValueChanged: if (enabled) appSettings.windowScaling = value; - stepSize: 0.05 - enabled: false - Component.onCompleted: { - minimumValue = 0.25 //Without this value gets set to 0.5 - value = appSettings.windowScaling; - enabled = true; - } + SizedLabel { + text: appSettings.fps !== 0 ? appSettings.fps : qsTr("Max") + } + Label { + text: qsTr("Texture Quality") + } + Slider { + id: txtslider + Layout.fillWidth: true + Layout.columnSpan: 2 + onValueChanged: if (enabled) + appSettings.windowScaling = value + stepSize: 0.05 + enabled: false + Component.onCompleted: { + from = 0.25 //Without this value gets set to 0.5 + value = appSettings.windowScaling + enabled = true } - SizedLabel{text: Math.round(txtslider.value * 100) + "%"} + } + SizedLabel { + text: Math.round(txtslider.value * 100) + "%" + } - Label{text: qsTr("Bloom Quality")} - Slider{ - Layout.fillWidth: true - id: bloomSlider - onValueChanged: if (enabled) appSettings.bloomQuality = value; - stepSize: 0.05 - enabled: false - Component.onCompleted: { - minimumValue = 0.25 - value = appSettings.bloomQuality; - enabled = true; - } + Label { + text: qsTr("Bloom Quality") + } + Slider { + Layout.fillWidth: true + Layout.columnSpan: 2 + id: bloomSlider + onValueChanged: if (enabled) + appSettings.bloomQuality = value + stepSize: 0.05 + enabled: false + Component.onCompleted: { + from = 0.25 + value = appSettings.bloomQuality + enabled = true } - SizedLabel{text: Math.round(bloomSlider.value * 100) + "%"} + } + SizedLabel { + text: Math.round(bloomSlider.value * 100) + "%" + } - Label{text: qsTr("BurnIn Quality")} - Slider{ - Layout.fillWidth: true - id: burnInSlider - onValueChanged: if (enabled) appSettings.burnInQuality = value; - stepSize: 0.05 - enabled: false - Component.onCompleted: { - minimumValue = 0.25 - value = appSettings.burnInQuality; - enabled = true; - } - } - SizedLabel{text: Math.round(burnInSlider.value * 100) + "%"} - CheckBox{ - Layout.columnSpan: 2 - text: qsTr("Burnin optimization (Might display timing artifacts)") - checked: appSettings.useFastBurnIn - onCheckedChanged: appSettings.useFastBurnIn = checked + Label { + text: qsTr("BurnIn Quality") + } + Slider { + Layout.fillWidth: true + id: burnInSlider + Layout.columnSpan: 2 + onValueChanged: if (enabled) + appSettings.burnInQuality = value + stepSize: 0.05 + enabled: false + Component.onCompleted: { + from = 0.25 + value = appSettings.burnInQuality + enabled = true } } + SizedLabel { + text: Math.round(burnInSlider.value * 100) + "%" + } } } } diff --git a/app/qml/SettingsEffectsTab.qml b/app/qml/SettingsEffectsTab.qml index c14ede2..9c97e55 100644 --- a/app/qml/SettingsEffectsTab.qml +++ b/app/qml/SettingsEffectsTab.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -17,74 +17,70 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ - import QtQuick 2.2 -import QtQuick.Controls 1.1 +import QtQuick.Controls 2.0 import QtQuick.Layouts 1.1 -Tab{ - ColumnLayout{ - anchors.fill: parent - spacing: 2 +ColumnLayout { + spacing: 2 - GroupBox{ - title: qsTr("Effects") - Layout.fillWidth: true + GroupBox { + title: qsTr("Effects") + Layout.fillWidth: true - ColumnLayout { - anchors.fill: parent + ColumnLayout { + anchors.fill: parent - CheckableSlider{ - name: qsTr("Bloom") - onNewValue: appSettings.bloom = newValue - value: appSettings.bloom - } - CheckableSlider{ - name: qsTr("BurnIn") - onNewValue: appSettings.burnIn = newValue - value: appSettings.burnIn - } - CheckableSlider{ - name: qsTr("Static Noise") - onNewValue: appSettings.staticNoise = newValue - value: appSettings.staticNoise - } - CheckableSlider{ - name: qsTr("Jitter") - onNewValue: appSettings.jitter = newValue - value: appSettings.jitter - } - CheckableSlider{ - name: qsTr("Glow Line") - onNewValue: appSettings.glowingLine = newValue; - value: appSettings.glowingLine - } - CheckableSlider{ - name: qsTr("Screen Curvature") - onNewValue: appSettings.screenCurvature = newValue; - value: appSettings.screenCurvature; - } - CheckableSlider{ - name: qsTr("Ambient Light") - onNewValue: appSettings.ambientLight = newValue; - value: appSettings.ambientLight - enabled: appSettings.framesIndex !== 0 - } - CheckableSlider{ - name: qsTr("Flickering") - onNewValue: appSettings.flickering = newValue; - value: appSettings.flickering; - } - CheckableSlider{ - name: qsTr("Horizontal Sync") - onNewValue: appSettings.horizontalSync = newValue; - value: appSettings.horizontalSync; - } - CheckableSlider{ - name: qsTr("RGB Shift") - onNewValue: appSettings.rbgShift = newValue; - value: appSettings.rbgShift; - } + CheckableSlider { + name: qsTr("Bloom") + onNewValue: appSettings.bloom = newValue + value: appSettings.bloom + } + CheckableSlider { + name: qsTr("BurnIn") + onNewValue: appSettings.burnIn = newValue + value: appSettings.burnIn + } + CheckableSlider { + name: qsTr("Static Noise") + onNewValue: appSettings.staticNoise = newValue + value: appSettings.staticNoise + } + CheckableSlider { + name: qsTr("Jitter") + onNewValue: appSettings.jitter = newValue + value: appSettings.jitter + } + CheckableSlider { + name: qsTr("Glow Line") + onNewValue: appSettings.glowingLine = newValue + value: appSettings.glowingLine + } + CheckableSlider { + name: qsTr("Screen Curvature") + onNewValue: appSettings.screenCurvature = newValue + value: appSettings.screenCurvature + } + CheckableSlider { + name: qsTr("Ambient Light") + onNewValue: appSettings.ambientLight = newValue + value: appSettings.ambientLight + enabled: appSettings.framesIndex !== 0 + } + CheckableSlider { + name: qsTr("Flickering") + onNewValue: appSettings.flickering = newValue + value: appSettings.flickering + } + CheckableSlider { + name: qsTr("Horizontal Sync") + onNewValue: appSettings.horizontalSync = newValue + value: appSettings.horizontalSync + } + CheckableSlider { + name: qsTr("RGB Shift") + onNewValue: appSettings.rbgShift = newValue + value: appSettings.rbgShift } } } diff --git a/app/qml/SettingsGeneralTab.qml b/app/qml/SettingsGeneralTab.qml index 9efaedb..40fbc0d 100644 --- a/app/qml/SettingsGeneralTab.qml +++ b/app/qml/SettingsGeneralTab.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -17,218 +17,252 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ - import QtQuick 2.2 -import QtQuick.Controls 1.1 +import QtQuick.Controls 2.4 import QtQuick.Layouts 1.1 import QtQuick.Dialogs 1.1 -Tab{ - ColumnLayout{ - anchors.fill: parent - GroupBox{ - Layout.fillWidth: true - Layout.fillHeight: true - title: qsTr("Profile") - RowLayout { - anchors.fill: parent - TableView { - id: profilesView +ColumnLayout { + GroupBox { + Layout.fillWidth: true + title: qsTr("Profile") + RowLayout { + anchors.fill: parent + ListView { + id: profilesView + Layout.fillWidth: true + Layout.fillHeight: true + model: appSettings.profilesList + clip: true + delegate: Rectangle { + width: label.width + height: label.height + color: (index == profilesView.currentIndex) ? palette.highlight : palette.base + Label { + id: label + text: appSettings.profilesList.get(index).text + MouseArea { + anchors.fill: parent + onClicked: profilesView.currentIndex = index + onDoubleClicked: appSettings.loadProfile(index) + } + } + } + } + ColumnLayout { + Layout.fillHeight: true + Layout.fillWidth: false + Button { Layout.fillWidth: true + text: qsTr("Save") + onClicked: { + insertname.profileName = "" + insertname.show() + } + } + Button { + Layout.fillWidth: true + property alias currentIndex: profilesView.currentIndex + enabled: currentIndex >= 0 + text: qsTr("Load") + onClicked: { + var index = currentIndex + if (index >= 0) + appSettings.loadProfile(index) + } + } + Button { + Layout.fillWidth: true + text: qsTr("Remove") + property alias currentIndex: profilesView.currentIndex + + enabled: currentIndex >= 0 && !appSettings.profilesList.get( + currentIndex).builtin + onClicked: { + appSettings.profilesList.remove(currentIndex) + profilesView.selection.clear() + + // TODO This is a very ugly workaround. The view didn't update on Qt 5.3.2. + profilesView.model = 0 + profilesView.model = appSettings.profilesList + } + } + Item { + // Spacing Layout.fillHeight: true - model: appSettings.profilesList - headerVisible: false - TableViewColumn { - title: qsTr("Profile") - role: "text" - width: parent.width * 0.5 - } - onActivated: { - appSettings.loadProfile(row); - } } - ColumnLayout { - Layout.fillHeight: true - Layout.fillWidth: false - Button{ - Layout.fillWidth: true - text: qsTr("Save") - onClicked: { - insertname.profileName = ""; - insertname.show() + Button { + Layout.fillWidth: true + text: qsTr("Import") + onClicked: { + fileDialog.selectExisting = true + fileDialog.callBack = function (url) { + loadFile(url) } + fileDialog.open() } - Button{ - Layout.fillWidth: true - property alias currentIndex: profilesView.currentRow - enabled: currentIndex >= 0 - text: qsTr("Load") - onClicked: { - var index = profilesView.currentRow; - if (index >= 0) - appSettings.loadProfile(index); - } - } - Button{ - Layout.fillWidth: true - text: qsTr("Remove") - property alias currentIndex: profilesView.currentRow + function loadFile(url) { + try { + if (appSettings.verbose) + console.log("Loading file: " + url) - enabled: currentIndex >= 0 && !appSettings.profilesList.get(currentIndex).builtin - onClicked: { - appSettings.profilesList.remove(currentIndex); - profilesView.selection.clear(); + var profileObject = JSON.parse(fileIO.read(url)) + var name = profileObject.name - // TODO This is a very ugly workaround. The view didn't update on Qt 5.3.2. - profilesView.model = 0; - profilesView.model = appSettings.profilesList; - } - } - Item { - // Spacing - Layout.fillHeight: true - } - Button{ - Layout.fillWidth: true - text: qsTr("Import") - onClicked: { - fileDialog.selectExisting = true; - fileDialog.callBack = function (url) {loadFile(url);}; - fileDialog.open(); - } - function loadFile(url) { - try { - if (appSettings.verbose) - console.log("Loading file: " + url); + if (!name) + throw "Profile doesn't have a name" - var profileObject = JSON.parse(fileIO.read(url)); - var name = profileObject.name; + var version = profileObject.version + !== undefined ? profileObject.version : 1 + if (version !== appSettings.profileVersion) + throw "This profile is not supported on this version of CRT." - if (!name) - throw "Profile doesn't have a name"; + delete profileObject.name - var version = profileObject.version !== undefined ? profileObject.version : 1; - if (version !== appSettings.profileVersion) - throw "This profile is not supported on this version of CRT."; - - delete profileObject.name; - - appSettings.appendCustomProfile(name, JSON.stringify(profileObject)); - } catch (err) { - messageDialog.text = qsTr(err) - messageDialog.open(); - } - } - } - Button{ - property alias currentIndex: profilesView.currentRow - - Layout.fillWidth: true - - text: qsTr("Export") - enabled: currentIndex >= 0 && !appSettings.profilesList.get(currentIndex).builtin - onClicked: { - fileDialog.selectExisting = false; - fileDialog.callBack = function (url) {storeFile(url);}; - fileDialog.open(); - } - function storeFile(url) { - try { - var urlString = url.toString(); - - // Fix the extension if it's missing. - var extension = urlString.substring(urlString.length - 5, urlString.length); - var urlTail = (extension === ".json" ? "" : ".json"); - url += urlTail; - - if (true) - console.log("Storing file: " + url); - - var profileObject = appSettings.profilesList.get(currentIndex); - var profileSettings = JSON.parse(profileObject.obj_string); - profileSettings["name"] = profileObject.text; - profileSettings["version"] = appSettings.profileVersion; - - var result = fileIO.write(url, JSON.stringify(profileSettings, undefined, 2)); - if (!result) - throw "The file could not be written."; - } catch (err) { - console.log(err); - messageDialog.text = qsTr("There has been an error storing the file.") - messageDialog.open(); - } + appSettings.appendCustomProfile(name, + JSON.stringify( + profileObject)) + } catch (err) { + messageDialog.text = qsTr(err) + messageDialog.open() } } } - } - } + Button { + property alias currentIndex: profilesView.currentIndex - GroupBox{ - title: qsTr("Screen") - Layout.fillWidth: true - GridLayout{ - anchors.fill: parent - columns: 2 - Label{ text: qsTr("Brightness") } - SimpleSlider{ - onValueChanged: appSettings.brightness = value - value: appSettings.brightness + Layout.fillWidth: true + + text: qsTr("Export") + enabled: currentIndex >= 0 && !appSettings.profilesList.get( + currentIndex).builtin + onClicked: { + fileDialog.selectExisting = false + fileDialog.callBack = function (url) { + storeFile(url) + } + fileDialog.open() + } + function storeFile(url) { + try { + var urlString = url.toString() + + // Fix the extension if it's missing. + var extension = urlString.substring( + urlString.length - 5, urlString.length) + var urlTail = (extension === ".json" ? "" : ".json") + url += urlTail + + if (true) + console.log("Storing file: " + url) + + var profileObject = appSettings.profilesList.get( + currentIndex) + var profileSettings = JSON.parse( + profileObject.obj_string) + profileSettings["name"] = profileObject.text + profileSettings["version"] = appSettings.profileVersion + + var result = fileIO.write(url, JSON.stringify( + profileSettings, + undefined, 2)) + if (!result) + throw "The file could not be written." + } catch (err) { + console.log(err) + messageDialog.text = qsTr( + "There has been an error storing the file.") + messageDialog.open() + } + } } - Label{ text: qsTr("Contrast") } - SimpleSlider{ - onValueChanged: appSettings.contrast = value - value: appSettings.contrast - } - Label{ text: qsTr("Margin") } - SimpleSlider{ - onValueChanged: appSettings._margin = value - value: appSettings._margin - } - Label{ text: qsTr("Opacity") } - SimpleSlider{ - onValueChanged: appSettings.windowOpacity = value - value: appSettings.windowOpacity - } - } - } - - // DIALOGS //////////////////////////////////////////////////////////////// - InsertNameDialog{ - id: insertname - onNameSelected: { - appSettings.appendCustomProfile(name, appSettings.composeProfileString()); - } - } - MessageDialog { - id: messageDialog - title: qsTr("File Error") - onAccepted: { - messageDialog.close(); - } - } - Loader { - property var callBack - property bool selectExisting: false - id: fileDialog - - sourceComponent: FileDialog{ - nameFilters: ["Json files (*.json)"] - selectMultiple: false - selectFolder: false - selectExisting: fileDialog.selectExisting - onAccepted: callBack(fileUrl); - } - - onSelectExistingChanged: reload() - - function open() { - item.open(); - } - - function reload() { - active = false; - active = true; } } } + + GroupBox { + title: qsTr("Screen") + Layout.fillWidth: true + GridLayout { + anchors.fill: parent + columns: 2 + Label { + text: qsTr("Brightness") + } + SimpleSlider { + onValueChanged: appSettings.brightness = value + value: appSettings.brightness + } + Label { + text: qsTr("Contrast") + } + SimpleSlider { + onValueChanged: appSettings.contrast = value + value: appSettings.contrast + } + Label { + text: qsTr("Margin") + } + SimpleSlider { + onValueChanged: appSettings._margin = value + value: appSettings._margin + } + Label { + text: qsTr("Frame size") + } + SimpleSlider { + onValueChanged: appSettings._frameMargin = value + value: appSettings._frameMargin + } + Label { + text: qsTr("Opacity") + visible: !appSettings.isMacOS + } + SimpleSlider { + onValueChanged: appSettings.windowOpacity = value + value: appSettings.windowOpacity + visible: !appSettings.isMacOS + } + } + } + + // DIALOGS //////////////////////////////////////////////////////////////// + InsertNameDialog { + id: insertname + onNameSelected: { + appSettings.appendCustomProfile(name, + appSettings.composeProfileString()) + } + } + MessageDialog { + id: messageDialog + title: qsTr("File Error") + onAccepted: { + messageDialog.close() + } + } + Loader { + property var callBack + property bool selectExisting: false + id: fileDialog + + sourceComponent: FileDialog { + nameFilters: ["Json files (*.json)"] + selectMultiple: false + selectFolder: false + selectExisting: fileDialog.selectExisting + onAccepted: callBack(fileUrl) + } + + onSelectExistingChanged: reload() + + function open() { + item.open() + } + + function reload() { + active = false + active = true + } + } } diff --git a/app/qml/SettingsTerminalTab.qml b/app/qml/SettingsTerminalTab.qml index 8cefdb8..222ea78 100644 --- a/app/qml/SettingsTerminalTab.qml +++ b/app/qml/SettingsTerminalTab.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -17,138 +17,154 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ - import QtQuick 2.2 -import QtQuick.Controls 1.1 +import QtQuick.Controls 2.1 import QtQuick.Layouts 1.1 +import QtQml 2.0 import "Components" -Tab{ - ColumnLayout{ - anchors.fill: parent +ColumnLayout { - GroupBox{ - title: qsTr("Font") - Layout.fillWidth: true - GridLayout{ - anchors.fill: parent - columns: 2 - Label { text: qsTr("Rasterization") } - ComboBox { - id: rasterizationBox + GroupBox { + title: qsTr("Font") + Layout.fillWidth: true + GridLayout { + anchors.fill: parent + columns: 2 + Label { + text: qsTr("Rasterization") + } + ComboBox { + id: rasterizationBox - property string selectedElement: model[currentIndex] + property string selectedElement: model[currentIndex] - Layout.fillWidth: true - model: [qsTr("Default"), qsTr("Scanlines"), qsTr("Pixels")] - currentIndex: appSettings.rasterization - onCurrentIndexChanged: { - appSettings.rasterization = currentIndex + Layout.fillWidth: true + model: [qsTr("Default"), qsTr("Scanlines"), qsTr("Pixels"), qsTr("Sub-Pixels")] + currentIndex: appSettings.rasterization + onCurrentIndexChanged: { + appSettings.rasterization = currentIndex + } + } + Label { + text: qsTr("Name") + } + ComboBox { + id: fontChanger + Layout.fillWidth: true + model: appSettings.fontlist + textRole: "text" + onActivated: { + var name = appSettings.fontlist.get(index).name + appSettings.fontNames[appSettings.rasterization] = name + appSettings.handleFontChanged() + } + function updateIndex() { + var name = appSettings.fontNames[appSettings.rasterization] + var index = appSettings.getIndexByName(name) + if (index !== undefined) + currentIndex = index + } + Connections { + target: appSettings + + onTerminalFontChanged: { + fontChanger.updateIndex() } } - Label{ text: qsTr("Name") } - ComboBox{ - id: fontChanger + Component.onCompleted: updateIndex() + } + Label { + text: qsTr("Scaling") + } + RowLayout { + Layout.fillWidth: true + Slider { Layout.fillWidth: true - model: appSettings.fontlist - onActivated: { - var name = appSettings.fontlist.get(index).name; - appSettings.fontNames[appSettings.rasterization] = name; - appSettings.handleFontChanged(); - } - function updateIndex(){ - var name = appSettings.fontNames[appSettings.rasterization]; - var index = appSettings.getIndexByName(name); - if (index !== undefined) - currentIndex = index; - } - Connections{ - target: appSettings - onTerminalFontChanged: fontChanger.updateIndex(); - } - Component.onCompleted: updateIndex(); + id: fontScalingChanger + onValueChanged: appSettings.fontScaling = value + value: appSettings.fontScaling + stepSize: 0.05 + from: appSettings.minimumFontScaling + to: appSettings.maximumFontScaling } - Label{ text: qsTr("Scaling") } - RowLayout{ - Layout.fillWidth: true - Slider{ - Layout.fillWidth: true - id: fontScalingChanger - onValueChanged: if(enabled) appSettings.fontScaling = value - stepSize: 0.05 - enabled: false // Another trick to fix initial bad behavior. - Component.onCompleted: { - minimumValue = appSettings.minimumFontScaling; - maximumValue = appSettings.maximumFontScaling; - value = appSettings.fontScaling; - enabled = true; - } - Connections{ - target: appSettings - onFontScalingChanged: fontScalingChanger.value = appSettings.fontScaling; - } - } - SizedLabel{ - text: Math.round(fontScalingChanger.value * 100) + "%" - } + SizedLabel { + text: Math.round(fontScalingChanger.value * 100) + "%" } - Label{ text: qsTr("Font Width") } - RowLayout{ + } + Label { + text: qsTr("Font Width") + } + RowLayout { + Layout.fillWidth: true + Slider { Layout.fillWidth: true - Slider{ - Layout.fillWidth: true - id: widthChanger - onValueChanged: appSettings.fontWidth = value; - value: appSettings.fontWidth - stepSize: 0.05 - Component.onCompleted: { - // This is needed to avoid unnecessary chnaged events. - minimumValue = 0.5; - maximumValue = 1.5; - } - } - SizedLabel{ - text: Math.round(widthChanger.value * 100) + "%" - } + id: widthChanger + onValueChanged: appSettings.fontWidth = value + value: appSettings.fontWidth + stepSize: 0.05 + from: 0.5 + to: 1.5 + } + SizedLabel { + text: Math.round(widthChanger.value * 100) + "%" } } } - GroupBox{ - title: qsTr("Colors") - Layout.fillWidth: true - ColumnLayout{ - anchors.fill: parent - ColumnLayout{ - Layout.fillWidth: true - CheckableSlider{ - name: qsTr("Chroma Color") - onNewValue: appSettings.chromaColor = newValue - value: appSettings.chromaColor - } - CheckableSlider{ - name: qsTr("Saturation Color") - onNewValue: appSettings.saturationColor = newValue - value: appSettings.saturationColor - enabled: appSettings.chromaColor !== 0 - } + } + GroupBox { + title: qsTr("Cursor") + Layout.fillWidth: true + 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 + } + } + } + GroupBox { + title: qsTr("Colors") + Layout.fillWidth: true + ColumnLayout { + anchors.fill: parent + ColumnLayout { + Layout.fillWidth: true + CheckableSlider { + name: qsTr("Chroma Color") + onNewValue: appSettings.chromaColor = newValue + value: appSettings.chromaColor } - RowLayout{ + CheckableSlider { + name: qsTr("Saturation Color") + onNewValue: appSettings.saturationColor = newValue + value: appSettings.saturationColor + enabled: appSettings.chromaColor !== 0 + } + } + RowLayout { + Layout.fillWidth: true + ColorButton { + name: qsTr("Font") + height: 50 Layout.fillWidth: true - ColorButton{ - name: qsTr("Font") - height: 50 - Layout.fillWidth: true - onColorSelected: appSettings._fontColor = color; - color: appSettings._fontColor - } - ColorButton{ - name: qsTr("Background") - height: 50 - Layout.fillWidth: true - onColorSelected: appSettings._backgroundColor = color; - color: appSettings._backgroundColor - } + onColorSelected: appSettings._fontColor = color + color: appSettings._fontColor + } + ColorButton { + name: qsTr("Background") + height: 50 + Layout.fillWidth: true + onColorSelected: appSettings._backgroundColor = color + color: appSettings._backgroundColor } } } diff --git a/app/qml/SettingsWindow.qml b/app/qml/SettingsWindow.qml index 78a0031..435516b 100644 --- a/app/qml/SettingsWindow.qml +++ b/app/qml/SettingsWindow.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -19,46 +19,57 @@ *******************************************************************************/ import QtQuick 2.2 -import QtQuick.Controls 1.1 +import QtQuick.Controls 2.1 import QtQuick.Window 2.1 -import QtQuick.Layouts 1.1 +import QtQuick.Layouts 1.3 import QtQuick.Dialogs 1.1 Window { id: settings_window title: qsTr("Settings") - width: 580 - height: 400 + width: 640 + height: 640 property int tabmargins: 15 - TabView{ - id: tabView - anchors.fill: parent - anchors.margins: 10 - SettingsGeneralTab { - id: generalTab - title: qsTr("General") - anchors.fill: parent - anchors.margins: tabmargins + Item { + anchors { fill: parent; margins: tabmargins } + + TabBar { + id: bar + anchors { left: parent.left; right: parent.right; top: parent.top; } + TabButton { + text: qsTr("General") + } + TabButton { + text: qsTr("Terminal") + } + TabButton { + text: qsTr("Effects") + } + TabButton { + text: qsTr("Advanced") + } } - SettingsTerminalTab { - id: terminalTab - title: qsTr("Terminal") - anchors.fill: parent - anchors.margins: tabmargins - } - SettingsEffectsTab { - id: effectsTab - title: qsTr("Effects") - anchors.fill: parent - anchors.margins: tabmargins - } - SettingsAdvancedTab { - id: performanceTab - title: qsTr("Advanced") - anchors.fill: parent - anchors.margins: tabmargins + + Frame { + anchors { + top: bar.bottom + left: parent.left + right: parent.right + bottom: parent.bottom + } + + StackLayout { + anchors.fill: parent + + currentIndex: bar.currentIndex + + SettingsGeneralTab { } + SettingsTerminalTab { } + SettingsEffectsTab { } + SettingsAdvancedTab { } + } } } } diff --git a/app/qml/ShaderLibrary.qml b/app/qml/ShaderLibrary.qml new file mode 100644 index 0000000..ae95f05 --- /dev/null +++ b/app/qml/ShaderLibrary.qml @@ -0,0 +1,91 @@ +import QtQuick 2.0 + +QtObject { + property string rasterizationShader: + (appSettings.rasterization === appSettings.no_rasterization ? " + lowp vec3 applyRasterization(vec2 screenCoords, lowp vec3 texel, vec2 virtualResolution, float intensity) { + return texel; + }" : "") + + + (appSettings.rasterization === appSettings.scanline_rasterization ? " + #define INTENSITY 0.30 + #define BRIGHTBOOST 0.30 + + lowp vec3 applyRasterization(vec2 screenCoords, lowp vec3 texel, vec2 virtualResolution, float intensity) { + lowp vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * texel)) * texel; + lowp vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * texel)) * texel; + + vec2 coords = fract(screenCoords * virtualResolution) * 2.0 - vec2(1.0); + lowp float mask = 1.0 - abs(coords.y); + + lowp vec3 rasterizationColor = mix(pixelLow, pixelHigh, mask); + return mix(texel, rasterizationColor, intensity); + }" : "") + + + (appSettings.rasterization === appSettings.pixel_rasterization ? " + #define INTENSITY 0.30 + #define BRIGHTBOOST 0.30 + + lowp vec3 applyRasterization(vec2 screenCoords, lowp vec3 texel, vec2 virtualResolution, float intensity) { + lowp vec3 result = texel; + + lowp vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * texel)) * texel; + lowp vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * texel)) * texel; + + vec2 coords = fract(screenCoords * virtualResolution) * 2.0 - vec2(1.0); + coords = coords * coords; + lowp float mask = 1.0 - coords.x - coords.y; + + lowp vec3 rasterizationColor = mix(pixelLow, pixelHigh, mask); + return mix(texel, rasterizationColor, intensity); + }" : "") + + + (appSettings.rasterization === appSettings.subpixel_rasterization ? " + #define INTENSITY 0.30 + #define BRIGHTBOOST 0.30 + #define SUBPIXELS 3.0 + const vec3 offsets = vec3(3.141592654) * vec3(1.0/2.0,1.0/2.0 - 2.0/3.0,1.0/2.0-4.0/3.0); + + lowp vec3 applyRasterization(vec2 screenCoords, lowp vec3 texel, vec2 virtualResolution, float intensity) { + vec2 omega = vec2(3.141592654) * vec2(2.0) * virtualResolution; + vec2 angle = screenCoords * omega; + vec3 xfactors = (SUBPIXELS + sin(angle.x + offsets)) / (SUBPIXELS + 1.0); + + lowp vec3 result = texel * xfactors; + lowp vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * result)) * result; + lowp vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * result)) * result; + + vec2 coords = fract(screenCoords * virtualResolution) * 2.0 - vec2(1.0); + lowp float mask = 1.0 - abs(coords.y); + + lowp vec3 rasterizationColor = mix(pixelLow, pixelHigh, mask); + return mix(texel, rasterizationColor, intensity); + }" : "") + + + "\n\n" + + property string min2: " + float min2(vec2 v) { + return min(v.x, v.y); + }\n\n" + + property string rgb2grey: " + float rgb2grey(vec3 v) { + return dot(v, vec3(0.21, 0.72, 0.04)); + }\n\n" + + property string max2: " + float max2(vec2 v) { + return max(v.x, v.y); + }\n\n" + + property string prod2: " + float prod2(vec2 v) { + return v.x * v.y; + }\n\n" + + property string sum2: " + float sum2(vec2 v) { + return v.x + v.y; + }\n\n" +} diff --git a/app/qml/ShaderTerminal.qml b/app/qml/ShaderTerminal.qml index ed367af..2de0d9b 100644 --- a/app/qml/ShaderTerminal.qml +++ b/app/qml/ShaderTerminal.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -24,7 +24,6 @@ import QtGraphicalEffects 1.0 import "utils.js" as Utils Item { - property SlowBurnIn slowBurnInEffect property ShaderEffectSource source property BurnInEffect burnInEffect property ShaderEffectSource bloomSource @@ -38,11 +37,19 @@ Item { property real ambientLight: appSettings.ambientLight * 0.2 - property size virtual_resolution + property size virtualResolution + property size screenResolution + + property real _screenDensity: Math.min( + screenResolution.width / virtualResolution.width, + screenResolution.height / virtualResolution.height + ) ShaderEffect { id: dynamicShader + property ShaderLibrary shaderLibrary: ShaderLibrary { } + property ShaderEffectSource screenBuffer: frameBuffer property ShaderEffectSource burnInSource: burnInEffect.source property ShaderEffectSource frameSource: terminalFrameLoader.item @@ -59,22 +66,24 @@ Item { property real glowingLine: appSettings.glowingLine * 0.2 // Fast burnin properties - property real burnIn: appSettings.useFastBurnIn ? appSettings.burnIn : 0 + property real burnIn: appSettings.burnIn property real burnInLastUpdate: burnInEffect.lastUpdate property real burnInTime: burnInEffect.burnInFadeTime - // Slow burnin properties - property real slowBurnIn: appSettings.useFastBurnIn ? 0 : appSettings.burnIn - property ShaderEffectSource slowBurnInSource: slowBurnInEffect.source - property real jitter: appSettings.jitter property size jitterDisplacement: Qt.size(0.007 * jitter, 0.002 * jitter) property real shadowLength: 0.25 * screenCurvature * Utils.lint(0.50, 1.5, ambientLight) property real staticNoise: appSettings.staticNoise - property size scaleNoiseSize: Qt.size((width) / (noiseTexture.width * appSettings.windowScaling * appSettings.totalFontScaling), - (height) / (noiseTexture.height * appSettings.windowScaling * appSettings.totalFontScaling)) + property size scaleNoiseSize: Qt.size((width * 0.75) / (noiseTexture.width * appSettings.windowScaling * appSettings.totalFontScaling), + (height * 0.75) / (noiseTexture.height * appSettings.windowScaling * appSettings.totalFontScaling)) - property size virtual_resolution: parent.virtual_resolution + property size virtualResolution: parent.virtualResolution + + // Rasterization might display oversamping issues if virtual resolution is close to physical display resolution. + // We progressively disable rasterization from 4x up to 2x resolution. + property real rasterizationIntensity: Utils.smoothstep(2.0, 4.0, _screenDensity) + + property real displayTerminalFrame: appSettings._frameMargin > 0 || appSettings.screenCurvature > 0 property real time: timeManager.time property ShaderEffectSource noiseSource: noiseShaderSource @@ -86,7 +95,7 @@ Item { blending: false //Smooth random texture used for flickering effect. - Image{ + Image { id: noiseTexture source: "images/allNoise512.png" width: 512 @@ -94,7 +103,7 @@ Item { fillMode: Image.Tile visible: false } - ShaderEffectSource{ + ShaderEffectSource { id: noiseShaderSource sourceItem: noiseTexture wrapMode: ShaderEffectSource.Repeat @@ -164,23 +173,22 @@ Item { uniform highp vec4 backgroundColor; uniform lowp float shadowLength; - uniform highp vec2 virtual_resolution;" + + uniform highp vec2 virtualResolution; + uniform lowp float rasterizationIntensity;\n" + (burnIn !== 0 ? " uniform sampler2D burnInSource; uniform highp float burnInLastUpdate; uniform highp float burnInTime;" : "") + - (slowBurnIn !== 0 ? " - uniform sampler2D slowBurnInSource;" : "") + (staticNoise !== 0 ? " uniform highp float staticNoise;" : "") + - (((staticNoise !== 0 || jitter !== 0) - ||(fallBack && (flickering || horizontalSync))) ? " + (((staticNoise !== 0 || jitter !== 0) ||(fallBack && (flickering || horizontalSync))) ? " uniform lowp sampler2D noiseSource; uniform highp vec2 scaleNoiseSize;" : "") + - (screenCurvature !== 0 ? " - uniform highp float screenCurvature; + (displayTerminalFrame ? " uniform lowp sampler2D frameSource;" : "") + + (screenCurvature !== 0 ? " + uniform highp float screenCurvature;" : "") + (glowingLine !== 0 ? " uniform highp float glowingLine;" : "") + (chromaColor !== 0 ? " @@ -203,17 +211,14 @@ Item { (glowingLine !== 0 ? " float randomPass(vec2 coords){ - return fract(smoothstep(-120.0, 0.0, coords.y - (virtual_resolution.y + 120.0) * fract(time * 0.00015))); + return fract(smoothstep(-120.0, 0.0, coords.y - (virtualResolution.y + 120.0) * fract(time * 0.00015))); }" : "") + - "float min2(vec2 v) { - return min(v.x, v.y); - } - - float rgb2grey(vec3 v){ - return dot(v, vec3(0.21, 0.72, 0.04)); - } + shaderLibrary.min2 + + shaderLibrary.rgb2grey + + shaderLibrary.rasterizationShader + + " float isInScreen(vec2 v) { return min2(step(0.0, v) - step(1.0, v)); } @@ -291,7 +296,7 @@ Item { color += noiseVal * noise * (1.0 - distance * 1.3);" : "") + (glowingLine !== 0 ? " - color += randomPass(coords * virtual_resolution) * glowingLine;" : "") + + color += randomPass(coords * virtualResolution) * glowingLine;" : "") + "vec3 txt_color = texture2D(screenBuffer, txt_coords).rgb;" + @@ -302,13 +307,10 @@ Item { txt_color = max(txt_color, convertWithChroma(burnInColor));" : "") + - (slowBurnIn !== 0 ? " - vec4 txt_blur = texture2D(slowBurnInSource, staticCoords); - txt_color = max(txt_color, convertWithChroma(txt_blur.rgb * txt_blur.a)); - " : "") + - "txt_color += fontColor.rgb * vec3(color);" + + "txt_color = applyRasterization(staticCoords, txt_color, virtualResolution, rasterizationIntensity);\n" + + "vec3 finalColor = txt_color;" + (flickering !== 0 ? " @@ -317,7 +319,7 @@ Item { (ambientLight !== 0 ? " finalColor += vec3(ambientLight) * (1.0 - distance) * (1.0 - distance);" : "") + - (screenCurvature !== 0 ? + (displayTerminalFrame ? "vec4 frameColor = texture2D(frameSource, qt_TexCoord0); finalColor = mix(finalColor, frameColor.rgb, frameColor.a);" : "") + @@ -340,7 +342,7 @@ Item { Loader { id: terminalFrameLoader - active: screenCurvature !== 0 + active: dynamicShader.displayTerminalFrame width: staticShader.width height: staticShader.height @@ -352,7 +354,7 @@ Item { visible: false format: ShaderEffectSource.RGBA - NewTerminalFrame { + TerminalFrame { id: terminalFrame blending: false anchors.fill: parent @@ -360,6 +362,10 @@ Item { } } + ShaderLibrary { + id: shaderLibrary + } + ShaderEffect { id: staticShader @@ -385,7 +391,7 @@ Item { property real ambientLight: parent.ambientLight - property size virtual_resolution: parent.virtual_resolution + property size virtualResolution: parent.virtualResolution blending: false visible: false @@ -408,7 +414,7 @@ Item { uniform highp vec4 backgroundColor; uniform lowp float screen_brightness; - uniform highp vec2 virtual_resolution;" + + uniform highp vec2 virtualResolution;" + (bloom !== 0 ? " uniform highp sampler2D bloomSource; @@ -426,36 +432,9 @@ Item { (ambientLight !== 0 ? " uniform lowp float ambientLight;" : "") + - "highp float getScanlineIntensity(vec2 coords) { - float result = 1.0;" + - - (appSettings.rasterization != appSettings.no_rasterization ? - "float val = 0.0; - vec2 rasterizationCoords = fract(coords * virtual_resolution); - val += smoothstep(0.0, 0.5, rasterizationCoords.y); - val -= smoothstep(0.5, 1.0, rasterizationCoords.y); - result *= mix(0.5, 1.0, val);" : "") + - - (appSettings.rasterization == appSettings.pixel_rasterization ? - "val = 0.0; - val += smoothstep(0.0, 0.5, rasterizationCoords.x); - val -= smoothstep(0.5, 1.0, rasterizationCoords.x); - result *= mix(0.5, 1.0, val);" : "") + " - - return result; - } - - float min2(vec2 v) { - return min(v.x, v.y); - } - - float sum2(vec2 v) { - return v.x + v.y; - } - - float rgb2grey(vec3 v){ - return dot(v, vec3(0.21, 0.72, 0.04)); - }" + + shaderLibrary.min2 + + shaderLibrary.sum2 + + shaderLibrary.rgb2grey + "vec3 convertWithChroma(vec3 inColor) { vec3 outColor = inColor;" + @@ -468,6 +447,7 @@ Item { " return outColor; }" + + shaderLibrary.rasterizationShader + "void main() {" + "vec2 cc = vec2(0.5) - qt_TexCoord0;" + @@ -490,8 +470,6 @@ Item { txt_color.b = leftColor.b * 0.30 + rightColor.b * 0.10 + txt_color.b * 0.60; " : "") + - "txt_color *= getScanlineIntensity(txt_coords);" + - "txt_color += vec3(0.0001);" + "float greyscale_color = rgb2grey(txt_color);" + diff --git a/app/qml/SimpleSlider.qml b/app/qml/SimpleSlider.qml index 44d3608..e2bf0bd 100644 --- a/app/qml/SimpleSlider.qml +++ b/app/qml/SimpleSlider.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -17,9 +17,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ - import QtQuick 2.2 -import QtQuick.Controls 1.1 +import QtQuick.Controls 2.0 import QtQuick.Layouts 1.1 import "Components" @@ -27,18 +26,18 @@ import "Components" RowLayout { property alias value: slider.value property alias stepSize: slider.stepSize - property alias minimumValue: slider.minimumValue - property alias maximumValue: slider.maximumValue + property alias minimumValue: slider.from + property alias maximumValue: slider.to property real maxMultiplier: 100 id: setting_component spacing: 10 - Slider{ + Slider { id: slider stepSize: parent.stepSize Layout.fillWidth: true } - SizedLabel{ + SizedLabel { text: Math.round(value * maxMultiplier) + "%" } } diff --git a/app/qml/SizeOverlay.qml b/app/qml/SizeOverlay.qml index 7d67314..247534d 100644 --- a/app/qml/SizeOverlay.qml +++ b/app/qml/SizeOverlay.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -17,12 +17,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ - import QtQuick 2.2 -Rectangle{ +Rectangle { property size terminalSize property real topOpacity: 0.6 + width: textSize.width * 2 height: textSize.height * 2 radius: 5 @@ -31,17 +31,21 @@ Rectangle{ color: "black" opacity: sizetimer.running ? 0.6 : 0.0 - Behavior on opacity{NumberAnimation{duration: 200}} + Behavior on opacity { + NumberAnimation { + duration: 200 + } + } onTerminalSizeChanged: sizetimer.restart() - Text{ + Text { id: textSize anchors.centerIn: parent color: "white" text: terminalSize.width + "x" + terminalSize.height } - Timer{ + Timer { id: sizetimer interval: 1000 running: false diff --git a/app/qml/SlowBurnIn.qml b/app/qml/SlowBurnIn.qml deleted file mode 100644 index 44f53e9..0000000 --- a/app/qml/SlowBurnIn.qml +++ /dev/null @@ -1,122 +0,0 @@ -import QtQuick 2.0 - -import "utils.js" as Utils - -Loader { - property ShaderEffectSource source: item ? item.source : null - - active: !appSettings.useFastBurnIn && appSettings.burnIn !== 0 - - anchors.fill: parent - - sourceComponent: Item { - property alias source: burnInSourceEffect - - property int burnInScaling: scaleTexture * appSettings.burnInQuality - - ShaderEffectSource { - property bool updateBurnIn: false - property real burnIn: appSettings.burnIn - property real fps: appSettings.fps !== 0 ? appSettings.fps : 60 - property real burnInFadeTime: Utils.lint(minBurnInFadeTime, maxBurnInFadeTime, burnIn) - property real burnInCoefficient: 1000 / (fps * burnInFadeTime) - property real minBurnInFadeTime: appSettings.minBurnInFadeTime - property real maxBurnInFadeTime: appSettings.maxBurnInFadeTime - - id: burnInSourceEffect - - anchors.fill: parent - - sourceItem: burnInEffect - recursive: true - live: false - hideSource: true - wrapMode: kterminalSource.wrapMode - - visible: false - - function restartBlurSource(){ - livetimer.restart(); - } - - // This updates the burnin synched with the timer. - Connections { - target: burnInSourceEffect.updateBurnIn ? timeManager : null - ignoreUnknownSignals: false - onTimeChanged: { - burnInSourceEffect.scheduleUpdate(); - } - } - - Timer{ - id: livetimer - - // The interval assumes 60 fps. This is the time needed burnout a white pixel. - // We multiply 1.1 to have a little bit of margin over the theoretical value. - // This solution is not extremely clean, but it's probably the best to avoid measuring fps. - - interval: burnInSourceEffect.burnInFadeTime * 1.1 - running: true - onTriggered: burnInSourceEffect.updateBurnIn = false; - } - Connections{ - target: kterminal - onImagePainted:{ - burnInSourceEffect.scheduleUpdate(); - burnInSourceEffect.updateBurnIn = true; - livetimer.restart(); - } - } - // Restart blurred source settings change. - Connections{ - target: appSettings - onBurnInChanged: burnInSourceEffect.restartBlurSource(); - onTerminalFontChanged: burnInSourceEffect.restartBlurSource(); - onRasterizationChanged: burnInSourceEffect.restartBlurSource(); - onBurnInQualityChanged: burnInSourceEffect.restartBlurSource(); - } - Connections { - target: kterminalScrollbar - onOpacityChanged: burnInSourceEffect.restartBlurSource(); - } - - ShaderEffect { - id: burnInEffect - - property variant txt_source: kterminalSource - property variant blurredSource: burnInSourceEffect - property real burnInCoefficient: burnInSourceEffect.burnInCoefficient - - anchors.fill: parent - blending: false - - fragmentShader: - "#ifdef GL_ES - precision mediump float; - #endif\n" + - - "uniform lowp float qt_Opacity;" + - "uniform lowp sampler2D txt_source;" + - - "varying highp vec2 qt_TexCoord0; - uniform lowp sampler2D blurredSource; - uniform highp float burnInCoefficient;" + - - "float max3(vec3 v) { - return max (max (v.x, v.y), v.z); - }" + - - "void main() {" + - "vec2 coords = qt_TexCoord0;" + - "vec3 origColor = texture2D(txt_source, coords).rgb;" + - "vec3 blur_color = texture2D(blurredSource, coords).rgb - vec3(burnInCoefficient);" + - "vec3 color = min(origColor + blur_color, max(origColor, blur_color));" + - - "gl_FragColor = vec4(color, max3(color - origColor));" + - "}" - - onStatusChanged: if (log) console.log(log) //Print warning messages - } - } - } -} diff --git a/app/qml/Storage.qml b/app/qml/Storage.qml index 6554314..cd6699d 100644 --- a/app/qml/Storage.qml +++ b/app/qml/Storage.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -27,7 +27,7 @@ QtObject { property bool initialized: false function getDatabase() { - return LocalStorage.openDatabaseSync("coolretroterm" + dbMajorVersion, dbMinorVersion, "StorageDatabase", 100000); + return LocalStorage.openDatabaseSync("coolretroterm" + dbMajorVersion, dbMinorVersion, "StorageDatabase", 100000) } function initialize() { @@ -35,43 +35,47 @@ QtObject { db.transaction( function(tx) { tx.executeSql('CREATE TABLE IF NOT EXISTS settings(setting TEXT UNIQUE, value TEXT)'); - }); + } + ) - initialized = true; + initialized = true } function setSetting(setting, value) { - if(!initialized) initialize(); + if(!initialized) initialize(); - var db = getDatabase(); - var res = ""; - db.transaction(function(tx) { - var rs = tx.executeSql('INSERT OR REPLACE INTO settings VALUES (?,?);', [setting,value]); - //console.log(rs.rowsAffected) - if (rs.rowsAffected > 0) { + var db = getDatabase(); + var res = ""; + db.transaction( + function(tx) { + var rs = tx.executeSql('INSERT OR REPLACE INTO settings VALUES (?,?);', [setting,value]); + //console.log(rs.rowsAffected) + if (rs.rowsAffected > 0) { res = "OK"; - } else { + } else { res = "Error"; - } - } - ); + } + } + ) // The function returns “OK” if it was successful, or “Error” if it wasn't - return res; + return res } function getSetting(setting) { - if(!initialized) initialize(); - var db = getDatabase(); - var res=""; - db.transaction(function(tx) { - var rs = tx.executeSql('SELECT value FROM settings WHERE setting=?;', [setting]); - if (rs.rows.length > 0) { - res = rs.rows.item(0).value; - } else { - res = undefined; - } - }) - return res + if(!initialized) initialize(); + var db = getDatabase(); + var res = ""; + db.transaction( + function(tx) { + var rs = tx.executeSql('SELECT value FROM settings WHERE setting=?;', [setting]); + if (rs.rows.length > 0) { + res = rs.rows.item(0).value; + } else { + res = undefined; + } + } + ) + return res } function dropSettings(){ @@ -79,6 +83,7 @@ QtObject { db.transaction( function(tx) { tx.executeSql('DROP TABLE settings'); - }); + } + ) } } diff --git a/app/qml/TerminalContainer.qml b/app/qml/TerminalContainer.qml index 48d6ec1..b6be435 100644 --- a/app/qml/TerminalContainer.qml +++ b/app/qml/TerminalContainer.qml @@ -1,3 +1,22 @@ +/******************************************************************************* +* Copyright (c) 2013-2021 "Filippo Scognamiglio" +* https://github.com/Swordfish90/cool-retro-term +* +* This file is part of cool-retro-term. +* +* cool-retro-term is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* 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/>. +*******************************************************************************/ import QtQuick 2.2 import QtGraphicalEffects 1.0 @@ -7,44 +26,48 @@ ShaderTerminal { property alias title: terminal.title property alias terminalSize: terminal.terminalSize + property real devicePixelRatio: terminalWindow.screen.devicePixelRatio + id: mainShader opacity: appSettings.windowOpacity * 0.3 + 0.7 source: terminal.mainSource burnInEffect: terminal.burnInEffect - slowBurnInEffect: terminal.slowBurnInEffect - virtual_resolution: terminal.virtualResolution + virtualResolution: terminal.virtualResolution + screenResolution: Qt.size( + terminalWindow.width * devicePixelRatio * appSettings.windowScaling, + terminalWindow.height * devicePixelRatio * appSettings.windowScaling + ) - TimeManager{ + TimeManager { id: timeManager enableTimer: terminalWindow.visible } - PreprocessedTerminal{ + PreprocessedTerminal { id: terminal anchors.fill: parent } // EFFECTS //////////////////////////////////////////////////////////////// - - Loader{ + Loader { id: bloomEffectLoader active: appSettings.bloom asynchronous: true width: parent.width * appSettings.bloomQuality height: parent.height * appSettings.bloomQuality - sourceComponent: FastBlur{ - radius: Utils.lint(16, 64, appSettings.bloomQuality); + sourceComponent: FastBlur { + radius: Utils.lint(16, 64, appSettings.bloomQuality) source: terminal.mainSource transparentBorder: true } } - Loader{ + Loader { id: bloomSourceLoader active: appSettings.bloom !== 0 asynchronous: true - sourceComponent: ShaderEffectSource{ + sourceComponent: ShaderEffectSource { id: _bloomEffectSource sourceItem: bloomEffectLoader.item hideSource: true @@ -54,71 +77,4 @@ ShaderTerminal { } bloomSource: bloomSourceLoader.item - -// NewTerminalFrame { -// id: terminalFrame -// anchors.fill: parent -// blending: true -// } - - // This shader might be useful in the future. Since we used it only for a couple - // of calculations is probably best to move those in the main shader. If in the future - // we need to store another fullScreen channel this might be handy. - -// ShaderEffect { -// id: rasterizationEffect -// width: parent.width -// height: parent.height -// property real outColor: 0.0 -// property real dispX: (5 / width) * appSettings.windowScaling -// property real dispY: (5 / height) * appSettings.windowScaling -// property size virtual_resolution: terminal.virtualResolution - -// blending: false - -// fragmentShader: -// "uniform lowp float qt_Opacity;" + - -// "varying highp vec2 qt_TexCoord0; -// uniform highp vec2 virtual_resolution; -// uniform highp float dispX; -// uniform highp float dispY; -// uniform mediump float outColor; - -// highp float getScanlineIntensity(vec2 coords) { -// highp float result = 1.0;" + - -// (appSettings.rasterization != appSettings.no_rasterization ? -// "result *= abs(sin(coords.y * virtual_resolution.y * "+Math.PI+"));" : "") + -// (appSettings.rasterization == appSettings.pixel_rasterization ? -// "result *= abs(sin(coords.x * virtual_resolution.x * "+Math.PI+"));" : "") + " - -// return result; -// }" + - -// "void main() {" + -// "highp float color = getScanlineIntensity(qt_TexCoord0);" + - -// "float distance = length(vec2(0.5) - qt_TexCoord0);" + -// "color = mix(color, 0.0, 1.2 * distance * distance);" + - -// "color *= outColor + smoothstep(0.00, dispX, qt_TexCoord0.x) * (1.0 - outColor);" + -// "color *= outColor + smoothstep(0.00, dispY, qt_TexCoord0.y) * (1.0 - outColor);" + -// "color *= outColor + (1.0 - smoothstep(1.00 - dispX, 1.00, qt_TexCoord0.x)) * (1.0 - outColor);" + -// "color *= outColor + (1.0 - smoothstep(1.00 - dispY, 1.00, qt_TexCoord0.y)) * (1.0 - outColor);" + - -// "gl_FragColor.a = color;" + -// "}" - -// onStatusChanged: if (log) console.log(log) //Print warning messages -// } - -// rasterizationSource: ShaderEffectSource{ -// id: rasterizationEffectSource -// sourceItem: rasterizationEffect -// hideSource: true -// smooth: true -// wrapMode: ShaderEffectSource.ClampToEdge -// visible: false -// } } diff --git a/app/qml/TerminalFrame.qml b/app/qml/TerminalFrame.qml new file mode 100644 index 0000000..3e1baef --- /dev/null +++ b/app/qml/TerminalFrame.qml @@ -0,0 +1,104 @@ +/******************************************************************************* +* Copyright (c) 2013-2021 "Filippo Scognamiglio" +* https://github.com/Swordfish90/cool-retro-term +* +* This file is part of cool-retro-term. +* +* cool-retro-term is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* 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/>. +*******************************************************************************/ +import QtQuick 2.0 + +import "utils.js" as Utils + +ShaderEffect { + property color _staticFrameColor: "#fff" + property color _backgroundColor: appSettings.backgroundColor + property color _fontColor: appSettings.fontColor + property color _lightColor: Utils.mix(_fontColor, _backgroundColor, 0.2) + property real _ambientLight: Utils.lint(0.2, 0.8, appSettings.ambientLight) + + property color frameColor: Utils.mix(_staticFrameColor, _lightColor, _ambientLight) + property real screenCurvature: appSettings.screenCurvature * appSettings.screenCurvatureSize + + // Coefficient of the log curve used to approximate shadowing + property real screenShadowCoeff: Utils.lint(20.0, 10.0, _ambientLight) + property real frameShadowCoeff: Utils.lint(20.0, 10.0, _ambientLight) + + property size margin: Qt.size( + appSettings.frameMargin / width * appSettings.windowScaling, + appSettings.frameMargin / height * appSettings.windowScaling + ) + + ShaderLibrary { + id: shaderLibrary + } + + fragmentShader: " + #ifdef GL_ES + precision mediump float; + #endif + + uniform lowp float screenCurvature; + uniform lowp float screenShadowCoeff; + uniform lowp float frameShadowCoeff; + uniform highp float qt_Opacity; + uniform lowp vec4 frameColor; + uniform mediump vec2 margin; + + varying highp vec2 qt_TexCoord0; + + vec2 distortCoordinates(vec2 coords){ + vec2 cc = (coords - vec2(0.5)); + float dist = dot(cc, cc) * screenCurvature; + return (coords + cc * (1.0 + dist) * dist); + } + " + + + shaderLibrary.max2 + + shaderLibrary.min2 + + shaderLibrary.prod2 + + shaderLibrary.sum2 + + + " + + vec2 positiveLog(vec2 x) { + return clamp(log(x), vec2(0.0), vec2(100.0)); + } + + void main() { + vec2 staticCoords = qt_TexCoord0; + vec2 coords = distortCoordinates(staticCoords) * (vec2(1.0) + margin * 2.0) - margin; + + vec2 vignetteCoords = staticCoords * (1.0 - staticCoords.yx); + float vignette = pow(prod2(vignetteCoords) * 15.0, 0.25); + + vec3 color = frameColor.rgb * vec3(1.0 - vignette); + float alpha = 0.0; + + float frameShadow = max2(positiveLog(-coords * frameShadowCoeff + vec2(1.0)) + positiveLog(coords * frameShadowCoeff - (vec2(frameShadowCoeff) - vec2(1.0)))); + frameShadow = max(sqrt(frameShadow), 0.0); + color *= frameShadow; + alpha = sum2(1.0 - step(vec2(0.0), coords) + step(vec2(1.0), coords)); + alpha = clamp(alpha, 0.0, 1.0); + alpha *= mix(1.0, 0.9, frameShadow); + + float screenShadow = 1.0 - prod2(positiveLog(coords * screenShadowCoeff + vec2(1.0)) * positiveLog(-coords * screenShadowCoeff + vec2(screenShadowCoeff + 1.0))); + alpha = max(0.8 * screenShadow, alpha); + + gl_FragColor = vec4(color * alpha, alpha); + } + " + + onStatusChanged: if (log) console.log(log) //Print warning messages +} diff --git a/app/qml/TimeManager.qml b/app/qml/TimeManager.qml index 52da262..6424af2 100644 --- a/app/qml/TimeManager.qml +++ b/app/qml/TimeManager.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -17,10 +17,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ - import QtQuick 2.2 -Timer{ +Timer { default property bool enableTimer: false property real time diff --git a/app/qml/fonts/1971-ibm-3278/3270-Regular.ttf b/app/qml/fonts/1971-ibm-3278/3270-Regular.ttf new file mode 100644 index 0000000..d0a7271 Binary files /dev/null and b/app/qml/fonts/1971-ibm-3278/3270-Regular.ttf differ diff --git a/app/qml/fonts/1971-ibm-3278/3270Medium.ttf b/app/qml/fonts/1971-ibm-3278/3270Medium.ttf deleted file mode 100644 index c8527c4..0000000 Binary files a/app/qml/fonts/1971-ibm-3278/3270Medium.ttf and /dev/null differ diff --git a/app/qml/main.qml b/app/qml/main.qml index bdc06bd..0be04a7 100644 --- a/app/qml/main.qml +++ b/app/qml/main.qml @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2013 "Filippo Scognamiglio" +* Copyright (c) 2013-2021 "Filippo Scognamiglio" * https://github.com/Swordfish90/cool-retro-term * * This file is part of cool-retro-term. @@ -17,10 +17,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ - import QtQuick 2.2 import QtQuick.Window 2.1 -import QtQuick.Controls 1.1 +import QtQuick.Controls 2.3 import QtQuick.Controls.Styles 1.4 import QtGraphicalEffects 1.0 @@ -45,8 +44,6 @@ ApplicationWindow{ // Load saved window geometry and show the window Component.onCompleted: { - appSettings.handleFontChanged(); - x = appSettings.x y = appSettings.y width = appSettings.width @@ -63,22 +60,30 @@ ApplicationWindow{ property bool fullscreen: appSettings.fullscreen onFullscreenChanged: visibility = (fullscreen ? Window.FullScreen : Window.Windowed) - //Workaround: Without __contentItem a ugly thin border is visible. - menuBar: CRTMainMenuBar{ - id: mainMenu - visible: (Qt.platform.os === "osx" || appSettings.showMenubar) - __contentItem.visible: mainMenu.visible + menuBar: qtquickMenuLoader.item + + Loader { + id: qtquickMenuLoader + active: !appSettings.isMacOS && appSettings.showMenubar + sourceComponent: WindowMenu { } + } + + Loader { + id: globalMenuLoader + active: appSettings.isMacOS + sourceComponent: OSXMenu { } } property string wintitle: appSettings.wintitle color: "#00000000" + title: terminalContainer.title || qsTr(appSettings.wintitle) Action { id: showMenubarAction text: qsTr("Show Menubar") - enabled: Qt.platform.os !== "osx" + enabled: !appSettings.isMacOS shortcut: "Ctrl+Shift+M" checkable: true checked: appSettings.showMenubar @@ -87,9 +92,9 @@ ApplicationWindow{ Action { id: fullscreenAction text: qsTr("Fullscreen") - enabled: Qt.platform.os !== "osx" + enabled: !appSettings.isMacOS shortcut: "Alt+F11" - onTriggered: appSettings.fullscreen = !appSettings.fullscreen; + onTriggered: appSettings.fullscreen = !appSettings.fullscreen checkable: true checked: appSettings.fullscreen } @@ -97,69 +102,68 @@ ApplicationWindow{ id: quitAction text: qsTr("Quit") shortcut: "Ctrl+Shift+Q" - onTriggered: Qt.quit(); + onTriggered: Qt.quit() } - Action{ + Action { id: showsettingsAction text: qsTr("Settings") onTriggered: { - settingswindow.show(); - settingswindow.requestActivate(); - settingswindow.raise(); + settingswindow.show() + settingswindow.requestActivate() + settingswindow.raise() } } - Action{ + Action { id: copyAction text: qsTr("Copy") shortcut: "Ctrl+Shift+C" } - Action{ + Action { id: pasteAction text: qsTr("Paste") shortcut: "Ctrl+Shift+V" } - Action{ + Action { id: zoomIn text: qsTr("Zoom In") shortcut: "Ctrl++" - onTriggered: appSettings.incrementScaling(); + onTriggered: appSettings.incrementScaling() } - Action{ + Action { id: zoomOut text: qsTr("Zoom Out") shortcut: "Ctrl+-" - onTriggered: appSettings.decrementScaling(); + onTriggered: appSettings.decrementScaling() } - Action{ + Action { id: showAboutAction text: qsTr("About") onTriggered: { - aboutDialog.show(); - aboutDialog.requestActivate(); - aboutDialog.raise(); + aboutDialog.show() + aboutDialog.requestActivate() + aboutDialog.raise() } } - ApplicationSettings{ + ApplicationSettings { id: appSettings } - TerminalContainer{ + TerminalContainer { id: terminalContainer - y: appSettings.showMenubar ? 0 : -2 // Workaroud to hide the margin in the menubar. width: parent.width height: (parent.height + Math.abs(y)) } - SettingsWindow{ + SettingsWindow { id: settingswindow visible: false } - AboutDialog{ + AboutDialog { id: aboutDialog visible: false } - Loader{ + Loader { anchors.centerIn: parent active: appSettings.showTerminalSize - sourceComponent: SizeOverlay{ + sourceComponent: SizeOverlay { z: 3 terminalSize: terminalContainer.terminalSize } @@ -167,7 +171,7 @@ ApplicationWindow{ onClosing: { // OSX Since we are currently supporting only one window // quit the application when it is closed. - if (Qt.platform.os === "osx") + if (appSettings.isMacOS) Qt.quit() } } diff --git a/app/qml/menus/FullContextMenu.qml b/app/qml/menus/FullContextMenu.qml new file mode 100644 index 0000000..d9feb58 --- /dev/null +++ b/app/qml/menus/FullContextMenu.qml @@ -0,0 +1,95 @@ +/******************************************************************************* +* Copyright (c) 2013-2021 "Filippo Scognamiglio" +* https://github.com/Swordfish90/cool-retro-term +* +* This file is part of cool-retro-term. +* +* cool-retro-term is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* 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/>. +*******************************************************************************/ +import QtQuick 2.2 +import QtQuick.Controls 2.3 + +Menu { + id: contextmenu + MenuItem { + action: copyAction + } + MenuItem { + action: pasteAction + } + MenuItem { + action: showsettingsAction + } + + MenuSeparator {} + + Menu { + title: qsTr("File") + MenuItem { + action: quitAction + } + } + Menu { + title: qsTr("Edit") + MenuItem { + action: copyAction + } + MenuItem { + action: pasteAction + } + MenuSeparator {} + MenuItem { + action: showsettingsAction + } + } + Menu { + title: qsTr("View") + MenuItem { + action: fullscreenAction + visible: fullscreenAction.enabled + } + MenuItem { + action: showMenubarAction + visible: showMenubarAction.enabled + } + MenuItem { + action: zoomIn + } + MenuItem { + action: zoomOut + } + } + Menu { + id: profilesMenu + title: qsTr("Profiles") + Instantiator { + model: appSettings.profilesList + delegate: MenuItem { + text: model.text + onTriggered: { + appSettings.loadProfileString(obj_string) + appSettings.handleFontChanged() + } + } + onObjectAdded: profilesMenu.insertItem(index, object) + onObjectRemoved: profilesMenu.removeItem(object) + } + } + Menu { + title: qsTr("Help") + MenuItem { + action: showAboutAction + } + } +} diff --git a/app/qml/menus/OSXMenu.qml b/app/qml/menus/OSXMenu.qml new file mode 100644 index 0000000..3fe9971 --- /dev/null +++ b/app/qml/menus/OSXMenu.qml @@ -0,0 +1,89 @@ +/******************************************************************************* +* Copyright (c) 2013-2021 "Filippo Scognamiglio" +* https://github.com/Swordfish90/cool-retro-term +* +* This file is part of cool-retro-term. +* +* cool-retro-term is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* 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/>. +*******************************************************************************/ + +import QtQuick 2.3 +import Qt.labs.platform 1.1 + +MenuBar { + id: defaultMenuBar + + Menu { + title: qsTr("File") + MenuItem { + text: quitAction.text + onTriggered: quitAction.trigger() + } + } + Menu { + title: qsTr("Edit") + MenuItem { + text: copyAction.text + shortcut: "Meta+C" + onTriggered: copyAction.trigger() + } + MenuItem { + text: pasteAction.text + shortcut: "Meta+V" + onTriggered: pasteAction.trigger() + } + MenuSeparator {} + MenuItem { + text: showsettingsAction.text + shortcut: showsettingsAction.shortcut + onTriggered: showsettingsAction.trigger() + } + } + Menu { + title: qsTr("View") + MenuItem { + text: zoomIn.text + shortcut: "Meta++" + onTriggered: zoomIn.trigger() + } + MenuItem { + text: zoomOut.text + shortcut: "Meta+-" + onTriggered: zoomOut.trigger() + } + } + Menu { + id: profilesMenu + title: qsTr("Profiles") + Instantiator { + model: appSettings.profilesList + delegate: MenuItem { + text: model.text + onTriggered: { + appSettings.loadProfileString(obj_string) + appSettings.handleFontChanged() + } + } + onObjectAdded: profilesMenu.insertItem(index, object) + onObjectRemoved: profilesMenu.removeItem(object) + } + } + Menu { + title: qsTr("Help") + MenuItem { + text: showAboutAction.text + onTriggered: showAboutAction.trigger() + } + } +} diff --git a/app/qml/menus/ShortContextMenu.qml b/app/qml/menus/ShortContextMenu.qml new file mode 100644 index 0000000..9d8f63b --- /dev/null +++ b/app/qml/menus/ShortContextMenu.qml @@ -0,0 +1,31 @@ +/******************************************************************************* +* Copyright (c) 2013-2021 "Filippo Scognamiglio" +* https://github.com/Swordfish90/cool-retro-term +* +* This file is part of cool-retro-term. +* +* cool-retro-term is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* 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/>. +*******************************************************************************/ +import QtQuick 2.2 +import QtQuick.Controls 2.3 + +Menu { + id: contextmenu + MenuItem { + action: copyAction + } + MenuItem { + action: pasteAction + } +} diff --git a/app/qml/menus/WindowMenu.qml b/app/qml/menus/WindowMenu.qml new file mode 100644 index 0000000..937153b --- /dev/null +++ b/app/qml/menus/WindowMenu.qml @@ -0,0 +1,85 @@ +/******************************************************************************* +* Copyright (c) 2013-2021 "Filippo Scognamiglio" +* https://github.com/Swordfish90/cool-retro-term +* +* This file is part of cool-retro-term. +* +* cool-retro-term is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* 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/>. +*******************************************************************************/ +import QtQuick 2.2 +import QtQuick.Controls 2.3 + +MenuBar { + id: defaultMenuBar + visible: appSettings.showMenubar + + Menu { + title: qsTr("File") + MenuItem { + action: quitAction + } + } + Menu { + title: qsTr("Edit") + MenuItem { + action: copyAction + } + MenuItem { + action: pasteAction + } + MenuSeparator {} + MenuItem { + action: showsettingsAction + } + } + Menu { + title: qsTr("View") + MenuItem { + action: fullscreenAction + visible: fullscreenAction.enabled + } + MenuItem { + action: showMenubarAction + visible: showMenubarAction.enabled + } + MenuItem { + action: zoomIn + } + MenuItem { + action: zoomOut + } + } + Menu { + id: profilesMenu + title: qsTr("Profiles") + Instantiator { + model: appSettings.profilesList + delegate: MenuItem { + text: model.text + onTriggered: { + appSettings.loadProfileString(obj_string) + appSettings.handleFontChanged() + } + } + onObjectAdded: profilesMenu.insertItem(index, object) + onObjectRemoved: profilesMenu.removeItem(object) + } + } + Menu { + title: qsTr("Help") + MenuItem { + action: showAboutAction + } + } +} diff --git a/app/qml/resources.qrc b/app/qml/resources.qrc index 8df465f..1114d8d 100644 --- a/app/qml/resources.qrc +++ b/app/qml/resources.qrc @@ -12,7 +12,6 @@ <file>TimeManager.qml</file> <file>SimpleSlider.qml</file> <file>ColorButton.qml</file> - <file>Glossy.qml</file> <file>AboutDialog.qml</file> <file>InsertNameDialog.qml</file> <file>SettingsEffectsTab.qml</file> @@ -20,9 +19,8 @@ <file>SettingsTerminalTab.qml</file> <file>FontScanlines.qml</file> <file>fonts/1977-apple2/PrintChar21.ttf</file> - <file>fonts/1971-ibm-3278/3270Medium.ttf</file> + <file>fonts/1971-ibm-3278/3270-Regular.ttf</file> <file>Storage.qml</file> - <file>CRTMainMenuBar.qml</file> <file>SettingsAdvancedTab.qml</file> <file>TerminalContainer.qml</file> <file>images/crt256.png</file> @@ -42,7 +40,11 @@ <file>fonts/1977-commodore-pet/PetMe.ttf</file> <file>BurnInEffect.qml</file> <file>fonts/modern-terminus/TerminusTTF-4.46.0.ttf</file> - <file>NewTerminalFrame.qml</file> - <file>SlowBurnIn.qml</file> + <file>TerminalFrame.qml</file> + <file>menus/WindowMenu.qml</file> + <file>menus/FullContextMenu.qml</file> + <file>menus/ShortContextMenu.qml</file> + <file>ShaderLibrary.qml</file> + <file>menus/OSXMenu.qml</file> </qresource> </RCC> diff --git a/app/qml/utils.js b/app/qml/utils.js index a8e1af0..3cb5a67 100644 --- a/app/qml/utils.js +++ b/app/qml/utils.js @@ -1,3 +1,23 @@ +/******************************************************************************* +* Copyright (c) 2013-2021 "Filippo Scognamiglio" +* https://github.com/Swordfish90/cool-retro-term +* +* This file is part of cool-retro-term. +* +* cool-retro-term is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* 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/>. +*******************************************************************************/ + .pragma library function clamp(x, min, max) { if (x <= min) @@ -6,15 +26,23 @@ function clamp(x, min, max) { return max; return x; } + function lint(a, b, t) { return (1 - t) * a + (t) * b; } -function mix(c1, c2, alpha){ + +function mix(c1, c2, alpha) { return Qt.rgba(c1.r * alpha + c2.r * (1-alpha), c1.g * alpha + c2.g * (1-alpha), c1.b * alpha + c2.b * (1-alpha), c1.a * alpha + c2.a * (1-alpha)) } + +function smoothstep(min, max, value) { + let x = Math.max(0, Math.min(1, (value - min) / (max - min))); + return x * x * (3 - 2 * x); +} + function strToColor(s){ var r = parseInt(s.substring(1,3), 16) / 256; var g = parseInt(s.substring(3,5), 16) / 256; diff --git a/qmltermwidget b/qmltermwidget index 48274c7..6322802 160000 --- a/qmltermwidget +++ b/qmltermwidget @@ -1 +1 @@ -Subproject commit 48274c75660e28d44af7c195e79accdf1bd44963 +Subproject commit 63228027e1f97c24abb907550b22ee91836929c5 diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 149d0a9..bc6b990 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -66,4 +66,6 @@ parts: - libgl1-mesa-dev - qtdeclarative5-dev-tools - qml-module-qtquick-extras + - qml-module-qt-labs-settings + - qml-module-qt-labs-folderlistmodel