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 <QGridLayout>
14 #include <QWidgetAction>
16 DolphinTabPage::DolphinTabPage(const QUrl
&primaryUrl
, const QUrl
&secondaryUrl
, QWidget
* parent
) :
18 m_primaryViewActive(true),
19 m_splitViewEnabled(false),
22 QGridLayout
*layout
= new QGridLayout(this);
23 layout
->setSpacing(0);
24 layout
->setContentsMargins(0, 0, 0, 0);
26 m_splitter
= new QSplitter(Qt::Horizontal
, this);
27 m_splitter
->setChildrenCollapsible(false);
28 connect(m_splitter
, &QSplitter::splitterMoved
,
29 this, &DolphinTabPage::splitterMoved
);
30 layout
->addWidget(m_splitter
, 1, 0);
31 layout
->setRowStretch(1, 1);
33 // Create a new primary view
34 m_primaryViewContainer
= createViewContainer(primaryUrl
);
35 connect(m_primaryViewContainer
->view(), &DolphinView::urlChanged
,
36 this, &DolphinTabPage::activeViewUrlChanged
);
37 connect(m_primaryViewContainer
->view(), &DolphinView::redirection
,
38 this, &DolphinTabPage::slotViewUrlRedirection
);
40 m_splitter
->addWidget(m_primaryViewContainer
);
41 m_primaryViewContainer
->installEventFilter(this);
42 m_primaryViewContainer
->show();
44 if (secondaryUrl
.isValid() || GeneralSettings::splitView()) {
45 // Provide a secondary view, if the given secondary url is valid or if the
46 // startup settings are set this way (use the url of the primary view).
47 m_splitViewEnabled
= true;
48 const QUrl
& url
= secondaryUrl
.isValid() ? secondaryUrl
: primaryUrl
;
49 m_secondaryViewContainer
= createViewContainer(url
);
50 m_splitter
->addWidget(m_secondaryViewContainer
);
51 m_secondaryViewContainer
->installEventFilter(this);
52 m_secondaryViewContainer
->show();
55 m_primaryViewContainer
->setActive(true);
58 bool DolphinTabPage::primaryViewActive() const
60 return m_primaryViewActive
;
63 bool DolphinTabPage::splitViewEnabled() const
65 return m_splitViewEnabled
;
68 void DolphinTabPage::setSplitViewEnabled(bool enabled
, const QUrl
&secondaryUrl
)
70 if (m_splitViewEnabled
!= enabled
) {
71 m_splitViewEnabled
= enabled
;
74 const QUrl
& url
= (secondaryUrl
.isEmpty()) ? m_primaryViewContainer
->url() : secondaryUrl
;
75 m_secondaryViewContainer
= createViewContainer(url
);
77 auto secondaryNavigator
= m_navigatorsWidget
->secondaryUrlNavigator();
78 if (!secondaryNavigator
) {
79 m_navigatorsWidget
->createSecondaryUrlNavigator();
80 secondaryNavigator
= m_navigatorsWidget
->secondaryUrlNavigator();
82 m_secondaryViewContainer
->connectUrlNavigator(secondaryNavigator
);
83 m_navigatorsWidget
->setSecondaryNavigatorVisible(true);
85 m_splitter
->addWidget(m_secondaryViewContainer
);
86 m_secondaryViewContainer
->installEventFilter(this);
87 m_secondaryViewContainer
->show();
88 m_secondaryViewContainer
->setActive(true);
90 m_navigatorsWidget
->setSecondaryNavigatorVisible(false);
91 m_secondaryViewContainer
->disconnectUrlNavigator();
93 DolphinViewContainer
* view
;
94 if (GeneralSettings::closeActiveSplitView()) {
95 view
= activeViewContainer();
96 if (m_primaryViewActive
) {
97 m_primaryViewContainer
->disconnectUrlNavigator();
98 m_secondaryViewContainer
->connectUrlNavigator(
99 m_navigatorsWidget
->primaryUrlNavigator());
101 // If the primary view is active, we have to swap the pointers
102 // because the secondary view will be the new primary view.
103 qSwap(m_primaryViewContainer
, m_secondaryViewContainer
);
104 m_primaryViewActive
= false;
107 view
= m_primaryViewActive
? m_secondaryViewContainer
: m_primaryViewContainer
;
108 if (!m_primaryViewActive
) {
109 m_primaryViewContainer
->disconnectUrlNavigator();
110 m_secondaryViewContainer
->connectUrlNavigator(
111 m_navigatorsWidget
->primaryUrlNavigator());
113 // If the secondary view is active, we have to swap the pointers
114 // because the secondary view will be the new primary view.
115 qSwap(m_primaryViewContainer
, m_secondaryViewContainer
);
116 m_primaryViewActive
= true;
119 m_primaryViewContainer
->setActive(true);
126 DolphinViewContainer
* DolphinTabPage::primaryViewContainer() const
128 return m_primaryViewContainer
;
131 DolphinViewContainer
* DolphinTabPage::secondaryViewContainer() const
133 return m_secondaryViewContainer
;
136 DolphinViewContainer
* DolphinTabPage::activeViewContainer() const
138 return m_primaryViewActive
? m_primaryViewContainer
:
139 m_secondaryViewContainer
;
142 KFileItemList
DolphinTabPage::selectedItems() const
144 KFileItemList items
= m_primaryViewContainer
->view()->selectedItems();
145 if (m_splitViewEnabled
) {
146 items
+= m_secondaryViewContainer
->view()->selectedItems();
151 int DolphinTabPage::selectedItemsCount() const
153 int selectedItemsCount
= m_primaryViewContainer
->view()->selectedItemsCount();
154 if (m_splitViewEnabled
) {
155 selectedItemsCount
+= m_secondaryViewContainer
->view()->selectedItemsCount();
157 return selectedItemsCount
;
160 void DolphinTabPage::connectNavigators(DolphinNavigatorsWidgetAction
*navigatorsWidget
)
162 insertNavigatorsWidget(navigatorsWidget
);
163 m_navigatorsWidget
= navigatorsWidget
;
164 auto primaryNavigator
= navigatorsWidget
->primaryUrlNavigator();
165 m_primaryViewContainer
->connectUrlNavigator(primaryNavigator
);
166 if (m_splitViewEnabled
) {
167 auto secondaryNavigator
= navigatorsWidget
->secondaryUrlNavigator();
168 m_secondaryViewContainer
->connectUrlNavigator(secondaryNavigator
);
173 void DolphinTabPage::disconnectNavigators()
175 m_navigatorsWidget
= nullptr;
176 m_primaryViewContainer
->disconnectUrlNavigator();
177 if (m_splitViewEnabled
) {
178 m_secondaryViewContainer
->disconnectUrlNavigator();
182 bool DolphinTabPage::eventFilter(QObject
*watched
, QEvent
*event
)
184 if (event
->type() == QEvent::Resize
&& m_navigatorsWidget
) {
188 return QWidget::eventFilter(watched
, event
);
191 void DolphinTabPage::insertNavigatorsWidget(DolphinNavigatorsWidgetAction
* navigatorsWidget
)
193 QGridLayout
*gridLayout
= static_cast<QGridLayout
*>(layout());
194 if (navigatorsWidget
->isInToolbar()) {
195 gridLayout
->setRowMinimumHeight(0, 0);
197 // We set a row minimum height, so the height does not visibly change whenever
198 // navigatorsWidget is inserted which happens every time the current tab is changed.
199 gridLayout
->setRowMinimumHeight(0, navigatorsWidget
->primaryUrlNavigator()->height());
200 gridLayout
->addWidget(navigatorsWidget
->requestWidget(this), 0, 0);
205 void DolphinTabPage::resizeNavigators() const
207 if (!m_splitViewEnabled
) {
208 m_navigatorsWidget
->followViewContainerGeometry(
209 m_primaryViewContainer
->mapToGlobal(QPoint(0,0)).x(),
210 m_primaryViewContainer
->width());
212 m_navigatorsWidget
->followViewContainersGeometry(
213 m_primaryViewContainer
->mapToGlobal(QPoint(0,0)).x(),
214 m_primaryViewContainer
->width(),
215 m_secondaryViewContainer
->mapToGlobal(QPoint(0,0)).x(),
216 m_secondaryViewContainer
->width());
220 void DolphinTabPage::markUrlsAsSelected(const QList
<QUrl
>& urls
)
222 m_primaryViewContainer
->view()->markUrlsAsSelected(urls
);
223 if (m_splitViewEnabled
) {
224 m_secondaryViewContainer
->view()->markUrlsAsSelected(urls
);
228 void DolphinTabPage::markUrlAsCurrent(const QUrl
& url
)
230 m_primaryViewContainer
->view()->markUrlAsCurrent(url
);
231 if (m_splitViewEnabled
) {
232 m_secondaryViewContainer
->view()->markUrlAsCurrent(url
);
236 void DolphinTabPage::refreshViews()
238 m_primaryViewContainer
->readSettings();
239 if (m_splitViewEnabled
) {
240 m_secondaryViewContainer
->readSettings();
244 QByteArray
DolphinTabPage::saveState() const
247 QDataStream
stream(&state
, QIODevice::WriteOnly
);
249 stream
<< quint32(2); // Tab state version
251 stream
<< m_splitViewEnabled
;
253 stream
<< m_primaryViewContainer
->url();
254 stream
<< m_primaryViewContainer
->urlNavigatorInternalWithHistory()->isUrlEditable();
255 m_primaryViewContainer
->view()->saveState(stream
);
257 if (m_splitViewEnabled
) {
258 stream
<< m_secondaryViewContainer
->url();
259 stream
<< m_secondaryViewContainer
->urlNavigatorInternalWithHistory()->isUrlEditable();
260 m_secondaryViewContainer
->view()->saveState(stream
);
263 stream
<< m_primaryViewActive
;
264 stream
<< m_splitter
->saveState();
269 void DolphinTabPage::restoreState(const QByteArray
& state
)
271 if (state
.isEmpty()) {
275 QByteArray sd
= state
;
276 QDataStream
stream(&sd
, QIODevice::ReadOnly
);
278 // Read the version number of the tab state and check if the version is supported.
282 // The version of the tab state isn't supported, we can't restore it.
286 bool isSplitViewEnabled
= false;
287 stream
>> isSplitViewEnabled
;
288 setSplitViewEnabled(isSplitViewEnabled
);
291 stream
>> primaryUrl
;
292 m_primaryViewContainer
->setUrl(primaryUrl
);
293 bool primaryUrlEditable
;
294 stream
>> primaryUrlEditable
;
295 m_primaryViewContainer
->urlNavigatorInternalWithHistory()->setUrlEditable(primaryUrlEditable
);
296 m_primaryViewContainer
->view()->restoreState(stream
);
298 if (isSplitViewEnabled
) {
300 stream
>> secondaryUrl
;
301 m_secondaryViewContainer
->setUrl(secondaryUrl
);
302 bool secondaryUrlEditable
;
303 stream
>> secondaryUrlEditable
;
304 m_secondaryViewContainer
->urlNavigatorInternalWithHistory()->setUrlEditable(secondaryUrlEditable
);
305 m_secondaryViewContainer
->view()->restoreState(stream
);
308 stream
>> m_primaryViewActive
;
309 if (m_primaryViewActive
) {
310 m_primaryViewContainer
->setActive(true);
312 Q_ASSERT(m_splitViewEnabled
);
313 m_secondaryViewContainer
->setActive(true);
316 QByteArray splitterState
;
317 stream
>> splitterState
;
318 m_splitter
->restoreState(splitterState
);
321 void DolphinTabPage::restoreStateV1(const QByteArray
& state
)
323 if (state
.isEmpty()) {
327 QByteArray sd
= state
;
328 QDataStream
stream(&sd
, QIODevice::ReadOnly
);
330 bool isSplitViewEnabled
= false;
331 stream
>> isSplitViewEnabled
;
332 setSplitViewEnabled(isSplitViewEnabled
);
335 stream
>> primaryUrl
;
336 m_primaryViewContainer
->setUrl(primaryUrl
);
337 bool primaryUrlEditable
;
338 stream
>> primaryUrlEditable
;
339 m_primaryViewContainer
->urlNavigatorInternalWithHistory()->setUrlEditable(primaryUrlEditable
);
341 if (isSplitViewEnabled
) {
343 stream
>> secondaryUrl
;
344 m_secondaryViewContainer
->setUrl(secondaryUrl
);
345 bool secondaryUrlEditable
;
346 stream
>> secondaryUrlEditable
;
347 m_secondaryViewContainer
->urlNavigatorInternalWithHistory()->setUrlEditable(secondaryUrlEditable
);
350 stream
>> m_primaryViewActive
;
351 if (m_primaryViewActive
) {
352 m_primaryViewContainer
->setActive(true);
354 Q_ASSERT(m_splitViewEnabled
);
355 m_secondaryViewContainer
->setActive(true);
358 QByteArray splitterState
;
359 stream
>> splitterState
;
360 m_splitter
->restoreState(splitterState
);
363 void DolphinTabPage::setActive(bool active
)
368 // we should bypass changing active view in split mode
369 m_active
= !m_splitViewEnabled
;
371 // we want view to fire activated when goes from false to true
372 activeViewContainer()->setActive(active
);
375 void DolphinTabPage::slotViewActivated()
377 const DolphinView
* oldActiveView
= activeViewContainer()->view();
379 // Set the view, which was active before, to inactive
380 // and update the active view type, if tab is active
382 if (m_splitViewEnabled
) {
383 activeViewContainer()->setActive(false);
384 m_primaryViewActive
= !m_primaryViewActive
;
386 m_primaryViewActive
= true;
387 if (m_secondaryViewContainer
) {
388 m_secondaryViewContainer
->setActive(false);
393 const DolphinView
* newActiveView
= activeViewContainer()->view();
395 if (newActiveView
== oldActiveView
) {
399 disconnect(oldActiveView
, &DolphinView::urlChanged
,
400 this, &DolphinTabPage::activeViewUrlChanged
);
401 disconnect(oldActiveView
, &DolphinView::redirection
,
402 this, &DolphinTabPage::slotViewUrlRedirection
);
403 connect(newActiveView
, &DolphinView::urlChanged
,
404 this, &DolphinTabPage::activeViewUrlChanged
);
405 connect(newActiveView
, &DolphinView::redirection
,
406 this, &DolphinTabPage::slotViewUrlRedirection
);
407 Q_EMIT
activeViewChanged(activeViewContainer());
408 Q_EMIT
activeViewUrlChanged(activeViewContainer()->url());
411 void DolphinTabPage::slotViewUrlRedirection(const QUrl
& oldUrl
, const QUrl
& newUrl
)
415 Q_EMIT
activeViewUrlChanged(newUrl
);
418 void DolphinTabPage::switchActiveView()
420 if (!m_splitViewEnabled
) {
423 if (m_primaryViewActive
) {
424 m_secondaryViewContainer
->setActive(true);
426 m_primaryViewContainer
->setActive(true);
430 DolphinViewContainer
* DolphinTabPage::createViewContainer(const QUrl
& url
) const
432 DolphinViewContainer
* container
= new DolphinViewContainer(url
, m_splitter
);
433 container
->setActive(false);
435 const DolphinView
* view
= container
->view();
436 connect(view
, &DolphinView::activated
,
437 this, &DolphinTabPage::slotViewActivated
);
439 connect(view
, &DolphinView::toggleActiveViewRequested
,
440 this, &DolphinTabPage::switchActiveView
);