diff --git a/app/qml/ApplicationSettings.qml b/app/qml/ApplicationSettings.qml index 4ce607a..92bbe2d 100644 --- a/app/qml/ApplicationSettings.qml +++ b/app/qml/ApplicationSettings.qml @@ -813,6 +813,7 @@ QtObject { wintitle = args[args.indexOf("-T") + 1] } + settingsInitialized = true initializedSettings() } Component.onDestruction: { @@ -826,4 +827,5 @@ QtObject { text: "100%" } property real labelWidth: _sampleLabel.width + property bool settingsInitialized: false } diff --git a/app/qml/PreprocessedTerminal.qml b/app/qml/PreprocessedTerminal.qml index a44669f..a8c1d0e 100644 --- a/app/qml/PreprocessedTerminal.qml +++ b/app/qml/PreprocessedTerminal.qml @@ -42,6 +42,7 @@ Item{ property size terminalSize: kterminal.terminalSize property size fontMetrics: kterminal.fontMetrics + property bool sessionStarted: false // Manage copy and paste Connections { @@ -168,6 +169,10 @@ Item{ } function startSession() { + if (terminalContainer.sessionStarted) + return + + terminalContainer.sessionStarted = true appSettings.initializedSettings.disconnect(startSession); // Retrieve the variable set in main.cpp if arguments are passed. @@ -192,6 +197,8 @@ Item{ Component.onCompleted: { appSettings.terminalFontChanged.connect(handleFontChanged); appSettings.initializedSettings.connect(startSession); + if (appSettings.settingsInitialized) + startSession(); appSettings.updateFont() } } @@ -232,6 +239,7 @@ Item{ kterminal.simulateMouseDoubleClick(coord.x, coord.y, mouse.button, mouse.buttons, mouse.modifiers); } onPressed: function(mouse) { + kterminal.forceActiveFocus() if ((!kterminal.terminalUsesMouse || mouse.modifiers & Qt.ShiftModifier) && mouse.button == Qt.RightButton) { contextmenu.popup(); } else { diff --git a/app/qml/SettingsWindow.qml b/app/qml/SettingsWindow.qml index 99ac3c4..8f5b22e 100644 --- a/app/qml/SettingsWindow.qml +++ b/app/qml/SettingsWindow.qml @@ -25,6 +25,8 @@ import QtQuick.Layouts 1.3 import QtQuick.Dialogs ApplicationWindow { + readonly property real tabButtonPadding: 10 + id: settings_window title: qsTr("Settings") width: 640 @@ -37,15 +39,19 @@ ApplicationWindow { id: bar anchors { left: parent.left; right: parent.right; top: parent.top; } TabButton { + padding: tabButtonPadding text: qsTr("General") } TabButton { + padding: tabButtonPadding text: qsTr("Terminal") } TabButton { + padding: tabButtonPadding text: qsTr("Effects") } TabButton { + padding: tabButtonPadding text: qsTr("Advanced") } } diff --git a/app/qml/ShaderLibrary.qml b/app/qml/ShaderLibrary.qml deleted file mode 100644 index d555d46..0000000 --- a/app/qml/ShaderLibrary.qml +++ /dev/null @@ -1,92 +0,0 @@ -import QtQuick 2.0 - -QtObject { - property string rasterizationShader: - ((appSettings.rasterization === appSettings.no_rasterization) || - (appSettings.rasterization === appSettings.modern_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 f3d4246..6f6afb9 100644 --- a/app/qml/ShaderTerminal.qml +++ b/app/qml/ShaderTerminal.qml @@ -50,6 +50,7 @@ Item { property ShaderEffectSource source property BurnInEffect burnInEffect property ShaderEffectSource bloomSource + property QtObject timeManager property color fontColor: appSettings.fontColor property color backgroundColor: appSettings.backgroundColor @@ -105,7 +106,7 @@ Item { property real displayTerminalFrame: appSettings._frameSize > 0 || appSettings.screenCurvature > 0 - property real time: timeManager.time + property real time: timeManager ? timeManager.time : 0 property ShaderEffectSource noiseSource: noiseShaderSource property real frameSize: appSettings.frameSize @@ -160,10 +161,6 @@ Item { } } - ShaderLibrary { - id: shaderLibrary - } - ShaderEffect { id: staticShader diff --git a/app/qml/TerminalContainer.qml b/app/qml/TerminalContainer.qml index 2e9e361..c5411b3 100644 --- a/app/qml/TerminalContainer.qml +++ b/app/qml/TerminalContainer.qml @@ -32,6 +32,7 @@ ShaderTerminal { id: mainShader opacity: appSettings.windowOpacity * 0.3 + 0.7 + timeManager: terminalWindow.timeManager source: terminal.mainSource burnInEffect: terminal.burnInEffect virtualResolution: terminal.virtualResolution @@ -41,16 +42,15 @@ ShaderTerminal { ) bloomSource: bloomSourceLoader.item - TimeManager { - id: timeManager - enableTimer: terminalWindow.visible - } - PreprocessedTerminal { id: terminal anchors.fill: parent } + function activate() { + terminal.mainTerminal.forceActiveFocus() + } + // EFFECTS //////////////////////////////////////////////////////////////// Loader { id: bloomEffectLoader diff --git a/app/qml/TerminalTabs.qml b/app/qml/TerminalTabs.qml new file mode 100644 index 0000000..6fe61cb --- /dev/null +++ b/app/qml/TerminalTabs.qml @@ -0,0 +1,128 @@ +/******************************************************************************* +* 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 . +*******************************************************************************/ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +Item { + id: tabsRoot + + readonly property string title: stack.currentItem ? stack.currentItem.title : "" + readonly property size terminalSize: stack.currentItem ? stack.currentItem.terminalSize : Qt.size(0, 0) + property alias currentIndex: tabBar.currentIndex + readonly property int count: tabsModel.count + + function addTab() { + tabsModel.append({ title: qsTr("Tab %1").arg(tabsModel.count + 1) }) + tabBar.currentIndex = tabsModel.count - 1 + } + + function closeTab(index) { + if (tabsModel.count <= 1) + return + + tabsModel.remove(index) + if (tabBar.currentIndex >= tabsModel.count) { + tabBar.currentIndex = tabsModel.count - 1 + } + } + + function closeCurrentTab() { + closeTab(tabBar.currentIndex) + } + + ListModel { + id: tabsModel + } + + Component.onCompleted: addTab() + + ColumnLayout { + anchors.fill: parent + spacing: 0 + + TabBar { + id: tabBar + Layout.fillWidth: true + focusPolicy: Qt.NoFocus + visible: tabsModel.count > 1 + + background: Rectangle { + color: palette.window + } + + Repeater { + model: tabsModel + TabButton { + id: tabButton + contentItem: RowLayout { + anchors.fill: parent + anchors { leftMargin: 6; rightMargin: 6 } + spacing: 6 + + Label { + text: model.title + elide: Text.ElideRight + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + } + + ToolButton { + text: "\u00d7" + focusPolicy: Qt.NoFocus + visible: tabsModel.count > 1 + enabled: visible + Layout.alignment: Qt.AlignVCenter + onClicked: tabsRoot.closeTab(index) + } + } + } + } + } + + StackLayout { + id: stack + Layout.fillWidth: true + Layout.fillHeight: true + currentIndex: tabBar.currentIndex + + Repeater { + model: tabsModel + onItemAdded: function(index, item) { + if (index === tabBar.currentIndex) + item.activate() + } + TerminalContainer { + Layout.fillWidth: true + Layout.fillHeight: true + onTitleChanged: tabsModel.setProperty(index, "title", title) + } + } + } + } + + Connections { + target: tabBar + onCurrentIndexChanged: { + if (stack.currentItem) + stack.currentItem.activate() + } + } +} diff --git a/app/qml/main.qml b/app/qml/main.qml index 8ae0774..e6321c4 100644 --- a/app/qml/main.qml +++ b/app/qml/main.qml @@ -71,7 +71,7 @@ ApplicationWindow { color: "#00000000" - title: terminalContainer.title || qsTr(appSettings.wintitle) + title: terminalTabs.title || qsTr(appSettings.wintitle) Action { id: showMenubarAction @@ -137,11 +137,27 @@ ApplicationWindow { aboutDialog.raise() } } + Action { + id: newTabAction + text: qsTr("New Tab") + onTriggered: terminalTabs.addTab() + } + Action { + id: closeTabAction + text: qsTr("Close Tab") + enabled: terminalTabs.count > 1 + onTriggered: terminalTabs.closeCurrentTab() + } ApplicationSettings { id: appSettings } - TerminalContainer { - id: terminalContainer + TimeManager { + id: sharedTimeManager + enableTimer: terminalWindow.visible + } + property alias timeManager: sharedTimeManager + TerminalTabs { + id: terminalTabs width: parent.width height: (parent.height + Math.abs(y)) } @@ -158,7 +174,7 @@ ApplicationWindow { active: appSettings.showTerminalSize sourceComponent: SizeOverlay { z: 3 - terminalSize: terminalContainer.terminalSize + terminalSize: terminalTabs.terminalSize } } onClosing: { diff --git a/app/qml/menus/FullContextMenu.qml b/app/qml/menus/FullContextMenu.qml index 2be1639..c22d1f8 100644 --- a/app/qml/menus/FullContextMenu.qml +++ b/app/qml/menus/FullContextMenu.qml @@ -33,6 +33,15 @@ Menu { } MenuSeparator {} + Menu { + title: qsTr("Tabs") + MenuItem { + action: newTabAction + } + MenuItem { + action: closeTabAction + } + } Menu { title: qsTr("File") diff --git a/app/qml/menus/ShortContextMenu.qml b/app/qml/menus/ShortContextMenu.qml index 9d8f63b..95cef0e 100644 --- a/app/qml/menus/ShortContextMenu.qml +++ b/app/qml/menus/ShortContextMenu.qml @@ -28,4 +28,14 @@ Menu { MenuItem { action: pasteAction } + MenuSeparator {} + Menu { + title: qsTr("Tabs") + MenuItem { + action: newTabAction + } + MenuItem { + action: closeTabAction + } + } } diff --git a/app/qml/resources.qrc b/app/qml/resources.qrc index f2d0960..4e4fc9c 100644 --- a/app/qml/resources.qrc +++ b/app/qml/resources.qrc @@ -21,6 +21,7 @@ Storage.qml SettingsAdvancedTab.qml TerminalContainer.qml + TerminalTabs.qml images/crt256.png utils.js images/allNoise512.png @@ -42,7 +43,6 @@ menus/WindowMenu.qml menus/FullContextMenu.qml menus/ShortContextMenu.qml - ShaderLibrary.qml menus/OSXMenu.qml ../shaders/terminal_dynamic.vert.qsb ../shaders/terminal_static.vert.qsb diff --git a/app/shaders/terminal_static_rgb0_bloom0_curve0_shine0.frag.qsb b/app/shaders/terminal_static_rgb0_bloom0_curve0_shine0.frag.qsb new file mode 100644 index 0000000..afaa6c3 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_bloom0_curve0_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_bloom0_curve0_shine1.frag.qsb b/app/shaders/terminal_static_rgb0_bloom0_curve0_shine1.frag.qsb new file mode 100644 index 0000000..6bba6e7 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_bloom0_curve0_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_bloom0_curve1_shine0.frag.qsb b/app/shaders/terminal_static_rgb0_bloom0_curve1_shine0.frag.qsb new file mode 100644 index 0000000..eade077 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_bloom0_curve1_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_bloom0_curve1_shine1.frag.qsb b/app/shaders/terminal_static_rgb0_bloom0_curve1_shine1.frag.qsb new file mode 100644 index 0000000..9f97211 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_bloom0_curve1_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_bloom1_curve0_shine0.frag.qsb b/app/shaders/terminal_static_rgb0_bloom1_curve0_shine0.frag.qsb new file mode 100644 index 0000000..93be2df Binary files /dev/null and b/app/shaders/terminal_static_rgb0_bloom1_curve0_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_bloom1_curve0_shine1.frag.qsb b/app/shaders/terminal_static_rgb0_bloom1_curve0_shine1.frag.qsb new file mode 100644 index 0000000..d5658a9 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_bloom1_curve0_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_bloom1_curve1_shine0.frag.qsb b/app/shaders/terminal_static_rgb0_bloom1_curve1_shine0.frag.qsb new file mode 100644 index 0000000..b4a2ec8 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_bloom1_curve1_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_bloom1_curve1_shine1.frag.qsb b/app/shaders/terminal_static_rgb0_bloom1_curve1_shine1.frag.qsb new file mode 100644 index 0000000..6b275b1 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_bloom1_curve1_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_bloom0_curve0_shine0.frag.qsb b/app/shaders/terminal_static_rgb1_bloom0_curve0_shine0.frag.qsb new file mode 100644 index 0000000..d22b6f7 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_bloom0_curve0_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_bloom0_curve0_shine1.frag.qsb b/app/shaders/terminal_static_rgb1_bloom0_curve0_shine1.frag.qsb new file mode 100644 index 0000000..11ac6ac Binary files /dev/null and b/app/shaders/terminal_static_rgb1_bloom0_curve0_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_bloom0_curve1_shine0.frag.qsb b/app/shaders/terminal_static_rgb1_bloom0_curve1_shine0.frag.qsb new file mode 100644 index 0000000..5911d99 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_bloom0_curve1_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_bloom0_curve1_shine1.frag.qsb b/app/shaders/terminal_static_rgb1_bloom0_curve1_shine1.frag.qsb new file mode 100644 index 0000000..8153274 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_bloom0_curve1_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_bloom1_curve0_shine0.frag.qsb b/app/shaders/terminal_static_rgb1_bloom1_curve0_shine0.frag.qsb new file mode 100644 index 0000000..e28fd4a Binary files /dev/null and b/app/shaders/terminal_static_rgb1_bloom1_curve0_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_bloom1_curve0_shine1.frag.qsb b/app/shaders/terminal_static_rgb1_bloom1_curve0_shine1.frag.qsb new file mode 100644 index 0000000..4ae50ea Binary files /dev/null and b/app/shaders/terminal_static_rgb1_bloom1_curve0_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_bloom1_curve1_shine0.frag.qsb b/app/shaders/terminal_static_rgb1_bloom1_curve1_shine0.frag.qsb new file mode 100644 index 0000000..705559c Binary files /dev/null and b/app/shaders/terminal_static_rgb1_bloom1_curve1_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_bloom1_curve1_shine1.frag.qsb b/app/shaders/terminal_static_rgb1_bloom1_curve1_shine1.frag.qsb new file mode 100644 index 0000000..085ed5b Binary files /dev/null and b/app/shaders/terminal_static_rgb1_bloom1_curve1_shine1.frag.qsb differ