]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphinviewcontainer.cpp
Compile with QT_NO_KEYWORDS
[dolphin.git] / src / dolphinviewcontainer.cpp
1 /*
2 * SPDX-FileCopyrightText: 2007 Peter Penz <peter.penz19@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "dolphinviewcontainer.h"
8
9 #include "dolphin_generalsettings.h"
10 #include "dolphinplacesmodelsingleton.h"
11 #include "dolphindebug.h"
12 #include "filterbar/filterbar.h"
13 #include "global.h"
14 #include "search/dolphinsearchbox.h"
15 #include "statusbar/dolphinstatusbar.h"
16 #include "trash/dolphintrash.h"
17 #include "views/viewmodecontroller.h"
18 #include "views/viewproperties.h"
19 #include "dolphin_detailsmodesettings.h"
20
21 #ifdef HAVE_KACTIVITIES
22 #include <KActivities/ResourceInstance>
23 #endif
24 #include <KFileItemActions>
25 #include <KFilePlacesModel>
26 #include <KIO/PreviewJob>
27 #include <KIO/OpenUrlJob>
28 #include <KIO/JobUiDelegate>
29 #include <KLocalizedString>
30 #include <KMessageWidget>
31 #include <KProtocolManager>
32 #include <KShell>
33 #include <KUrlComboBox>
34
35 #include <QDropEvent>
36 #include <QLoggingCategory>
37 #include <QMimeData>
38 #include <QTimer>
39 #include <QUrl>
40 #include <QVBoxLayout>
41 #include <QDesktopServices>
42
43 DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) :
44 QWidget(parent),
45 m_topLayout(nullptr),
46 m_navigatorWidget(nullptr),
47 m_urlNavigator(nullptr),
48 m_emptyTrashButton(nullptr),
49 m_searchBox(nullptr),
50 m_searchModeEnabled(false),
51 m_messageWidget(nullptr),
52 m_view(nullptr),
53 m_filterBar(nullptr),
54 m_statusBar(nullptr),
55 m_statusBarTimer(nullptr),
56 m_statusBarTimestamp(),
57 m_autoGrabFocus(true)
58 #ifdef HAVE_KACTIVITIES
59 , m_activityResourceInstance(nullptr)
60 #endif
61 {
62 hide();
63
64 m_topLayout = new QVBoxLayout(this);
65 m_topLayout->setSpacing(0);
66 m_topLayout->setContentsMargins(0, 0, 0, 0);
67
68 m_navigatorWidget = new QWidget(this);
69 QHBoxLayout* navigatorLayout = new QHBoxLayout(m_navigatorWidget);
70 navigatorLayout->setSpacing(0);
71 navigatorLayout->setContentsMargins(0, 0, 0, 0);
72 m_navigatorWidget->setWhatsThis(xi18nc("@info:whatsthis location bar",
73 "<para>This line describes the location of the files and folders "
74 "displayed below.</para><para>The name of the currently viewed "
75 "folder can be read at the very right. To the left of it is the "
76 "name of the folder that contains it. The whole line is called "
77 "the <emphasis>path</emphasis> to the current location because "
78 "following these folders from left to right leads here.</para>"
79 "<para>The path is displayed on the <emphasis>location bar</emphasis> "
80 "which is more powerful than one would expect. To learn more "
81 "about the basic and advanced features of the location bar "
82 "<link url='help:/dolphin/location-bar.html'>click here</link>. "
83 "This will open the dedicated page in the Handbook.</para>"));
84
85 m_urlNavigator = new KUrlNavigator(DolphinPlacesModelSingleton::instance().placesModel(), url, this);
86 connect(m_urlNavigator, &KUrlNavigator::activated,
87 this, &DolphinViewContainer::activate);
88 connect(m_urlNavigator->editor(), &KUrlComboBox::completionModeChanged,
89 this, &DolphinViewContainer::saveUrlCompletionMode);
90
91 const GeneralSettings* settings = GeneralSettings::self();
92 m_urlNavigator->setUrlEditable(settings->editableUrl());
93 m_urlNavigator->setShowFullPath(settings->showFullPath());
94 m_urlNavigator->setHomeUrl(Dolphin::homeUrl());
95 KUrlComboBox* editor = m_urlNavigator->editor();
96 editor->setCompletionMode(KCompletion::CompletionMode(settings->urlCompletionMode()));
97
98 m_emptyTrashButton = new QPushButton(QIcon::fromTheme(QStringLiteral("user-trash")), i18nc("@action:button", "Empty Trash"), this);
99 m_emptyTrashButton->setFlat(true);
100 connect(m_emptyTrashButton, &QPushButton::clicked, this, [this]() { Trash::empty(this); });
101 connect(&Trash::instance(), &Trash::emptinessChanged, m_emptyTrashButton, &QPushButton::setDisabled);
102 m_emptyTrashButton->setDisabled(Trash::isEmpty());
103 m_emptyTrashButton->hide();
104
105 m_searchBox = new DolphinSearchBox(this);
106 m_searchBox->hide();
107 connect(m_searchBox, &DolphinSearchBox::activated, this, &DolphinViewContainer::activate);
108 connect(m_searchBox, &DolphinSearchBox::closeRequest, this, &DolphinViewContainer::closeSearchBox);
109 connect(m_searchBox, &DolphinSearchBox::searchRequest, this, &DolphinViewContainer::startSearching);
110 connect(m_searchBox, &DolphinSearchBox::focusViewRequest, this, &DolphinViewContainer::requestFocus);
111 m_searchBox->setWhatsThis(xi18nc("@info:whatsthis findbar",
112 "<para>This helps you find files and folders. Enter a <emphasis>"
113 "search term</emphasis> and specify search settings with the "
114 "buttons at the bottom:<list><item>Filename/Content: "
115 "Does the item you are looking for contain the search terms "
116 "within its filename or its contents?<nl/>The contents of images, "
117 "audio files and videos will not be searched.</item><item>"
118 "From Here/Everywhere: Do you want to search in this "
119 "folder and its sub-folders or everywhere?</item><item>"
120 "More Options: Click this to search by media type, access "
121 "time or rating.</item><item>More Search Tools: Install other "
122 "means to find an item.</item></list></para>"));
123
124 m_messageWidget = new KMessageWidget(this);
125 m_messageWidget->setCloseButtonVisible(true);
126 m_messageWidget->hide();
127
128 #ifndef Q_OS_WIN
129 if (getuid() == 0) {
130
131 // We must be logged in as the root user; show a big scary warning
132 showMessage(i18n("Running Dolphin as root can be dangerous. Please be careful."), Warning);
133 }
134 #endif
135
136 // Initialize filter bar
137 m_filterBar = new FilterBar(this);
138 m_filterBar->setVisible(settings->filterBar());
139
140 connect(m_filterBar, &FilterBar::filterChanged,
141 this, &DolphinViewContainer::setNameFilter);
142 connect(m_filterBar, &FilterBar::closeRequest,
143 this, &DolphinViewContainer::closeFilterBar);
144 connect(m_filterBar, &FilterBar::focusViewRequest,
145 this, &DolphinViewContainer::requestFocus);
146
147 // Initialize the main view
148 m_view = new DolphinView(url, this);
149 connect(m_view, &DolphinView::urlChanged,
150 m_filterBar, &FilterBar::slotUrlChanged);
151 connect(m_view, &DolphinView::urlChanged,
152 m_urlNavigator, &KUrlNavigator::setLocationUrl);
153 connect(m_view, &DolphinView::urlChanged,
154 m_messageWidget, &KMessageWidget::hide);
155 connect(m_view, &DolphinView::writeStateChanged,
156 this, &DolphinViewContainer::writeStateChanged);
157 connect(m_view, &DolphinView::requestItemInfo,
158 this, &DolphinViewContainer::showItemInfo);
159 connect(m_view, &DolphinView::itemActivated,
160 this, &DolphinViewContainer::slotItemActivated);
161 connect(m_view, &DolphinView::itemsActivated,
162 this, &DolphinViewContainer::slotItemsActivated);
163 connect(m_view, &DolphinView::redirection,
164 this, &DolphinViewContainer::redirect);
165 connect(m_view, &DolphinView::directoryLoadingStarted,
166 this, &DolphinViewContainer::slotDirectoryLoadingStarted);
167 connect(m_view, &DolphinView::directoryLoadingCompleted,
168 this, &DolphinViewContainer::slotDirectoryLoadingCompleted);
169 connect(m_view, &DolphinView::directoryLoadingCanceled,
170 this, &DolphinViewContainer::slotDirectoryLoadingCanceled);
171 connect(m_view, &DolphinView::itemCountChanged,
172 this, &DolphinViewContainer::delayedStatusBarUpdate);
173 connect(m_view, &DolphinView::directoryLoadingProgress,
174 this, &DolphinViewContainer::updateDirectoryLoadingProgress);
175 connect(m_view, &DolphinView::directorySortingProgress,
176 this, &DolphinViewContainer::updateDirectorySortingProgress);
177 connect(m_view, &DolphinView::selectionChanged,
178 this, &DolphinViewContainer::delayedStatusBarUpdate);
179 connect(m_view, &DolphinView::errorMessage,
180 this, &DolphinViewContainer::showErrorMessage);
181 connect(m_view, &DolphinView::urlIsFileError,
182 this, &DolphinViewContainer::slotUrlIsFileError);
183 connect(m_view, &DolphinView::activated,
184 this, &DolphinViewContainer::activate);
185
186 connect(m_urlNavigator, &KUrlNavigator::urlAboutToBeChanged,
187 this, &DolphinViewContainer::slotUrlNavigatorLocationAboutToBeChanged);
188 connect(m_urlNavigator, &KUrlNavigator::urlChanged,
189 this, &DolphinViewContainer::slotUrlNavigatorLocationChanged);
190 connect(m_urlNavigator, &KUrlNavigator::urlSelectionRequested,
191 this, &DolphinViewContainer::slotUrlSelectionRequested);
192 connect(m_urlNavigator, &KUrlNavigator::returnPressed,
193 this, &DolphinViewContainer::slotReturnPressed);
194 connect(m_urlNavigator, &KUrlNavigator::urlsDropped, this, [=](const QUrl &destination, QDropEvent *event) {
195 m_view->dropUrls(destination, event, m_urlNavigator->dropWidget());
196 });
197
198 connect(m_view, &DolphinView::directoryLoadingCompleted, this, [this]() {
199 m_emptyTrashButton->setVisible(m_view->url().scheme() == QLatin1String("trash"));
200 });
201
202 // Initialize status bar
203 m_statusBar = new DolphinStatusBar(this);
204 m_statusBar->setUrl(m_view->url());
205 m_statusBar->setZoomLevel(m_view->zoomLevel());
206 connect(m_view, &DolphinView::urlChanged,
207 m_statusBar, &DolphinStatusBar::setUrl);
208 connect(m_view, &DolphinView::zoomLevelChanged,
209 m_statusBar, &DolphinStatusBar::setZoomLevel);
210 connect(m_view, &DolphinView::infoMessage,
211 m_statusBar, &DolphinStatusBar::setText);
212 connect(m_view, &DolphinView::operationCompletedMessage,
213 m_statusBar, &DolphinStatusBar::setText);
214 connect(m_statusBar, &DolphinStatusBar::stopPressed,
215 this, &DolphinViewContainer::stopDirectoryLoading);
216 connect(m_statusBar, &DolphinStatusBar::zoomLevelChanged,
217 this, &DolphinViewContainer::slotStatusBarZoomLevelChanged);
218
219 m_statusBarTimer = new QTimer(this);
220 m_statusBarTimer->setSingleShot(true);
221 m_statusBarTimer->setInterval(300);
222 connect(m_statusBarTimer, &QTimer::timeout, this, &DolphinViewContainer::updateStatusBar);
223
224 KIO::FileUndoManager* undoManager = KIO::FileUndoManager::self();
225 connect(undoManager, &KIO::FileUndoManager::jobRecordingFinished,
226 this, &DolphinViewContainer::delayedStatusBarUpdate);
227
228 navigatorLayout->addWidget(m_urlNavigator);
229 navigatorLayout->addWidget(m_emptyTrashButton);
230
231 m_topLayout->addWidget(m_navigatorWidget);
232 m_topLayout->addWidget(m_searchBox);
233 m_topLayout->addWidget(m_messageWidget);
234 m_topLayout->addWidget(m_view);
235 m_topLayout->addWidget(m_filterBar);
236 m_topLayout->addWidget(m_statusBar);
237
238 setSearchModeEnabled(isSearchUrl(url));
239
240 connect(DetailsModeSettings::self(), &KCoreConfigSkeleton::configChanged, this, [=]() {
241 if (view()->mode() == DolphinView::Mode::DetailsView) {
242 view()->reload();
243 }
244 });
245
246 // Initialize kactivities resource instance
247
248 #ifdef HAVE_KACTIVITIES
249 m_activityResourceInstance = new KActivities::ResourceInstance(window()->winId(), url);
250 m_activityResourceInstance->setParent(this);
251 #endif
252 }
253
254 DolphinViewContainer::~DolphinViewContainer()
255 {
256 }
257
258 QUrl DolphinViewContainer::url() const
259 {
260 return m_view->url();
261 }
262
263 void DolphinViewContainer::setActive(bool active)
264 {
265 m_searchBox->setActive(active);
266 m_urlNavigator->setActive(active);
267 m_view->setActive(active);
268
269 #ifdef HAVE_KACTIVITIES
270 if (active) {
271 m_activityResourceInstance->notifyFocusedIn();
272 } else {
273 m_activityResourceInstance->notifyFocusedOut();
274 }
275 #endif
276 }
277
278 bool DolphinViewContainer::isActive() const
279 {
280 Q_ASSERT(m_view->isActive() == m_urlNavigator->isActive());
281 return m_view->isActive();
282 }
283
284 void DolphinViewContainer::setAutoGrabFocus(bool grab)
285 {
286 m_autoGrabFocus = grab;
287 }
288
289 bool DolphinViewContainer::autoGrabFocus() const
290 {
291 return m_autoGrabFocus;
292 }
293
294 QString DolphinViewContainer::currentSearchText() const
295 {
296 return m_searchBox->text();
297 }
298
299 const DolphinStatusBar* DolphinViewContainer::statusBar() const
300 {
301 return m_statusBar;
302 }
303
304 DolphinStatusBar* DolphinViewContainer::statusBar()
305 {
306 return m_statusBar;
307 }
308
309 const KUrlNavigator* DolphinViewContainer::urlNavigator() const
310 {
311 return m_urlNavigator;
312 }
313
314 KUrlNavigator* DolphinViewContainer::urlNavigator()
315 {
316 return m_urlNavigator;
317 }
318
319 const DolphinView* DolphinViewContainer::view() const
320 {
321 return m_view;
322 }
323
324 DolphinView* DolphinViewContainer::view()
325 {
326 return m_view;
327 }
328
329 void DolphinViewContainer::showMessage(const QString& msg, MessageType type)
330 {
331 if (msg.isEmpty()) {
332 return;
333 }
334
335 m_messageWidget->setText(msg);
336
337 // TODO: wrap at arbitrary character positions once QLabel can do this
338 // https://bugreports.qt.io/browse/QTBUG-1276
339 m_messageWidget->setWordWrap(true);
340
341 switch (type) {
342 case Information: m_messageWidget->setMessageType(KMessageWidget::Information); break;
343 case Warning: m_messageWidget->setMessageType(KMessageWidget::Warning); break;
344 case Error: m_messageWidget->setMessageType(KMessageWidget::Error); break;
345 default:
346 Q_ASSERT(false);
347 break;
348 }
349
350 m_messageWidget->setWordWrap(false);
351 const int unwrappedWidth = m_messageWidget->sizeHint().width();
352 m_messageWidget->setWordWrap(unwrappedWidth > size().width());
353
354 if (m_messageWidget->isVisible()) {
355 m_messageWidget->hide();
356 }
357 m_messageWidget->animatedShow();
358 }
359
360 void DolphinViewContainer::readSettings()
361 {
362 if (GeneralSettings::modifiedStartupSettings()) {
363 // The startup settings should only get applied if they have been
364 // modified by the user. Otherwise keep the (possibly) different current
365 // settings of the URL navigator and the filterbar.
366 m_urlNavigator->setUrlEditable(GeneralSettings::editableUrl());
367 m_urlNavigator->setShowFullPath(GeneralSettings::showFullPath());
368 m_urlNavigator->setHomeUrl(Dolphin::homeUrl());
369 setFilterBarVisible(GeneralSettings::filterBar());
370 }
371
372 m_view->readSettings();
373 m_statusBar->readSettings();
374 }
375
376 bool DolphinViewContainer::isFilterBarVisible() const
377 {
378 return m_filterBar->isVisible();
379 }
380
381 void DolphinViewContainer::setSearchModeEnabled(bool enabled)
382 {
383 m_searchBox->setVisible(enabled);
384 m_navigatorWidget->setVisible(!enabled);
385
386 if (enabled) {
387 const QUrl& locationUrl = m_urlNavigator->locationUrl();
388 m_searchBox->fromSearchUrl(locationUrl);
389 }
390
391 if (enabled == isSearchModeEnabled()) {
392 if (enabled && !m_searchBox->hasFocus()) {
393 m_searchBox->setFocus();
394 m_searchBox->selectAll();
395 }
396 return;
397 }
398
399 if (!enabled) {
400 m_view->setViewPropertiesContext(QString());
401
402 // Restore the URL for the URL navigator. If Dolphin has been
403 // started with a search-URL, the home URL is used as fallback.
404 QUrl url = m_searchBox->searchPath();
405 if (url.isEmpty() || !url.isValid() || isSearchUrl(url)) {
406 url = Dolphin::homeUrl();
407 }
408 m_urlNavigator->setLocationUrl(url);
409 }
410
411 m_searchModeEnabled = enabled;
412
413 Q_EMIT searchModeEnabledChanged(enabled);
414 }
415
416 bool DolphinViewContainer::isSearchModeEnabled() const
417 {
418 return m_searchModeEnabled;
419 }
420
421 QString DolphinViewContainer::placesText() const
422 {
423 QString text;
424
425 if (isSearchModeEnabled()) {
426 text = i18n("Search for %1 in %2", m_searchBox->text(), m_searchBox->searchPath().fileName());
427 } else {
428 text = url().adjusted(QUrl::StripTrailingSlash).fileName();
429 if (text.isEmpty()) {
430 text = url().host();
431 }
432 if (text.isEmpty()) {
433 text = url().scheme();
434 }
435 }
436
437 return text;
438 }
439
440 void DolphinViewContainer::reload()
441 {
442 view()->reload();
443 m_messageWidget->hide();
444 }
445
446 QString DolphinViewContainer::captionWindowTitle() const
447 {
448 if (GeneralSettings::showFullPathInTitlebar() && !isSearchModeEnabled()) {
449 if (!url().isLocalFile()) {
450 return url().adjusted(QUrl::StripTrailingSlash).toString();
451 }
452 return url().adjusted(QUrl::StripTrailingSlash).path();
453 } else {
454 return DolphinViewContainer::caption();
455 }
456 }
457
458 QString DolphinViewContainer::caption() const
459 {
460 if (isSearchModeEnabled()) {
461 if (currentSearchText().isEmpty()){
462 return i18n("Search");
463 } else {
464 return i18n("Search for %1", currentSearchText());
465 }
466 }
467
468 KFilePlacesModel *placesModel = DolphinPlacesModelSingleton::instance().placesModel();
469 const auto& matchedPlaces = placesModel->match(placesModel->index(0,0), KFilePlacesModel::UrlRole, QUrl(url().adjusted(QUrl::StripTrailingSlash).toString(QUrl::FullyEncoded).append("/?")), 1, Qt::MatchRegExp);
470
471 if (!matchedPlaces.isEmpty()) {
472 return placesModel->text(matchedPlaces.first());
473 }
474
475
476 if (!url().isLocalFile()) {
477 QUrl adjustedUrl = url().adjusted(QUrl::StripTrailingSlash);
478 QString caption;
479 if (!adjustedUrl.fileName().isEmpty()) {
480 caption = adjustedUrl.fileName();
481 } else if (!adjustedUrl.path().isEmpty() && adjustedUrl.path() != "/") {
482 caption = adjustedUrl.path();
483 } else if (!adjustedUrl.host().isEmpty()) {
484 caption = adjustedUrl.host();
485 } else {
486 caption = adjustedUrl.toString();
487 }
488 return caption;
489 }
490
491 QString fileName = url().adjusted(QUrl::StripTrailingSlash).fileName();
492 if (fileName.isEmpty()) {
493 fileName = '/';
494 }
495
496 return fileName;
497 }
498
499 void DolphinViewContainer::setUrl(const QUrl& newUrl)
500 {
501 if (newUrl != m_urlNavigator->locationUrl()) {
502 m_urlNavigator->setLocationUrl(newUrl);
503 }
504
505 #ifdef HAVE_KACTIVITIES
506 m_activityResourceInstance->setUri(newUrl);
507 #endif
508 }
509
510 void DolphinViewContainer::setFilterBarVisible(bool visible)
511 {
512 Q_ASSERT(m_filterBar);
513 if (visible) {
514 m_view->hideToolTip(ToolTipManager::HideBehavior::Instantly);
515 m_filterBar->show();
516 m_filterBar->setFocus();
517 m_filterBar->selectAll();
518 } else {
519 closeFilterBar();
520 }
521 }
522
523 void DolphinViewContainer::delayedStatusBarUpdate()
524 {
525 if (m_statusBarTimer->isActive() && (m_statusBarTimestamp.elapsed() > 2000)) {
526 // No update of the statusbar has been done during the last 2 seconds,
527 // although an update has been requested. Trigger an immediate update.
528 m_statusBarTimer->stop();
529 updateStatusBar();
530 } else {
531 // Invoke updateStatusBar() with a small delay. This assures that
532 // when a lot of delayedStatusBarUpdates() are done in a short time,
533 // no bottleneck is given.
534 m_statusBarTimer->start();
535 }
536 }
537
538 void DolphinViewContainer::updateStatusBar()
539 {
540 m_statusBarTimestamp.start();
541
542 const QString text = m_view->statusBarText();
543 m_statusBar->setDefaultText(text);
544 m_statusBar->resetToDefaultText();
545 }
546
547 void DolphinViewContainer::updateDirectoryLoadingProgress(int percent)
548 {
549 if (m_statusBar->progressText().isEmpty()) {
550 m_statusBar->setProgressText(i18nc("@info:progress", "Loading folder..."));
551 }
552 m_statusBar->setProgress(percent);
553 }
554
555 void DolphinViewContainer::updateDirectorySortingProgress(int percent)
556 {
557 if (m_statusBar->progressText().isEmpty()) {
558 m_statusBar->setProgressText(i18nc("@info:progress", "Sorting..."));
559 }
560 m_statusBar->setProgress(percent);
561 }
562
563 void DolphinViewContainer::slotDirectoryLoadingStarted()
564 {
565 if (isSearchUrl(url())) {
566 // Search KIO-slaves usually don't provide any progress information. Give
567 // a hint to the user that a searching is done:
568 updateStatusBar();
569 m_statusBar->setProgressText(i18nc("@info", "Searching..."));
570 m_statusBar->setProgress(-1);
571 } else {
572 // Trigger an undetermined progress indication. The progress
573 // information in percent will be triggered by the percent() signal
574 // of the directory lister later.
575 m_statusBar->setProgressText(QString());
576 updateDirectoryLoadingProgress(-1);
577 }
578 }
579
580 void DolphinViewContainer::slotDirectoryLoadingCompleted()
581 {
582 if (!m_statusBar->progressText().isEmpty()) {
583 m_statusBar->setProgressText(QString());
584 m_statusBar->setProgress(100);
585 }
586
587 if (isSearchUrl(url()) && m_view->itemsCount() == 0) {
588 // The dir lister has been completed on a Baloo-URI and no items have been found. Instead
589 // of showing the default status bar information ("0 items") a more helpful information is given:
590 m_statusBar->setText(i18nc("@info:status", "No items found."));
591 } else {
592 updateStatusBar();
593 }
594 }
595
596 void DolphinViewContainer::slotDirectoryLoadingCanceled()
597 {
598 if (!m_statusBar->progressText().isEmpty()) {
599 m_statusBar->setProgressText(QString());
600 m_statusBar->setProgress(100);
601 }
602
603 m_statusBar->setText(QString());
604 }
605
606 void DolphinViewContainer::slotUrlIsFileError(const QUrl& url)
607 {
608 const KFileItem item(url);
609
610 // Find out if the file can be opened in the view (for example, this is the
611 // case if the file is an archive). The mime type must be known for that.
612 item.determineMimeType();
613 const QUrl& folderUrl = DolphinView::openItemAsFolderUrl(item, true);
614 if (!folderUrl.isEmpty()) {
615 setUrl(folderUrl);
616 } else {
617 slotItemActivated(item);
618 }
619 }
620
621 void DolphinViewContainer::slotItemActivated(const KFileItem& item)
622 {
623 // It is possible to activate items on inactive views by
624 // drag & drop operations. Assure that activating an item always
625 // results in an active view.
626 m_view->setActive(true);
627
628 const QUrl& url = DolphinView::openItemAsFolderUrl(item, GeneralSettings::browseThroughArchives());
629 if (!url.isEmpty()) {
630 setUrl(url);
631 return;
632 }
633
634 KIO::OpenUrlJob *job = new KIO::OpenUrlJob(item.targetUrl());
635 job->setUiDelegate(new KIO::JobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this));
636 job->setShowOpenOrExecuteDialog(true);
637 job->start();
638 }
639
640 void DolphinViewContainer::slotItemsActivated(const KFileItemList& items)
641 {
642 Q_ASSERT(items.count() >= 2);
643
644 KFileItemActions fileItemActions(this);
645 fileItemActions.runPreferredApplications(items, QString());
646 }
647
648 void DolphinViewContainer::showItemInfo(const KFileItem& item)
649 {
650 if (item.isNull()) {
651 m_statusBar->resetToDefaultText();
652 } else {
653 m_statusBar->setText(item.getStatusBarInfo());
654 }
655 }
656
657 void DolphinViewContainer::closeFilterBar()
658 {
659 m_filterBar->closeFilterBar();
660 m_view->setFocus();
661 Q_EMIT showFilterBarChanged(false);
662 }
663
664 void DolphinViewContainer::setNameFilter(const QString& nameFilter)
665 {
666 m_view->hideToolTip(ToolTipManager::HideBehavior::Instantly);
667 m_view->setNameFilter(nameFilter);
668 delayedStatusBarUpdate();
669 }
670
671 void DolphinViewContainer::activate()
672 {
673 setActive(true);
674 }
675
676 void DolphinViewContainer::slotUrlNavigatorLocationAboutToBeChanged(const QUrl&)
677 {
678 saveViewState();
679 }
680
681 void DolphinViewContainer::slotUrlNavigatorLocationChanged(const QUrl& url)
682 {
683 slotReturnPressed();
684
685 if (KProtocolManager::supportsListing(url)) {
686 setSearchModeEnabled(isSearchUrl(url));
687 m_view->setUrl(url);
688 tryRestoreViewState();
689
690 if (m_autoGrabFocus && isActive() && !isSearchUrl(url)) {
691 // When an URL has been entered, the view should get the focus.
692 // The focus must be requested asynchronously, as changing the URL might create
693 // a new view widget.
694 QTimer::singleShot(0, this, &DolphinViewContainer::requestFocus);
695 }
696 } else if (KProtocolManager::isSourceProtocol(url)) {
697 if (url.scheme().startsWith(QLatin1String("http"))) {
698 showMessage(i18nc("@info:status", // krazy:exclude=qmethods
699 "Dolphin does not support web pages, the web browser has been launched"),
700 Information);
701 } else {
702 showMessage(i18nc("@info:status",
703 "Protocol not supported by Dolphin, default application has been launched"),
704 Information);
705 }
706
707 QDesktopServices::openUrl(url);
708 redirect(QUrl(), m_urlNavigator->locationUrl(1));
709 } else {
710 showMessage(i18nc("@info:status", "Invalid protocol"), Error);
711 m_urlNavigator->goBack();
712 }
713 }
714
715 void DolphinViewContainer::slotUrlSelectionRequested(const QUrl& url)
716 {
717 m_view->markUrlsAsSelected({url});
718 m_view->markUrlAsCurrent(url); // makes the item scroll into view
719 }
720
721 void DolphinViewContainer::redirect(const QUrl& oldUrl, const QUrl& newUrl)
722 {
723 Q_UNUSED(oldUrl)
724 const bool block = m_urlNavigator->signalsBlocked();
725 m_urlNavigator->blockSignals(true);
726
727 // Assure that the location state is reset for redirection URLs. This
728 // allows to skip redirection URLs when going back or forward in the
729 // URL history.
730 m_urlNavigator->saveLocationState(QByteArray());
731 m_urlNavigator->setLocationUrl(newUrl);
732 setSearchModeEnabled(isSearchUrl(newUrl));
733
734 m_urlNavigator->blockSignals(block);
735 }
736
737 void DolphinViewContainer::requestFocus()
738 {
739 m_view->setFocus();
740 }
741
742 void DolphinViewContainer::saveUrlCompletionMode(KCompletion::CompletionMode completion)
743 {
744 GeneralSettings::setUrlCompletionMode(completion);
745 }
746
747 void DolphinViewContainer::slotReturnPressed()
748 {
749 if (!GeneralSettings::editableUrl()) {
750 m_urlNavigator->setUrlEditable(false);
751 }
752 }
753
754 void DolphinViewContainer::startSearching()
755 {
756 const QUrl url = m_searchBox->urlForSearching();
757 if (url.isValid() && !url.isEmpty()) {
758 m_view->setViewPropertiesContext(QStringLiteral("search"));
759 m_urlNavigator->setLocationUrl(url);
760 }
761 }
762
763 void DolphinViewContainer::closeSearchBox()
764 {
765 setSearchModeEnabled(false);
766 }
767
768 void DolphinViewContainer::stopDirectoryLoading()
769 {
770 m_view->stopLoading();
771 m_statusBar->setProgress(100);
772 }
773
774 void DolphinViewContainer::slotStatusBarZoomLevelChanged(int zoomLevel)
775 {
776 m_view->setZoomLevel(zoomLevel);
777 }
778
779 void DolphinViewContainer::showErrorMessage(const QString& msg)
780 {
781 showMessage(msg, Error);
782 }
783
784 bool DolphinViewContainer::isSearchUrl(const QUrl& url) const
785 {
786 return url.scheme().contains(QLatin1String("search"));
787 }
788
789 void DolphinViewContainer::saveViewState()
790 {
791 QByteArray locationState;
792 QDataStream stream(&locationState, QIODevice::WriteOnly);
793 m_view->saveState(stream);
794 m_urlNavigator->saveLocationState(locationState);
795 }
796
797 void DolphinViewContainer::tryRestoreViewState()
798 {
799 QByteArray locationState = m_urlNavigator->locationState();
800 if (!locationState.isEmpty()) {
801 QDataStream stream(&locationState, QIODevice::ReadOnly);
802 m_view->restoreState(stream);
803 }
804 }