Is there a nice way to record the window state of a QtQuick application? The documentation gives the following method:
Settings {
property alias x: mainWindow.x
property alias y: mainWindow.y
property alias width: mainWindow.width
property alias height: mainWindow.height
However that has three flaws:
Does anyone have any better code?
I managed to make something which works pretty well, as far as my limited testing shows. I did have to do one hacky bit which is because unfortunately Window.visibility
is updated after Window.x/y/width/height
, which means that if you are trying to record the windowed geometry, you can't just check the state of Window.visibility
in onXChanged
. Instead I had to record the two previous values and then discard the most recent one if the window is maximised.
Edit: This doesn't quite work perfectly. If you maximise the window, then close the app. Then open it then close it again. Then open it once more, when you unmaximise it won't go back to the correct windowed size. I think fixing that would be ugly enough QML that I'll probably implement this in C++ where it really belongs.
import QtQuick 2.3
import QtQuick.Window 2.2
import QtQuick.Controls 1.3
import Qt.labs.settings 1.0
Item {
property Window window
// Default properties for the application's first run.
property int defaultX: 100
property int defaultY: 100
property int defaultWidth: 500
property int defaultHeight: 500
property bool defaultMaximised: false
Settings {
id: windowStateSettings
category: "WindowState"
property int x
property int y
property int width
property int height
property bool maximised
}
Component.onCompleted: {
if (windowStateSettings.width === 0 || windowStateSettings.height === 0)
{
// First run, or width/height are screwed up.
curX = defaultX;
curY = defaultY;
curWidth = defaultWidth;
curHeight = defaultHeight;
curMaximised = defaultMaximised
}
else
{
curX = windowStateSettings.x;
curY = windowStateSettings.y;
curWidth = windowStateSettings.width;
curHeight = windowStateSettings.height;
curMaximised = windowStateSettings.maximised
}
window.x = prevX = curX;
window.y = prevY = curY;
window.width = prevWidth = curWidth;
window.height = prevHeight = curHeight;
if (curMaximised)
window.visibility = Window.Maximized;
}
// Remember the windowed geometry, and whether it is maximised or not.
// Internal use only.
property int curX
property int curY
property int curWidth
property int curHeight
property bool curMaximised
// We also have to save the previous values of X/Y/Width/Height so they can be restored if we maximise, since we
// can't tell that the updated X,Y values are because of maximisation until *after* the maximisation.
property int prevX
property int prevY
property int prevWidth
property int prevHeight
Connections {
target: window
onVisibilityChanged: {
if (window.visibility === Window.Maximized)
{
curMaximised = true;
// Ignore the latest X/Y/width/height values.
curX = prevX;
curY = prevY;
curWidth = prevWidth;
curHeight = prevHeight;
}
else if (window.visibility === Window.Windowed)
{
curMaximised = false;
}
else if (window.visibility === Window.Hidden)
{
// Save settings.
windowStateSettings.x = curX;
windowStateSettings.y = curY;
windowStateSettings.width = curWidth;
windowStateSettings.height = curHeight;
windowStateSettings.maximised = curMaximised;
}
}
// We can't use window.visibility here to ignore the maximised geometry because it changes after the geometry.
// Instead we cache the two previous values and revert them if maximised.
onXChanged: {
prevX = curX;
curX = window.x;
}
onYChanged: {
prevY = curY;
curY = window.y;
}
onWidthChanged: {
prevWidth = curWidth;
curWidth = window.width;
}
onHeightChanged: {
prevHeight = curHeight;
curHeight = window.height;
}
}
}
Use it like this:
ApplicationWindow {
id: mainWindow
WindowStateSaver {
window: mainWindow
defaultWidth: 1000 // Or whatever. You can also specify the defaultX/Y if you want.
defaultHeight: 700
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With