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 (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
462
    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
463
464
465
466

    if (!matchedPlaces.isEmpty()) {
        return placesModel->text(matchedPlaces.first());
    }
467
468
469
470
471
472
473
474
475

    if (isSearchModeEnabled()) {
        if (currentSearchText().isEmpty()){
            return i18n("Search");
        } else {
            return i18n("Search for %1", currentSearchText());
        }
    }

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

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

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

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

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

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

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

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

587
    if (isSearchUrl(url()) && m_view->itemsCount() == 0) {
Vishesh Handa's avatar
Vishesh Handa committed
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
592
593
    } else {
        updateStatusBar();
    }
594
595
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

712
713
714
715
716
717
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
718
void DolphinViewContainer::redirect(const QUrl& oldUrl, const QUrl& newUrl)
719
{
720
    Q_UNUSED(oldUrl)
721
722
    const bool block = m_urlNavigator->signalsBlocked();
    m_urlNavigator->blockSignals(true);
723

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

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

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

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

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

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

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

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

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

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

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