]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphintabpage.cpp
e9607cc53767ab03d2918ba0c772a3863abb060d
[dolphin.git] / src / dolphintabpage.cpp
1 /*
2 * SPDX-FileCopyrightText: 2014 Emmanuel Pescosta <emmanuelpescosta099@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "dolphintabpage.h"
8
9 #include "dolphin_generalsettings.h"
10 #include "dolphinviewcontainer.h"
11
12 #include <QSplitter>
13 #include <QVBoxLayout>
14
15 DolphinTabPage::DolphinTabPage(const QUrl &primaryUrl, const QUrl &secondaryUrl, QWidget* parent) :
16 QWidget(parent),
17 m_primaryViewActive(true),
18 m_splitViewEnabled(false),
19 m_active(true)
20 {
21 QVBoxLayout* layout = new QVBoxLayout(this);
22 layout->setSpacing(0);
23 layout->setContentsMargins(0, 0, 0, 0);
24
25 m_splitter = new QSplitter(Qt::Horizontal, this);
26 m_splitter->setChildrenCollapsible(false);
27 layout->addWidget(m_splitter);
28
29 // Create a new primary view
30 m_primaryViewContainer = createViewContainer(primaryUrl);
31 connect(m_primaryViewContainer->view(), &DolphinView::urlChanged,
32 this, &DolphinTabPage::activeViewUrlChanged);
33 connect(m_primaryViewContainer->view(), &DolphinView::redirection,
34 this, &DolphinTabPage::slotViewUrlRedirection);
35
36 m_splitter->addWidget(m_primaryViewContainer);
37 m_primaryViewContainer->show();
38
39 if (secondaryUrl.isValid() || GeneralSettings::splitView()) {
40 // Provide a secondary view, if the given secondary url is valid or if the
41 // startup settings are set this way (use the url of the primary view).
42 m_splitViewEnabled = true;
43 const QUrl& url = secondaryUrl.isValid() ? secondaryUrl : primaryUrl;
44 m_secondaryViewContainer = createViewContainer(url);
45 m_splitter->addWidget(m_secondaryViewContainer);
46 m_secondaryViewContainer->show();
47 }
48
49 m_primaryViewContainer->setActive(true);
50 }
51
52 bool DolphinTabPage::primaryViewActive() const
53 {
54 return m_primaryViewActive;
55 }
56
57 bool DolphinTabPage::splitViewEnabled() const
58 {
59 return m_splitViewEnabled;
60 }
61
62 void DolphinTabPage::setSplitViewEnabled(bool enabled, const QUrl &secondaryUrl)
63 {
64 if (m_splitViewEnabled != enabled) {
65 m_splitViewEnabled = enabled;
66
67 if (enabled) {
68 const QUrl& url = (secondaryUrl.isEmpty()) ? m_primaryViewContainer->url() : secondaryUrl;
69 m_secondaryViewContainer = createViewContainer(url);
70
71 const bool placesSelectorVisible = m_primaryViewContainer->urlNavigator()->isPlacesSelectorVisible();
72 m_secondaryViewContainer->urlNavigator()->setPlacesSelectorVisible(placesSelectorVisible);
73
74 m_splitter->addWidget(m_secondaryViewContainer);
75 m_secondaryViewContainer->show();
76 m_secondaryViewContainer->setActive(true);
77 } else {
78 DolphinViewContainer* view;
79 if (GeneralSettings::closeActiveSplitView()) {
80 view = activeViewContainer();
81 if (m_primaryViewActive) {
82 // If the primary view is active, we have to swap the pointers
83 // because the secondary view will be the new primary view.
84 qSwap(m_primaryViewContainer, m_secondaryViewContainer);
85 m_primaryViewActive = false;
86 }
87 } else {
88 view = m_primaryViewActive ? m_secondaryViewContainer : m_primaryViewContainer;
89 if (!m_primaryViewActive) {
90 // If the secondary view is active, we have to swap the pointers
91 // because the secondary view will be the new primary view.
92 qSwap(m_primaryViewContainer, m_secondaryViewContainer);
93 m_primaryViewActive = true;
94 }
95 }
96 m_primaryViewContainer->setActive(true);
97 view->close();
98 view->deleteLater();
99 }
100 }
101 }
102
103 DolphinViewContainer* DolphinTabPage::primaryViewContainer() const
104 {
105 return m_primaryViewContainer;
106 }
107
108 DolphinViewContainer* DolphinTabPage::secondaryViewContainer() const
109 {
110 return m_secondaryViewContainer;
111 }
112
113 DolphinViewContainer* DolphinTabPage::activeViewContainer() const
114 {
115 return m_primaryViewActive ? m_primaryViewContainer :
116 m_secondaryViewContainer;
117 }
118
119 KFileItemList DolphinTabPage::selectedItems() const
120 {
121 KFileItemList items = m_primaryViewContainer->view()->selectedItems();
122 if (m_splitViewEnabled) {
123 items += m_secondaryViewContainer->view()->selectedItems();
124 }
125 return items;
126 }
127
128 int DolphinTabPage::selectedItemsCount() const
129 {
130 int selectedItemsCount = m_primaryViewContainer->view()->selectedItemsCount();
131 if (m_splitViewEnabled) {
132 selectedItemsCount += m_secondaryViewContainer->view()->selectedItemsCount();
133 }
134 return selectedItemsCount;
135 }
136
137 void DolphinTabPage::markUrlsAsSelected(const QList<QUrl>& urls)
138 {
139 m_primaryViewContainer->view()->markUrlsAsSelected(urls);
140 if (m_splitViewEnabled) {
141 m_secondaryViewContainer->view()->markUrlsAsSelected(urls);
142 }
143 }
144
145 void DolphinTabPage::markUrlAsCurrent(const QUrl& url)
146 {
147 m_primaryViewContainer->view()->markUrlAsCurrent(url);
148 if (m_splitViewEnabled) {
149 m_secondaryViewContainer->view()->markUrlAsCurrent(url);
150 }
151 }
152
153 void DolphinTabPage::setPlacesSelectorVisible(bool visible)
154 {
155 m_primaryViewContainer->urlNavigator()->setPlacesSelectorVisible(visible);
156 if (m_splitViewEnabled) {
157 m_secondaryViewContainer->urlNavigator()->setPlacesSelectorVisible(visible);
158 }
159 }
160
161 void DolphinTabPage::refreshViews()
162 {
163 m_primaryViewContainer->readSettings();
164 if (m_splitViewEnabled) {
165 m_secondaryViewContainer->readSettings();
166 }
167 }
168
169 QByteArray DolphinTabPage::saveState() const
170 {
171 QByteArray state;
172 QDataStream stream(&state, QIODevice::WriteOnly);
173
174 stream << quint32(2); // Tab state version
175
176 stream << m_splitViewEnabled;
177
178 stream << m_primaryViewContainer->url();
179 stream << m_primaryViewContainer->urlNavigator()->isUrlEditable();
180 m_primaryViewContainer->view()->saveState(stream);
181
182 if (m_splitViewEnabled) {
183 stream << m_secondaryViewContainer->url();
184 stream << m_secondaryViewContainer->urlNavigator()->isUrlEditable();
185 m_secondaryViewContainer->view()->saveState(stream);
186 }
187
188 stream << m_primaryViewActive;
189 stream << m_splitter->saveState();
190
191 return state;
192 }
193
194 void DolphinTabPage::restoreState(const QByteArray& state)
195 {
196 if (state.isEmpty()) {
197 return;
198 }
199
200 QByteArray sd = state;
201 QDataStream stream(&sd, QIODevice::ReadOnly);
202
203 // Read the version number of the tab state and check if the version is supported.
204 quint32 version = 0;
205 stream >> version;
206 if (version != 2) {
207 // The version of the tab state isn't supported, we can't restore it.
208 return;
209 }
210
211 bool isSplitViewEnabled = false;
212 stream >> isSplitViewEnabled;
213 setSplitViewEnabled(isSplitViewEnabled);
214
215 QUrl primaryUrl;
216 stream >> primaryUrl;
217 m_primaryViewContainer->setUrl(primaryUrl);
218 bool primaryUrlEditable;
219 stream >> primaryUrlEditable;
220 m_primaryViewContainer->urlNavigator()->setUrlEditable(primaryUrlEditable);
221 m_primaryViewContainer->view()->restoreState(stream);
222
223 if (isSplitViewEnabled) {
224 QUrl secondaryUrl;
225 stream >> secondaryUrl;
226 m_secondaryViewContainer->setUrl(secondaryUrl);
227 bool secondaryUrlEditable;
228 stream >> secondaryUrlEditable;
229 m_secondaryViewContainer->urlNavigator()->setUrlEditable(secondaryUrlEditable);
230 m_secondaryViewContainer->view()->restoreState(stream);
231 }
232
233 stream >> m_primaryViewActive;
234 if (m_primaryViewActive) {
235 m_primaryViewContainer->setActive(true);
236 } else {
237 Q_ASSERT(m_splitViewEnabled);
238 m_secondaryViewContainer->setActive(true);
239 }
240
241 QByteArray splitterState;
242 stream >> splitterState;
243 m_splitter->restoreState(splitterState);
244 }
245
246 void DolphinTabPage::restoreStateV1(const QByteArray& state)
247 {
248 if (state.isEmpty()) {
249 return;
250 }
251
252 QByteArray sd = state;
253 QDataStream stream(&sd, QIODevice::ReadOnly);
254
255 bool isSplitViewEnabled = false;
256 stream >> isSplitViewEnabled;
257 setSplitViewEnabled(isSplitViewEnabled);
258
259 QUrl primaryUrl;
260 stream >> primaryUrl;
261 m_primaryViewContainer->setUrl(primaryUrl);
262 bool primaryUrlEditable;
263 stream >> primaryUrlEditable;
264 m_primaryViewContainer->urlNavigator()->setUrlEditable(primaryUrlEditable);
265
266 if (isSplitViewEnabled) {
267 QUrl secondaryUrl;
268 stream >> secondaryUrl;
269 m_secondaryViewContainer->setUrl(secondaryUrl);
270 bool secondaryUrlEditable;
271 stream >> secondaryUrlEditable;
272 m_secondaryViewContainer->urlNavigator()->setUrlEditable(secondaryUrlEditable);
273 }
274
275 stream >> m_primaryViewActive;
276 if (m_primaryViewActive) {
277 m_primaryViewContainer->setActive(true);
278 } else {
279 Q_ASSERT(m_splitViewEnabled);
280 m_secondaryViewContainer->setActive(true);
281 }
282
283 QByteArray splitterState;
284 stream >> splitterState;
285 m_splitter->restoreState(splitterState);
286 }
287
288 void DolphinTabPage::setActive(bool active)
289 {
290 if (active) {
291 m_active = active;
292 } else {
293 // we should bypass changing active view in split mode
294 m_active = !m_splitViewEnabled;
295 }
296 // we want view to fire activated when goes from false to true
297 activeViewContainer()->setActive(active);
298 }
299
300 void DolphinTabPage::slotViewActivated()
301 {
302 const DolphinView* oldActiveView = activeViewContainer()->view();
303
304 // Set the view, which was active before, to inactive
305 // and update the active view type, if tab is active
306 if (m_active) {
307 if (m_splitViewEnabled) {
308 activeViewContainer()->setActive(false);
309 m_primaryViewActive = !m_primaryViewActive;
310 } else {
311 m_primaryViewActive = true;
312 if (m_secondaryViewContainer) {
313 m_secondaryViewContainer->setActive(false);
314 }
315 }
316 }
317
318 const DolphinView* newActiveView = activeViewContainer()->view();
319
320 if (newActiveView == oldActiveView) {
321 return;
322 }
323
324 disconnect(oldActiveView, &DolphinView::urlChanged,
325 this, &DolphinTabPage::activeViewUrlChanged);
326 disconnect(oldActiveView, &DolphinView::redirection,
327 this, &DolphinTabPage::slotViewUrlRedirection);
328 connect(newActiveView, &DolphinView::urlChanged,
329 this, &DolphinTabPage::activeViewUrlChanged);
330 connect(newActiveView, &DolphinView::redirection,
331 this, &DolphinTabPage::slotViewUrlRedirection);
332 emit activeViewChanged(activeViewContainer());
333 emit activeViewUrlChanged(activeViewContainer()->url());
334 }
335
336 void DolphinTabPage::slotViewUrlRedirection(const QUrl& oldUrl, const QUrl& newUrl)
337 {
338 Q_UNUSED(oldUrl)
339
340 emit activeViewUrlChanged(newUrl);
341 }
342
343 void DolphinTabPage::switchActiveView()
344 {
345 if (!m_splitViewEnabled) {
346 return;
347 }
348 if (m_primaryViewActive) {
349 m_secondaryViewContainer->setActive(true);
350 } else {
351 m_primaryViewContainer->setActive(true);
352 }
353 }
354
355 DolphinViewContainer* DolphinTabPage::createViewContainer(const QUrl& url) const
356 {
357 DolphinViewContainer* container = new DolphinViewContainer(url, m_splitter);
358 container->setActive(false);
359
360 const DolphinView* view = container->view();
361 connect(view, &DolphinView::activated,
362 this, &DolphinTabPage::slotViewActivated);
363
364 connect(view, &DolphinView::toggleActiveViewRequested,
365 this, &DolphinTabPage::switchActiveView);
366
367 return container;
368 }