]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphintabpage.cpp
88b4b726e5a6b3dc0b2adf61cef3c128795879f4
[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->setContentsMargins(0, 0, 0, 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 DolphinViewContainer* view;
92 if (GeneralSettings::closeActiveSplitView()) {
93 view = activeViewContainer();
94 if (m_primaryViewActive) {
95 // If the primary view is active, we have to swap the pointers
96 // because the secondary view will be the new primary view.
97 qSwap(m_primaryViewContainer, m_secondaryViewContainer);
98 m_primaryViewActive = false;
99 }
100 } else {
101 view = m_primaryViewActive ? m_secondaryViewContainer : m_primaryViewContainer;
102 if (!m_primaryViewActive) {
103 // If the secondary view is active, we have to swap the pointers
104 // because the secondary view will be the new primary view.
105 qSwap(m_primaryViewContainer, m_secondaryViewContainer);
106 m_primaryViewActive = true;
107 }
108 }
109 m_primaryViewContainer->setActive(true);
110 view->close();
111 view->deleteLater();
112 }
113 }
114 }
115
116 DolphinViewContainer* DolphinTabPage::primaryViewContainer() const
117 {
118 return m_primaryViewContainer;
119 }
120
121 DolphinViewContainer* DolphinTabPage::secondaryViewContainer() const
122 {
123 return m_secondaryViewContainer;
124 }
125
126 DolphinViewContainer* DolphinTabPage::activeViewContainer() const
127 {
128 return m_primaryViewActive ? m_primaryViewContainer :
129 m_secondaryViewContainer;
130 }
131
132 KFileItemList DolphinTabPage::selectedItems() const
133 {
134 KFileItemList items = m_primaryViewContainer->view()->selectedItems();
135 if (m_splitViewEnabled) {
136 items += m_secondaryViewContainer->view()->selectedItems();
137 }
138 return items;
139 }
140
141 int DolphinTabPage::selectedItemsCount() const
142 {
143 int selectedItemsCount = m_primaryViewContainer->view()->selectedItemsCount();
144 if (m_splitViewEnabled) {
145 selectedItemsCount += m_secondaryViewContainer->view()->selectedItemsCount();
146 }
147 return selectedItemsCount;
148 }
149
150 void DolphinTabPage::markUrlsAsSelected(const QList<QUrl>& urls)
151 {
152 m_primaryViewContainer->view()->markUrlsAsSelected(urls);
153 if (m_splitViewEnabled) {
154 m_secondaryViewContainer->view()->markUrlsAsSelected(urls);
155 }
156 }
157
158 void DolphinTabPage::markUrlAsCurrent(const QUrl& url)
159 {
160 m_primaryViewContainer->view()->markUrlAsCurrent(url);
161 if (m_splitViewEnabled) {
162 m_secondaryViewContainer->view()->markUrlAsCurrent(url);
163 }
164 }
165
166 void DolphinTabPage::setPlacesSelectorVisible(bool visible)
167 {
168 m_primaryViewContainer->urlNavigator()->setPlacesSelectorVisible(visible);
169 if (m_splitViewEnabled) {
170 m_secondaryViewContainer->urlNavigator()->setPlacesSelectorVisible(visible);
171 }
172 }
173
174 void DolphinTabPage::refreshViews()
175 {
176 m_primaryViewContainer->readSettings();
177 if (m_splitViewEnabled) {
178 m_secondaryViewContainer->readSettings();
179 }
180 }
181
182 QByteArray DolphinTabPage::saveState() const
183 {
184 QByteArray state;
185 QDataStream stream(&state, QIODevice::WriteOnly);
186
187 stream << quint32(2); // Tab state version
188
189 stream << m_splitViewEnabled;
190
191 stream << m_primaryViewContainer->url();
192 stream << m_primaryViewContainer->urlNavigator()->isUrlEditable();
193 m_primaryViewContainer->view()->saveState(stream);
194
195 if (m_splitViewEnabled) {
196 stream << m_secondaryViewContainer->url();
197 stream << m_secondaryViewContainer->urlNavigator()->isUrlEditable();
198 m_secondaryViewContainer->view()->saveState(stream);
199 }
200
201 stream << m_primaryViewActive;
202 stream << m_splitter->saveState();
203
204 return state;
205 }
206
207 void DolphinTabPage::restoreState(const QByteArray& state)
208 {
209 if (state.isEmpty()) {
210 return;
211 }
212
213 QByteArray sd = state;
214 QDataStream stream(&sd, QIODevice::ReadOnly);
215
216 // Read the version number of the tab state and check if the version is supported.
217 quint32 version = 0;
218 stream >> version;
219 if (version != 2) {
220 // The version of the tab state isn't supported, we can't restore it.
221 return;
222 }
223
224 bool isSplitViewEnabled = false;
225 stream >> isSplitViewEnabled;
226 setSplitViewEnabled(isSplitViewEnabled);
227
228 QUrl primaryUrl;
229 stream >> primaryUrl;
230 m_primaryViewContainer->setUrl(primaryUrl);
231 bool primaryUrlEditable;
232 stream >> primaryUrlEditable;
233 m_primaryViewContainer->urlNavigator()->setUrlEditable(primaryUrlEditable);
234 m_primaryViewContainer->view()->restoreState(stream);
235
236 if (isSplitViewEnabled) {
237 QUrl secondaryUrl;
238 stream >> secondaryUrl;
239 m_secondaryViewContainer->setUrl(secondaryUrl);
240 bool secondaryUrlEditable;
241 stream >> secondaryUrlEditable;
242 m_secondaryViewContainer->urlNavigator()->setUrlEditable(secondaryUrlEditable);
243 m_secondaryViewContainer->view()->restoreState(stream);
244 }
245
246 stream >> m_primaryViewActive;
247 if (m_primaryViewActive) {
248 m_primaryViewContainer->setActive(true);
249 } else {
250 Q_ASSERT(m_splitViewEnabled);
251 m_secondaryViewContainer->setActive(true);
252 }
253
254 QByteArray splitterState;
255 stream >> splitterState;
256 m_splitter->restoreState(splitterState);
257 }
258
259 void DolphinTabPage::restoreStateV1(const QByteArray& state)
260 {
261 if (state.isEmpty()) {
262 return;
263 }
264
265 QByteArray sd = state;
266 QDataStream stream(&sd, QIODevice::ReadOnly);
267
268 bool isSplitViewEnabled = false;
269 stream >> isSplitViewEnabled;
270 setSplitViewEnabled(isSplitViewEnabled);
271
272 QUrl primaryUrl;
273 stream >> primaryUrl;
274 m_primaryViewContainer->setUrl(primaryUrl);
275 bool primaryUrlEditable;
276 stream >> primaryUrlEditable;
277 m_primaryViewContainer->urlNavigator()->setUrlEditable(primaryUrlEditable);
278
279 if (isSplitViewEnabled) {
280 QUrl secondaryUrl;
281 stream >> secondaryUrl;
282 m_secondaryViewContainer->setUrl(secondaryUrl);
283 bool secondaryUrlEditable;
284 stream >> secondaryUrlEditable;
285 m_secondaryViewContainer->urlNavigator()->setUrlEditable(secondaryUrlEditable);
286 }
287
288 stream >> m_primaryViewActive;
289 if (m_primaryViewActive) {
290 m_primaryViewContainer->setActive(true);
291 } else {
292 Q_ASSERT(m_splitViewEnabled);
293 m_secondaryViewContainer->setActive(true);
294 }
295
296 QByteArray splitterState;
297 stream >> splitterState;
298 m_splitter->restoreState(splitterState);
299 }
300
301 void DolphinTabPage::setActive(bool active)
302 {
303 if (active) {
304 m_active = active;
305 } else {
306 // we should bypass changing active view in split mode
307 m_active = !m_splitViewEnabled;
308 }
309 // we want view to fire activated when goes from false to true
310 activeViewContainer()->setActive(active);
311 }
312
313 void DolphinTabPage::slotViewActivated()
314 {
315 const DolphinView* oldActiveView = activeViewContainer()->view();
316
317 // Set the view, which was active before, to inactive
318 // and update the active view type, if tab is active
319 if (m_active) {
320 if (m_splitViewEnabled) {
321 activeViewContainer()->setActive(false);
322 m_primaryViewActive = !m_primaryViewActive;
323 } else {
324 m_primaryViewActive = true;
325 if (m_secondaryViewContainer) {
326 m_secondaryViewContainer->setActive(false);
327 }
328 }
329 }
330
331 const DolphinView* newActiveView = activeViewContainer()->view();
332
333 if (newActiveView == oldActiveView) {
334 return;
335 }
336
337 disconnect(oldActiveView, &DolphinView::urlChanged,
338 this, &DolphinTabPage::activeViewUrlChanged);
339 disconnect(oldActiveView, &DolphinView::redirection,
340 this, &DolphinTabPage::slotViewUrlRedirection);
341 connect(newActiveView, &DolphinView::urlChanged,
342 this, &DolphinTabPage::activeViewUrlChanged);
343 connect(newActiveView, &DolphinView::redirection,
344 this, &DolphinTabPage::slotViewUrlRedirection);
345 emit activeViewChanged(activeViewContainer());
346 emit activeViewUrlChanged(activeViewContainer()->url());
347 }
348
349 void DolphinTabPage::slotViewUrlRedirection(const QUrl& oldUrl, const QUrl& newUrl)
350 {
351 Q_UNUSED(oldUrl)
352
353 emit activeViewUrlChanged(newUrl);
354 }
355
356 void DolphinTabPage::switchActiveView()
357 {
358 if (!m_splitViewEnabled) {
359 return;
360 }
361 if (m_primaryViewActive) {
362 m_secondaryViewContainer->setActive(true);
363 } else {
364 m_primaryViewContainer->setActive(true);
365 }
366 }
367
368 DolphinViewContainer* DolphinTabPage::createViewContainer(const QUrl& url) const
369 {
370 DolphinViewContainer* container = new DolphinViewContainer(url, m_splitter);
371 container->setActive(false);
372
373 const DolphinView* view = container->view();
374 connect(view, &DolphinView::activated,
375 this, &DolphinTabPage::slotViewActivated);
376
377 connect(view, &DolphinView::toggleActiveViewRequested,
378 this, &DolphinTabPage::switchActiveView);
379
380 return container;
381 }