Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmlpreviewposition.cpp
Go to the documentation of this file.
1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QtCore/qiodevice.h>
7#include <QtGui/qwindow.h>
8#include <QtGui/qscreen.h>
9#include <QtGui/qguiapplication.h>
10#include <QtCore/QIODevice>
11#include <private/qhighdpiscaling_p.h>
12
14
16{
17 QVector<QQmlPreviewPosition::ScreenData> screensData;
18
19 for (QScreen *screen : QGuiApplication::screens()) {
20 QQmlPreviewPosition::ScreenData sd{screen->name(), screen->geometry()};
21 screensData.append(sd);
22 }
23 return screensData;
24}
25
26static QScreen *findScreen(const QString &nameOfScreen)
27{
28 for (QScreen *screen : QGuiApplication::screens()) {
29 if (screen->name() == nameOfScreen)
30 return screen;
31 }
32 return nullptr;
33}
34
35static QDataStream &operator<<(QDataStream &out, const QQmlPreviewPosition::ScreenData &screenData)
36{
37 out << screenData.name;
38 out << screenData.rect;
39 return out;
40}
41
42static QDataStream &operator>>(QDataStream &in, QQmlPreviewPosition::ScreenData &screenData)
43{
44 in >> screenData.name;
45 in >> screenData.rect;
46 return in;
47}
48
50{
51 return other.rect == rect && other.name == name;
52}
53
55 : m_settings("QtProject", "QtQmlPreview")
56{
57 m_savePositionTimer.setSingleShot(true);
58 m_savePositionTimer.setInterval(500);
59 QObject::connect(&m_savePositionTimer, &QTimer::timeout, &m_savePositionTimer, [this]() {
60 saveWindowPosition();
61 });
62}
63
67
69{
70 Q_ASSERT(window);
71 // only save the position if we already tried to get the last saved position
72 if (m_initializeState == PositionInitialized) {
73 m_hasPosition = true;
74 auto screen = window->screen();
75 auto nativePosition = QHighDpiScaling::mapPositionToNative(window->framePosition(),
76 screen->handle());
77 m_lastWindowPosition = { screen->name(), nativePosition, window->size() };
78
79 m_savePositionTimer.start();
80 }
81 if (state == InitializePosition)
82 m_initializeState = InitializePosition;
83}
84
85void QQmlPreviewPosition::saveWindowPosition()
86{
87 if (m_hasPosition) {
88 const QByteArray positionAsByteArray = fromPositionToByteArray(m_lastWindowPosition);
89 if (!m_settingsKey.isNull())
90 m_settings.setValue(m_settingsKey, positionAsByteArray);
91
92 m_settings.setValue(QLatin1String("global_lastpostion"), positionAsByteArray);
93 }
94}
95
97{
98 m_settingsKey = url.toString(QUrl::PreferLocalFile) + QLatin1String("_lastpostion");
99
100 if (m_settings.contains(m_settingsKey)) {
101 m_hasPosition = true;
102 readLastPositionFromByteArray(m_settings.value(m_settingsKey).toByteArray());
103 }
104}
105
107{
108 Q_ASSERT(window);
109 m_initializeState = PositionInitialized;
110 if (m_currentInitScreensData.isEmpty())
111 m_currentInitScreensData = initScreensData();
112 // if it is the first time we just use the fall back from a last shown qml file
113 if (!m_hasPosition) {
114 if (!m_settings.contains(QLatin1String("global_lastpostion")))
115 return;
116 readLastPositionFromByteArray(m_settings.value(QLatin1String("global_lastpostion"))
117 .toByteArray());
118 }
119 setPosition(m_lastWindowPosition, window);
120}
121
122QByteArray QQmlPreviewPosition::fromPositionToByteArray(
123 const QQmlPreviewPosition::Position &position)
124{
125 QByteArray array;
126 QDataStream stream(&array, QIODevice::WriteOnly);
127 stream.setVersion(QDataStream::Qt_5_12);
128
129 const quint16 majorVersion = 1;
130 const quint16 minorVersion = 0;
131
132 stream << majorVersion << minorVersion << m_currentInitScreensData << position.screenName
133 << position.nativePosition << position.size;
134 return array;
135}
136
137void QQmlPreviewPosition::readLastPositionFromByteArray(const QByteArray &array)
138{
139 QDataStream stream(array);
140 stream.setVersion(QDataStream::Qt_5_12);
141
142 // no version check for 1.0
143 //const quint16 currentMajorVersion = 1;
144 quint16 majorVersion = 0;
145 quint16 minorVersion = 0;
146
147 stream >> majorVersion >> minorVersion;
148
149 QVector<ScreenData> initScreensData;
150 stream >> initScreensData;
151
152 if (m_currentInitScreensData != initScreensData)
153 return;
154
155 QString nameOfScreen;
156 stream >> nameOfScreen;
157
158 QScreen *screen = findScreen(nameOfScreen);
159 if (!screen)
160 return;
161
162 QPoint nativePosition;
163 stream >> nativePosition;
164 if (nativePosition.isNull())
165 return;
166
167 QSize size;
168 stream >> size;
169
170 m_lastWindowPosition = { nameOfScreen, nativePosition, size };
171}
172
173void QQmlPreviewPosition::setPosition(const QQmlPreviewPosition::Position &position,
174 QWindow *window)
175{
176 if (position.nativePosition.isNull())
177 return;
178 if (QScreen *screen = findScreen(position.screenName)) {
179 window->setScreen(screen);
180 const auto point = QHighDpiScaling::mapPositionFromNative(position.nativePosition,
181 screen->handle());
182
183 const QRect geometry(point, position.size);
184 if (screen->virtualGeometry().contains(geometry))
185 window->setFramePosition(point);
186 else
187 qWarning("preview position is out of screen");
188 }
189}
190
191QT_END_NAMESPACE
bool operator==(const QQmlPreviewPosition::ScreenData &other) const
void loadWindowPositionSettings(const QUrl &url)
void takePosition(QWindow *window, InitializeState state=PositionInitialized)
void initLastSavedWindowPosition(QWindow *window)
static QT_BEGIN_NAMESPACE QVector< QQmlPreviewPosition::ScreenData > initScreensData()
static QDataStream & operator<<(QDataStream &out, const QQmlPreviewPosition::ScreenData &screenData)
static QScreen * findScreen(const QString &nameOfScreen)
static QDataStream & operator>>(QDataStream &in, QQmlPreviewPosition::ScreenData &screenData)