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 primaryNavigator
->setActive(m_primaryViewActive
);
163 m_primaryViewContainer
->connectUrlNavigator(primaryNavigator
);
164 if (m_splitViewEnabled
) {
165 auto secondaryNavigator
= navigatorsWidget
->secondaryUrlNavigator();
166 secondaryNavigator
->setActive(!m_primaryViewActive
);
167 m_secondaryViewContainer
->connectUrlNavigator(secondaryNavigator
);
172 void DolphinTabPage::disconnectNavigators()
174 m_navigatorsWidget
= nullptr;
175 m_primaryViewContainer
->disconnectUrlNavigator();
176 if (m_splitViewEnabled
) {
177 m_secondaryViewContainer
->disconnectUrlNavigator();
181 bool DolphinTabPage::eventFilter(QObject */
* watched */
, QEvent
*event
)
183 if (event
->type() == QEvent::Resize
&& m_navigatorsWidget
) {
189 void DolphinTabPage::resizeNavigators() const
191 if (!m_splitViewEnabled
) {
192 m_navigatorsWidget
->followViewContainerGeometry(
193 m_primaryViewContainer
->mapToGlobal(QPoint(0,0)).x(),
194 m_primaryViewContainer
->width());
196 m_navigatorsWidget
->followViewContainersGeometry(
197 m_primaryViewContainer
->mapToGlobal(QPoint(0,0)).x(),
198 m_primaryViewContainer
->width(),
199 m_secondaryViewContainer
->mapToGlobal(QPoint(0,0)).x(),
200 m_secondaryViewContainer
->width());
204 void DolphinTabPage::markUrlsAsSelected(const QList
<QUrl
>& urls
)
206 m_primaryViewContainer
->view()->markUrlsAsSelected(urls
);
207 if (m_splitViewEnabled
) {
208 m_secondaryViewContainer
->view()->markUrlsAsSelected(urls
);
212 void DolphinTabPage::markUrlAsCurrent(const QUrl
& url
)
214 m_primaryViewContainer
->view()->markUrlAsCurrent(url
);
215 if (m_splitViewEnabled
) {
216 m_secondaryViewContainer
->view()->markUrlAsCurrent(url
);
220 void DolphinTabPage::refreshViews()
222 m_primaryViewContainer
->readSettings();
223 if (m_splitViewEnabled
) {
224 m_secondaryViewContainer
->readSettings();
228 QByteArray
DolphinTabPage::saveState() const
231 QDataStream
stream(&state
, QIODevice::WriteOnly
);
233 stream
<< quint32(2); // Tab state version
235 stream
<< m_splitViewEnabled
;
237 stream
<< m_primaryViewContainer
->url();
238 stream
<< m_primaryViewContainer
->urlNavigatorInternalWithHistory()->isUrlEditable();
239 m_primaryViewContainer
->view()->saveState(stream
);
241 if (m_splitViewEnabled
) {
242 stream
<< m_secondaryViewContainer
->url();
243 stream
<< m_secondaryViewContainer
->urlNavigatorInternalWithHistory()->isUrlEditable();
244 m_secondaryViewContainer
->view()->saveState(stream
);
247 stream
<< m_primaryViewActive
;
248 stream
<< m_splitter
->saveState();
253 void DolphinTabPage::restoreState(const QByteArray
& state
)
255 if (state
.isEmpty()) {
259 QByteArray sd
= state
;
260 QDataStream
stream(&sd
, QIODevice::ReadOnly
);
262 // Read the version number of the tab state and check if the version is supported.
266 // The version of the tab state isn't supported, we can't restore it.
270 bool isSplitViewEnabled
= false;
271 stream
>> isSplitViewEnabled
;
272 setSplitViewEnabled(isSplitViewEnabled
);
275 stream
>> primaryUrl
;
276 m_primaryViewContainer
->setUrl(primaryUrl
);
277 bool primaryUrlEditable
;
278 stream
>> primaryUrlEditable
;
279 m_primaryViewContainer
->urlNavigatorInternalWithHistory()->setUrlEditable(primaryUrlEditable
);
280 m_primaryViewContainer
->view()->restoreState(stream
);
282 if (isSplitViewEnabled
) {
284 stream
>> secondaryUrl
;
285 m_secondaryViewContainer
->setUrl(secondaryUrl
);
286 bool secondaryUrlEditable
;
287 stream
>> secondaryUrlEditable
;
288 m_secondaryViewContainer
->urlNavigatorInternalWithHistory()->setUrlEditable(secondaryUrlEditable
);
289 m_secondaryViewContainer
->view()->restoreState(stream
);
292 stream
>> m_primaryViewActive
;
293 if (m_primaryViewActive
) {
294 m_primaryViewContainer
->setActive(true);
295 m_navigatorsWidget
->primaryUrlNavigator()->setActive(true);
297 Q_ASSERT(m_splitViewEnabled
);
298 m_secondaryViewContainer
->setActive(true);
299 m_navigatorsWidget
->primaryUrlNavigator()->setActive(false);
302 QByteArray splitterState
;
303 stream
>> splitterState
;
304 m_splitter
->restoreState(splitterState
);
307 void DolphinTabPage::restoreStateV1(const QByteArray
& state
)
309 if (state
.isEmpty()) {
313 QByteArray sd
= state
;
314 QDataStream
stream(&sd
, QIODevice::ReadOnly
);
316 bool isSplitViewEnabled
= false;
317 stream
>> isSplitViewEnabled
;
318 setSplitViewEnabled(isSplitViewEnabled
);
321 stream
>> primaryUrl
;
322 m_primaryViewContainer
->setUrl(primaryUrl
);
323 bool primaryUrlEditable
;
324 stream
>> primaryUrlEditable
;
325 m_primaryViewContainer
->urlNavigatorInternalWithHistory()->setUrlEditable(primaryUrlEditable
);
327 if (isSplitViewEnabled
) {
329 stream
>> secondaryUrl
;
330 m_secondaryViewContainer
->setUrl(secondaryUrl
);
331 bool secondaryUrlEditable
;
332 stream
>> secondaryUrlEditable
;
333 m_secondaryViewContainer
->urlNavigatorInternalWithHistory()->setUrlEditable(secondaryUrlEditable
);
336 stream
>> m_primaryViewActive
;
337 if (m_primaryViewActive
) {
338 m_primaryViewContainer
->setActive(true);
340 Q_ASSERT(m_splitViewEnabled
);
341 m_secondaryViewContainer
->setActive(true);
344 QByteArray splitterState
;
345 stream
>> splitterState
;
346 m_splitter
->restoreState(splitterState
);
349 void DolphinTabPage::setActive(bool active
)
354 // we should bypass changing active view in split mode
355 m_active
= !m_splitViewEnabled
;
357 // we want view to fire activated when goes from false to true
358 activeViewContainer()->setActive(active
);
361 void DolphinTabPage::slotViewActivated()
363 const DolphinView
* oldActiveView
= activeViewContainer()->view();
365 // Set the view, which was active before, to inactive
366 // and update the active view type, if tab is active
368 if (m_splitViewEnabled
) {
369 activeViewContainer()->setActive(false);
370 m_primaryViewActive
= !m_primaryViewActive
;
372 m_primaryViewActive
= true;
373 if (m_secondaryViewContainer
) {
374 m_secondaryViewContainer
->setActive(false);
379 const DolphinView
* newActiveView
= activeViewContainer()->view();
381 if (newActiveView
== oldActiveView
) {
385 disconnect(oldActiveView
, &DolphinView::urlChanged
,
386 this, &DolphinTabPage::activeViewUrlChanged
);
387 disconnect(oldActiveView
, &DolphinView::redirection
,
388 this, &DolphinTabPage::slotViewUrlRedirection
);
389 connect(newActiveView
, &DolphinView::urlChanged
,
390 this, &DolphinTabPage::activeViewUrlChanged
);
391 connect(newActiveView
, &DolphinView::redirection
,
392 this, &DolphinTabPage::slotViewUrlRedirection
);
393 Q_EMIT
activeViewChanged(activeViewContainer());
394 Q_EMIT
activeViewUrlChanged(activeViewContainer()->url());
397 void DolphinTabPage::slotViewUrlRedirection(const QUrl
& oldUrl
, const QUrl
& newUrl
)
401 Q_EMIT
activeViewUrlChanged(newUrl
);
404 void DolphinTabPage::switchActiveView()
406 if (!m_splitViewEnabled
) {
409 if (m_primaryViewActive
) {
410 m_secondaryViewContainer
->setActive(true);
412 m_primaryViewContainer
->setActive(true);
416 DolphinViewContainer
* DolphinTabPage::createViewContainer(const QUrl
& url
) const
418 DolphinViewContainer
* container
= new DolphinViewContainer(url
, m_splitter
);
419 container
->setActive(false);
421 const DolphinView
* view
= container
->view();
422 connect(view
, &DolphinView::activated
,
423 this, &DolphinTabPage::slotViewActivated
);
425 connect(view
, &DolphinView::toggleActiveViewRequested
,
426 this, &DolphinTabPage::switchActiveView
);