KIO

kurlnavigator.cpp
1/*
2 SPDX-FileCopyrightText: 2006-2010 Peter Penz <peter.penz@gmx.at>
3 SPDX-FileCopyrightText: 2006 Aaron J. Seigo <aseigo@kde.org>
4 SPDX-FileCopyrightText: 2007 Kevin Ottens <ervin@kde.org>
5 SPDX-FileCopyrightText: 2007 Urs Wolfer <uwolfer @ kde.org>
6
7 SPDX-License-Identifier: LGPL-2.0-or-later
8*/
9
10#include "kurlnavigator.h"
11#include "kcoreurlnavigator.h"
12
13#include "../utils_p.h"
14#include "kurlnavigatorbutton_p.h"
15#include "kurlnavigatordropdownbutton_p.h"
16#include "kurlnavigatorpathselectoreventfilter_p.h"
17#include "kurlnavigatorplacesselector_p.h"
18#include "kurlnavigatorschemecombo_p.h"
19#include "kurlnavigatortogglebutton_p.h"
20
21#include <KIO/StatJob>
22#include <KLocalizedString>
23#include <kfileitem.h>
24#include <kfileplacesmodel.h>
25#include <kprotocolinfo.h>
26#include <kurifilter.h>
27#include <kurlcombobox.h>
28#include <kurlcompletion.h>
29
30#include <QActionGroup>
31#include <QApplication>
32#include <QClipboard>
33#include <QDir>
34#include <QDropEvent>
35#include <QHBoxLayout>
36#include <QKeyEvent>
37#include <QMenu>
38#include <QMetaMethod>
39#include <QMimeData>
40#include <QMimeDatabase>
41#include <QTimer>
42#include <QUrlQuery>
43
44#include <algorithm>
45#include <numeric>
46
47using namespace KDEPrivate;
48
49struct KUrlNavigatorData {
50 QByteArray state;
51};
52Q_DECLARE_METATYPE(KUrlNavigatorData)
53
54class KUrlNavigatorPrivate
55{
56public:
57 KUrlNavigatorPrivate(const QUrl &url, KUrlNavigator *qq, KFilePlacesModel *placesModel);
58
59 ~KUrlNavigatorPrivate()
60 {
61 m_dropDownButton->removeEventFilter(q);
62 m_pathBox->removeEventFilter(q);
63 m_toggleEditableMode->removeEventFilter(q);
64
65 for (KUrlNavigatorButton *button : std::as_const(m_navButtons)) {
66 button->removeEventFilter(q);
67 }
68 }
69
70 /** Applies the edited URL in m_pathBox to the URL navigator */
71 void applyUncommittedUrl();
72 void slotApplyUrl(QUrl url);
73 // Returns true if "text" matched a URI filter (i.e. was fitlered),
74 // otherwise returns false
75 bool slotCheckFilters(const QString &text);
76
77 void slotReturnPressed();
78 void slotSchemeChanged(const QString &);
79 void openPathSelectorMenu();
80
81 /**
82 * Appends the widget at the end of the URL navigator. It is assured
83 * that the filler widget remains as last widget to fill the remaining
84 * width.
85 */
86 void appendWidget(QWidget *widget, int stretch = 0);
87
88 /**
89 * This slot is connected to the clicked signal of the navigation bar button. It calls switchView().
90 * Moreover, if switching from "editable" mode to the breadcrumb view, it calls applyUncommittedUrl().
91 */
92 void slotToggleEditableButtonPressed();
93
94 /**
95 * Switches the navigation bar between the breadcrumb view and the
96 * traditional view (see setUrlEditable()).
97 */
98 void switchView();
99
100 /** Emits the signal urlsDropped(). */
101 void dropUrls(const QUrl &destination, QDropEvent *event, KUrlNavigatorButton *dropButton);
102
103 /**
104 * Is invoked when a navigator button has been clicked.
105 * Different combinations of mouse clicks and keyboard modifiers have different effects on how
106 * the url is opened. The behaviours are the following:
107 * - shift+middle-click or ctrl+shift+left-click => activeTabRequested() signal is emitted
108 * - ctrl+left-click or middle-click => tabRequested() signal is emitted
109 * - shift+left-click => newWindowRequested() signal is emitted
110 * - left-click => open the new url in-place
111 */
112 void slotNavigatorButtonClicked(const QUrl &url, Qt::MouseButton button, Qt::KeyboardModifiers modifiers);
113
114 void openContextMenu(const QPoint &p);
115
116 void slotPathBoxChanged(const QString &text);
117
118 void updateContent();
119
120 /**
121 * Updates all buttons to have one button for each part of the
122 * current URL. Existing buttons, which are available by m_navButtons,
123 * are reused if possible. If the URL is longer, new buttons will be
124 * created, if the URL is shorter, the remaining buttons will be deleted.
125 * @param startIndex Start index of URL part (/), where the buttons
126 * should be created for each following part.
127 */
128 void updateButtons(int startIndex);
129
130 /**
131 * Updates the visibility state of all buttons describing the URL. If the
132 * width of the URL navigator is too small, the buttons representing the upper
133 * paths of the URL will be hidden and moved to a drop down menu.
134 */
135 void updateButtonVisibility();
136
137 /**
138 * @return Text for the first button of the URL navigator.
139 */
140 QString firstButtonText() const;
141
142 /**
143 * Returns the URL that should be applied for the button with the index \a index.
144 */
145 QUrl buttonUrl(int index) const;
146
147 void switchToBreadcrumbMode();
148
149 /**
150 * Deletes all URL navigator buttons. m_navButtons is
151 * empty after this operation.
152 */
153 void deleteButtons();
154
155 /**
156 * Retrieves the place url for the current url.
157 * E. g. for the path "fish://root@192.168.0.2/var/lib" the string
158 * "fish://root@192.168.0.2" will be returned, which leads to the
159 * navigation indication 'Custom Path > var > lib". For e. g.
160 * "settings:///System/" the path "settings://" will be returned.
161 */
162 QUrl retrievePlaceUrl() const;
163
164 KUrlNavigator *const q;
165
166 QHBoxLayout *m_layout = new QHBoxLayout(q);
167 KCoreUrlNavigator *m_coreUrlNavigator = nullptr;
168 QList<KUrlNavigatorButton *> m_navButtons;
169 QStringList m_supportedSchemes;
170 QUrl m_homeUrl;
171 KUrlNavigatorPlacesSelector *m_placesSelector = nullptr;
172 KUrlComboBox *m_pathBox = nullptr;
173 KUrlNavigatorSchemeCombo *m_schemes = nullptr;
174 KUrlNavigatorDropDownButton *m_dropDownButton = nullptr;
175 KUrlNavigatorButtonBase *m_toggleEditableMode = nullptr;
176 QWidget *m_dropWidget = nullptr;
177
178 bool m_editable = false;
179 bool m_active = true;
180 bool m_showPlacesSelector = false;
181 bool m_showFullPath = false;
182
183 struct {
184 bool showHidden = false;
185 bool sortHiddenLast = false;
186 } m_subfolderOptions;
187};
188
189KUrlNavigatorPrivate::KUrlNavigatorPrivate(const QUrl &url, KUrlNavigator *qq, KFilePlacesModel *placesModel)
190 : q(qq)
191 , m_coreUrlNavigator(new KCoreUrlNavigator(url, qq))
192 , m_showPlacesSelector(placesModel != nullptr)
193{
194 m_layout->setSpacing(0);
195 m_layout->setContentsMargins(0, 0, 0, 0);
196
197 q->connect(m_coreUrlNavigator, &KCoreUrlNavigator::currentLocationUrlChanged, q, [this]() {
198 Q_EMIT q->urlChanged(m_coreUrlNavigator->currentLocationUrl());
199 });
200 q->connect(m_coreUrlNavigator, &KCoreUrlNavigator::currentUrlAboutToChange, q, [this](const QUrl &url) {
201 Q_EMIT q->urlAboutToBeChanged(url);
202 });
203 q->connect(m_coreUrlNavigator, &KCoreUrlNavigator::historySizeChanged, q, [this]() {
204 Q_EMIT q->historyChanged();
205 });
206 q->connect(m_coreUrlNavigator, &KCoreUrlNavigator::historyIndexChanged, q, [this]() {
207 Q_EMIT q->historyChanged();
208 });
209 q->connect(m_coreUrlNavigator, &KCoreUrlNavigator::historyChanged, q, [this]() {
210 Q_EMIT q->historyChanged();
211 });
212 q->connect(m_coreUrlNavigator, &KCoreUrlNavigator::urlSelectionRequested, q, [this](const QUrl &url) {
213 Q_EMIT q->urlSelectionRequested(url);
214 });
215
216 // initialize the places selector
217 q->setAutoFillBackground(false);
218
219 if (placesModel != nullptr) {
220 m_placesSelector = new KUrlNavigatorPlacesSelector(q, placesModel);
221 q->connect(m_placesSelector, &KUrlNavigatorPlacesSelector::placeActivated, q, &KUrlNavigator::setLocationUrl);
222 q->connect(m_placesSelector, &KUrlNavigatorPlacesSelector::tabRequested, q, &KUrlNavigator::tabRequested);
223
224 auto updateContentFunc = [this]() {
225 updateContent();
226 };
227 q->connect(placesModel, &KFilePlacesModel::rowsInserted, q, updateContentFunc);
228 q->connect(placesModel, &KFilePlacesModel::rowsRemoved, q, updateContentFunc);
229 q->connect(placesModel, &KFilePlacesModel::dataChanged, q, updateContentFunc);
230 }
231
232 // create scheme combo
233 m_schemes = new KUrlNavigatorSchemeCombo(QString(), q);
234 q->connect(m_schemes, &KUrlNavigatorSchemeCombo::activated, q, [this](const QString &schene) {
235 slotSchemeChanged(schene);
236 });
237
238 // create drop down button for accessing all paths of the URL
239 m_dropDownButton = new KUrlNavigatorDropDownButton(q);
240 m_dropDownButton->setForegroundRole(QPalette::WindowText);
241 m_dropDownButton->installEventFilter(q);
242 q->connect(m_dropDownButton, &KUrlNavigatorDropDownButton::clicked, q, [this]() {
243 openPathSelectorMenu();
244 });
245
246 // initialize the path box of the traditional view
247 m_pathBox = new KUrlComboBox(KUrlComboBox::Directories, true, q);
248 m_pathBox->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
249 m_pathBox->installEventFilter(q);
250
251 KUrlCompletion *kurlCompletion = new KUrlCompletion(KUrlCompletion::DirCompletion);
252 m_pathBox->setCompletionObject(kurlCompletion);
253 m_pathBox->setAutoDeleteCompletionObject(true);
254
255 // TODO KF6: remove this QOverload, only KUrlComboBox::returnPressed(const QString &) will remain
256 q->connect(m_pathBox, &KUrlComboBox::returnPressed, q, [this]() {
257 slotReturnPressed();
258 });
260 q->connect(m_pathBox, &QComboBox::editTextChanged, q, [this](const QString &text) {
261 slotPathBoxChanged(text);
262 });
263
264 // create toggle button which allows to switch between
265 // the breadcrumb and traditional view
266 m_toggleEditableMode = new KUrlNavigatorToggleButton(q);
267 m_toggleEditableMode->installEventFilter(q);
268 m_toggleEditableMode->setMinimumWidth(20);
269 q->connect(m_toggleEditableMode, &KUrlNavigatorToggleButton::clicked, q, [this]() {
270 slotToggleEditableButtonPressed();
271 });
272
273 if (m_placesSelector != nullptr) {
274 m_layout->addWidget(m_placesSelector);
275 }
276 m_layout->addWidget(m_schemes);
277 m_layout->addWidget(m_dropDownButton);
278 m_layout->addWidget(m_pathBox, 1);
279 m_layout->addWidget(m_toggleEditableMode);
280
281 q->setContextMenuPolicy(Qt::CustomContextMenu);
282 q->connect(q, &QWidget::customContextMenuRequested, q, [this](const QPoint &pos) {
283 openContextMenu(pos);
284 });
285}
286
287void KUrlNavigatorPrivate::appendWidget(QWidget *widget, int stretch)
288{
289 m_layout->insertWidget(m_layout->count() - 1, widget, stretch);
290}
291
292void KUrlNavigatorPrivate::slotApplyUrl(QUrl url)
293{
294 // Parts of the following code have been taken from the class KateFileSelector
295 // located in kate/app/katefileselector.hpp of Kate.
296 // SPDX-FileCopyrightText: 2001 Christoph Cullmann <cullmann@kde.org>
297 // SPDX-FileCopyrightText: 2001 Joseph Wenninger <jowenn@kde.org>
298 // SPDX-FileCopyrightText: 2001 Anders Lund <anders.lund@lund.tdcadsl.dk>
299
300 // For example "desktop:/" _not_ "desktop:", see the comment in slotSchemeChanged()
301 if (!url.isEmpty() && url.path().isEmpty() && KProtocolInfo::protocolClass(url.scheme()) == QLatin1String(":local")) {
302 url.setPath(QStringLiteral("/"));
303 }
304
305 const auto urlStr = url.toString();
306 QStringList urls = m_pathBox->urls();
307 urls.removeAll(urlStr);
308 urls.prepend(urlStr);
309 m_pathBox->setUrls(urls, KUrlComboBox::RemoveBottom);
310
311 q->setLocationUrl(url);
312 // The URL might have been adjusted by KUrlNavigator::setUrl(), hence
313 // synchronize the result in the path box.
314 m_pathBox->setUrl(q->locationUrl());
315}
316
317bool KUrlNavigatorPrivate::slotCheckFilters(const QString &text)
318{
319 KUriFilterData filteredData(text);
320 filteredData.setCheckForExecutables(false);
321 // Using kshorturifilter to fix up e.g. "ftp.kde.org" ---> "ftp://ftp.kde.org"
322 const auto filtersList = QStringList{QStringLiteral("kshorturifilter")};
323 const bool wasFiltered = KUriFilter::self()->filterUri(filteredData, filtersList);
324 if (wasFiltered) {
325 slotApplyUrl(filteredData.uri()); // The text was filtered
326 }
327 return wasFiltered;
328}
329
330void KUrlNavigatorPrivate::applyUncommittedUrl()
331{
332 const QString text = m_pathBox->currentText().trimmed();
333 QUrl url = q->locationUrl();
334
335 // Using the stat job below, check if the url and text match a local dir; but first
336 // handle a special case where "url" is empty in the unittests which use
337 // KUrlNavigator::setLocationUrl(QUrl()); in practice (e.g. in Dolphin, or KFileWidget),
338 // locationUrl() is never empty
339 if (url.isEmpty() && !text.isEmpty()) {
340 if (slotCheckFilters(text)) {
341 return;
342 }
343 }
344
345 // Treat absolute paths as absolute paths.
346 // Relative paths get appended to the current path.
347 if (text.startsWith(QLatin1Char('/'))) {
348 url.setPath(text);
349 } else {
350 url.setPath(Utils::concatPaths(url.path(), text));
351 }
352
353 // Dirs and symlinks to dirs
354 constexpr auto details = KIO::StatBasic | KIO::StatResolveSymlink;
355 auto *job = KIO::stat(url, KIO::StatJob::DestinationSide, details, KIO::HideProgressInfo);
356 q->connect(job, &KJob::result, q, [this, job, text]() {
357 // If there is a dir matching "text" relative to the current url, use that, e.g.:
358 // - typing "bar" while at "/path/to/foo" ---> "/path/to/foo/bar/"
359 // - typing ".config" while at "/home/foo" ---> "/home/foo/.config"
360 if (!job->error() && job->statResult().isDir()) {
361 slotApplyUrl(job->url());
362 return;
363 }
364
365 // Check if text matches a URI filter
366 if (slotCheckFilters(text)) {
367 return;
368 }
369
370 // ... otherwise fallback to whatever QUrl::fromUserInput() returns
371 slotApplyUrl(QUrl::fromUserInput(text));
372 });
373}
374
375void KUrlNavigatorPrivate::slotReturnPressed()
376{
377 applyUncommittedUrl();
378
379 Q_EMIT q->returnPressed();
380
382 // Pressing Ctrl+Return automatically switches back to the breadcrumb mode.
383 // The switch must be done asynchronously, as we are in the context of the
384 // editor.
385 auto switchModeFunc = [this]() {
386 switchToBreadcrumbMode();
387 };
389 }
390}
391
392void KUrlNavigatorPrivate::slotSchemeChanged(const QString &scheme)
393{
394 Q_ASSERT(m_editable);
395
396 QUrl url;
397 url.setScheme(scheme);
398 if (KProtocolInfo::protocolClass(scheme) == QLatin1String(":local")) {
399 // E.g. "file:/" or "desktop:/", _not_ "file:" or "desktop:" respectively.
400 // This is the more expected behaviour, "file:somedir" treats somedir as
401 // a path relative to current dir; file:/somedir is an absolute path to /somedir.
402 url.setPath(QStringLiteral("/"));
403 } else {
404 // With no authority set we'll get e.g. "ftp:" instead of "ftp://".
405 // We want the latter, so let's set an empty authority.
406 url.setAuthority(QString());
407 }
408
409 m_pathBox->setEditUrl(url);
410}
411
412void KUrlNavigatorPrivate::openPathSelectorMenu()
413{
414 if (m_navButtons.count() <= 0) {
415 return;
416 }
417
418 const QUrl firstVisibleUrl = m_navButtons.constFirst()->url();
419
420 QString spacer;
421 QPointer<QMenu> popup = new QMenu(q);
422
423 auto *popupFilter = new KUrlNavigatorPathSelectorEventFilter(popup.data());
424 q->connect(popupFilter, &KUrlNavigatorPathSelectorEventFilter::tabRequested, q, &KUrlNavigator::tabRequested);
425 popup->installEventFilter(popupFilter);
426
427 const QUrl placeUrl = retrievePlaceUrl();
428 int idx = placeUrl.path().count(QLatin1Char('/')); // idx points to the first directory
429 // after the place path
430
431 const QString path = m_coreUrlNavigator->locationUrl(m_coreUrlNavigator->historyIndex()).path();
432 QString dirName = path.section(QLatin1Char('/'), idx, idx);
433 if (dirName.isEmpty()) {
434 if (placeUrl.isLocalFile()) {
435 dirName = QStringLiteral("/");
436 } else {
437 dirName = placeUrl.toDisplayString();
438 }
439 }
440 do {
441 const QString text = spacer + dirName;
442
443 QAction *action = new QAction(text, popup);
444 const QUrl currentUrl = buttonUrl(idx);
445 if (currentUrl == firstVisibleUrl) {
446 popup->addSeparator();
447 }
448 action->setData(QVariant(currentUrl.toString()));
449 popup->addAction(action);
450
451 ++idx;
452 spacer.append(QLatin1String(" "));
453 dirName = path.section(QLatin1Char('/'), idx, idx);
454 } while (!dirName.isEmpty());
455
456 const QPoint pos = q->mapToGlobal(m_dropDownButton->geometry().bottomRight());
457 const QAction *activatedAction = popup->exec(pos);
458 if (activatedAction != nullptr) {
459 const QUrl url(activatedAction->data().toString());
460 q->setLocationUrl(url);
461 }
462
463 // Delete the menu, unless it has been deleted in its own nested event loop already.
464 if (popup) {
465 popup->deleteLater();
466 }
467}
468
469void KUrlNavigatorPrivate::slotToggleEditableButtonPressed()
470{
471 if (m_editable) {
472 applyUncommittedUrl();
473 }
474
475 switchView();
476}
477
478void KUrlNavigatorPrivate::switchView()
479{
480 m_toggleEditableMode->setFocus();
481 m_editable = !m_editable;
482 m_toggleEditableMode->setChecked(m_editable);
483 updateContent();
484 if (q->isUrlEditable()) {
485 m_pathBox->setFocus();
486 }
487
489 Q_EMIT q->editableStateChanged(m_editable);
490}
491
492void KUrlNavigatorPrivate::dropUrls(const QUrl &destination, QDropEvent *event, KUrlNavigatorButton *dropButton)
493{
494 if (event->mimeData()->hasUrls()) {
495 m_dropWidget = qobject_cast<QWidget *>(dropButton);
496 Q_EMIT q->urlsDropped(destination, event);
497 }
498}
499
500void KUrlNavigatorPrivate::slotNavigatorButtonClicked(const QUrl &url, Qt::MouseButton button, Qt::KeyboardModifiers modifiers)
501{
502 if ((button & Qt::MiddleButton && modifiers & Qt::ShiftModifier) || (button & Qt::LeftButton && modifiers & (Qt::ControlModifier | Qt::ShiftModifier))) {
503 Q_EMIT q->activeTabRequested(url);
504 } else if (button & Qt::MiddleButton || (button & Qt::LeftButton && modifiers & Qt::ControlModifier)) {
505 Q_EMIT q->tabRequested(url);
506 } else if (button & Qt::LeftButton && modifiers & Qt::ShiftModifier) {
507 Q_EMIT q->newWindowRequested(url);
508 } else if (button & Qt::LeftButton) {
509 q->setLocationUrl(url);
510 }
511}
512
513void KUrlNavigatorPrivate::openContextMenu(const QPoint &p)
514{
515 q->setActive(true);
516
517 QPointer<QMenu> popup = new QMenu(q);
518
519 // provide 'Copy' action, which copies the current URL of
520 // the URL navigator into the clipboard
521 QAction *copyAction = popup->addAction(QIcon::fromTheme(QStringLiteral("edit-copy")), i18n("Copy"));
522
523 // provide 'Paste' action, which copies the current clipboard text
524 // into the URL navigator
525 QAction *pasteAction = popup->addAction(QIcon::fromTheme(QStringLiteral("edit-paste")), i18n("Paste"));
526 QClipboard *clipboard = QApplication::clipboard();
527 pasteAction->setEnabled(!clipboard->text().isEmpty());
528
529 popup->addSeparator();
530
531 // We are checking whether the signal is connected because it's odd to have a tab entry even
532 // if it's not supported, like in the case of the open dialog
535 if (isTabSignal || isWindowSignal) {
536 auto it = std::find_if(m_navButtons.cbegin(), m_navButtons.cend(), [&p](const KUrlNavigatorButton *button) {
537 return button->geometry().contains(p);
538 });
539 if (it != m_navButtons.cend()) {
540 const auto *button = *it;
541 const QUrl url = button->url();
542 const QString text = button->text();
543
544 if (isTabSignal) {
545 QAction *openInTab = popup->addAction(QIcon::fromTheme(QStringLiteral("tab-new")), i18nc("@item:inmenu", "Open \"%1\" in New Tab", text));
546 q->connect(openInTab, &QAction::triggered, q, [this, url]() {
547 Q_EMIT q->tabRequested(url);
548 });
549 }
550
551 if (isWindowSignal) {
552 QAction *openInWindow =
553 popup->addAction(QIcon::fromTheme(QStringLiteral("window-new")), i18nc("@item:inmenu", "Open \"%1\" in New Window", text));
554 q->connect(openInWindow, &QAction::triggered, q, [this, url]() {
555 Q_EMIT q->newWindowRequested(url);
556 });
557 }
558 }
559 }
560
561 // provide radiobuttons for toggling between the edit and the navigation mode
562 QAction *editAction = popup->addAction(i18n("Edit"));
563 editAction->setCheckable(true);
564
565 QAction *navigateAction = popup->addAction(i18n("Navigate"));
566 navigateAction->setCheckable(true);
567
568 QActionGroup *modeGroup = new QActionGroup(popup);
569 modeGroup->addAction(editAction);
570 modeGroup->addAction(navigateAction);
571 if (q->isUrlEditable()) {
572 editAction->setChecked(true);
573 } else {
574 navigateAction->setChecked(true);
575 }
576
577 popup->addSeparator();
578
579 // allow showing of the full path
580 QAction *showFullPathAction = popup->addAction(i18n("Show Full Path"));
581 showFullPathAction->setCheckable(true);
582 showFullPathAction->setChecked(q->showFullPath());
583
584 QAction *activatedAction = popup->exec(QCursor::pos());
585 if (activatedAction == copyAction) {
586 QMimeData *mimeData = new QMimeData();
588 clipboard->setMimeData(mimeData);
589 } else if (activatedAction == pasteAction) {
590 q->setLocationUrl(QUrl::fromUserInput(clipboard->text()));
591 } else if (activatedAction == editAction) {
592 q->setUrlEditable(true);
593 } else if (activatedAction == navigateAction) {
594 q->setUrlEditable(false);
595 } else if (activatedAction == showFullPathAction) {
596 q->setShowFullPath(showFullPathAction->isChecked());
597 }
598
599 // Delete the menu, unless it has been deleted in its own nested event loop already.
600 if (popup) {
601 popup->deleteLater();
602 }
603}
604
605void KUrlNavigatorPrivate::slotPathBoxChanged(const QString &text)
606{
607 if (text.isEmpty()) {
608 const QString scheme = q->locationUrl().scheme();
609 m_schemes->setScheme(scheme);
610 if (m_supportedSchemes.count() != 1) {
611 m_schemes->show();
612 }
613 } else {
614 m_schemes->hide();
615 }
616}
617
618void KUrlNavigatorPrivate::updateContent()
619{
620 const QUrl currentUrl = q->locationUrl();
621 if (m_placesSelector != nullptr) {
622 m_placesSelector->updateSelection(currentUrl);
623 }
624
625 if (m_editable) {
626 m_schemes->hide();
627 m_dropDownButton->hide();
628
629 deleteButtons();
630 m_toggleEditableMode->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
632
633 m_pathBox->show();
634 m_pathBox->setUrl(currentUrl);
635 } else {
636 m_pathBox->hide();
637
638 m_schemes->hide();
639
640 m_toggleEditableMode->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
642
643 // Calculate the start index for the directories that should be shown as buttons
644 // and create the buttons
645 QUrl placeUrl;
646 if ((m_placesSelector != nullptr) && !m_showFullPath) {
647 placeUrl = m_placesSelector->selectedPlaceUrl();
648 }
649
650 if (!placeUrl.isValid()) {
651 placeUrl = retrievePlaceUrl();
652 }
653 QString placePath = Utils::trailingSlashRemoved(placeUrl.path());
654
655 const int startIndex = placePath.count(QLatin1Char('/'));
656 updateButtons(startIndex);
657 }
658}
659
660void KUrlNavigatorPrivate::updateButtons(int startIndex)
661{
662 QUrl currentUrl = q->locationUrl();
663 if (!currentUrl.isValid()) { // QFileDialog::setDirectory not called yet
664 return;
665 }
666
667 const QString path = currentUrl.path();
668
669 const int oldButtonCount = m_navButtons.count();
670
671 int idx = startIndex;
672 bool hasNext = true;
673 do {
674 const bool createButton = (idx - startIndex) >= oldButtonCount;
675 const bool isFirstButton = (idx == startIndex);
676 const QString dirName = path.section(QLatin1Char('/'), idx, idx);
677 hasNext = isFirstButton || !dirName.isEmpty();
678 if (hasNext) {
679 KUrlNavigatorButton *button = nullptr;
680 if (createButton) {
681 button = new KUrlNavigatorButton(buttonUrl(idx), q);
682 button->installEventFilter(q);
683 button->setForegroundRole(QPalette::WindowText);
684 q->connect(button, &KUrlNavigatorButton::urlsDroppedOnNavButton, q, [this, button](const QUrl &destination, QDropEvent *event) {
685 dropUrls(destination, event, button);
686 });
687
688 auto activatedFunc = [this](const QUrl &url, Qt::MouseButton btn, Qt::KeyboardModifiers modifiers) {
689 slotNavigatorButtonClicked(url, btn, modifiers);
690 };
691 q->connect(button, &KUrlNavigatorButton::navigatorButtonActivated, q, activatedFunc);
692
693 q->connect(button, &KUrlNavigatorButton::finishedTextResolving, q, [this]() {
694 updateButtonVisibility();
695 });
696
697 appendWidget(button);
698 } else {
699 button = m_navButtons[idx - startIndex];
700 button->setUrl(buttonUrl(idx));
701 }
702
703 if (isFirstButton) {
704 button->setText(firstButtonText());
705 }
706 button->setActive(q->isActive());
707
708 if (createButton) {
709 if (!isFirstButton) {
710 q->setTabOrder(m_navButtons.constLast(), button);
711 }
712 m_navButtons.append(button);
713 }
714
715 ++idx;
716 button->setActiveSubDirectory(path.section(QLatin1Char('/'), idx, idx));
717 }
718 } while (hasNext);
719
720 // delete buttons which are not used anymore
721 const int newButtonCount = idx - startIndex;
722 if (newButtonCount < oldButtonCount) {
723 const auto itBegin = m_navButtons.begin() + newButtonCount;
724 const auto itEnd = m_navButtons.end();
725 for (auto it = itBegin; it != itEnd; ++it) {
726 auto *navBtn = *it;
727 navBtn->hide();
728 navBtn->deleteLater();
729 }
730 m_navButtons.erase(itBegin, itEnd);
731 }
732
733 q->setTabOrder(m_dropDownButton, m_navButtons.constFirst());
734 q->setTabOrder(m_navButtons.constLast(), m_toggleEditableMode);
735
736 updateButtonVisibility();
737}
738
739void KUrlNavigatorPrivate::updateButtonVisibility()
740{
741 if (m_editable) {
742 return;
743 }
744
745 const int buttonsCount = m_navButtons.count();
746 if (buttonsCount == 0) {
747 m_dropDownButton->hide();
748 return;
749 }
750
751 // Subtract all widgets from the available width, that must be shown anyway
752 int availableWidth = q->width() - m_toggleEditableMode->minimumWidth();
753
754 if ((m_placesSelector != nullptr) && m_placesSelector->isVisible()) {
755 availableWidth -= m_placesSelector->width();
756 }
757
758 if ((m_schemes != nullptr) && m_schemes->isVisible()) {
759 availableWidth -= m_schemes->width();
760 }
761
762 // Check whether buttons must be hidden at all...
763 int requiredButtonWidth = 0;
764 for (const auto *button : std::as_const(m_navButtons)) {
765 requiredButtonWidth += button->minimumWidth();
766 }
767
768 if (requiredButtonWidth > availableWidth) {
769 // At least one button must be hidden. This implies that the
770 // drop-down button must get visible, which again decreases the
771 // available width.
772 availableWidth -= m_dropDownButton->width();
773 }
774
775 // Hide buttons...
776 bool isLastButton = true;
777 bool hasHiddenButtons = false;
778 QList<KUrlNavigatorButton *> buttonsToShow;
779 for (auto it = m_navButtons.crbegin(); it != m_navButtons.crend(); ++it) {
780 KUrlNavigatorButton *button = *it;
781 availableWidth -= button->minimumWidth();
782 if ((availableWidth <= 0) && !isLastButton) {
783 button->hide();
784 hasHiddenButtons = true;
785 } else {
786 // Don't show the button immediately, as setActive()
787 // might change the size and a relayout gets triggered
788 // after showing the button. So the showing of all buttons
789 // is postponed until all buttons have the correct
790 // activation state.
791 buttonsToShow.append(button);
792 }
793 isLastButton = false;
794 }
795
796 // All buttons have the correct activation state and
797 // can be shown now
798 for (KUrlNavigatorButton *button : std::as_const(buttonsToShow)) {
799 button->show();
800 }
801
802 if (hasHiddenButtons) {
803 m_dropDownButton->show();
804 } else {
805 // Check whether going upwards is possible. If this is the case, show the drop-down button.
806 QUrl url(m_navButtons.front()->url());
807 const bool visible = !url.matches(KIO::upUrl(url), QUrl::StripTrailingSlash) //
808 && url.scheme() != QLatin1String("baloosearch") //
809 && url.scheme() != QLatin1String("filenamesearch");
810 m_dropDownButton->setVisible(visible);
811 }
812}
813
814QString KUrlNavigatorPrivate::firstButtonText() const
815{
816 QString text;
817
818 // The first URL navigator button should get the name of the
819 // place instead of the directory name
820 if ((m_placesSelector != nullptr) && !m_showFullPath) {
821 text = m_placesSelector->selectedPlaceText();
822 }
823
824 const QUrl currentUrl = q->locationUrl();
825
826 if (text.isEmpty()) {
827 if (currentUrl.isLocalFile()) {
828#ifdef Q_OS_WIN
829 text = currentUrl.path().length() > 1 ? currentUrl.path().left(2) : QDir::rootPath();
830#else
831 text = QStringLiteral("/");
832#endif
833 }
834 }
835
836 if (text.isEmpty()) {
837 if (currentUrl.path().isEmpty() || currentUrl.path() == QLatin1Char('/')) {
838 QUrlQuery query(currentUrl);
839 text = query.queryItemValue(QStringLiteral("title"));
840 }
841 }
842
843 if (text.isEmpty()) {
844 text = currentUrl.scheme() + QLatin1Char(':');
845 if (!currentUrl.host().isEmpty()) {
846 text += QLatin1Char(' ') + currentUrl.host();
847 }
848 }
849
850 return text;
851}
852
853QUrl KUrlNavigatorPrivate::buttonUrl(int index) const
854{
855 if (index < 0) {
856 index = 0;
857 }
858
859 // Keep scheme, hostname etc. as this is needed for e. g. browsing
860 // FTP directories
861 QUrl url = q->locationUrl();
862 QString path = url.path();
863
864 if (!path.isEmpty()) {
865 if (index == 0) {
866 // prevent the last "/" from being stripped
867 // or we end up with an empty path
868#ifdef Q_OS_WIN
869 path = path.length() > 1 ? path.left(2) : QDir::rootPath();
870#else
871 path = QStringLiteral("/");
872#endif
873 } else {
874 path = path.section(QLatin1Char('/'), 0, index);
875 }
876 }
877
878 url.setPath(path);
879 return url;
880}
881
882void KUrlNavigatorPrivate::switchToBreadcrumbMode()
883{
884 q->setUrlEditable(false);
885}
886
887void KUrlNavigatorPrivate::deleteButtons()
888{
889 for (KUrlNavigatorButton *button : std::as_const(m_navButtons)) {
890 button->hide();
891 button->deleteLater();
892 }
893 m_navButtons.clear();
894}
895
896QUrl KUrlNavigatorPrivate::retrievePlaceUrl() const
897{
898 QUrl currentUrl = q->locationUrl();
899 currentUrl.setPath(QString());
900 return currentUrl;
901}
902
903// ------------------------------------------------------------------------------------------------
904
906 : KUrlNavigator(nullptr, QUrl{}, parent)
907{
908}
909
911 : QWidget(parent)
912 , d(new KUrlNavigatorPrivate(url, this, placesModel))
913{
914 const int minHeight = d->m_pathBox->sizeHint().height();
915 setMinimumHeight(minHeight);
916
917 setMinimumWidth(100);
918
919 d->updateContent();
920}
921
922KUrlNavigator::~KUrlNavigator()
923{
924 d->m_dropDownButton->removeEventFilter(this);
925 d->m_pathBox->removeEventFilter(this);
926 for (auto *button : std::as_const(d->m_navButtons)) {
927 button->removeEventFilter(this);
928 }
929}
930
931QUrl KUrlNavigator::locationUrl(int historyIndex) const
932{
933 return d->m_coreUrlNavigator->locationUrl(historyIndex);
934}
935
937{
938 auto current = d->m_coreUrlNavigator->locationState().value<KUrlNavigatorData>();
939 current.state = state;
940 d->m_coreUrlNavigator->saveLocationState(QVariant::fromValue(current));
941}
942
944{
945 return d->m_coreUrlNavigator->locationState(historyIndex).value<KUrlNavigatorData>().state;
946}
947
949{
950 return d->m_coreUrlNavigator->goBack();
951}
952
954{
955 return d->m_coreUrlNavigator->goForward();
956}
957
959{
960 return d->m_coreUrlNavigator->goUp();
961}
962
964{
965 if (d->m_homeUrl.isEmpty() || !d->m_homeUrl.isValid()) {
967 } else {
968 setLocationUrl(d->m_homeUrl);
969 }
970}
971
973{
974 d->m_homeUrl = url;
975}
976
977QUrl KUrlNavigator::homeUrl() const
978{
979 return d->m_homeUrl;
980}
981
983{
984 if (d->m_editable != editable) {
985 d->switchView();
986 }
987}
988
990{
991 return d->m_editable;
992}
993
995{
996 if (d->m_showFullPath != show) {
997 d->m_showFullPath = show;
998 d->updateContent();
999 }
1000}
1001
1003{
1004 return d->m_showFullPath;
1005}
1006
1008{
1009 if (active != d->m_active) {
1010 d->m_active = active;
1011
1012 d->m_dropDownButton->setActive(active);
1013 for (KUrlNavigatorButton *button : std::as_const(d->m_navButtons)) {
1014 button->setActive(active);
1015 }
1016
1017 update();
1018 if (active) {
1019 Q_EMIT activated();
1020 }
1021 }
1022}
1023
1025{
1026 return d->m_active;
1027}
1028
1030{
1031 if (visible == d->m_showPlacesSelector) {
1032 return;
1033 }
1034
1035 if (visible && (d->m_placesSelector == nullptr)) {
1036 // the places selector cannot get visible as no
1037 // places model is available
1038 return;
1039 }
1040
1041 d->m_showPlacesSelector = visible;
1042 d->m_placesSelector->setVisible(visible);
1043}
1044
1046{
1047 return d->m_showPlacesSelector;
1048}
1049
1051{
1052 KUriFilterData filteredData(d->m_pathBox->currentText().trimmed());
1053 filteredData.setCheckForExecutables(false);
1054 if (KUriFilter::self()->filterUri(filteredData, QStringList{QStringLiteral("kshorturifilter")})) {
1055 return filteredData.uri();
1056 } else {
1057 return QUrl::fromUserInput(filteredData.typedString());
1058 }
1059}
1060
1062{
1063 d->m_coreUrlNavigator->setCurrentLocationUrl(newUrl);
1064
1065 d->updateContent();
1066
1068}
1069
1071{
1072 setActive(true);
1073}
1074
1076{
1077 if (isUrlEditable()) {
1078 d->m_pathBox->setFocus();
1079 } else {
1081 }
1082}
1083
1085{
1086 if (isUrlEditable() && (event->key() == Qt::Key_Escape)) {
1087 setUrlEditable(false);
1088 } else {
1090 }
1091}
1092
1094{
1096}
1097
1099{
1100 if (event->button() == Qt::MiddleButton) {
1102 }
1104}
1105
1107{
1108 if (event->button() == Qt::MiddleButton) {
1109 const QRect bounds = d->m_toggleEditableMode->geometry();
1110 if (bounds.contains(event->pos())) {
1111 // The middle mouse button has been clicked above the
1112 // toggle-editable-mode-button. Paste the clipboard content
1113 // as location URL.
1114 QClipboard *clipboard = QApplication::clipboard();
1115 const QMimeData *mimeData = clipboard->mimeData();
1116 if (mimeData->hasText()) {
1117 const QString text = mimeData->text();
1119 }
1120 }
1121 }
1123}
1124
1126{
1127 QTimer::singleShot(0, this, [this]() {
1128 d->updateButtonVisibility();
1129 });
1131}
1132
1134{
1135 setActive(true);
1137}
1138
1139bool KUrlNavigator::eventFilter(QObject *watched, QEvent *event)
1140{
1141 switch (event->type()) {
1142 case QEvent::FocusIn:
1143 if (watched == d->m_pathBox) {
1145 setFocus();
1146 }
1147 for (KUrlNavigatorButton *button : std::as_const(d->m_navButtons)) {
1148 button->setShowMnemonic(true);
1149 }
1150 break;
1151
1152 case QEvent::FocusOut:
1153 for (KUrlNavigatorButton *button : std::as_const(d->m_navButtons)) {
1154 button->setShowMnemonic(false);
1155 }
1156 break;
1157
1158 default:
1159 break;
1160 }
1161
1162 return QWidget::eventFilter(watched, event);
1163}
1164
1166{
1167 return d->m_coreUrlNavigator->historySize();
1168}
1169
1171{
1172 return d->m_coreUrlNavigator->historyIndex();
1173}
1174
1176{
1177 return d->m_pathBox;
1178}
1179
1181{
1182 d->m_supportedSchemes = schemes;
1183 d->m_schemes->setSupportedSchemes(d->m_supportedSchemes);
1184}
1185
1187{
1188 return d->m_supportedSchemes;
1189}
1190
1192{
1193 return d->m_dropWidget;
1194}
1195
1196void KUrlNavigator::setShowHiddenFolders(bool showHiddenFolders)
1197{
1198 d->m_subfolderOptions.showHidden = showHiddenFolders;
1199}
1200
1202{
1203 return d->m_subfolderOptions.showHidden;
1204}
1205
1206void KUrlNavigator::setSortHiddenFoldersLast(bool sortHiddenFoldersLast)
1207{
1208 d->m_subfolderOptions.sortHiddenLast = sortHiddenFoldersLast;
1209}
1210
1212{
1213 return d->m_subfolderOptions.sortHiddenLast;
1214}
1215
1216#include "moc_kurlnavigator.cpp"
void setEditUrl(const QUrl &url)
void returnPressed(const QString &text)
Object that helps with keeping track of URLs in file-manager like interfaces.
Q_SIGNAL void urlSelectionRequested(const QUrl &url)
When the URL is changed and the new URL (e.g. /home/user1/) is a parent of the previous URL (e....
Q_SIGNAL void currentUrlAboutToChange(const QUrl &newUrl)
Is emitted, before the location URL is going to be changed to newUrl.
int historyIndex
The history index of the current location, where 0 <= history index < KCoreUrlNavigator::historySize(...
Q_SIGNAL void historyChanged()
Is emitted, if the history has been changed.
Q_INVOKABLE QUrl locationUrl(int historyIndex=-1) const
This class is a list view model.
void result(KJob *job)
static QString protocolClass(const QString &protocol)
Returns the protocol class for the specified protocol.
This class is a basic messaging class used to exchange filtering information between the filter plugi...
Definition kurifilter.h:153
QUrl uri() const
Returns the filtered or the original URL.
QString typedString() const
The string as typed by the user, before any URL processing is done.
void setCheckForExecutables(bool check)
Check whether the provided uri is executable or not.
static KUriFilter * self()
Returns an instance of KUriFilter.
bool filterUri(KUriFilterData &data, const QStringList &filters=QStringList())
Filters data using the specified filters.
This combobox shows a number of recent URLs/directories, as well as some default directories.
void setUrls(const QStringList &urls)
Inserts urls into the combobox below the "default urls" (see addDefaultUrl).
void setUrl(const QUrl &url)
Sets the current url.
void urlActivated(const QUrl &url)
Emitted when an item was clicked at.
This class does completion of URLs including user directories (~user) and environment variables.
Widget that allows to navigate through the paths of an URL.
void newWindowRequested(const QUrl &url)
Is emitted if the URL url should be opened in a new window because the user left-clicked on a breadcr...
void setShowFullPath(bool show)
Shows the full path of the URL even if a place represents a part of the URL.
void setSortHiddenFoldersLast(bool sortHiddenFoldersLast)
Sets whether to sort hidden folders in the subdirectories popup last.
void setPlacesSelectorVisible(bool visible)
Sets the places selector visible, if visible is true.
void setLocationUrl(const QUrl &url)
Sets the location to url.
bool goUp()
Goes up one step of the URL path and remembers the old path in the history.
bool showHiddenFolders() const
Returns whether to show hidden folders in the subdirectories popup.
void editableStateChanged(bool editable)
Is emitted, if the editable state for the URL has been changed (see KUrlNavigator::setUrlEditable()).
QUrl uncommittedUrl() const
KUrlComboBox * editor() const
int historyIndex() const
QStringList supportedSchemes() const
Returns the URL schemes that the navigator should allow navigating to.
KUrlNavigator(QWidget *parent=nullptr)
bool sortHiddenFoldersLast() const
Returns whether to sort hidden folders in the subdirectories popup last.
void tabRequested(const QUrl &url)
Is emitted if the URL url should be opened in a new inactive tab because the user clicked on a breadc...
void saveLocationState(const QByteArray &state)
Saves the location state described by state for the current location.
void goHome()
Goes to the home URL and remembers the old URL in the history.
void setHomeUrl(const QUrl &url)
Sets the home URL used by KUrlNavigator::goHome().
void activeTabRequested(const QUrl &url)
Is emitted if the URL url should be opened in a new active tab because the user clicked on a breadcru...
bool goBack()
Goes back one step in the URL history.
QUrl locationUrl(int historyIndex=-1) const
void requestActivation()
Activates the URL navigator (KUrlNavigator::isActive() will return true) and emits the signal KUrlNav...
void setUrlEditable(bool editable)
Allows to edit the URL of the navigation bar if editable is true, and sets the focus accordingly.
bool isPlacesSelectorVisible() const
bool isActive() const
int historySize() const
bool showFullPath() const
bool goForward()
Goes forward one step in the URL history.
void setShowHiddenFolders(bool showHiddenFolders)
Sets whether to show hidden folders in the subdirectories popup.
void urlsDropped(const QUrl &destination, QDropEvent *event)
Is emitted if a dropping has been done above the destination destination.
void setActive(bool active)
Set the URL navigator to the active mode, if active is true.
QWidget * dropWidget() const
The child widget that received the QDropEvent when dropping on the URL navigator.
void activated()
Is emitted, if the URL navigator has been activated by an user interaction.
QByteArray locationState(int historyIndex=-1) const
bool isUrlEditable() const
void returnPressed()
This signal is emitted when the Return or Enter key is pressed.
void setSupportedSchemes(const QStringList &schemes)
Set the URL schemes that the navigator should allow navigating to.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
KSERVICE_EXPORT KService::List query(FilterFunc filterFunc)
KIOCORE_EXPORT StatJob * stat(const QUrl &url, JobFlags flags=DefaultFlags)
Find all details for one file or directory.
Definition statjob.cpp:203
KIOCORE_EXPORT QUrl upUrl(const QUrl &url)
This function is useful to implement the "Up" button in a file manager for example.
Definition global.cpp:236
@ HideProgressInfo
Hide progress information dialog, i.e. don't show a GUI.
Definition job_base.h:251
@ StatBasic
Filename, access, type, size, linkdest.
Definition global.h:251
@ StatResolveSymlink
Resolve symlinks.
Definition global.h:257
QString path(const QString &relativePath)
const QList< QKeySequence > & openContextMenu()
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles)
void rowsInserted(const QModelIndex &parent, int first, int last)
void rowsRemoved(const QModelIndex &parent, int first, int last)
void setCheckable(bool)
void setChecked(bool)
QVariant data() const const
void setEnabled(bool)
void setData(const QVariant &data)
void triggered(bool checked)
QAction * addAction(QAction *action)
virtual int count() const const override
void insertWidget(int index, QWidget *widget, int stretch, Qt::Alignment alignment)
const QMimeData * mimeData(Mode mode) const const
void setMimeData(QMimeData *src, Mode mode)
QString text(Mode mode) const const
AdjustToContentsOnFirstShow
void editTextChanged(const QString &text)
QPoint pos()
QString homePath()
QString rootPath()
QClipboard * clipboard()
Qt::KeyboardModifiers keyboardModifiers()
QIcon fromTheme(const QString &name)
void append(QList< T > &&value)
iterator begin()
const_iterator cbegin() const const
const_iterator cend() const const
void clear()
const T & constFirst() const const
const T & constLast() const const
qsizetype count() const const
const_reverse_iterator crbegin() const const
const_reverse_iterator crend() const const
iterator end()
iterator erase(const_iterator begin, const_iterator end)
reference front()
void prepend(parameter_type value)
qsizetype removeAll(const AT &t)
QMetaMethod fromSignal(PointerToMemberFunction signal)
bool invokeMethod(QObject *context, Functor &&function, FunctorReturnType *ret)
bool hasText() const const
void setText(const QString &text)
QString text() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
virtual bool eventFilter(QObject *watched, QEvent *event)
bool isSignalConnected(const QMetaMethod &signal) const const
void removeEventFilter(QObject *obj)
T * data() const const
bool contains(const QPoint &point, bool proper) const const
qsizetype count() const const
QString & append(QChar ch)
bool isEmpty() const const
QString left(qsizetype n) const const
qsizetype length() const const
QString section(QChar sep, qsizetype start, qsizetype end, SectionFlags flags) const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QueuedConnection
CustomContextMenu
Key_Escape
typedef KeyboardModifiers
MouseButton
PreferLocalFile
QUrl fromLocalFile(const QString &localFile)
QUrl fromUserInput(const QString &userInput, const QString &workingDirectory, UserInputResolutionOptions options)
QString host(ComponentFormattingOptions options) const const
bool isEmpty() const const
bool isLocalFile() const const
bool isValid() const const
bool matches(const QUrl &url, FormattingOptions options) const const
QString path(ComponentFormattingOptions options) const const
QString scheme() const const
void setAuthority(const QString &authority, ParsingMode mode)
void setPath(const QString &path, ParsingMode mode)
void setScheme(const QString &scheme)
QString toDisplayString(FormattingOptions options) const const
QString toString(FormattingOptions options) const const
QString url(FormattingOptions options) const const
QVariant fromValue(T &&value)
QString toString() const const
void customContextMenuRequested(const QPoint &pos)
virtual bool event(QEvent *event) override
void hide()
virtual void keyPressEvent(QKeyEvent *event)
virtual void keyReleaseEvent(QKeyEvent *event)
QPoint mapToGlobal(const QPoint &pos) const const
void setMinimumHeight(int minh)
void setMinimumWidth(int minw)
virtual void mousePressEvent(QMouseEvent *event)
virtual void mouseReleaseEvent(QMouseEvent *event)
virtual void resizeEvent(QResizeEvent *event)
void setFocus()
void setTabOrder(QWidget *first, QWidget *second)
void show()
void setSizePolicy(QSizePolicy)
void update()
virtual void wheelEvent(QWheelEvent *event)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:18:52 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.