Changeset View
Changeset View
Standalone View
Standalone View
containments/desktop/plugins/folder/screenmapper.cpp
Show First 20 Lines • Show All 60 Lines • ▼ Show 20 Line(s) | |||||
61 | void ScreenMapper::removeScreen(int screenId, const QUrl &screenUrl) | 61 | void ScreenMapper::removeScreen(int screenId, const QUrl &screenUrl) | ||
62 | { | 62 | { | ||
63 | if (screenId < 0 || !m_availableScreens.contains(screenId)) | 63 | if (screenId < 0 || !m_availableScreens.contains(screenId)) | ||
64 | return; | 64 | return; | ||
65 | 65 | | |||
66 | const auto screenPathWithScheme = screenUrl.url(); | 66 | const auto screenPathWithScheme = screenUrl.url(); | ||
67 | // store the original location for the items | 67 | // store the original location for the items | ||
68 | auto it = m_screenItemMap.constBegin(); | 68 | auto it = m_screenItemMap.constBegin(); | ||
69 | QVector<QUrl> urlsToRemoveFromMapping; | ||||
69 | while (it != m_screenItemMap.constEnd()) { | 70 | while (it != m_screenItemMap.constEnd()) { | ||
70 | const auto name = it.key(); | 71 | const auto name = it.key(); | ||
71 | if (it.value() == screenId && name.url().startsWith(screenPathWithScheme)) { | 72 | if (it.value() == screenId && name.url().startsWith(screenPathWithScheme)) { | ||
73 | bool found = false; | ||||
74 | for (const auto &disabledUrls: qAsConst(m_itemsOnDisabledScreensMap)) { | ||||
75 | found = disabledUrls.contains(name); | ||||
76 | if (found) | ||||
77 | break; | ||||
78 | } | ||||
79 | if (!found) | ||||
72 | m_itemsOnDisabledScreensMap[screenId].append(name); | 80 | m_itemsOnDisabledScreensMap[screenId].append(name); | ||
81 | urlsToRemoveFromMapping.append(name); | ||||
73 | } | 82 | } | ||
74 | ++it; | 83 | ++it; | ||
75 | } | 84 | } | ||
76 | 85 | | |||
86 | saveDisabledScreensMap(); | ||||
87 | | ||||
88 | for (const auto &url: urlsToRemoveFromMapping) | ||||
89 | removeFromMap(url); | ||||
90 | | ||||
77 | m_availableScreens.removeAll(screenId); | 91 | m_availableScreens.removeAll(screenId); | ||
78 | 92 | | |||
79 | const auto newFirstScreen = std::min_element(m_availableScreens.constBegin(), m_availableScreens.constEnd()); | | |||
80 | auto pathIt = m_screensPerPath.find(screenUrl); | 93 | auto pathIt = m_screensPerPath.find(screenUrl); | ||
81 | if (pathIt != m_screensPerPath.end() && pathIt.value() > 0) { | 94 | if (pathIt != m_screensPerPath.end() && pathIt.value().size() > 0) { | ||
82 | int firstScreen = m_firstScreenForPath.value(screenUrl, -1); | 95 | // remove the screen for a certain url, used when switching the URL for a screen | ||
83 | if (firstScreen == screenId) { | 96 | pathIt->removeAll(screenId); | ||
84 | m_firstScreenForPath[screenUrl] = (newFirstScreen == m_availableScreens.constEnd()) ? -1 : *newFirstScreen; | | |||
85 | } | | |||
86 | *pathIt = pathIt.value() - 1; | | |||
87 | } else if (screenUrl.isEmpty()) { | 97 | } else if (screenUrl.isEmpty()) { | ||
88 | // The screen got completely removed, not only its path changed. | 98 | // the screen was indeed removed so all references to it needs to be cleaned up | ||
89 | // If the removed screen was the first screen for a desktop path, the first screen for that path | 99 | for (auto & pathIt: m_screensPerPath) { | ||
90 | // needs to be updated. | 100 | pathIt.removeAll(screenId); | ||
91 | for (auto it = m_firstScreenForPath.begin(); it != m_firstScreenForPath.end(); ++it) { | | |||
92 | if (*it == screenId) { | | |||
93 | *it = *newFirstScreen; | | |||
94 | | ||||
95 | // we have now the path for the screen that was removed, so adjust it | | |||
96 | pathIt = m_screensPerPath.find(it.key()); | | |||
97 | if (pathIt != m_screensPerPath.end()) { | | |||
98 | *pathIt = pathIt.value() - 1; | | |||
99 | } | | |||
100 | } | | |||
101 | } | 101 | } | ||
102 | } | 102 | } | ||
103 | 103 | | |||
104 | emit screensChanged(); | 104 | emit screensChanged(); | ||
105 | } | 105 | } | ||
106 | 106 | | |||
107 | void ScreenMapper::addScreen(int screenId, const QUrl &screenUrl) | 107 | void ScreenMapper::addScreen(int screenId, const QUrl &screenUrl) | ||
108 | { | 108 | { | ||
109 | if (screenId < 0 || m_availableScreens.contains(screenId)) | 109 | if (screenId < 0 || m_availableScreens.contains(screenId)) | ||
110 | return; | 110 | return; | ||
111 | 111 | | |||
112 | const auto screenPathWithScheme = screenUrl.url(); | 112 | const auto screenPathWithScheme = screenUrl.url(); | ||
113 | const bool isEmpty = (screenUrl.isEmpty() || screenUrl.path() == QLatin1String("/")); | | |||
114 | // restore the stored locations | 113 | // restore the stored locations | ||
115 | auto it = m_itemsOnDisabledScreensMap.find(screenId); | 114 | auto it = m_itemsOnDisabledScreensMap.find(screenId); | ||
116 | if (it != m_itemsOnDisabledScreensMap.end()) { | 115 | if (it != m_itemsOnDisabledScreensMap.end()) { | ||
117 | auto items = it.value(); | 116 | auto items = it.value(); | ||
118 | for (const auto &name: it.value()) { | 117 | for (const auto &name: it.value()) { | ||
119 | // add the items to the new screen, if they are on a disabled screen and their | 118 | // add the items to the new screen, if they are on a disabled screen and their | ||
120 | // location is below the new screen's path | 119 | // location is below the new screen's path | ||
121 | if (isEmpty || name.url().startsWith(screenPathWithScheme)) { | 120 | if (name.url().startsWith(screenPathWithScheme)) { | ||
122 | addMapping(name, screenId, DelayedSignal); | 121 | addMapping(name, screenId, DelayedSignal); | ||
123 | items.removeAll(name); | 122 | items.removeAll(name); | ||
124 | } | 123 | } | ||
125 | } | 124 | } | ||
126 | if (items.isEmpty()) { | 125 | if (items.isEmpty()) { | ||
127 | m_itemsOnDisabledScreensMap.erase(it); | 126 | m_itemsOnDisabledScreensMap.erase(it); | ||
128 | } else { | 127 | } else { | ||
129 | *it = items; | 128 | *it = items; | ||
130 | } | 129 | } | ||
131 | } | 130 | } | ||
131 | saveDisabledScreensMap(); | ||||
132 | 132 | | |||
133 | m_availableScreens.append(screenId); | 133 | m_availableScreens.append(screenId); | ||
134 | 134 | | |||
135 | // path is empty when a new screen appears that has no folderview base path associated with | 135 | // path is empty when a new screen appears that has no folderview base path associated with | ||
136 | if (!screenUrl.isEmpty()) { | 136 | if (!screenUrl.isEmpty()) { | ||
137 | auto it = m_screensPerPath.find(screenUrl); | 137 | auto it = m_screensPerPath.find(screenUrl); | ||
138 | int firstScreen = m_firstScreenForPath.value(screenUrl, -1); | | |||
139 | if (firstScreen == -1 || screenId < firstScreen) { | | |||
140 | m_firstScreenForPath[screenUrl] = screenId; | | |||
141 | } | | |||
142 | if (it == m_screensPerPath.end()) { | 138 | if (it == m_screensPerPath.end()) { | ||
143 | m_screensPerPath[screenUrl] = 1; | 139 | m_screensPerPath[screenUrl] = {screenId}; | ||
144 | } else { | 140 | } else { | ||
145 | *it = it.value() + 1; | 141 | it->append(screenId); | ||
146 | } | 142 | } | ||
147 | } | 143 | } | ||
148 | 144 | | |||
149 | emit screensChanged(); | 145 | emit screensChanged(); | ||
150 | } | 146 | } | ||
151 | 147 | | |||
152 | void ScreenMapper::addMapping(const QUrl &url, int screen, MappingSignalBehavior behavior) | 148 | void ScreenMapper::addMapping(const QUrl &url, int screen, MappingSignalBehavior behavior) | ||
153 | { | 149 | { | ||
154 | m_screenItemMap[url] = screen; | 150 | m_screenItemMap[url] = screen; | ||
155 | if (behavior == DelayedSignal) { | 151 | if (behavior == DelayedSignal) { | ||
156 | m_screenMappingChangedTimer->start(); | 152 | m_screenMappingChangedTimer->start(); | ||
157 | } else { | 153 | } else { | ||
158 | emit screenMappingChanged(); | 154 | emit screenMappingChanged(); | ||
159 | } | 155 | } | ||
160 | } | 156 | } | ||
161 | 157 | | |||
162 | void ScreenMapper::removeFromMap(const QUrl &url) | 158 | void ScreenMapper::removeFromMap(const QUrl &url) | ||
163 | { | 159 | { | ||
164 | m_screenItemMap.remove(url); | 160 | m_screenItemMap.remove(url); | ||
165 | m_screenMappingChangedTimer->start(); | 161 | m_screenMappingChangedTimer->start(); | ||
166 | } | 162 | } | ||
167 | 163 | | |||
168 | int ScreenMapper::firstAvailableScreen(const QUrl &screenUrl) const | 164 | int ScreenMapper::firstAvailableScreen(const QUrl &screenUrl) const | ||
169 | { | 165 | { | ||
170 | return m_firstScreenForPath.value(screenUrl, -1); | 166 | auto screens = m_screensPerPath[screenUrl]; | ||
167 | const auto newFirstScreen = std::min_element(screens.constBegin(), screens.constEnd()); | ||||
168 | return newFirstScreen == screens.constEnd() ? -1 : *newFirstScreen; | ||||
171 | } | 169 | } | ||
172 | 170 | | |||
173 | void ScreenMapper::removeItemFromDisabledScreen(const QUrl &url) | 171 | void ScreenMapper::removeItemFromDisabledScreen(const QUrl &url) | ||
174 | { | 172 | { | ||
175 | for (auto it = m_itemsOnDisabledScreensMap.begin(); | 173 | for (auto it = m_itemsOnDisabledScreensMap.begin(); | ||
176 | it != m_itemsOnDisabledScreensMap.end(); ++it) { | 174 | it != m_itemsOnDisabledScreensMap.end(); ++it) { | ||
177 | auto urls = &(*it); | 175 | auto urls = &(*it); | ||
178 | urls->removeAll(url); | 176 | urls->removeAll(url); | ||
179 | } | 177 | } | ||
180 | } | 178 | } | ||
181 | 179 | | |||
182 | #ifdef BUILD_TESTING | 180 | #ifdef BUILD_TESTING | ||
183 | void ScreenMapper::cleanup() | 181 | void ScreenMapper::cleanup() | ||
184 | { | 182 | { | ||
185 | m_screenItemMap.clear(); | 183 | m_screenItemMap.clear(); | ||
186 | m_itemsOnDisabledScreensMap.clear(); | 184 | m_itemsOnDisabledScreensMap.clear(); | ||
187 | m_firstScreenForPath.clear(); | | |||
188 | m_screensPerPath.clear(); | 185 | m_screensPerPath.clear(); | ||
189 | m_availableScreens.clear(); | 186 | m_availableScreens.clear(); | ||
190 | } | 187 | } | ||
191 | #endif | 188 | #endif | ||
192 | 189 | | |||
193 | void ScreenMapper::setCorona(Plasma::Corona *corona) | 190 | void ScreenMapper::setCorona(Plasma::Corona *corona) | ||
194 | { | 191 | { | ||
195 | if (m_corona != corona) { | 192 | if (m_corona != corona) { | ||
196 | Q_ASSERT(!m_corona); | 193 | Q_ASSERT(!m_corona); | ||
197 | 194 | | |||
198 | m_corona = corona; | 195 | m_corona = corona; | ||
199 | if (m_corona) { | 196 | if (m_corona) { | ||
200 | connect(m_corona, &Plasma::Corona::screenRemoved, this, [this] (int screenId) { | 197 | connect(m_corona, &Plasma::Corona::screenRemoved, this, [this] (int screenId) { | ||
201 | removeScreen(screenId, {}); | 198 | removeScreen(screenId, {}); | ||
202 | }); | 199 | }); | ||
203 | connect(m_corona, &Plasma::Corona::screenAdded, this, [this] (int screenId) { | 200 | connect(m_corona, &Plasma::Corona::screenAdded, this, [this] (int screenId) { | ||
204 | addScreen(screenId, {}); | 201 | addScreen(screenId, {}); | ||
205 | }); | 202 | }); | ||
206 | 203 | | |||
207 | auto config = m_corona->config(); | 204 | auto config = m_corona->config(); | ||
208 | KConfigGroup group(config, QLatin1String("ScreenMapping")); | 205 | KConfigGroup group(config, QLatin1String("ScreenMapping")); | ||
209 | const QStringList mapping = group.readEntry(QLatin1String("screenMapping"), QStringList{}); | 206 | const QStringList mapping = group.readEntry(QLatin1String("screenMapping"), QStringList{}); | ||
210 | setScreenMapping(mapping); | 207 | setScreenMapping(mapping); | ||
208 | readDisabledScreensMap(); | ||||
211 | } | 209 | } | ||
212 | } | 210 | } | ||
213 | } | 211 | } | ||
214 | 212 | | |||
215 | QStringList ScreenMapper::screenMapping() const | 213 | QStringList ScreenMapper::screenMapping() const | ||
216 | { | 214 | { | ||
217 | QStringList result; | 215 | QStringList result; | ||
218 | result.reserve(m_screenItemMap.count() * 2); | 216 | result.reserve(m_screenItemMap.count() * 2); | ||
Show All 33 Lines | 246 | { | |||
252 | 250 | | |||
253 | return screen; | 251 | return screen; | ||
254 | } | 252 | } | ||
255 | 253 | | |||
256 | QUrl ScreenMapper::stringToUrl(const QString &path) | 254 | QUrl ScreenMapper::stringToUrl(const QString &path) | ||
257 | { | 255 | { | ||
258 | return QUrl::fromUserInput(path, {}, QUrl::AssumeLocalFile); | 256 | return QUrl::fromUserInput(path, {}, QUrl::AssumeLocalFile); | ||
259 | } | 257 | } | ||
258 | | ||||
259 | void ScreenMapper::readDisabledScreensMap() | ||||
260 | { | ||||
261 | if (!m_corona) | ||||
262 | return; | ||||
263 | | ||||
264 | auto config = m_corona->config(); | ||||
265 | KConfigGroup group(config, QLatin1String("ScreenMapping")); | ||||
266 | const QStringList serializedMap = group.readEntry(QLatin1String("itemsOnDisabledScreens"), QStringList{}); | ||||
267 | m_itemsOnDisabledScreensMap.clear(); | ||||
268 | bool readingScreenId = true; | ||||
269 | int vectorSize = -1; | ||||
270 | int screenId = -1; | ||||
271 | int vectorCounter = 0; | ||||
272 | for (const auto &entry : serializedMap) { | ||||
273 | if (readingScreenId) { | ||||
274 | screenId = entry.toInt(); | ||||
275 | readingScreenId = false; | ||||
276 | } else if (vectorSize == -1) { | ||||
277 | vectorSize = entry.toInt(); | ||||
278 | } else { | ||||
279 | const auto url = stringToUrl(entry); | ||||
280 | m_itemsOnDisabledScreensMap[screenId].append(url); | ||||
281 | vectorCounter++; | ||||
282 | if (vectorCounter == vectorSize) { | ||||
283 | readingScreenId = true; | ||||
284 | screenId = -1; | ||||
285 | vectorCounter = 0; | ||||
286 | vectorSize = -1; | ||||
287 | } | ||||
288 | } | ||||
289 | } | ||||
290 | | ||||
291 | } | ||||
292 | | ||||
293 | void ScreenMapper::saveDisabledScreensMap() const | ||||
294 | { | ||||
295 | if (!m_corona) | ||||
296 | return; | ||||
297 | | ||||
298 | auto config = m_corona->config(); | ||||
299 | KConfigGroup group(config, QLatin1String("ScreenMapping")); | ||||
300 | QStringList serializedMap; | ||||
301 | auto it = m_itemsOnDisabledScreensMap.constBegin(); | ||||
302 | for (; it != m_itemsOnDisabledScreensMap.constEnd(); ++it) { | ||||
303 | serializedMap.append(QString::number(it.key())); | ||||
304 | const auto urls= it.value(); | ||||
305 | serializedMap.append(QString::number(urls.size())); | ||||
306 | for (const auto &url : urls) { | ||||
307 | serializedMap.append(url.toString()); | ||||
308 | } | ||||
309 | } | ||||
310 | | ||||
311 | group.writeEntry(QLatin1String("itemsOnDisabledScreens"), serializedMap); | ||||
312 | | ||||
313 | } |