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