dolphinviewcontainer.cpp 27 KB
Newer Older
1
/***************************************************************************
2
 *   Copyright (C) 2007 by Peter Penz <peter.penz19@gmail.com>             *
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
 ***************************************************************************/

#include "dolphinviewcontainer.h"

Roman Inflianskas's avatar
Roman Inflianskas committed
22
#include "dolphin_generalsettings.h"
23
#include "dolphinplacesmodelsingleton.h"
Roman Inflianskas's avatar
Roman Inflianskas committed
24
25
26
27
28
#include "dolphindebug.h"
#include "filterbar/filterbar.h"
#include "global.h"
#include "search/dolphinsearchbox.h"
#include "statusbar/dolphinstatusbar.h"
29
#include "trash/dolphintrash.h"
Roman Inflianskas's avatar
Roman Inflianskas committed
30
31
#include "views/viewmodecontroller.h"
#include "views/viewproperties.h"
32

33
34
35
#ifdef HAVE_KACTIVITIES
#include <KActivities/ResourceInstance>
#endif
36
#include <KFileItemActions>
David Hallas's avatar
David Hallas committed
37
#include <KFilePlacesModel>
Peter Penz's avatar
Peter Penz committed
38
#include <KIO/PreviewJob>
Roman Inflianskas's avatar
Roman Inflianskas committed
39
#include <KLocalizedString>
40
#include <KMessageWidget>
Roman Inflianskas's avatar
Roman Inflianskas committed
41
42
#include <KProtocolManager>
#include <KRun>
Peter Penz's avatar
Peter Penz committed
43
44
45
#include <KShell>
#include <KUrlComboBox>
#include <KUrlNavigator>
46

Roman Inflianskas's avatar
Roman Inflianskas committed
47
48
49
50
51
52
#include <QDropEvent>
#include <QLoggingCategory>
#include <QMimeData>
#include <QTimer>
#include <QUrl>
#include <QVBoxLayout>
53
#include <QDesktopServices>
54

Lukáš Tinkl's avatar
Lukáš Tinkl committed
55
DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) :
56
    QWidget(parent),
Kevin Funk's avatar
Kevin Funk committed
57
    m_topLayout(nullptr),
58
    m_navigatorWidget(nullptr),
Kevin Funk's avatar
Kevin Funk committed
59
    m_urlNavigator(nullptr),
60
    m_emptyTrashButton(nullptr),
Kevin Funk's avatar
Kevin Funk committed
61
    m_searchBox(nullptr),
62
    m_searchModeEnabled(false),
Kevin Funk's avatar
Kevin Funk committed
63
64
65
66
67
    m_messageWidget(nullptr),
    m_view(nullptr),
    m_filterBar(nullptr),
    m_statusBar(nullptr),
    m_statusBarTimer(nullptr),
68
    m_statusBarTimestamp(),
69
    m_autoGrabFocus(true)
70
71
#ifdef HAVE_KACTIVITIES
    , m_activityResourceInstance(nullptr)
72
#endif
73
74
{
    hide();
75

76
77
    m_topLayout = new QVBoxLayout(this);
    m_topLayout->setSpacing(0);
Laurent Montel's avatar
Laurent Montel committed
78
    m_topLayout->setContentsMargins(0, 0, 0, 0);
79

80
81
82
    m_navigatorWidget = new QWidget(this);
    QHBoxLayout* navigatorLayout = new QHBoxLayout(m_navigatorWidget);
    navigatorLayout->setSpacing(0);
Laurent Montel's avatar
Laurent Montel committed
83
    navigatorLayout->setContentsMargins(0, 0, 0, 0);
84
85
86
87
88
89
90
91
92
93
94
95
    m_navigatorWidget->setWhatsThis(xi18nc("@info:whatsthis location bar",
        "<para>This line describes the location of the files and folders "
        "displayed below.</para><para>The name of the currently viewed "
        "folder can be read at the very right. To the left of it is the "
        "name of the folder that contains it. The whole line is called "
        "the <emphasis>path</emphasis> to the current location because "
        "following these folders from left to right leads here.</para>"
        "<para>The path is displayed on the <emphasis>location bar</emphasis> "
        "which is more powerful than one would expect. To learn more "
        "about the basic and advanced features of the location bar "
        "<link url='help:/dolphin/location-bar.html'>click here</link>. "
        "This will open the dedicated page in the Handbook.</para>"));
96

97
    m_urlNavigator = new KUrlNavigator(DolphinPlacesModelSingleton::instance().placesModel(), url, this);
98
99
100
101
    connect(m_urlNavigator, &KUrlNavigator::activated,
            this, &DolphinViewContainer::activate);
    connect(m_urlNavigator->editor(), &KUrlComboBox::completionModeChanged,
            this, &DolphinViewContainer::saveUrlCompletionMode);
102

103
    const GeneralSettings* settings = GeneralSettings::self();
104
    m_urlNavigator->setUrlEditable(settings->editableUrl());
105
    m_urlNavigator->setShowFullPath(settings->showFullPath());
106
    m_urlNavigator->setHomeUrl(Dolphin::homeUrl());
107
    KUrlComboBox* editor = m_urlNavigator->editor();
108
    editor->setCompletionMode(KCompletion::CompletionMode(settings->urlCompletionMode()));
109

Melanie Genz's avatar
Melanie Genz committed
110
    m_emptyTrashButton = new QPushButton(QIcon::fromTheme(QStringLiteral("user-trash")), i18nc("@action:button", "Empty Trash"), this);
111
112
113
114
115
116
    m_emptyTrashButton->setFlat(true);
    connect(m_emptyTrashButton, &QPushButton::clicked, this, [this]() { Trash::empty(this); });
    connect(&Trash::instance(), &Trash::emptinessChanged, m_emptyTrashButton, &QPushButton::setDisabled);
    m_emptyTrashButton->setDisabled(Trash::isEmpty());
    m_emptyTrashButton->hide();

117
118
    m_searchBox = new DolphinSearchBox(this);
    m_searchBox->hide();
119
120
121
122
    connect(m_searchBox, &DolphinSearchBox::activated, this, &DolphinViewContainer::activate);
    connect(m_searchBox, &DolphinSearchBox::closeRequest, this, &DolphinViewContainer::closeSearchBox);
    connect(m_searchBox, &DolphinSearchBox::searchRequest, this, &DolphinViewContainer::startSearching);
    connect(m_searchBox, &DolphinSearchBox::returnPressed, this, &DolphinViewContainer::requestFocus);
123
124
125
126
127
128
129
130
131
132
133
134
    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>"));
135

136
137
138
139
    m_messageWidget = new KMessageWidget(this);
    m_messageWidget->setCloseButtonVisible(true);
    m_messageWidget->hide();

140
141
142
143
144
145
146
147
#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

148
149
150
151
152
153
154
155
156
157
158
159
    // Initialize filter bar
    m_filterBar = new FilterBar(this);
    m_filterBar->setVisible(settings->filterBar());

    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
160
    m_view = new DolphinView(url, this);
161
162
    connect(m_view, &DolphinView::urlChanged,
            m_filterBar, &FilterBar::slotUrlChanged);
163
    connect(m_view, &DolphinView::urlChanged,
164
            m_urlNavigator, &KUrlNavigator::setLocationUrl);
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
    connect(m_view, &DolphinView::urlChanged,
            m_messageWidget, &KMessageWidget::hide);
    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);
195
196
    connect(m_view, &DolphinView::activated,
            this, &DolphinViewContainer::activate);
197
198
199
200
201

    connect(m_urlNavigator, &KUrlNavigator::urlAboutToBeChanged,
            this, &DolphinViewContainer::slotUrlNavigatorLocationAboutToBeChanged);
    connect(m_urlNavigator, &KUrlNavigator::urlChanged,
            this, &DolphinViewContainer::slotUrlNavigatorLocationChanged);
202
203
    connect(m_urlNavigator, &KUrlNavigator::urlSelectionRequested,
            this, &DolphinViewContainer::slotUrlSelectionRequested);
204
205
    connect(m_urlNavigator, &KUrlNavigator::returnPressed,
            this, &DolphinViewContainer::slotReturnPressed);
206
207
208
    connect(m_urlNavigator, &KUrlNavigator::urlsDropped, this, [=](const QUrl &destination, QDropEvent *event) {
        m_view->dropUrls(destination, event, m_urlNavigator->dropWidget());
    });
209

210
211
212
213
    connect(m_view, &DolphinView::directoryLoadingCompleted, this, [this]() {
        m_emptyTrashButton->setVisible(m_view->url().scheme() == QLatin1String("trash"));
    });

214
215
216
217
    // Initialize status bar
    m_statusBar = new DolphinStatusBar(this);
    m_statusBar->setUrl(m_view->url());
    m_statusBar->setZoomLevel(m_view->zoomLevel());
218
219
220
221
222
223
224
225
226
227
228
229
    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);
    connect(m_statusBar, &DolphinStatusBar::stopPressed,
            this, &DolphinViewContainer::stopDirectoryLoading);
    connect(m_statusBar, &DolphinStatusBar::zoomLevelChanged,
            this, &DolphinViewContainer::slotStatusBarZoomLevelChanged);
230

231
232
233
    m_statusBarTimer = new QTimer(this);
    m_statusBarTimer->setSingleShot(true);
    m_statusBarTimer->setInterval(300);
234
    connect(m_statusBarTimer, &QTimer::timeout, this, &DolphinViewContainer::updateStatusBar);
235

236
    KIO::FileUndoManager* undoManager = KIO::FileUndoManager::self();
237
238
    connect(undoManager, &KIO::FileUndoManager::jobRecordingFinished,
            this, &DolphinViewContainer::delayedStatusBarUpdate);
239

240
241
242
243
    navigatorLayout->addWidget(m_urlNavigator);
    navigatorLayout->addWidget(m_emptyTrashButton);

    m_topLayout->addWidget(m_navigatorWidget);
244
    m_topLayout->addWidget(m_searchBox);
245
    m_topLayout->addWidget(m_messageWidget);
246
247
248
    m_topLayout->addWidget(m_view);
    m_topLayout->addWidget(m_filterBar);
    m_topLayout->addWidget(m_statusBar);
249
250

    setSearchModeEnabled(isSearchUrl(url));
251
252
253

    // Initialize kactivities resource instance

254
255
#ifdef HAVE_KACTIVITIES
    m_activityResourceInstance = new KActivities::ResourceInstance(window()->winId(), url);
256
    m_activityResourceInstance->setParent(this);
257
#endif
258
259
260
261
262
263
}

DolphinViewContainer::~DolphinViewContainer()
{
}

Lukáš Tinkl's avatar
Lukáš Tinkl committed
264
QUrl DolphinViewContainer::url() const
265
{
266
    return m_view->url();
267
268
269
270
}

void DolphinViewContainer::setActive(bool active)
{
271
    m_searchBox->setActive(active);
272
273
    m_urlNavigator->setActive(active);
    m_view->setActive(active);
274

275
#ifdef HAVE_KACTIVITIES
276
277
278
279
280
    if (active) {
        m_activityResourceInstance->notifyFocusedIn();
    } else {
        m_activityResourceInstance->notifyFocusedOut();
    }
281
#endif
282
283
284
285
286
287
288
289
}

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

290
291
292
293
294
295
296
297
298
299
void DolphinViewContainer::setAutoGrabFocus(bool grab)
{
    m_autoGrabFocus = grab;
}

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

300
301
302
303
304
QString DolphinViewContainer::currentSearchText() const
{
     return m_searchBox->text();
}

Peter Penz's avatar
Peter Penz committed
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
const DolphinStatusBar* DolphinViewContainer::statusBar() const
{
    return m_statusBar;
}

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

const KUrlNavigator* DolphinViewContainer::urlNavigator() const
{
    return m_urlNavigator;
}

KUrlNavigator* DolphinViewContainer::urlNavigator()
{
    return m_urlNavigator;
}

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

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

335
336
337
338
339
340
341
342
void DolphinViewContainer::showMessage(const QString& msg, MessageType type)
{
    if (msg.isEmpty()) {
        return;
    }

    m_messageWidget->setText(msg);

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

347
348
349
350
351
352
353
354
355
356
357
358
359
    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());

360
361
362
    if (m_messageWidget->isVisible()) {
        m_messageWidget->hide();
    }
363
364
365
    m_messageWidget->animatedShow();
}

366
void DolphinViewContainer::readSettings()
367
{
368
    if (GeneralSettings::modifiedStartupSettings()) {
369
370
371
        // The startup settings should only get applied if they have been
        // modified by the user. Otherwise keep the (possibly) different current
        // settings of the URL navigator and the filterbar.
372
373
        m_urlNavigator->setUrlEditable(GeneralSettings::editableUrl());
        m_urlNavigator->setShowFullPath(GeneralSettings::showFullPath());
374
        m_urlNavigator->setHomeUrl(Dolphin::homeUrl());
375
        setFilterBarVisible(GeneralSettings::filterBar());
376
377
    }

378
379
    m_view->readSettings();
    m_statusBar->readSettings();
380
381
}

382
383
384
385
386
bool DolphinViewContainer::isFilterBarVisible() const
{
    return m_filterBar->isVisible();
}

387
388
void DolphinViewContainer::setSearchModeEnabled(bool enabled)
{
389
390
391
    m_searchBox->setVisible(enabled);
    m_navigatorWidget->setVisible(!enabled);

392
393
394
395
396
    if (enabled) {
        const QUrl& locationUrl = m_urlNavigator->locationUrl();
        m_searchBox->fromSearchUrl(locationUrl);
    }

397
    if (enabled == isSearchModeEnabled()) {
398
399
400
401
        if (enabled && !m_searchBox->hasFocus()) {
            m_searchBox->setFocus();
            m_searchBox->selectAll();
        }
402
403
404
        return;
    }

405
    if (!enabled) {
406
407
        m_view->setViewPropertiesContext(QString());

408
409
        // 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
410
        QUrl url = m_searchBox->searchPath();
411
        if (url.isEmpty() || !url.isValid() || isSearchUrl(url)) {
412
            url = Dolphin::homeUrl();
413
        }
414
        m_urlNavigator->setLocationUrl(url);
415
    }
416
417

    m_searchModeEnabled = enabled;
418
419

    emit searchModeEnabledChanged(enabled);
420
421
422
423
}

bool DolphinViewContainer::isSearchModeEnabled() const
{
424
    return m_searchModeEnabled;
425
426
}

427
428
429
430
431
QString DolphinViewContainer::placesText() const
{
    QString text;

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

    return text;
}

446
447
448
449
450
451
void DolphinViewContainer::reload()
{
    view()->reload();
    m_messageWidget->hide();
}

452
QString DolphinViewContainer::caption() const
David Hallas's avatar
David Hallas committed
453
{
454
455
456
457
458
459
460
461
    if (isSearchModeEnabled()) {
        if (currentSearchText().isEmpty()){
            return i18n("Search");
        } else {
            return i18n("Search for %1", currentSearchText());
        }
    }

David Hallas's avatar
David Hallas committed
462
463
464
465
466
467
468
469
    if (GeneralSettings::showFullPathInTitlebar()) {
        if (!url().isLocalFile()) {
            return url().adjusted(QUrl::StripTrailingSlash).toString();
        }
        return url().adjusted(QUrl::StripTrailingSlash).path();
    }

    KFilePlacesModel *placesModel = DolphinPlacesModelSingleton::instance().placesModel();
Nazar Kalinowski's avatar
Nazar Kalinowski committed
470
    const auto& matchedPlaces = placesModel->match(placesModel->index(0,0), KFilePlacesModel::UrlRole, QUrl(url().adjusted(QUrl::StripTrailingSlash).toString(QUrl::FullyEncoded).append("/?")), 1, Qt::MatchRegExp);
David Hallas's avatar
David Hallas committed
471
472
473
474

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


David Hallas's avatar
David Hallas committed
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
    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
500
void DolphinViewContainer::setUrl(const QUrl& newUrl)
501
{
502
503
    if (newUrl != m_urlNavigator->locationUrl()) {
        m_urlNavigator->setLocationUrl(newUrl);
504
    }
505

506
#ifdef HAVE_KACTIVITIES
507
    m_activityResourceInstance->setUri(newUrl);
508
#endif
509
510
}

511
void DolphinViewContainer::setFilterBarVisible(bool visible)
512
{
513
    Q_ASSERT(m_filterBar);
514
    if (visible) {
515
        m_view->hideToolTip(ToolTipManager::HideBehavior::Instantly);
516
        m_filterBar->show();
517
        m_filterBar->setFocus();
518
        m_filterBar->selectAll();
519
520
521
522
523
    } else {
        closeFilterBar();
    }
}

524
525
void DolphinViewContainer::delayedStatusBarUpdate()
{
526
527
528
529
530
531
532
533
534
535
536
    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();
    }
537
538
539
540
}

void DolphinViewContainer::updateStatusBar()
{
541
542
    m_statusBarTimestamp.start();

543
544
545
    const QString text = m_view->statusBarText();
    m_statusBar->setDefaultText(text);
    m_statusBar->resetToDefaultText();
546
547
}

548
void DolphinViewContainer::updateDirectoryLoadingProgress(int percent)
549
550
551
552
553
554
555
{
    if (m_statusBar->progressText().isEmpty()) {
        m_statusBar->setProgressText(i18nc("@info:progress", "Loading folder..."));
    }
    m_statusBar->setProgress(percent);
}

556
void DolphinViewContainer::updateDirectorySortingProgress(int percent)
557
558
559
560
561
562
563
{
    if (m_statusBar->progressText().isEmpty()) {
        m_statusBar->setProgressText(i18nc("@info:progress", "Sorting..."));
    }
    m_statusBar->setProgress(percent);
}

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

581
void DolphinViewContainer::slotDirectoryLoadingCompleted()
582
{
583
    if (!m_statusBar->progressText().isEmpty()) {
584
585
586
587
        m_statusBar->setProgressText(QString());
        m_statusBar->setProgress(100);
    }

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

597
598
599
600
601
602
603
void DolphinViewContainer::slotDirectoryLoadingCanceled()
{
    if (!m_statusBar->progressText().isEmpty()) {
        m_statusBar->setProgressText(QString());
        m_statusBar->setProgress(100);
    }

604
    m_statusBar->setText(QString());
605
606
}

Lukáš Tinkl's avatar
Lukáš Tinkl committed
607
void DolphinViewContainer::slotUrlIsFileError(const QUrl& url)
608
{
609
    const KFileItem item(url);
610
611
612
613

    // 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
614
    const QUrl& folderUrl = DolphinView::openItemAsFolderUrl(item, true);
615
    if (!folderUrl.isEmpty()) {
616
        setUrl(folderUrl);
617
618
619
    } else {
        slotItemActivated(item);
    }
620
621
}

622
void DolphinViewContainer::slotItemActivated(const KFileItem& item)
623
{
624
625
626
627
628
    // 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
629
    const QUrl& url = DolphinView::openItemAsFolderUrl(item, GeneralSettings::browseThroughArchives());
630
    if (!url.isEmpty()) {
631
        setUrl(url);
632
633
634
        return;
    }

635
636
    KRun *run = new KRun(item.targetUrl(), this);
    run->setShowScriptExecutionPrompt(true);
637
638
}

639
640
641
642
643
644
645
646
void DolphinViewContainer::slotItemsActivated(const KFileItemList& items)
{
    Q_ASSERT(items.count() >= 2);

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

647
void DolphinViewContainer::showItemInfo(const KFileItem& item)
648
{
649
    if (item.isNull()) {
650
        m_statusBar->resetToDefaultText();
651
    } else {
652
        m_statusBar->setText(item.getStatusBarInfo());
653
654
655
    }
}

656
657
void DolphinViewContainer::closeFilterBar()
{
658
    m_filterBar->closeFilterBar();
659
    m_view->setFocus();
660
661
662
    emit showFilterBarChanged(false);
}

663
void DolphinViewContainer::setNameFilter(const QString& nameFilter)
664
{
665
    m_view->hideToolTip(ToolTipManager::HideBehavior::Instantly);
666
    m_view->setNameFilter(nameFilter);
667
    delayedStatusBarUpdate();
668
669
}

670
void DolphinViewContainer::activate()
671
{
672
    setActive(true);
673
674
}

675
void DolphinViewContainer::slotUrlNavigatorLocationAboutToBeChanged(const QUrl&)
676
{
677
    saveViewState();
678
}
679

Lukáš Tinkl's avatar
Lukáš Tinkl committed
680
void DolphinViewContainer::slotUrlNavigatorLocationChanged(const QUrl& url)
681
{
682
683
    slotReturnPressed();

684
    if (KProtocolManager::supportsListing(url)) {
685
        setSearchModeEnabled(isSearchUrl(url));
686
        m_view->setUrl(url);
687
        tryRestoreViewState();
688

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

706
707
        QDesktopServices::openUrl(url);
        redirect(QUrl(), m_urlNavigator->locationUrl(1));
708
    } else {
709
        showMessage(i18nc("@info:status", "Invalid protocol"), Error);
710
    }
711
712
}

713
714
715
716
717
718
void DolphinViewContainer::slotUrlSelectionRequested(const QUrl& url)
{
    m_view->markUrlsAsSelected({url});
    m_view->markUrlAsCurrent(url); // makes the item scroll into view
}

Lukáš Tinkl's avatar
Lukáš Tinkl committed
719
void DolphinViewContainer::redirect(const QUrl& oldUrl, const QUrl& newUrl)
720
{
721
    Q_UNUSED(oldUrl)
722
723
    const bool block = m_urlNavigator->signalsBlocked();
    m_urlNavigator->blockSignals(true);
724

725
726
727
728
    // 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());
729
    m_urlNavigator->setLocationUrl(newUrl);
730
    setSearchModeEnabled(isSearchUrl(newUrl));
731

732
733
734
    m_urlNavigator->blockSignals(block);
}

735
736
737
738
739
void DolphinViewContainer::requestFocus()
{
    m_view->setFocus();
}

740
void DolphinViewContainer::saveUrlCompletionMode(KCompletion::CompletionMode completion)
741
{
742
    GeneralSettings::setUrlCompletionMode(completion);
743
744
}

745
746
747
748
749
750
751
void DolphinViewContainer::slotReturnPressed()
{
    if (!GeneralSettings::editableUrl()) {
        m_urlNavigator->setUrlEditable(false);
    }
}

Peter Penz's avatar
Peter Penz committed
752
void DolphinViewContainer::startSearching()
753
{
Lukáš Tinkl's avatar
Lukáš Tinkl committed
754
    const QUrl url = m_searchBox->urlForSearching();
755
    if (url.isValid() && !url.isEmpty()) {
756
        m_view->setViewPropertiesContext(QStringLiteral("search"));
757
758
759
760
761
762
763
764
765
        m_urlNavigator->setLocationUrl(url);
    }
}

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

766
void DolphinViewContainer::stopDirectoryLoading()
767
768
{
    m_view->stopLoading();
769
    m_statusBar->setProgress(100);
770
771
}

772
773
774
775
776
777
778
779
780
781
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
782
bool DolphinViewContainer::isSearchUrl(const QUrl& url) const
783
{
784
    return url.scheme().contains(QLatin1String("search"));
785
786
}

787
void DolphinViewContainer::saveViewState()
788
{
789
790
791
792
    QByteArray locationState;
    QDataStream stream(&locationState, QIODevice::WriteOnly);
    m_view->saveState(stream);
    m_urlNavigator->saveLocationState(locationState);
793
}
794
795
796
797
798
799
800
801
802

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