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