+void DolphinViewContainer::slotUrlSelectionRequested(const QUrl &url)
+{
+ // We do not want to select any item here because there is no reason to assume that the user wants to edit the folder we are emerging from. BUG: 424723
+
+ m_view->markUrlAsCurrent(url); // makes the item scroll into view
+}
+
+void DolphinViewContainer::disableUrlNavigatorSelectionRequests()
+{
+ disconnect(m_urlNavigator.get(), &KUrlNavigator::urlSelectionRequested, this, &DolphinViewContainer::slotUrlSelectionRequested);
+}
+
+void DolphinViewContainer::enableUrlNavigatorSelectionRequests()
+{
+ connect(m_urlNavigator.get(), &KUrlNavigator::urlSelectionRequested, this, &DolphinViewContainer::slotUrlSelectionRequested);
+}
+
+void DolphinViewContainer::redirect(const QUrl &oldUrl, const QUrl &newUrl)
+{
+ Q_UNUSED(oldUrl)
+ const bool block = m_urlNavigator->signalsBlocked();
+ m_urlNavigator->blockSignals(true);
+
+ // Assure that the location state is reset for redirection URLs. This
+ // allows to skip redirection URLs when going back or forward in the
+ // URL history.
+ m_urlNavigator->saveLocationState(QByteArray());
+ m_urlNavigator->setLocationUrl(newUrl);
+ setSearchBarVisible(isSearchUrl(newUrl));
+
+ m_urlNavigator->blockSignals(block);
+}
+
+void DolphinViewContainer::requestFocus()
+{
+ m_view->setFocus();
+}
+
+void DolphinViewContainer::stopDirectoryLoading()
+{
+ m_view->stopLoading();
+ m_statusBar->showProgress(QString(), 100);
+}
+
+void DolphinViewContainer::slotStatusBarZoomLevelChanged(int zoomLevel)
+{
+ m_view->setZoomLevel(zoomLevel);
+}
+
+bool DolphinViewContainer::isTopMostParentFolderWritable(QUrl url)
+{
+ Q_ASSERT(url.isLocalFile());
+ while (url.isValid()) {
+ url = url.adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash);
+ QFileInfo info(url.toLocalFile());
+ if (info.exists()) {
+ return info.isWritable();
+ }
+ if (info.isSymLink()) {
+ return false;
+ }
+ }
+ return false;
+}
+
+void DolphinViewContainer::slotErrorMessageFromView(const QString &message, const int kioErrorCode)
+{
+ if (kioErrorCode == KIO::ERR_CANNOT_ENTER_DIRECTORY && m_view->url().scheme() == QStringLiteral("file")
+ && KProtocolInfo::isKnownProtocol(QStringLiteral("admin")) && !rootItem().isReadable()) {
+ // Explain to users that they need authentication to see the folder contents.
+ if (!m_authorizeToEnterFolderAction) { // This code is similar to parts of Admin::Bar::hideTheNextTimeAuthorizationExpires().
+ // We should not simply use the actAsAdminAction() itself here because that one always refers to the active view instead of this->m_view.
+ auto actAsAdminAction = Admin::WorkerIntegration::FriendAccess::actAsAdminAction();
+ m_authorizeToEnterFolderAction = new QAction{actAsAdminAction->icon(), actAsAdminAction->text(), this};
+ m_authorizeToEnterFolderAction->setToolTip(actAsAdminAction->toolTip());
+ m_authorizeToEnterFolderAction->setWhatsThis(actAsAdminAction->whatsThis());
+ connect(m_authorizeToEnterFolderAction, &QAction::triggered, this, [this, actAsAdminAction]() {
+ setActive(true);
+ actAsAdminAction->trigger();
+ });
+ }
+ showMessage(i18nc("@info", "Authorization required to enter this folder."), KMessageWidget::Error, {m_authorizeToEnterFolderAction});
+ return;
+ } else if (kioErrorCode == KIO::ERR_DOES_NOT_EXIST && m_view->url().isLocalFile()) {
+ if (!m_createFolderAction) {
+ m_createFolderAction = new QAction(this);
+ m_createFolderAction->setText(i18nc("@action", "Create missing folder"));
+ m_createFolderAction->setIcon(QIcon::fromTheme(QStringLiteral("folder-new")));
+ connect(m_createFolderAction, &QAction::triggered, this, [this](bool) {
+ KIO::MkpathJob *job = KIO::mkpath(m_view->url());
+ KIO::FileUndoManager::self()->recordJob(KIO::FileUndoManager::Mkpath, {}, m_view->url(), job);
+ connect(job, &KJob::result, this, [this](KJob *job) {
+ if (job->error()) {
+ showErrorMessage(job->errorString());
+ } else {
+ m_view->reload();
+ m_messageWidget->animatedHide();
+ }
+ });
+ });
+ }
+ if (isTopMostParentFolderWritable(m_view->url())) {
+ m_createFolderAction->setEnabled(true);
+ m_createFolderAction->setToolTip(i18nc("@info:tooltip", "Create the folder at this path and open it"));
+ } else {
+ m_createFolderAction->setEnabled(false);
+ m_createFolderAction->setToolTip(i18nc("@info:tooltip", "You do not have permission to create the folder"));
+ }
+ showMessage(message, KMessageWidget::Error, {m_createFolderAction});
+ return;
+ }
+ Q_EMIT showErrorMessage(message);
+}
+
+void DolphinViewContainer::showErrorMessage(const QString &message)
+{
+ showMessage(message, KMessageWidget::Error);
+}
+
+void DolphinViewContainer::slotPlacesModelChanged()
+{
+ if (!GeneralSettings::showFullPathInTitlebar()) {
+ Q_EMIT captionChanged();
+ }
+}
+
+void DolphinViewContainer::slotHiddenFilesShownChanged(bool showHiddenFiles)
+{
+ if (m_urlNavigatorConnected) {
+ m_urlNavigatorConnected->setShowHiddenFolders(showHiddenFiles);
+ }
+}
+
+void DolphinViewContainer::slotSortHiddenLastChanged(bool hiddenLast)
+{
+ if (m_urlNavigatorConnected) {
+ m_urlNavigatorConnected->setSortHiddenFoldersLast(hiddenLast);
+ }
+}
+
+void DolphinViewContainer::slotCurrentDirectoryRemoved()
+{
+ const QString location(url().toDisplayString(QUrl::PreferLocalFile));
+ if (url().isLocalFile()) {
+ const QString dirPath = url().toLocalFile();
+ const QString newPath = getNearestExistingAncestorOfPath(dirPath);
+ const QUrl newUrl = QUrl::fromLocalFile(newPath);
+ // #473377: Delay changing the url to avoid modifying KCoreDirLister before KCoreDirListerCache::deleteDir() returns.
+ QTimer::singleShot(0, this, [&, newUrl, location] {
+ setUrl(newUrl);
+ showMessage(xi18n("Current location changed, <filename>%1</filename> is no longer accessible.", location), KMessageWidget::Warning);
+ });
+ } else
+ showMessage(xi18n("Current location changed, <filename>%1</filename> is no longer accessible.", location), KMessageWidget::Warning);
+}
+
+void DolphinViewContainer::slotOpenUrlFinished(KJob *job)
+{
+ if (job->error() && job->error() != KIO::ERR_USER_CANCELED) {
+ showErrorMessage(job->errorString());
+ }
+}
+
+void DolphinViewContainer::saveViewState()
+{
+ QByteArray locationState;
+ QDataStream stream(&locationState, QIODevice::WriteOnly);
+ m_view->saveState(stream);
+ m_urlNavigator->saveLocationState(locationState);
+}
+
+void DolphinViewContainer::tryRestoreViewState()
+{
+ QByteArray locationState = m_urlNavigator->locationState();
+ if (!locationState.isEmpty()) {
+ QDataStream stream(&locationState, QIODevice::ReadOnly);
+ m_view->restoreState(stream);
+ }
+}
+
+QString DolphinViewContainer::getNearestExistingAncestorOfPath(const QString &path) const
+{
+ QDir dir(path);
+ do {
+ dir.setPath(QDir::cleanPath(dir.filePath(QStringLiteral(".."))));
+ } while (!dir.exists() && !dir.isRoot());
+
+ return dir.exists() ? dir.path() : QString{};
+}
+
+void DolphinViewContainer::updateStatusBarGeometry()
+{
+ if (!m_statusBar) {
+ return;
+ }
+ if (GeneralSettings::showStatusBar() == GeneralSettings::EnumShowStatusBar::Small) {
+ QRect statusBarRect(preferredSmallStatusBarGeometry());
+ if (view()->layoutDirection() == Qt::RightToLeft) {
+ const int splitterWidth = m_statusBar->clippingAmount();
+ statusBarRect.setLeft(rect().width() - m_statusBar->width() + splitterWidth); // Add clipping amount.
+ }
+ // Move statusbar to bottomLeft, or bottomRight with right-to-left-layout.
+ m_statusBar->setGeometry(statusBarRect);
+ // Add 1 due to how qrect coordinates work.
+ m_view->setStatusBarOffset(m_statusBar->geometry().height() - m_statusBar->clippingAmount() + 1);
+ } else {
+ m_view->setStatusBarOffset(0);
+ }
+}
+
+bool DolphinViewContainer::eventFilter(QObject *object, QEvent *event)
+{
+ if (GeneralSettings::showStatusBar() == GeneralSettings::EnumShowStatusBar::Small && object == m_view) {
+ switch (event->type()) {
+ case QEvent::Resize: {
+ m_statusBar->updateWidthToContent();
+ break;
+ }
+ case QEvent::LayoutRequest: {
+ m_statusBar->updateWidthToContent();
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+QRect DolphinViewContainer::preferredSmallStatusBarGeometry()
+{
+ // Add offset depending if horizontal scrollbar or filterbar is visible, we need to add 1 due to how QRect coordinates work.
+ const int yPos = m_view->geometry().bottom() - m_view->horizontalScrollBarHeight() - m_statusBar->minimumHeight() + 1;
+ QRect statusBarRect = rect().adjusted(0, yPos, 0, 0);
+ return statusBarRect;
+}
+
+#include "moc_dolphinviewcontainer.cpp"