File indexing completed on 2024-04-28 09:40:56
0001 /* 0002 * SPDX-FileCopyrightText: 2014 Emmanuel Pescosta <emmanuelpescosta099@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "dolphintabwidget.h" 0008 0009 #include "dolphin_generalsettings.h" 0010 #include "dolphintabbar.h" 0011 #include "dolphinviewcontainer.h" 0012 0013 #include <KAcceleratorManager> 0014 #include <KConfigGroup> 0015 #include <KIO/CommandLauncherJob> 0016 #include <KLocalizedString> 0017 #include <KShell> 0018 #include <KStringHandler> 0019 #include <kio/global.h> 0020 0021 #include <QApplication> 0022 #include <QDropEvent> 0023 0024 DolphinTabWidget::DolphinTabWidget(DolphinNavigatorsWidgetAction *navigatorsWidget, QWidget *parent) 0025 : QTabWidget(parent) 0026 , m_lastViewedTab(nullptr) 0027 , m_navigatorsWidget{navigatorsWidget} 0028 { 0029 KAcceleratorManager::setNoAccel(this); 0030 0031 connect(this, &DolphinTabWidget::tabCloseRequested, this, QOverload<int>::of(&DolphinTabWidget::closeTab)); 0032 connect(this, &DolphinTabWidget::currentChanged, this, &DolphinTabWidget::currentTabChanged); 0033 0034 DolphinTabBar *tabBar = new DolphinTabBar(this); 0035 connect(tabBar, &DolphinTabBar::openNewActivatedTab, this, QOverload<int>::of(&DolphinTabWidget::openNewActivatedTab)); 0036 connect(tabBar, &DolphinTabBar::tabDropEvent, this, &DolphinTabWidget::tabDropEvent); 0037 connect(tabBar, &DolphinTabBar::tabDetachRequested, this, &DolphinTabWidget::detachTab); 0038 0039 setTabBar(tabBar); 0040 setDocumentMode(true); 0041 setElideMode(Qt::ElideRight); 0042 setUsesScrollButtons(true); 0043 setTabBarAutoHide(true); 0044 } 0045 0046 DolphinTabPage *DolphinTabWidget::currentTabPage() const 0047 { 0048 return tabPageAt(currentIndex()); 0049 } 0050 0051 DolphinTabPage *DolphinTabWidget::nextTabPage() const 0052 { 0053 const int index = currentIndex() + 1; 0054 return tabPageAt(index < count() ? index : 0); 0055 } 0056 0057 DolphinTabPage *DolphinTabWidget::prevTabPage() const 0058 { 0059 const int index = currentIndex() - 1; 0060 return tabPageAt(index >= 0 ? index : (count() - 1)); 0061 } 0062 0063 DolphinTabPage *DolphinTabWidget::tabPageAt(const int index) const 0064 { 0065 return static_cast<DolphinTabPage *>(widget(index)); 0066 } 0067 0068 void DolphinTabWidget::saveProperties(KConfigGroup &group) const 0069 { 0070 const int tabCount = count(); 0071 group.writeEntry("Tab Count", tabCount); 0072 group.writeEntry("Active Tab Index", currentIndex()); 0073 0074 for (int i = 0; i < tabCount; ++i) { 0075 const DolphinTabPage *tabPage = tabPageAt(i); 0076 group.writeEntry("Tab Data " % QString::number(i), tabPage->saveState()); 0077 } 0078 } 0079 0080 void DolphinTabWidget::readProperties(const KConfigGroup &group) 0081 { 0082 const int tabCount = group.readEntry("Tab Count", 0); 0083 for (int i = 0; i < tabCount; ++i) { 0084 if (i >= count()) { 0085 openNewActivatedTab(); 0086 } 0087 const QByteArray state = group.readEntry("Tab Data " % QString::number(i), QByteArray()); 0088 tabPageAt(i)->restoreState(state); 0089 } 0090 0091 const int index = group.readEntry("Active Tab Index", 0); 0092 setCurrentIndex(index); 0093 } 0094 0095 void DolphinTabWidget::refreshViews() 0096 { 0097 // Left-elision is better when showing full paths, since you care most 0098 // about the current directory which is on the right 0099 if (GeneralSettings::showFullPathInTitlebar()) { 0100 setElideMode(Qt::ElideLeft); 0101 } else { 0102 setElideMode(Qt::ElideRight); 0103 } 0104 0105 const int tabCount = count(); 0106 for (int i = 0; i < tabCount; ++i) { 0107 tabBar()->setTabText(i, tabName(tabPageAt(i))); 0108 tabPageAt(i)->refreshViews(); 0109 } 0110 } 0111 0112 bool DolphinTabWidget::isUrlOpen(const QUrl &url) const 0113 { 0114 return viewOpenAtDirectory(url).has_value(); 0115 } 0116 0117 bool DolphinTabWidget::isItemVisibleInAnyView(const QUrl &urlOfItem) const 0118 { 0119 return viewShowingItem(urlOfItem).has_value(); 0120 } 0121 0122 void DolphinTabWidget::openNewActivatedTab() 0123 { 0124 std::unique_ptr<DolphinUrlNavigator::VisualState> oldNavigatorState; 0125 if (currentTabPage()->primaryViewActive() || !m_navigatorsWidget->secondaryUrlNavigator()) { 0126 oldNavigatorState = m_navigatorsWidget->primaryUrlNavigator()->visualState(); 0127 } else { 0128 oldNavigatorState = m_navigatorsWidget->secondaryUrlNavigator()->visualState(); 0129 } 0130 0131 const DolphinViewContainer *oldActiveViewContainer = currentTabPage()->activeViewContainer(); 0132 Q_ASSERT(oldActiveViewContainer); 0133 0134 openNewActivatedTab(oldActiveViewContainer->url()); 0135 0136 DolphinViewContainer *newActiveViewContainer = currentTabPage()->activeViewContainer(); 0137 Q_ASSERT(newActiveViewContainer); 0138 0139 // The URL navigator of the new tab should have the same editable state 0140 // as the current tab 0141 newActiveViewContainer->urlNavigator()->setVisualState(*oldNavigatorState.get()); 0142 0143 // Always focus the new tab's view 0144 newActiveViewContainer->view()->setFocus(); 0145 } 0146 0147 void DolphinTabWidget::openNewActivatedTab(const QUrl &primaryUrl, const QUrl &secondaryUrl) 0148 { 0149 openNewTab(primaryUrl, secondaryUrl); 0150 if (GeneralSettings::openNewTabAfterLastTab()) { 0151 setCurrentIndex(count() - 1); 0152 } else { 0153 setCurrentIndex(currentIndex() + 1); 0154 } 0155 } 0156 0157 void DolphinTabWidget::openNewTab(const QUrl &primaryUrl, const QUrl &secondaryUrl, DolphinTabWidget::NewTabPosition position) 0158 { 0159 QWidget *focusWidget = QApplication::focusWidget(); 0160 0161 DolphinTabPage *tabPage = new DolphinTabPage(primaryUrl, secondaryUrl, this); 0162 tabPage->setActive(false); 0163 connect(tabPage, &DolphinTabPage::activeViewChanged, this, &DolphinTabWidget::activeViewChanged); 0164 connect(tabPage, &DolphinTabPage::activeViewUrlChanged, this, &DolphinTabWidget::tabUrlChanged); 0165 connect(tabPage->activeViewContainer(), &DolphinViewContainer::captionChanged, this, [this, tabPage]() { 0166 const int tabIndex = indexOf(tabPage); 0167 Q_ASSERT(tabIndex >= 0); 0168 tabBar()->setTabText(tabIndex, tabName(tabPage)); 0169 }); 0170 0171 if (position == NewTabPosition::FollowSetting) { 0172 if (GeneralSettings::openNewTabAfterLastTab()) { 0173 position = NewTabPosition::AtEnd; 0174 } else { 0175 position = NewTabPosition::AfterCurrent; 0176 } 0177 } 0178 0179 int newTabIndex = -1; 0180 if (position == NewTabPosition::AfterCurrent || (position == NewTabPosition::FollowSetting && !GeneralSettings::openNewTabAfterLastTab())) { 0181 newTabIndex = currentIndex() + 1; 0182 } 0183 0184 insertTab(newTabIndex, tabPage, QIcon() /* loaded in tabInserted */, tabName(tabPage)); 0185 0186 if (focusWidget) { 0187 // The DolphinViewContainer grabbed the keyboard focus. As the tab is opened 0188 // in background, assure that the previous focused widget gets the focus back. 0189 focusWidget->setFocus(); 0190 } 0191 } 0192 0193 void DolphinTabWidget::openDirectories(const QList<QUrl> &dirs, bool splitView) 0194 { 0195 Q_ASSERT(dirs.size() > 0); 0196 0197 bool somethingWasAlreadyOpen = false; 0198 0199 QList<QUrl>::const_iterator it = dirs.constBegin(); 0200 while (it != dirs.constEnd()) { 0201 const QUrl &primaryUrl = *(it++); 0202 const std::optional<ViewIndex> viewIndexAtDirectory = viewOpenAtDirectory(primaryUrl); 0203 0204 // When the user asks for a URL that's already open, 0205 // activate it instead of opening a new tab 0206 if (viewIndexAtDirectory.has_value()) { 0207 somethingWasAlreadyOpen = true; 0208 activateViewContainerAt(viewIndexAtDirectory.value()); 0209 } else if (splitView && (it != dirs.constEnd())) { 0210 const QUrl &secondaryUrl = *(it++); 0211 if (somethingWasAlreadyOpen) { 0212 openNewTab(primaryUrl, secondaryUrl); 0213 } else { 0214 openNewActivatedTab(primaryUrl, secondaryUrl); 0215 } 0216 } else { 0217 if (somethingWasAlreadyOpen) { 0218 openNewTab(primaryUrl); 0219 } else { 0220 openNewActivatedTab(primaryUrl); 0221 } 0222 } 0223 } 0224 } 0225 0226 void DolphinTabWidget::openFiles(const QList<QUrl> &files, bool splitView) 0227 { 0228 Q_ASSERT(files.size() > 0); 0229 0230 // Get all distinct directories from 'files'. 0231 QList<QUrl> dirsThatNeedToBeOpened; 0232 QList<QUrl> dirsThatWereAlreadyOpen; 0233 for (const QUrl &file : files) { 0234 const QUrl dir(file.adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash)); 0235 if (dirsThatNeedToBeOpened.contains(dir) || dirsThatWereAlreadyOpen.contains(dir)) { 0236 continue; 0237 } 0238 0239 // The selecting of files that we do later will not work in views that already have items selected. 0240 // So we check if dir is already open and clear the selection if it is. BUG: 417230 0241 // We also make sure the view will be activated. 0242 auto viewIndex = viewShowingItem(file); 0243 if (viewIndex.has_value()) { 0244 viewContainerAt(viewIndex.value())->view()->clearSelection(); 0245 activateViewContainerAt(viewIndex.value()); 0246 dirsThatWereAlreadyOpen.append(dir); 0247 } else { 0248 dirsThatNeedToBeOpened.append(dir); 0249 } 0250 } 0251 0252 const int oldTabCount = count(); 0253 // Open a tab for each directory. If the "split view" option is enabled, 0254 // two directories are shown inside one tab (see openDirectories()). 0255 if (dirsThatNeedToBeOpened.size() > 0) { 0256 openDirectories(dirsThatNeedToBeOpened, splitView); 0257 } 0258 const int tabCount = count(); 0259 0260 // Select the files. Although the files can be split between several 0261 // tabs, there is no need to split 'files' accordingly, as 0262 // the DolphinView will just ignore invalid selections. 0263 for (int i = 0; i < tabCount; ++i) { 0264 DolphinTabPage *tabPage = tabPageAt(i); 0265 tabPage->markUrlsAsSelected(files); 0266 tabPage->markUrlAsCurrent(files.first()); 0267 if (i < oldTabCount) { 0268 // Force selection of file if directory was already open, BUG: 417230 0269 tabPage->activeViewContainer()->view()->updateViewState(); 0270 } 0271 } 0272 } 0273 0274 void DolphinTabWidget::closeTab() 0275 { 0276 closeTab(currentIndex()); 0277 } 0278 0279 void DolphinTabWidget::closeTab(const int index) 0280 { 0281 Q_ASSERT(index >= 0); 0282 Q_ASSERT(index < count()); 0283 0284 if (count() < 2) { 0285 // Close Dolphin when closing the last tab. 0286 parentWidget()->close(); 0287 return; 0288 } 0289 0290 DolphinTabPage *tabPage = tabPageAt(index); 0291 Q_EMIT rememberClosedTab(tabPage->activeViewContainer()->url(), tabPage->saveState()); 0292 0293 removeTab(index); 0294 tabPage->deleteLater(); 0295 } 0296 0297 void DolphinTabWidget::activateTab(const int index) 0298 { 0299 if (index < count()) { 0300 setCurrentIndex(index); 0301 } 0302 } 0303 0304 void DolphinTabWidget::activateLastTab() 0305 { 0306 setCurrentIndex(count() - 1); 0307 } 0308 0309 void DolphinTabWidget::activateNextTab() 0310 { 0311 const int index = currentIndex() + 1; 0312 setCurrentIndex(index < count() ? index : 0); 0313 } 0314 0315 void DolphinTabWidget::activatePrevTab() 0316 { 0317 const int index = currentIndex() - 1; 0318 setCurrentIndex(index >= 0 ? index : (count() - 1)); 0319 } 0320 0321 void DolphinTabWidget::restoreClosedTab(const QByteArray &state) 0322 { 0323 openNewActivatedTab(); 0324 currentTabPage()->restoreState(state); 0325 } 0326 0327 void DolphinTabWidget::copyToInactiveSplitView() 0328 { 0329 const DolphinTabPage *tabPage = currentTabPage(); 0330 if (!tabPage->splitViewEnabled()) { 0331 return; 0332 } 0333 0334 const KFileItemList selectedItems = tabPage->activeViewContainer()->view()->selectedItems(); 0335 if (selectedItems.isEmpty()) { 0336 return; 0337 } 0338 0339 DolphinView *const inactiveView = tabPage->inactiveViewContainer()->view(); 0340 inactiveView->copySelectedItems(selectedItems, inactiveView->url()); 0341 } 0342 0343 void DolphinTabWidget::moveToInactiveSplitView() 0344 { 0345 const DolphinTabPage *tabPage = currentTabPage(); 0346 if (!tabPage->splitViewEnabled()) { 0347 return; 0348 } 0349 0350 const KFileItemList selectedItems = tabPage->activeViewContainer()->view()->selectedItems(); 0351 if (selectedItems.isEmpty()) { 0352 return; 0353 } 0354 0355 DolphinView *const inactiveView = tabPage->inactiveViewContainer()->view(); 0356 inactiveView->moveSelectedItems(selectedItems, inactiveView->url()); 0357 } 0358 0359 void DolphinTabWidget::detachTab(int index) 0360 { 0361 Q_ASSERT(index >= 0); 0362 0363 QStringList args; 0364 0365 const DolphinTabPage *tabPage = tabPageAt(index); 0366 args << tabPage->primaryViewContainer()->url().url(); 0367 if (tabPage->splitViewEnabled()) { 0368 args << tabPage->secondaryViewContainer()->url().url(); 0369 args << QStringLiteral("--split"); 0370 } 0371 args << QStringLiteral("--new-window"); 0372 0373 KIO::CommandLauncherJob *job = new KIO::CommandLauncherJob("dolphin", args, this); 0374 job->setDesktopName(QStringLiteral("org.kde.dolphin")); 0375 job->start(); 0376 0377 closeTab(index); 0378 } 0379 0380 void DolphinTabWidget::openNewActivatedTab(int index) 0381 { 0382 Q_ASSERT(index >= 0); 0383 const DolphinTabPage *tabPage = tabPageAt(index); 0384 openNewActivatedTab(tabPage->activeViewContainer()->url()); 0385 } 0386 0387 void DolphinTabWidget::tabDropEvent(int index, QDropEvent *event) 0388 { 0389 if (index >= 0) { 0390 DolphinView *view = tabPageAt(index)->activeViewContainer()->view(); 0391 view->dropUrls(view->url(), event, view); 0392 } else { 0393 const auto urls = event->mimeData()->urls(); 0394 0395 for (const QUrl &url : urls) { 0396 auto *job = KIO::stat(url, KIO::StatJob::SourceSide, KIO::StatDetail::StatBasic, KIO::JobFlag::HideProgressInfo); 0397 connect(job, &KJob::result, this, [this, job]() { 0398 if (!job->error() && job->statResult().isDir()) { 0399 openNewTab(job->url(), QUrl(), NewTabPosition::AtEnd); 0400 } 0401 }); 0402 } 0403 } 0404 } 0405 0406 void DolphinTabWidget::tabUrlChanged(const QUrl &url) 0407 { 0408 const int index = indexOf(qobject_cast<QWidget *>(sender())); 0409 if (index >= 0) { 0410 tabBar()->setTabText(index, tabName(tabPageAt(index))); 0411 tabBar()->setTabToolTip(index, url.toDisplayString(QUrl::PreferLocalFile)); 0412 if (tabBar()->isVisible()) { 0413 // ensure the path url ends with a slash to have proper folder icon for remote folders 0414 const QUrl pathUrl = QUrl(url.adjusted(QUrl::StripTrailingSlash).toString(QUrl::FullyEncoded).append("/")); 0415 tabBar()->setTabIcon(index, QIcon::fromTheme(KIO::iconNameForUrl(pathUrl))); 0416 } else { 0417 // Mark as dirty, actually load once the tab bar actually gets shown 0418 tabBar()->setTabIcon(index, QIcon()); 0419 } 0420 0421 // Emit the currentUrlChanged signal if the url of the current tab has been changed. 0422 if (index == currentIndex()) { 0423 Q_EMIT currentUrlChanged(url); 0424 } 0425 } 0426 } 0427 0428 void DolphinTabWidget::currentTabChanged(int index) 0429 { 0430 DolphinTabPage *tabPage = tabPageAt(index); 0431 if (tabPage == m_lastViewedTab) { 0432 return; 0433 } 0434 if (m_lastViewedTab) { 0435 m_lastViewedTab->disconnectNavigators(); 0436 m_lastViewedTab->setActive(false); 0437 } 0438 if (tabPage->splitViewEnabled() && !m_navigatorsWidget->secondaryUrlNavigator()) { 0439 m_navigatorsWidget->createSecondaryUrlNavigator(); 0440 } 0441 DolphinViewContainer *viewContainer = tabPage->activeViewContainer(); 0442 Q_EMIT activeViewChanged(viewContainer); 0443 Q_EMIT currentUrlChanged(viewContainer->url()); 0444 tabPage->setActive(true); 0445 tabPage->connectNavigators(m_navigatorsWidget); 0446 m_navigatorsWidget->setSecondaryNavigatorVisible(tabPage->splitViewEnabled()); 0447 m_lastViewedTab = tabPage; 0448 } 0449 0450 void DolphinTabWidget::tabInserted(int index) 0451 { 0452 QTabWidget::tabInserted(index); 0453 0454 if (tabBar()->isVisible()) { 0455 // Resolve all pending tab icons 0456 for (int i = 0; i < count(); ++i) { 0457 const QUrl url = tabPageAt(i)->activeViewContainer()->url(); 0458 if (tabBar()->tabIcon(i).isNull()) { 0459 // ensure the path url ends with a slash to have proper folder icon for remote folders 0460 const QUrl pathUrl = QUrl(url.adjusted(QUrl::StripTrailingSlash).toString(QUrl::FullyEncoded).append("/")); 0461 tabBar()->setTabIcon(i, QIcon::fromTheme(KIO::iconNameForUrl(pathUrl))); 0462 } 0463 if (tabBar()->tabToolTip(i).isEmpty()) { 0464 tabBar()->setTabToolTip(index, url.toDisplayString(QUrl::PreferLocalFile)); 0465 } 0466 } 0467 } 0468 0469 Q_EMIT tabCountChanged(count()); 0470 } 0471 0472 void DolphinTabWidget::tabRemoved(int index) 0473 { 0474 QTabWidget::tabRemoved(index); 0475 0476 Q_EMIT tabCountChanged(count()); 0477 } 0478 0479 QString DolphinTabWidget::tabName(DolphinTabPage *tabPage) const 0480 { 0481 if (!tabPage) { 0482 return QString(); 0483 } 0484 // clang-format off 0485 QString name; 0486 if (tabPage->splitViewEnabled()) { 0487 if (tabPage->primaryViewActive()) { 0488 // i18n: %1 is the primary view and %2 the secondary view. For left to right languages the primary view is on the left so we also want it to be on the 0489 // left in the tab name. In right to left languages the primary view would be on the right so the tab name should match. 0490 name = i18nc("@title:tab Active primary view | (Inactive secondary view)", "%1 | (%2)", tabPage->primaryViewContainer()->caption(), tabPage->secondaryViewContainer()->caption()); 0491 } else { 0492 // i18n: %1 is the primary view and %2 the secondary view. For left to right languages the primary view is on the left so we also want it to be on the 0493 // left in the tab name. In right to left languages the primary view would be on the right so the tab name should match. 0494 name = i18nc("@title:tab (Inactive primary view) | Active secondary view", "(%1) | %2", tabPage->primaryViewContainer()->caption(), tabPage->secondaryViewContainer()->caption()); 0495 } 0496 } else { 0497 name = tabPage->activeViewContainer()->caption(); 0498 } 0499 // clang-format on 0500 0501 // Make sure that a '&' inside the directory name is displayed correctly 0502 // and not misinterpreted as a keyboard shortcut in QTabBar::setTabText() 0503 return KStringHandler::rsqueeze(name.replace('&', QLatin1String("&&")), 40 /* default maximum visible folder name visible */); 0504 } 0505 0506 DolphinViewContainer *DolphinTabWidget::viewContainerAt(DolphinTabWidget::ViewIndex viewIndex) const 0507 { 0508 const auto tabPage = tabPageAt(viewIndex.tabIndex); 0509 if (!tabPage) { 0510 return nullptr; 0511 } 0512 return viewIndex.isInPrimaryView ? tabPage->primaryViewContainer() : tabPage->secondaryViewContainer(); 0513 } 0514 0515 DolphinViewContainer *DolphinTabWidget::activateViewContainerAt(DolphinTabWidget::ViewIndex viewIndex) 0516 { 0517 activateTab(viewIndex.tabIndex); 0518 auto viewContainer = viewContainerAt(viewIndex); 0519 if (!viewContainer) { 0520 return nullptr; 0521 } 0522 viewContainer->setActive(true); 0523 return viewContainer; 0524 } 0525 0526 const std::optional<const DolphinTabWidget::ViewIndex> DolphinTabWidget::viewOpenAtDirectory(const QUrl &directory) const 0527 { 0528 int i = currentIndex(); 0529 if (i < 0) { 0530 return std::nullopt; 0531 } 0532 // loop over the tabs starting from the current one 0533 do { 0534 const auto tabPage = tabPageAt(i); 0535 if (tabPage->primaryViewContainer()->url() == directory) { 0536 return std::optional(ViewIndex{i, true}); 0537 } 0538 0539 if (tabPage->splitViewEnabled() && tabPage->secondaryViewContainer()->url() == directory) { 0540 return std::optional(ViewIndex{i, false}); 0541 } 0542 0543 i = (i + 1) % count(); 0544 } while (i != currentIndex()); 0545 0546 return std::nullopt; 0547 } 0548 0549 const std::optional<const DolphinTabWidget::ViewIndex> DolphinTabWidget::viewShowingItem(const QUrl &item) const 0550 { 0551 // The item might not be loaded yet even though it exists. So instead 0552 // we check if the folder containing the item is showing its contents. 0553 const QUrl dirContainingItem(item.adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash)); 0554 0555 // The dirContainingItem is either open directly or expanded in a tree-style view mode. 0556 // Is dirContainingitem the base url of a view? 0557 auto viewOpenAtContainingDirectory = viewOpenAtDirectory(dirContainingItem); 0558 if (viewOpenAtContainingDirectory.has_value()) { 0559 return viewOpenAtContainingDirectory; 0560 } 0561 0562 // Is dirContainingItem expanded in some tree-style view? 0563 // The rest of this method is about figuring this out. 0564 0565 int i = currentIndex(); 0566 if (i < 0) { 0567 return std::nullopt; 0568 } 0569 // loop over the tabs starting from the current one 0570 do { 0571 const auto tabPage = tabPageAt(i); 0572 if (tabPage->primaryViewContainer()->url().isParentOf(item)) { 0573 const KFileItem fileItemContainingItem = tabPage->primaryViewContainer()->view()->items().findByUrl(dirContainingItem); 0574 if (!fileItemContainingItem.isNull() && tabPage->primaryViewContainer()->view()->isExpanded(fileItemContainingItem)) { 0575 return std::optional(ViewIndex{i, true}); 0576 } 0577 } 0578 0579 if (tabPage->splitViewEnabled() && tabPage->secondaryViewContainer()->url().isParentOf(item)) { 0580 const KFileItem fileItemContainingItem = tabPage->secondaryViewContainer()->view()->items().findByUrl(dirContainingItem); 0581 if (!fileItemContainingItem.isNull() && tabPage->secondaryViewContainer()->view()->isExpanded(fileItemContainingItem)) { 0582 return std::optional(ViewIndex{i, false}); 0583 } 0584 } 0585 0586 i = (i + 1) % count(); 0587 } while (i != currentIndex()); 0588 0589 return std::nullopt; 0590 } 0591 0592 #include "moc_dolphintabwidget.cpp"