diff --git a/app/qml/TerminalTabs.qml b/app/qml/TerminalTabs.qml
index 361a172..9a26886 100644
--- a/app/qml/TerminalTabs.qml
+++ b/app/qml/TerminalTabs.qml
@@ -18,18 +18,19 @@
* along with this program. If not, see .
*******************************************************************************/
import QtQuick
-import QtQuick.Controls
import QtQuick.Layouts
Item {
id: tabsRoot
- readonly property int innerPadding: 6
- readonly property string currentTitle: tabsModel.get(currentIndex).title ?? "cool-retro-term"
+ readonly property string currentTitle: tabsModel.count > 0
+ ? (tabsModel.get(currentIndex).title ?? "cool-retro-term")
+ : "cool-retro-term"
readonly property size terminalSize: stack.currentItem ? stack.currentItem.terminalSize : Qt.size(0, 0)
- property alias currentIndex: tabBar.currentIndex
+ property int currentIndex: 0
readonly property int count: tabsModel.count
property var hostWindow
+ property alias tabsModel: tabsModel
function normalizeTitle(rawTitle) {
if (rawTitle === undefined || rawTitle === null) {
@@ -40,7 +41,7 @@ Item {
function addTab() {
tabsModel.append({ title: "" })
- tabBar.currentIndex = tabsModel.count - 1
+ currentIndex = tabsModel.count - 1
}
function closeTab(index) {
@@ -50,7 +51,7 @@ Item {
}
tabsModel.remove(index)
- tabBar.currentIndex = Math.min(tabBar.currentIndex, tabsModel.count - 1)
+ currentIndex = Math.min(currentIndex, tabsModel.count - 1)
}
ListModel {
@@ -63,69 +64,11 @@ Item {
anchors.fill: parent
spacing: 0
- Rectangle {
- id: tabRow
- Layout.fillWidth: true
- height: rowLayout.implicitHeight
- color: palette.window
- visible: tabsModel.count > 1
-
- RowLayout {
- id: rowLayout
- anchors.fill: parent
- spacing: 0
-
- TabBar {
- id: tabBar
- Layout.fillWidth: true
- Layout.fillHeight: true
- focusPolicy: Qt.NoFocus
-
- Repeater {
- model: tabsModel
- TabButton {
- id: tabButton
- contentItem: RowLayout {
- anchors.fill: parent
- anchors { leftMargin: innerPadding; rightMargin: innerPadding }
- spacing: innerPadding
-
- Label {
- text: model.title
- elide: Text.ElideRight
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignVCenter
- }
-
- ToolButton {
- text: "\u00d7"
- focusPolicy: Qt.NoFocus
- padding: innerPadding
- Layout.alignment: Qt.AlignVCenter
- onClicked: tabsRoot.closeTab(index)
- }
- }
- }
- }
- }
-
- ToolButton {
- id: addTabButton
- text: "+"
- focusPolicy: Qt.NoFocus
- Layout.fillHeight: true
- padding: innerPadding
- Layout.alignment: Qt.AlignVCenter
- onClicked: tabsRoot.addTab()
- }
- }
- }
-
StackLayout {
id: stack
Layout.fillWidth: true
Layout.fillHeight: true
- currentIndex: tabBar.currentIndex
+ currentIndex: tabsRoot.currentIndex
Repeater {
model: tabsModel
diff --git a/app/qml/TerminalTabsBar.qml b/app/qml/TerminalTabsBar.qml
new file mode 100644
index 0000000..cf08eeb
--- /dev/null
+++ b/app/qml/TerminalTabsBar.qml
@@ -0,0 +1,217 @@
+/*******************************************************************************
+* 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
+import QtQuick.Window
+
+Item {
+ id: barRoot
+
+ readonly property int innerPadding: 6
+ readonly property int leftInset: (isMacOS && !showWindowControls) ? 72 : 0
+ property var tabsController
+ property var hostWindow
+ property bool isMacOS: false
+ property bool showWindowControls: true
+ property bool windowControlsOnLeft: false
+ property bool enableSystemMove: true
+ property bool enableDoubleClickMaximize: true
+
+ implicitHeight: rowLayout.implicitHeight
+
+ function toggleMaximize() {
+ if (!hostWindow) {
+ return
+ }
+ hostWindow.visibility = (hostWindow.visibility === Window.Maximized)
+ ? Window.Windowed
+ : Window.Maximized
+ }
+
+ onTabsControllerChanged: {
+ if (tabsController) {
+ tabBar.currentIndex = tabsController.currentIndex
+ }
+ }
+
+ Component.onCompleted: {
+ if (tabsController) {
+ tabBar.currentIndex = tabsController.currentIndex
+ }
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ color: palette.window
+ }
+
+ RowLayout {
+ id: rowLayout
+ anchors.fill: parent
+ spacing: 0
+
+ Item {
+ Layout.fillHeight: true
+ Layout.preferredWidth: leftInset
+ visible: leftInset > 0
+ }
+
+ Loader {
+ active: showWindowControls && windowControlsOnLeft
+ sourceComponent: windowControlsComponent
+ }
+
+ TabBar {
+ id: tabBar
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ focusPolicy: Qt.NoFocus
+
+ onCurrentIndexChanged: {
+ if (tabsController && tabsController.currentIndex !== currentIndex) {
+ tabsController.currentIndex = currentIndex
+ }
+ }
+
+ Repeater {
+ model: tabsController ? tabsController.tabsModel : null
+ TabButton {
+ id: tabButton
+ contentItem: RowLayout {
+ anchors.fill: parent
+ anchors { leftMargin: innerPadding; rightMargin: innerPadding }
+ spacing: innerPadding
+
+ Label {
+ text: model.title
+ elide: Text.ElideRight
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignVCenter
+ }
+
+ ToolButton {
+ text: "\u00d7"
+ focusPolicy: Qt.NoFocus
+ padding: innerPadding
+ Layout.alignment: Qt.AlignVCenter
+ onClicked: {
+ if (tabsController) {
+ tabsController.closeTab(index)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ ToolButton {
+ id: addTabButton
+ text: "+"
+ focusPolicy: Qt.NoFocus
+ Layout.fillHeight: true
+ padding: innerPadding
+ Layout.alignment: Qt.AlignVCenter
+ onClicked: {
+ if (tabsController) {
+ tabsController.addTab()
+ }
+ }
+ }
+
+ Loader {
+ active: showWindowControls && !windowControlsOnLeft
+ sourceComponent: windowControlsComponent
+ }
+ }
+
+ Component {
+ id: windowControlsComponent
+ RowLayout {
+ id: windowControls
+ Layout.fillHeight: true
+ Layout.alignment: Qt.AlignVCenter
+ spacing: 0
+
+ ToolButton {
+ text: "\u2212"
+ focusPolicy: Qt.NoFocus
+ padding: innerPadding
+ Layout.alignment: Qt.AlignVCenter
+ onClicked: {
+ if (hostWindow) {
+ hostWindow.visibility = Window.Minimized
+ }
+ }
+ }
+
+ ToolButton {
+ text: hostWindow && hostWindow.visibility === Window.Maximized ? "\u2752" : "\u25a1"
+ focusPolicy: Qt.NoFocus
+ padding: innerPadding
+ Layout.alignment: Qt.AlignVCenter
+ onClicked: toggleMaximize()
+ }
+
+ ToolButton {
+ text: "\u00d7"
+ focusPolicy: Qt.NoFocus
+ padding: innerPadding
+ Layout.alignment: Qt.AlignVCenter
+ onClicked: {
+ if (hostWindow) {
+ hostWindow.close()
+ }
+ }
+ }
+ }
+ }
+
+ Connections {
+ target: tabsController
+ function onCurrentIndexChanged() {
+ if (tabBar.currentIndex !== tabsController.currentIndex) {
+ tabBar.currentIndex = tabsController.currentIndex
+ }
+ }
+ }
+
+ DragHandler {
+ acceptedDevices: PointerDevice.Mouse
+ acceptedButtons: Qt.LeftButton
+ grabPermissions: PointerHandler.CanTakeOverFromItems
+ target: null
+ onActiveChanged: {
+ if (active && hostWindow && enableSystemMove) {
+ hostWindow.startSystemMove()
+ }
+ }
+ }
+
+ TapHandler {
+ acceptedButtons: Qt.LeftButton
+ onTapped: {
+ if (tapCount === 2 && enableDoubleClickMaximize) {
+ toggleMaximize()
+ }
+ }
+ }
+}
diff --git a/app/qml/TerminalWindow.qml b/app/qml/TerminalWindow.qml
index 232c4aa..dda4e42 100644
--- a/app/qml/TerminalWindow.qml
+++ b/app/qml/TerminalWindow.qml
@@ -20,6 +20,7 @@
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 2.3
+import QtQuick.Layouts
import "menus"
@@ -39,6 +40,8 @@ ApplicationWindow {
visible: false
+ flags: Qt.Window | Qt.FramelessWindowHint
+
property bool fullscreen: appSettings.fullscreen
onFullscreenChanged: visibility = (fullscreen ? Window.FullScreen : Window.Windowed)
@@ -137,11 +140,27 @@ ApplicationWindow {
text: qsTr("New Tab")
onTriggered: terminalTabs.addTab()
}
- TerminalTabs {
- id: terminalTabs
- width: parent.width
- height: (parent.height + Math.abs(y))
- hostWindow: terminalWindow
+ ColumnLayout {
+ anchors.fill: parent
+ spacing: 0
+
+ TerminalTabsBar {
+ Layout.fillWidth: true
+ tabsController: terminalTabs
+ hostWindow: terminalWindow
+ isMacOS: appSettings.isMacOS
+ showWindowControls: true
+ windowControlsOnLeft: appSettings.isMacOS
+ enableSystemMove: true
+ enableDoubleClickMaximize: true
+ }
+
+ TerminalTabs {
+ id: terminalTabs
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ hostWindow: terminalWindow
+ }
}
Loader {
anchors.centerIn: parent
@@ -151,6 +170,77 @@ ApplicationWindow {
terminalSize: terminalTabs.terminalSize
}
}
+
+ Item {
+ id: resizeHandles
+ anchors.fill: parent
+ visible: true
+ property int resizeMargin: 6
+
+ MouseArea {
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ width: resizeHandles.resizeMargin
+ cursorShape: Qt.SizeHorCursor
+ onPressed: terminalWindow.startSystemResize(Qt.LeftEdge)
+ }
+
+ MouseArea {
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ width: resizeHandles.resizeMargin
+ cursorShape: Qt.SizeHorCursor
+ onPressed: terminalWindow.startSystemResize(Qt.RightEdge)
+ }
+
+ MouseArea {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ height: resizeHandles.resizeMargin
+ cursorShape: Qt.SizeVerCursor
+ onPressed: terminalWindow.startSystemResize(Qt.BottomEdge)
+ }
+
+ MouseArea {
+ anchors.left: parent.left
+ anchors.top: parent.top
+ width: resizeHandles.resizeMargin
+ height: resizeHandles.resizeMargin
+ cursorShape: Qt.SizeFDiagCursor
+ onPressed: terminalWindow.startSystemResize(Qt.TopEdge | Qt.LeftEdge)
+ }
+
+ MouseArea {
+ anchors.right: parent.right
+ anchors.top: parent.top
+ width: resizeHandles.resizeMargin
+ height: resizeHandles.resizeMargin
+ cursorShape: Qt.SizeBDiagCursor
+ onPressed: terminalWindow.startSystemResize(Qt.TopEdge | Qt.RightEdge)
+ }
+
+ MouseArea {
+ anchors.left: parent.left
+ anchors.bottom: parent.bottom
+ width: resizeHandles.resizeMargin
+ height: resizeHandles.resizeMargin
+ cursorShape: Qt.SizeBDiagCursor
+ onPressed: terminalWindow.startSystemResize(Qt.BottomEdge | Qt.LeftEdge)
+ }
+
+ MouseArea {
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ width: resizeHandles.resizeMargin
+ height: resizeHandles.resizeMargin
+ cursorShape: Qt.SizeFDiagCursor
+ onPressed: terminalWindow.startSystemResize(Qt.BottomEdge | Qt.RightEdge)
+ }
+ }
+
onClosing: {
appRoot.closeWindow(terminalWindow)
}
diff --git a/app/qml/main.qml b/app/qml/main.qml
index a0e7eaa..0f96190 100644
--- a/app/qml/main.qml
+++ b/app/qml/main.qml
@@ -38,14 +38,15 @@ QtObject {
visible: false
}
- property Component windowComponent: Component {
- TerminalWindow { }
- }
-
property ListModel windowsModel: ListModel { }
function createWindow() {
- var window = windowComponent.createObject(null)
+ var component = Qt.createComponent("TerminalWindow.qml")
+ if (component.status === Component.Error) {
+ console.error(component.errorString())
+ return
+ }
+ var window = component.createObject(null)
if (!window)
return
diff --git a/app/qml/resources.qrc b/app/qml/resources.qrc
index 961600e..886897c 100644
--- a/app/qml/resources.qrc
+++ b/app/qml/resources.qrc
@@ -22,6 +22,7 @@
SettingsAdvancedTab.qml
TerminalContainer.qml
TerminalTabs.qml
+ TerminalTabsBar.qml
images/crt256.png
utils.js
images/allNoise512.png
diff --git a/qmltermwidget b/qmltermwidget
index a3822c5..7a5f3b6 160000
--- a/qmltermwidget
+++ b/qmltermwidget
@@ -1 +1 @@
-Subproject commit a3822c5de93bd72138fbb5d606da96cb1f7e79f0
+Subproject commit 7a5f3b68a58bab963ac97a8cde0d13bfe0ae4d0b