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// Qt-Security score:significant
4
6
7#include <QtCore/qiodevice.h>
8#include <QtGui/qwindow.h>
9#include <QtGui/qscreen.h>
10#include <QtGui/qguiapplication.h>
11#include <QtCore/QIODevice>
12#include <private/qhighdpiscaling_p.h>
13
15
17{
18 QVector<QQmlPreviewPosition::ScreenData> screensData;
19
20 for (QScreen *screen : QGuiApplication::screens()) {
21 QQmlPreviewPosition::ScreenData sd{screen->name(), screen->geometry()};
22 screensData.append(sd);
23 }
24 return screensData;
25}
26
27static QScreen *findScreen(const QString &nameOfScreen)
28{
29 for (QScreen *screen : QGuiApplication::screens()) {
30 if (screen->name() == nameOfScreen)
31 return screen;
32 }
33 return nullptr;
34}
35
36static QDataStream &operator<<(QDataStream &out, const QQmlPreviewPosition::ScreenData &screenData)
37{
38 out << screenData.name;
39 out << screenData.rect;
40 return out;
41}
42
43static QDataStream &operator>>(QDataStream &in, QQmlPreviewPosition::ScreenData &screenData)
44{
45 in >> screenData.name;
46 in >> screenData.rect;
47 return in;
48}
49
51{
52 return other.rect == rect && other.name == name;
53}
54
56 : m_settings("QtProject", "QtQmlPreview")
57{
58 m_savePositionTimer.setSingleShot(true);
59 m_savePositionTimer.setInterval(500);
60 QObject::connect(&m_savePositionTimer, &QTimer::timeout, &m_savePositionTimer, [this]() {
61 saveWindowPosition();
62 });
63}
64
68
70{
71 Q_ASSERT(window);
72 // only save the position if we already tried to get the last saved position
73 if (m_initializeState == PositionInitialized) {
74 m_hasPosition = true;
75 auto screen = window->screen();
76 auto nativePosition = QHighDpiScaling::mapPositionToNative(window->framePosition(),
77 screen->handle());
78 m_lastWindowPosition = { screen->name(), nativePosition, window->size() };
79
80 m_savePositionTimer.start();
81 }
82 if (state == InitializePosition)
83 m_initializeState = InitializePosition;
84}
85
86void QQmlPreviewPosition::saveWindowPosition()
87{
88 if (m_hasPosition) {
89 const QByteArray positionAsByteArray = fromPositionToByteArray(m_lastWindowPosition);
90 if (!m_settingsKey.isNull())
91 m_settings.setValue(m_settingsKey, positionAsByteArray);
92
93 m_settings.setValue(QLatin1String("global_lastpostion"), positionAsByteArray);
94 }
95}
96
98{
99 m_settingsKey = url.toString(QUrl::PreferLocalFile) + QLatin1String("_lastpostion");
100
101 if (m_settings.contains(m_settingsKey)) {
102 m_hasPosition = true;
103 readLastPositionFromByteArray(m_settings.value(m_settingsKey).toByteArray());
104 }
105}
106
108{
109 Q_ASSERT(window);
110 m_initializeState = PositionInitialized;
111 if (m_currentInitScreensData.isEmpty())
112 m_currentInitScreensData = initScreensData();
113 // if it is the first time we just use the fall back from a last shown qml file
114 if (!m_hasPosition) {
115 if (!m_settings.contains(QLatin1String("global_lastpostion")))
116 return;
117 readLastPositionFromByteArray(m_settings.value(QLatin1String("global_lastpostion"))
118 .toByteArray());
119 }
120 setPosition(m_lastWindowPosition, window);
121}
122
123QByteArray QQmlPreviewPosition::fromPositionToByteArray(
124 const QQmlPreviewPosition::Position &position)
125{
126 QByteArray array;
127 QDataStream stream(&array, QIODevice::WriteOnly);
128 stream.setVersion(QDataStream::Qt_5_12);
129
130 const quint16 majorVersion = 1;
131 const quint16 minorVersion = 0;
132
133 stream << majorVersion << minorVersion << m_currentInitScreensData << position.screenName
134 << position.nativePosition << position.size;
135 return array;
136}
137
138void QQmlPreviewPosition::readLastPositionFromByteArray(const QByteArray &array)
139{
140 QDataStream stream(array);
141 stream.setVersion(QDataStream::Qt_5_12);
142
143 // no version check for 1.0
144 //const quint16 currentMajorVersion = 1;
145 quint16 majorVersion = 0;
146 quint16 minorVersion = 0;
147
148 stream >> majorVersion >> minorVersion;
149
150 QVector<ScreenData> initScreensData;
151 stream >> initScreensData;
152
153 if (m_currentInitScreensData != initScreensData)
154 return;
155
156 QString nameOfScreen;
157 stream >> nameOfScreen;
158
159 QScreen *screen = findScreen(nameOfScreen);
160 if (!screen)
161 return;
162
163 QPoint nativePosition;
164 stream >> nativePosition;
165 if (nativePosition.isNull())
166 return;
167
168 QSize size;
169 stream >> size;
170
171 m_lastWindowPosition = { nameOfScreen, nativePosition, size };
172}
173
174void QQmlPreviewPosition::setPosition(const QQmlPreviewPosition::Position &position,
175 QWindow *window)
176{
177 if (position.nativePosition.isNull())
178 return;
179 if (QScreen *screen = findScreen(position.screenName)) {
180 window->setScreen(screen);
181 const auto point = QHighDpiScaling::mapPositionFromNative(position.nativePosition,
182 screen->handle());
183
184 const QRect geometry(point, position.size);
185 if (screen->virtualGeometry().contains(geometry))
186 window->setFramePosition(point);
187 else
188 qWarning("preview position is out of screen");
189 }
190}
191
192QT_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)
Combined button and popup list for selecting options.
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)