2 * SPDX-FileCopyrightText: 2014 Emmanuel Pescosta <emmanuelpescosta099@gmail.com>
4 * SPDX-License-Identifier: GPL-2.0-or-later
7 #include "dolphintabpage.h"
9 #include "dolphin_generalsettings.h"
10 #include "dolphinviewcontainer.h"
13 #include <QVBoxLayout>
15 DolphinTabPage::DolphinTabPage(const QUrl
&primaryUrl
, const QUrl
&secondaryUrl
, QWidget
* parent
) :
17 m_primaryViewActive(true),
18 m_splitViewEnabled(false),
21 QVBoxLayout
* layout
= new QVBoxLayout(this);
22 layout
->setSpacing(0);
23 layout
->setContentsMargins(0, 0, 0, 0);
25 m_splitter
= new QSplitter(Qt::Horizontal
, this);
26 m_splitter
->setChildrenCollapsible(false);
27 connect(m_splitter
, &QSplitter::splitterMoved
,
28 this, &DolphinTabPage::splitterMoved
);
29 layout
->addWidget(m_splitter
);
31 // Create a new primary view
32 m_primaryViewContainer
= createViewContainer(primaryUrl
);
33 connect(m_primaryViewContainer
->view(), &DolphinView::urlChanged
,
34 this, &DolphinTabPage::activeViewUrlChanged
);
35 connect(m_primaryViewContainer
->view(), &DolphinView::redirection
,
36 this, &DolphinTabPage::slotViewUrlRedirection
);
38 m_splitter
->addWidget(m_primaryViewContainer
);
39 m_primaryViewContainer
->installEventFilter(this);
40 m_primaryViewContainer
->show();
42 if (secondaryUrl
.isValid() || GeneralSettings::splitView()) {
43 // Provide a secondary view, if the given secondary url is valid or if the
44 // startup settings are set this way (use the url of the primary view).
45 m_splitViewEnabled
= true;
46 const QUrl
& url
= secondaryUrl
.isValid() ? secondaryUrl
: primaryUrl
;
47 m_secondaryViewContainer
= createViewContainer(url
);
48 m_splitter
->addWidget(m_secondaryViewContainer
);
49 m_secondaryViewContainer
->installEventFilter(this);
50 m_secondaryViewContainer
->show();
53 m_primaryViewContainer
->setActive(true);
56 bool DolphinTabPage::primaryViewActive() const
58 return m_primaryViewActive
;
61 bool DolphinTabPage::splitViewEnabled() const
63 return m_splitViewEnabled
;
66 void DolphinTabPage::setSplitViewEnabled(bool enabled
, const QUrl
&secondaryUrl
)
68 if (m_splitViewEnabled
!= enabled
) {
69 m_splitViewEnabled
= enabled
;
72 const QUrl
& url
= (secondaryUrl
.isEmpty()) ? m_primaryViewContainer
->url() : secondaryUrl
;
73 m_secondaryViewContainer
= createViewContainer(url
);
75 auto secondaryNavigator
= m_navigatorsWidget
->secondaryUrlNavigator();
76 if (!secondaryNavigator
) {
77 m_navigatorsWidget
->createSecondaryUrlNavigator();
78 secondaryNavigator
= m_navigatorsWidget
->secondaryUrlNavigator();
80 m_secondaryViewContainer
->connectUrlNavigator(secondaryNavigator
);
81 m_navigatorsWidget
->setSecondaryNavigatorVisible(true);
83 m_splitter
->addWidget(m_secondaryViewContainer
);
84 m_secondaryViewContainer
->installEventFilter(this);
85 m_secondaryViewContainer
->show();
86 m_secondaryViewContainer
->setActive(true);
88 m_navigatorsWidget
->setSecondaryNavigatorVisible(false);
89 m_secondaryViewContainer
->disconnectUrlNavigator();
91 DolphinViewContainer
* view
;
92 if (GeneralSettings::closeActiveSplitView()) {
93 view
= activeViewContainer();
94 if (m_primaryViewActive
) {
95 m_primaryViewContainer
->disconnectUrlNavigator();
96 m_secondaryViewContainer
->connectUrlNavigator(
97 m_navigatorsWidget
->primaryUrlNavigator());
99 // If the primary view is active, we have to swap the pointers
100 // because the secondary view will be the new primary view.
101 qSwap(m_primaryViewContainer
, m_secondaryViewContainer
);
102 m_primaryViewActive
= false;
105 view
= m_primaryViewActive
? m_secondaryViewContainer
: m_primaryViewContainer
;
106 if (!m_primaryViewActive
) {
107 m_primaryViewContainer
->disconnectUrlNavigator();
108 m_secondaryViewContainer
->connectUrlNavigator(
109 m_navigatorsWidget
->primaryUrlNavigator());
111 // If the secondary view is active, we have to swap the pointers
112 // because the secondary view will be the new primary view.
113 qSwap(m_primaryViewContainer
, m_secondaryViewContainer
);
114 m_primaryViewActive
= true;
117 m_primaryViewContainer
->setActive(true);
124 DolphinViewContainer
* DolphinTabPage::primaryViewContainer() const
126 return m_primaryViewContainer
;
129 DolphinViewContainer
* DolphinTabPage::secondaryViewContainer() const
131 return m_secondaryViewContainer
;
134 DolphinViewContainer
* DolphinTabPage::activeViewContainer() const
136 return m_primaryViewActive
? m_primaryViewContainer
:
137 m_secondaryViewContainer
;
140 KFileItemList
DolphinTabPage::selectedItems() const
142 KFileItemList items
= m_primaryViewContainer
->view()->selectedItems();
143 if (m_splitViewEnabled
) {
144 items
+= m_secondaryViewContainer
->view()->selectedItems();
149 int DolphinTabPage::selectedItemsCount() const
151 int selectedItemsCount
= m_primaryViewContainer
->view()->selectedItemsCount();
152 if (m_splitViewEnabled
) {
153 selectedItemsCount
+= m_secondaryViewContainer
->view()->selectedItemsCount();
155 return selectedItemsCount
;
158 void DolphinTabPage::connectNavigators(DolphinNavigatorsWidgetAction
*navigatorsWidget
)
160 m_navigatorsWidget
= navigatorsWidget
;
161 auto primaryNavigator
= navigatorsWidget
->primaryUrlNavigator();
162 m_primaryViewContainer
->connectUrlNavigator(primaryNavigator
);
163 if (m_splitViewEnabled
) {
164 auto secondaryNavigator
= navigatorsWidget
->secondaryUrlNavigator();
165 m_secondaryViewContainer
->connectUrlNavigator(secondaryNavigator
);
170 void DolphinTabPage::disconnectNavigators()
172 m_navigatorsWidget
= nullptr;
173 m_primaryViewContainer
->disconnectUrlNavigator();
174 if (m_splitViewEnabled
) {
175 m_secondaryViewContainer
->disconnectUrlNavigator();
179 bool DolphinTabPage::eventFilter(QObject
*watched
, QEvent
*event
)
181 if (event
->type() == QEvent::Resize
&& m_navigatorsWidget
) {
185 return QWidget::eventFilter(watched
, event
);
188 void DolphinTabPage::resizeNavigators() const
190 if (!m_splitViewEnabled
) {
191 m_navigatorsWidget
->followViewContainerGeometry(
192 m_primaryViewContainer
->mapToGlobal(QPoint(0,0)).x(),
193 m_primaryViewContainer
->width());
195 m_navigatorsWidget
->followViewContainersGeometry(
196 m_primaryViewContainer
->mapToGlobal(QPoint(0,0)).x(),
197 m_primaryViewContainer
->width(),
198 m_secondaryViewContainer
->mapToGlobal(QPoint(0,0)).x(),
199 m_secondaryViewContainer
->width());
203 void DolphinTabPage::markUrlsAsSelected(const QList
<QUrl
>& urls
)
205 m_primaryViewContainer
->view()->markUrlsAsSelected(urls
);
206 if (m_splitViewEnabled
) {
207 m_secondaryViewContainer
->view()->markUrlsAsSelected(urls
);
211 void DolphinTabPage::markUrlAsCurrent(const QUrl
& url
)
213 m_primaryViewContainer
->view()->markUrlAsCurrent(url
);
214 if (m_splitViewEnabled
) {
215 m_secondaryViewContainer
->view()->markUrlAsCurrent(url
);
219 void DolphinTabPage::refreshViews()
221 m_primaryViewContainer
->readSettings();
222 if (m_splitViewEnabled
) {
223 m_secondaryViewContainer
->readSettings();
227 QByteArray
DolphinTabPage::saveState() const
230 QDataStream
stream(&state
, QIODevice::WriteOnly
);
232 stream
<< quint32(2); // Tab state version
234 stream
<< m_splitViewEnabled
;
236 stream
<< m_primaryViewContainer
->url();
237 stream
<< m_primaryViewContainer
->urlNavigatorInternalWithHistory()->isUrlEditable();
238 m_primaryViewContainer
->view()->saveState(stream
);
240 if (m_splitViewEnabled
) {
241 stream
<< m_secondaryViewContainer
->url();
242 stream
<< m_secondaryViewContainer
->urlNavigatorInternalWithHistory()->isUrlEditable();
243 m_secondaryViewContainer
->view()->saveState(stream
);
246 stream
<< m_primaryViewActive
;
247 stream
<< m_splitter
->saveState();
252 void DolphinTabPage::restoreState(const QByteArray
& state
)
254 if (state
.isEmpty()) {
258 QByteArray sd
= state
;
259 QDataStream
stream(&sd
, QIODevice::ReadOnly
);
261 // Read the version number of the tab state and check if the version is supported.
265 // The version of the tab state isn't supported, we can't restore it.
269 bool isSplitViewEnabled
= false;
270 stream
>> isSplitViewEnabled
;
271 setSplitViewEnabled(isSplitViewEnabled
);
274 stream
>> primaryUrl
;
275 m_primaryViewContainer
->setUrl(primaryUrl
);
276 bool primaryUrlEditable
;
277 stream
>> primaryUrlEditable
;
278 m_primaryViewContainer
->urlNavigatorInternalWithHistory()->setUrlEditable(primaryUrlEditable
);
279 m_primaryViewContainer
->view()->restoreState(stream
);
281 if (isSplitViewEnabled
) {
283 stream
>> secondaryUrl
;
284 m_secondaryViewContainer
->setUrl(secondaryUrl
);
285 bool secondaryUrlEditable
;
286 stream
>> secondaryUrlEditable
;
287 m_secondaryViewContainer
->urlNavigatorInternalWithHistory()->setUrlEditable(secondaryUrlEditable
);
288 m_secondaryViewContainer
->view()->restoreState(stream
);
291 stream
>> m_primaryViewActive
;
292 if (m_primaryViewActive
) {
293 m_primaryViewContainer
->setActive(true);
295 Q_ASSERT(m_splitViewEnabled
);
296 m_secondaryViewContainer
->setActive(true);
299 QByteArray splitterState
;
300 stream
>> splitterState
;
301 m_splitter
->restoreState(splitterState
);
304 void DolphinTabPage::restoreStateV1(const QByteArray
& state
)
306 if (state
.isEmpty()) {
310 QByteArray sd
= state
;
311 QDataStream
stream(&sd
, QIODevice::ReadOnly
);
313 bool isSplitViewEnabled
= false;
314 stream
>> isSplitViewEnabled
;
315 setSplitViewEnabled(isSplitViewEnabled
);
318 stream
>> primaryUrl
;
319 m_primaryViewContainer
->setUrl(primaryUrl
);
320 bool primaryUrlEditable
;
321 stream
>> primaryUrlEditable
;
322 m_primaryViewContainer
->urlNavigatorInternalWithHistory()->setUrlEditable(primaryUrlEditable
);
324 if (isSplitViewEnabled
) {
326 stream
>> secondaryUrl
;
327 m_secondaryViewContainer
->setUrl(secondaryUrl
);
328 bool secondaryUrlEditable
;
329 stream
>> secondaryUrlEditable
;
330 m_secondaryViewContainer
->urlNavigatorInternalWithHistory()->setUrlEditable(secondaryUrlEditable
);
333 stream
>> m_primaryViewActive
;
334 if (m_primaryViewActive
) {
335 m_primaryViewContainer
->setActive(true);
337 Q_ASSERT(m_splitViewEnabled
);
338 m_secondaryViewContainer
->setActive(true);
341 QByteArray splitterState
;
342 stream
>> splitterState
;
343 m_splitter
->restoreState(splitterState
);
346 void DolphinTabPage::setActive(bool active
)
351 // we should bypass changing active view in split mode
352 m_active
= !m_splitViewEnabled
;
354 // we want view to fire activated when goes from false to true
355 activeViewContainer()->setActive(active
);
358 void DolphinTabPage::slotViewActivated()
360 const DolphinView
* oldActiveView
= activeViewContainer()->view();
362 // Set the view, which was active before, to inactive
363 // and update the active view type, if tab is active
365 if (m_splitViewEnabled
) {
366 activeViewContainer()->setActive(false);
367 m_primaryViewActive
= !m_primaryViewActive
;
369 m_primaryViewActive
= true;
370 if (m_secondaryViewContainer
) {
371 m_secondaryViewContainer
->setActive(false);
376 const DolphinView
* newActiveView
= activeViewContainer()->view();
378 if (newActiveView
== oldActiveView
) {
382 disconnect(oldActiveView
, &DolphinView::urlChanged
,
383 this, &DolphinTabPage::activeViewUrlChanged
);
384 disconnect(oldActiveView
, &DolphinView::redirection
,
385 this, &DolphinTabPage::slotViewUrlRedirection
);
386 connect(newActiveView
, &DolphinView::urlChanged
,
387 this, &DolphinTabPage::activeViewUrlChanged
);
388 connect(newActiveView
, &DolphinView::redirection
,
389 this, &DolphinTabPage::slotViewUrlRedirection
);
390 Q_EMIT
activeViewChanged(activeViewContainer());
391 Q_EMIT
activeViewUrlChanged(activeViewContainer()->url());
394 void DolphinTabPage::slotViewUrlRedirection(const QUrl
& oldUrl
, const QUrl
& newUrl
)
398 Q_EMIT
activeViewUrlChanged(newUrl
);
401 void DolphinTabPage::switchActiveView()
403 if (!m_splitViewEnabled
) {
406 if (m_primaryViewActive
) {
407 m_secondaryViewContainer
->setActive(true);
409 m_primaryViewContainer
->setActive(true);
413 DolphinViewContainer
* DolphinTabPage::createViewContainer(const QUrl
& url
) const
415 DolphinViewContainer
* container
= new DolphinViewContainer(url
, m_splitter
);
416 container
->setActive(false);
418 const DolphinView
* view
= container
->view();
419 connect(view
, &DolphinView::activated
,
420 this, &DolphinTabPage::slotViewActivated
);
422 connect(view
, &DolphinView::toggleActiveViewRequested
,
423 this, &DolphinTabPage::switchActiveView
);