dolphinviewcontainer.cpp 26 KB
Newer Older
1
2
3
4
5
/*
 * SPDX-FileCopyrightText: 2007 Peter Penz <peter.penz19@gmail.com>
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */
6
7
8

#include "dolphinviewcontainer.h"

Roman Inflianskas's avatar
Roman Inflianskas committed
9
10
#include "dolphin_generalsettings.h"
#include "dolphindebug.h"
11
#include "dolphinplacesmodelsingleton.h"
Roman Inflianskas's avatar
Roman Inflianskas committed
12
13
14
15
16
17
#include "filterbar/filterbar.h"
#include "global.h"
#include "search/dolphinsearchbox.h"
#include "statusbar/dolphinstatusbar.h"
#include "views/viewmodecontroller.h"
#include "views/viewproperties.h"
18
#include "dolphin_detailsmodesettings.h"
19

20
21
22
#ifdef HAVE_KACTIVITIES
#include <KActivities/ResourceInstance>
#endif
23
#include <KFileItemActions>
David Hallas's avatar
David Hallas committed
24
#include <KFilePlacesModel>
Peter Penz's avatar
Peter Penz committed
25
#include <KIO/PreviewJob>
Ahmad Samir's avatar
Ahmad Samir committed
26
27
#include <KIO/OpenUrlJob>
#include <KIO/JobUiDelegate>
Roman Inflianskas's avatar
Roman Inflianskas committed
28
#include <KLocalizedString>
29
#include <KMessageWidget>
Roman Inflianskas's avatar
Roman Inflianskas committed
30
#include <KProtocolManager>
Peter Penz's avatar
Peter Penz committed
31
32
#include <KShell>
#include <KUrlComboBox>
33
#include <KUrlNavigator>
34

Roman Inflianskas's avatar
Roman Inflianskas committed
35
36
37
38
39
40
#include <QDropEvent>
#include <QLoggingCategory>
#include <QMimeData>
#include <QTimer>
#include <QUrl>
#include <QVBoxLayout>
41
#include <QDesktopServices>
42

Lukáš Tinkl's avatar
Lukáš Tinkl committed
43
DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) :
44
    QWidget(parent),
Kevin Funk's avatar
Kevin Funk committed
45
    m_topLayout(nullptr),
46
47
    m_urlNavigator{new DolphinUrlNavigator(url)},
    m_urlNavigatorConnected{nullptr},
Kevin Funk's avatar
Kevin Funk committed
48
    m_searchBox(nullptr),
49
    m_searchModeEnabled(false),
Kevin Funk's avatar
Kevin Funk committed
50
51
52
53
54
    m_messageWidget(nullptr),
    m_view(nullptr),
    m_filterBar(nullptr),
    m_statusBar(nullptr),
    m_statusBarTimer(nullptr),
55
    m_statusBarTimestamp(),
56
    m_autoGrabFocus(true)
57
58
#ifdef HAVE_KACTIVITIES
    , m_activityResourceInstance(nullptr)
59
#endif
60
61
{
    hide();
62

63
64
    m_topLayout = new QVBoxLayout(this);
    m_topLayout->setSpacing(0);
Laurent Montel's avatar
Laurent Montel committed
65
    m_topLayout->setContentsMargins(0, 0, 0, 0);
66

67
68
    m_searchBox = new DolphinSearchBox(this);
    m_searchBox->hide();
69
70
71
    connect(m_searchBox, &DolphinSearchBox::activated, this, &DolphinViewContainer::activate);
    connect(m_searchBox, &DolphinSearchBox::closeRequest, this, &DolphinViewContainer::closeSearchBox);
    connect(m_searchBox, &DolphinSearchBox::searchRequest, this, &DolphinViewContainer::startSearching);
72
    connect(m_searchBox, &DolphinSearchBox::focusViewRequest, this, &DolphinViewContainer::requestFocus);
73
74
75
76
77
78
79
80
81
82
83
84
    m_searchBox->setWhatsThis(xi18nc("@info:whatsthis findbar",
        "<para>This helps you find files and folders. Enter a <emphasis>"
        "search term</emphasis> and specify search settings with the "
        "buttons at the bottom:<list><item>Filename/Content: "
        "Does the item you are looking for contain the search terms "
        "within its filename or its contents?<nl/>The contents of images, "
        "audio files and videos will not be searched.</item><item>"
        "From Here/Everywhere: Do you want to search in this "
        "folder and its sub-folders or everywhere?</item><item>"
        "More Options: Click this to search by media type, access "
        "time or rating.</item><item>More Search Tools: Install other "
        "means to find an item.</item></list></para>"));
85

86
87
88
89
    m_messageWidget = new KMessageWidget(this);
    m_messageWidget->setCloseButtonVisible(true);
    m_messageWidget->hide();

90
91
92
93
94
95
96
97
#ifndef Q_OS_WIN
    if (getuid() == 0) {

        // We must be logged in as the root user; show a big scary warning
        showMessage(i18n("Running Dolphin as root can be dangerous. Please be careful."), Warning);
    }
#endif

98
99
    // Initialize filter bar
    m_filterBar = new FilterBar(this);
100
    m_filterBar->setVisible(GeneralSettings::filterBar());
101
102
103
104
105
106
107
108
109

    connect(m_filterBar, &FilterBar::filterChanged,
            this, &DolphinViewContainer::setNameFilter);
    connect(m_filterBar, &FilterBar::closeRequest,
            this, &DolphinViewContainer::closeFilterBar);
    connect(m_filterBar, &FilterBar::focusViewRequest,
            this, &DolphinViewContainer::requestFocus);

    // Initialize the main view
110
    m_view = new DolphinView(url, this);
111
112
    connect(m_view, &DolphinView::urlChanged,
            m_filterBar, &FilterBar::slotUrlChanged);
113
114
    connect(m_view, &DolphinView::urlChanged,
            m_messageWidget, &KMessageWidget::hide);
115
116
117
    // m_urlNavigator stays in sync with m_view's location changes and
    // keeps track of them so going back and forth in the history works.
    connect(m_view, &DolphinView::urlChanged,
118
119
            m_urlNavigator.get(), &DolphinUrlNavigator::setLocationUrl);
    connect(m_urlNavigator.get(), &DolphinUrlNavigator::urlChanged,
120
            this, &DolphinViewContainer::slotUrlNavigatorLocationChanged);
121
122
123
124
    connect(m_urlNavigator.get(), &DolphinUrlNavigator::urlAboutToBeChanged,
            this, &DolphinViewContainer::slotUrlNavigatorLocationAboutToBeChanged);
    connect(m_urlNavigator.get(), &DolphinUrlNavigator::urlSelectionRequested,
            this, &DolphinViewContainer::slotUrlSelectionRequested);
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
    connect(m_view, &DolphinView::writeStateChanged,
            this, &DolphinViewContainer::writeStateChanged);
    connect(m_view, &DolphinView::requestItemInfo,
            this, &DolphinViewContainer::showItemInfo);
    connect(m_view, &DolphinView::itemActivated,
            this, &DolphinViewContainer::slotItemActivated);
    connect(m_view, &DolphinView::itemsActivated,
            this, &DolphinViewContainer::slotItemsActivated);
    connect(m_view, &DolphinView::redirection,
            this, &DolphinViewContainer::redirect);
    connect(m_view, &DolphinView::directoryLoadingStarted,
            this, &DolphinViewContainer::slotDirectoryLoadingStarted);
    connect(m_view, &DolphinView::directoryLoadingCompleted,
            this, &DolphinViewContainer::slotDirectoryLoadingCompleted);
    connect(m_view, &DolphinView::directoryLoadingCanceled,
            this, &DolphinViewContainer::slotDirectoryLoadingCanceled);
    connect(m_view, &DolphinView::itemCountChanged,
            this, &DolphinViewContainer::delayedStatusBarUpdate);
    connect(m_view, &DolphinView::directoryLoadingProgress,
            this, &DolphinViewContainer::updateDirectoryLoadingProgress);
    connect(m_view, &DolphinView::directorySortingProgress,
            this, &DolphinViewContainer::updateDirectorySortingProgress);
    connect(m_view, &DolphinView::selectionChanged,
            this, &DolphinViewContainer::delayedStatusBarUpdate);
    connect(m_view, &DolphinView::errorMessage,
            this, &DolphinViewContainer::showErrorMessage);
    connect(m_view, &DolphinView::urlIsFileError,
            this, &DolphinViewContainer::slotUrlIsFileError);
153
154
    connect(m_view, &DolphinView::activated,
            this, &DolphinViewContainer::activate);
155

156
157
158
159
    // Initialize status bar
    m_statusBar = new DolphinStatusBar(this);
    m_statusBar->setUrl(m_view->url());
    m_statusBar->setZoomLevel(m_view->zoomLevel());
160
161
162
163
164
165
166
167
    connect(m_view, &DolphinView::urlChanged,
            m_statusBar, &DolphinStatusBar::setUrl);
    connect(m_view, &DolphinView::zoomLevelChanged,
            m_statusBar, &DolphinStatusBar::setZoomLevel);
    connect(m_view, &DolphinView::infoMessage,
            m_statusBar, &DolphinStatusBar::setText);
    connect(m_view, &DolphinView::operationCompletedMessage,
            m_statusBar, &DolphinStatusBar::setText);
168
169
170
171
    connect(m_view, &DolphinView::statusBarTextChanged,
            m_statusBar, &DolphinStatusBar::setDefaultText);
    connect(m_view, &DolphinView::statusBarTextChanged,
            m_statusBar, &DolphinStatusBar::resetToDefaultText);
172
173
174
175
    connect(m_statusBar, &DolphinStatusBar::stopPressed,
            this, &DolphinViewContainer::stopDirectoryLoading);
    connect(m_statusBar, &DolphinStatusBar::zoomLevelChanged,
            this, &DolphinViewContainer::slotStatusBarZoomLevelChanged);
176

177
178
179
    m_statusBarTimer = new QTimer(this);
    m_statusBarTimer->setSingleShot(true);
    m_statusBarTimer->setInterval(300);
180
    connect(m_statusBarTimer, &QTimer::timeout, this, &DolphinViewContainer::updateStatusBar);
181

182
    KIO::FileUndoManager* undoManager = KIO::FileUndoManager::self();
183
184
    connect(undoManager, &KIO::FileUndoManager::jobRecordingFinished,
            this, &DolphinViewContainer::delayedStatusBarUpdate);
185

186
    m_topLayout->addWidget(m_searchBox);
187
    m_topLayout->addWidget(m_messageWidget);
188
189
190
    m_topLayout->addWidget(m_view);
    m_topLayout->addWidget(m_filterBar);
    m_topLayout->addWidget(m_statusBar);
191
192

    setSearchModeEnabled(isSearchUrl(url));
193

194
195
196
197
198
199
    connect(DetailsModeSettings::self(), &KCoreConfigSkeleton::configChanged, this, [=]() {
        if (view()->mode() == DolphinView::Mode::DetailsView) {
            view()->reload();
        }
    });

200
201
    // Initialize kactivities resource instance

202
203
#ifdef HAVE_KACTIVITIES
    m_activityResourceInstance = new KActivities::ResourceInstance(window()->winId(), url);
204
    m_activityResourceInstance->setParent(this);
205
#endif
206
207
208
209
210
211
}

DolphinViewContainer::~DolphinViewContainer()
{
}

Lukáš Tinkl's avatar
Lukáš Tinkl committed
212
QUrl DolphinViewContainer::url() const
213
{
214
    return m_view->url();
215
216
217
218
}

void DolphinViewContainer::setActive(bool active)
{
219
    m_searchBox->setActive(active);
220
221
222
    if (m_urlNavigatorConnected) {
        m_urlNavigatorConnected->setActive(active);
    }
223
    m_view->setActive(active);
224

225
#ifdef HAVE_KACTIVITIES
226
227
228
229
230
    if (active) {
        m_activityResourceInstance->notifyFocusedIn();
    } else {
        m_activityResourceInstance->notifyFocusedOut();
    }
231
#endif
232
233
234
235
236
237
238
}

bool DolphinViewContainer::isActive() const
{
    return m_view->isActive();
}

239
240
241
242
243
244
245
246
247
248
void DolphinViewContainer::setAutoGrabFocus(bool grab)
{
    m_autoGrabFocus = grab;
}

bool DolphinViewContainer::autoGrabFocus() const
{
    return m_autoGrabFocus;
}

249
250
251
252
253
QString DolphinViewContainer::currentSearchText() const
{
     return m_searchBox->text();
}

Peter Penz's avatar
Peter Penz committed
254
255
256
257
258
259
260
261
262
263
const DolphinStatusBar* DolphinViewContainer::statusBar() const
{
    return m_statusBar;
}

DolphinStatusBar* DolphinViewContainer::statusBar()
{
    return m_statusBar;
}

264
265
266
267
268
269
270
271
272
273
const DolphinUrlNavigator* DolphinViewContainer::urlNavigator() const
{
    return m_urlNavigatorConnected;
}

DolphinUrlNavigator* DolphinViewContainer::urlNavigator()
{
    return m_urlNavigatorConnected;
}

274
const DolphinUrlNavigator *DolphinViewContainer::urlNavigatorInternalWithHistory() const
Peter Penz's avatar
Peter Penz committed
275
{
276
    return m_urlNavigator.get();
Peter Penz's avatar
Peter Penz committed
277
278
}

279
DolphinUrlNavigator *DolphinViewContainer::urlNavigatorInternalWithHistory()
Peter Penz's avatar
Peter Penz committed
280
{
281
    return m_urlNavigator.get();
Peter Penz's avatar
Peter Penz committed
282
283
284
285
286
287
288
289
290
291
292
293
}

const DolphinView* DolphinViewContainer::view() const
{
    return m_view;
}

DolphinView* DolphinViewContainer::view()
{
    return m_view;
}

294
295
296
297
void DolphinViewContainer::connectUrlNavigator(DolphinUrlNavigator *urlNavigator)
{
    Q_CHECK_PTR(urlNavigator);
    Q_ASSERT(!m_urlNavigatorConnected);
298
    Q_ASSERT(m_urlNavigator.get() != urlNavigator);
299
300
    Q_CHECK_PTR(m_view);

301
302
303
304
305
    urlNavigator->setLocationUrl(m_view->url());
    if (m_urlNavigatorVisualState) {
        urlNavigator->setVisualState(*m_urlNavigatorVisualState.get());
        m_urlNavigatorVisualState.reset();
    }
306
    urlNavigator->setActive(isActive());
307

308
    // Url changes are still done via m_urlNavigator.
309
    connect(urlNavigator, &DolphinUrlNavigator::urlChanged,
310
            m_urlNavigator.get(), &DolphinUrlNavigator::setLocationUrl);
311
312
    connect(urlNavigator, &DolphinUrlNavigator::urlsDropped,
            this, [=](const QUrl &destination, QDropEvent *event) {
313
314
        m_view->dropUrls(destination, event, urlNavigator->dropWidget());
    });
315
316
317
318
319
    // Aside from these, only visual things need to be connected.
    connect(m_view, &DolphinView::urlChanged,
            urlNavigator, &DolphinUrlNavigator::setLocationUrl);
    connect(urlNavigator, &DolphinUrlNavigator::activated,
            this, &DolphinViewContainer::activate);
320

321
    m_urlNavigatorConnected = urlNavigator;
322
323
324
325
326
327
328
329
}

void DolphinViewContainer::disconnectUrlNavigator()
{
    if (!m_urlNavigatorConnected) {
        return;
    }

330
331
332
333
    disconnect(m_urlNavigatorConnected, &DolphinUrlNavigator::urlChanged,
               m_urlNavigator.get(), &DolphinUrlNavigator::setLocationUrl);
    disconnect(m_urlNavigatorConnected, &DolphinUrlNavigator::urlsDropped,
               this, nullptr);
334
335
    disconnect(m_view, &DolphinView::urlChanged,
               m_urlNavigatorConnected, &DolphinUrlNavigator::setLocationUrl);
336
    disconnect(m_urlNavigatorConnected, &DolphinUrlNavigator::activated,
337
               this, &DolphinViewContainer::activate);
338

339
    m_urlNavigatorVisualState = m_urlNavigatorConnected->visualState();
340
341
342
    m_urlNavigatorConnected = nullptr;
}

343
void DolphinViewContainer::showMessage(const QString& msg, MessageType type)
344
345
{
    if (msg.isEmpty()) {
346
        return;
347
348
349
350
    }

    m_messageWidget->setText(msg);

Nate Graham's avatar
Nate Graham committed
351
352
353
354
    // TODO: wrap at arbitrary character positions once QLabel can do this
    // https://bugreports.qt.io/browse/QTBUG-1276
    m_messageWidget->setWordWrap(true);

355
356
357
358
359
360
361
362
363
364
365
366
367
    switch (type) {
    case Information: m_messageWidget->setMessageType(KMessageWidget::Information); break;
    case Warning:     m_messageWidget->setMessageType(KMessageWidget::Warning); break;
    case Error:       m_messageWidget->setMessageType(KMessageWidget::Error); break;
    default:
        Q_ASSERT(false);
        break;
    }

    m_messageWidget->setWordWrap(false);
    const int unwrappedWidth = m_messageWidget->sizeHint().width();
    m_messageWidget->setWordWrap(unwrappedWidth > size().width());

368
369
370
    if (m_messageWidget->isVisible()) {
        m_messageWidget->hide();
    }
371
372
373
    m_messageWidget->animatedShow();
}

374
void DolphinViewContainer::readSettings()
375
{
376
377
378
    // The startup settings should (only) get applied if they have been
    // modified by the user. Otherwise keep the (possibly) different current
    // setting of the filterbar.
379
380
    if (GeneralSettings::modifiedStartupSettings()) {
        setFilterBarVisible(GeneralSettings::filterBar());
381
382
    }

383
384
    m_view->readSettings();
    m_statusBar->readSettings();
385
386
}

387
388
389
390
391
bool DolphinViewContainer::isFilterBarVisible() const
{
    return m_filterBar->isVisible();
}

392
393
void DolphinViewContainer::setSearchModeEnabled(bool enabled)
{
394
395
    m_searchBox->setVisible(enabled);

396
    if (enabled) {
397
        const QUrl& locationUrl = m_urlNavigator->locationUrl();
398
399
400
        m_searchBox->fromSearchUrl(locationUrl);
    }

401
    if (enabled == isSearchModeEnabled()) {
402
403
404
405
        if (enabled && !m_searchBox->hasFocus()) {
            m_searchBox->setFocus();
            m_searchBox->selectAll();
        }
406
407
408
        return;
    }

409
    if (!enabled) {
410
411
        m_view->setViewPropertiesContext(QString());

412
413
        // Restore the URL for the URL navigator. If Dolphin has been
        // started with a search-URL, the home URL is used as fallback.
Lukáš Tinkl's avatar
Lukáš Tinkl committed
414
        QUrl url = m_searchBox->searchPath();
415
        if (url.isEmpty() || !url.isValid() || isSearchUrl(url)) {
416
            url = Dolphin::homeUrl();
417
        }
418
        m_urlNavigatorConnected->setLocationUrl(url);
419
    }
420
421

    m_searchModeEnabled = enabled;
422

Alexander Lohnau's avatar
Alexander Lohnau committed
423
    Q_EMIT searchModeEnabledChanged(enabled);
424
425
426
427
}

bool DolphinViewContainer::isSearchModeEnabled() const
{
428
    return m_searchModeEnabled;
429
430
}

431
432
433
434
435
QString DolphinViewContainer::placesText() const
{
    QString text;

    if (isSearchModeEnabled()) {
436
        text = i18n("Search for %1 in %2", m_searchBox->text(), m_searchBox->searchPath().fileName());
437
    } else {
438
        text = url().adjusted(QUrl::StripTrailingSlash).fileName();
439
440
441
        if (text.isEmpty()) {
            text = url().host();
        }
442
443
444
        if (text.isEmpty()) {
            text = url().scheme();
        }
445
446
447
448
449
    }

    return text;
}

450
451
452
453
454
455
void DolphinViewContainer::reload()
{
    view()->reload();
    m_messageWidget->hide();
}

456
457
458
459
460
461
462
463
464
465
466
467
QString DolphinViewContainer::captionWindowTitle() const
{
    if (GeneralSettings::showFullPathInTitlebar() && !isSearchModeEnabled()) {
        if (!url().isLocalFile()) {
            return url().adjusted(QUrl::StripTrailingSlash).toString();
        }
        return url().adjusted(QUrl::StripTrailingSlash).path();
    } else {
        return DolphinViewContainer::caption();
    }
}

468
QString DolphinViewContainer::caption() const
David Hallas's avatar
David Hallas committed
469
{
470
471
472
473
474
475
476
477
    if (isSearchModeEnabled()) {
        if (currentSearchText().isEmpty()){
            return i18n("Search");
        } else {
            return i18n("Search for %1", currentSearchText());
        }
    }

David Hallas's avatar
David Hallas committed
478
    KFilePlacesModel *placesModel = DolphinPlacesModelSingleton::instance().placesModel();
479
    const auto& matchedPlaces = placesModel->match(placesModel->index(0,0), KFilePlacesModel::UrlRole, QUrl(url().adjusted(QUrl::StripTrailingSlash).toString(QUrl::FullyEncoded).append("/?")), 1, Qt::MatchRegularExpression);
David Hallas's avatar
David Hallas committed
480
481
482
483

    if (!matchedPlaces.isEmpty()) {
        return placesModel->text(matchedPlaces.first());
    }
484
485


David Hallas's avatar
David Hallas committed
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
    if (!url().isLocalFile()) {
        QUrl adjustedUrl = url().adjusted(QUrl::StripTrailingSlash);
        QString caption;
        if (!adjustedUrl.fileName().isEmpty()) {
            caption = adjustedUrl.fileName();
        } else if (!adjustedUrl.path().isEmpty() && adjustedUrl.path() != "/") {
            caption = adjustedUrl.path();
        } else if (!adjustedUrl.host().isEmpty()) {
            caption = adjustedUrl.host();
        } else {
            caption = adjustedUrl.toString();
        }
        return caption;
    }

    QString fileName = url().adjusted(QUrl::StripTrailingSlash).fileName();
    if (fileName.isEmpty()) {
        fileName = '/';
    }

    return fileName;
}

Lukáš Tinkl's avatar
Lukáš Tinkl committed
509
void DolphinViewContainer::setUrl(const QUrl& newUrl)
510
{
511
512
    if (newUrl != m_urlNavigator->locationUrl()) {
        m_urlNavigator->setLocationUrl(newUrl);
513
    }
514

515
#ifdef HAVE_KACTIVITIES
516
    m_activityResourceInstance->setUri(newUrl);
517
#endif
518
519
}

520
void DolphinViewContainer::setFilterBarVisible(bool visible)
521
{
522
    Q_ASSERT(m_filterBar);
523
    if (visible) {
524
        m_view->hideToolTip(ToolTipManager::HideBehavior::Instantly);
525
        m_filterBar->show();
526
        m_filterBar->setFocus();
527
        m_filterBar->selectAll();
528
529
530
531
532
    } else {
        closeFilterBar();
    }
}

533
534
void DolphinViewContainer::delayedStatusBarUpdate()
{
535
536
537
538
539
540
541
542
543
544
545
    if (m_statusBarTimer->isActive() && (m_statusBarTimestamp.elapsed() > 2000)) {
        // No update of the statusbar has been done during the last 2 seconds,
        // although an update has been requested. Trigger an immediate update.
        m_statusBarTimer->stop();
        updateStatusBar();
    } else {
        // Invoke updateStatusBar() with a small delay. This assures that
        // when a lot of delayedStatusBarUpdates() are done in a short time,
        // no bottleneck is given.
        m_statusBarTimer->start();
    }
546
547
548
549
}

void DolphinViewContainer::updateStatusBar()
{
550
    m_statusBarTimestamp.start();
551
    m_view->requestStatusBarText();
552
553
}

554
void DolphinViewContainer::updateDirectoryLoadingProgress(int percent)
555
556
557
558
559
560
561
{
    if (m_statusBar->progressText().isEmpty()) {
        m_statusBar->setProgressText(i18nc("@info:progress", "Loading folder..."));
    }
    m_statusBar->setProgress(percent);
}

562
void DolphinViewContainer::updateDirectorySortingProgress(int percent)
563
564
565
566
567
568
569
{
    if (m_statusBar->progressText().isEmpty()) {
        m_statusBar->setProgressText(i18nc("@info:progress", "Sorting..."));
    }
    m_statusBar->setProgress(percent);
}

570
void DolphinViewContainer::slotDirectoryLoadingStarted()
Peter Penz's avatar
Peter Penz committed
571
{
572
573
    if (isSearchUrl(url())) {
        // Search KIO-slaves usually don't provide any progress information. Give
574
        // a hint to the user that a searching is done:
575
        updateStatusBar();
Peter Penz's avatar
Peter Penz committed
576
577
        m_statusBar->setProgressText(i18nc("@info", "Searching..."));
        m_statusBar->setProgress(-1);
578
579
580
581
    } else {
        // Trigger an undetermined progress indication. The progress
        // information in percent will be triggered by the percent() signal
        // of the directory lister later.
582
        m_statusBar->setProgressText(QString());
583
        updateDirectoryLoadingProgress(-1);
Peter Penz's avatar
Peter Penz committed
584
    }
585
586
}

587
void DolphinViewContainer::slotDirectoryLoadingCompleted()
588
{
589
    if (!m_statusBar->progressText().isEmpty()) {
590
591
592
593
        m_statusBar->setProgressText(QString());
        m_statusBar->setProgress(100);
    }

594
    if (isSearchUrl(url()) && m_view->itemsCount() == 0) {
Vishesh Handa's avatar
Vishesh Handa committed
595
        // The dir lister has been completed on a Baloo-URI and no items have been found. Instead
596
        // of showing the default status bar information ("0 items") a more helpful information is given:
597
        m_statusBar->setText(i18nc("@info:status", "No items found."));
598
599
600
    } else {
        updateStatusBar();
    }
601
602
}

603
604
605
606
607
608
609
void DolphinViewContainer::slotDirectoryLoadingCanceled()
{
    if (!m_statusBar->progressText().isEmpty()) {
        m_statusBar->setProgressText(QString());
        m_statusBar->setProgress(100);
    }

610
    m_statusBar->setText(QString());
611
612
}

Lukáš Tinkl's avatar
Lukáš Tinkl committed
613
void DolphinViewContainer::slotUrlIsFileError(const QUrl& url)
614
{
615
    const KFileItem item(url);
616
617
618
619

    // Find out if the file can be opened in the view (for example, this is the
    // case if the file is an archive). The mime type must be known for that.
    item.determineMimeType();
Lukáš Tinkl's avatar
Lukáš Tinkl committed
620
    const QUrl& folderUrl = DolphinView::openItemAsFolderUrl(item, true);
621
    if (!folderUrl.isEmpty()) {
622
        setUrl(folderUrl);
623
624
625
    } else {
        slotItemActivated(item);
    }
626
627
}

628
void DolphinViewContainer::slotItemActivated(const KFileItem& item)
629
{
630
631
632
633
634
    // It is possible to activate items on inactive views by
    // drag & drop operations. Assure that activating an item always
    // results in an active view.
    m_view->setActive(true);

Lukáš Tinkl's avatar
Lukáš Tinkl committed
635
    const QUrl& url = DolphinView::openItemAsFolderUrl(item, GeneralSettings::browseThroughArchives());
636
    if (!url.isEmpty()) {
637
        setUrl(url);
638
639
640
        return;
    }

Ahmad Samir's avatar
Ahmad Samir committed
641
642
643
644
    KIO::OpenUrlJob *job = new KIO::OpenUrlJob(item.targetUrl());
    job->setUiDelegate(new KIO::JobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this));
    job->setShowOpenOrExecuteDialog(true);
    job->start();
645
646
}

647
648
649
650
651
652
653
654
void DolphinViewContainer::slotItemsActivated(const KFileItemList& items)
{
    Q_ASSERT(items.count() >= 2);

    KFileItemActions fileItemActions(this);
    fileItemActions.runPreferredApplications(items, QString());
}

655
void DolphinViewContainer::showItemInfo(const KFileItem& item)
656
{
657
    if (item.isNull()) {
658
        m_statusBar->resetToDefaultText();
659
    } else {
660
        m_statusBar->setText(item.getStatusBarInfo());
661
662
663
    }
}

664
665
void DolphinViewContainer::closeFilterBar()
{
666
    m_filterBar->closeFilterBar();
667
    m_view->setFocus();
Alexander Lohnau's avatar
Alexander Lohnau committed
668
    Q_EMIT showFilterBarChanged(false);
669
670
}

671
void DolphinViewContainer::setNameFilter(const QString& nameFilter)
672
{
673
    m_view->hideToolTip(ToolTipManager::HideBehavior::Instantly);
674
    m_view->setNameFilter(nameFilter);
675
    delayedStatusBarUpdate();
676
677
}

678
void DolphinViewContainer::activate()
679
{
680
    setActive(true);
681
682
}

683
void DolphinViewContainer::slotUrlNavigatorLocationAboutToBeChanged(const QUrl&)
684
{
685
    saveViewState();
686
}
687

Lukáš Tinkl's avatar
Lukáš Tinkl committed
688
void DolphinViewContainer::slotUrlNavigatorLocationChanged(const QUrl& url)
689
{
690
691
692
    if (m_urlNavigatorConnected) {
        m_urlNavigatorConnected->slotReturnPressed();
    }
693

694
    if (KProtocolManager::supportsListing(url)) {
695
        setSearchModeEnabled(isSearchUrl(url));
696
        m_view->setUrl(url);
697
        tryRestoreViewState();
698

699
        if (m_autoGrabFocus && isActive() && !isSearchUrl(url)) {
700
701
            // When an URL has been entered, the view should get the focus.
            // The focus must be requested asynchronously, as changing the URL might create
702
            // a new view widget.
703
            QTimer::singleShot(0, this, &DolphinViewContainer::requestFocus);
704
        }
705
    } else if (KProtocolManager::isSourceProtocol(url)) {
Lukáš Tinkl's avatar
Lukáš Tinkl committed
706
        if (url.scheme().startsWith(QLatin1String("http"))) {
Peter Penz's avatar
Peter Penz committed
707
            showMessage(i18nc("@info:status", // krazy:exclude=qmethods
708
709
                              "Dolphin does not support web pages, the web browser has been launched"),
                        Information);
710
        } else {
711
            showMessage(i18nc("@info:status",
712
                              "Protocol not supported by Dolphin, default application has been launched"),
713
                        Information);
714
        }
715

716
717
        QDesktopServices::openUrl(url);
        redirect(QUrl(), m_urlNavigator->locationUrl(1));
718
    } else {
719
        showMessage(i18nc("@info:status", "Invalid protocol"), Error);
720
        m_urlNavigator->goBack();
721
    }
722
723
}

724
725
726
727
728
729
void DolphinViewContainer::slotUrlSelectionRequested(const QUrl& url)
{
    m_view->markUrlsAsSelected({url});
    m_view->markUrlAsCurrent(url); // makes the item scroll into view
}

730
731
732
733
734
735
736
737
738
739
740
741
void DolphinViewContainer::disableUrlNavigatorSelectionRequests()
{
    disconnect(m_urlNavigator.get(), &KUrlNavigator::urlSelectionRequested,
        this, &DolphinViewContainer::slotUrlSelectionRequested);
}

void DolphinViewContainer::enableUrlNavigatorSelectionRequests()
{
    connect(m_urlNavigator.get(), &KUrlNavigator::urlSelectionRequested,
        this, &DolphinViewContainer::slotUrlSelectionRequested);
}

Lukáš Tinkl's avatar
Lukáš Tinkl committed
742
void DolphinViewContainer::redirect(const QUrl& oldUrl, const QUrl& newUrl)
743
{
744
    Q_UNUSED(oldUrl)
745
746
    const bool block = m_urlNavigator->signalsBlocked();
    m_urlNavigator->blockSignals(true);
747

748
749
750
751
    // 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());
752
    m_urlNavigator->setLocationUrl(newUrl);
753
    setSearchModeEnabled(isSearchUrl(newUrl));
754

755
756
757
    m_urlNavigator->blockSignals(block);
}

758
759
760
761
762
void DolphinViewContainer::requestFocus()
{
    m_view->setFocus();
}

Peter Penz's avatar
Peter Penz committed
763
void DolphinViewContainer::startSearching()
764
{
765
    Q_CHECK_PTR(m_urlNavigatorConnected);
Lukáš Tinkl's avatar
Lukáš Tinkl committed
766
    const QUrl url = m_searchBox->urlForSearching();
767
    if (url.isValid() && !url.isEmpty()) {
768
        m_view->setViewPropertiesContext(QStringLiteral("search"));
769
        m_urlNavigatorConnected->setLocationUrl(url);
770
771
772
773
774
775
776
777
    }
}

void DolphinViewContainer::closeSearchBox()
{
    setSearchModeEnabled(false);
}

778
void DolphinViewContainer::stopDirectoryLoading()
779
780
{
    m_view->stopLoading();
781
    m_statusBar->setProgress(100);
782
783
}

784
785
786
787
788
789
790
791
792
793
void DolphinViewContainer::slotStatusBarZoomLevelChanged(int zoomLevel)
{
    m_view->setZoomLevel(zoomLevel);
}

void DolphinViewContainer::showErrorMessage(const QString& msg)
{
    showMessage(msg, Error);
}

Lukáš Tinkl's avatar
Lukáš Tinkl committed
794
bool DolphinViewContainer::isSearchUrl(const QUrl& url) const
795
{
796
    return url.scheme().contains(QLatin1String("search"));
797
798
}

799
void DolphinViewContainer::saveViewState()
800
{
801
802
803
804
    QByteArray locationState;
    QDataStream stream(&locationState, QIODevice::WriteOnly);
    m_view->saveState(stream);
    m_urlNavigator->saveLocationState(locationState);
805
}
806
807
808
809
810
811
812
813
814

void DolphinViewContainer::tryRestoreViewState()
{
    QByteArray locationState = m_urlNavigator->locationState();
    if (!locationState.isEmpty()) {
        QDataStream stream(&locationState, QIODevice::ReadOnly);
        m_view->restoreState(stream);
    }
}