KIO

kurlnavigatorbutton.cpp
1/*
2 SPDX-FileCopyrightText: 2006 Peter Penz <peter.penz@gmx.at>
3 SPDX-FileCopyrightText: 2006 Aaron J. Seigo <aseigo@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "kurlnavigatorbutton_p.h"
9
10#include "../utils_p.h"
11#include "kurlnavigator.h"
12#include "kurlnavigatormenu_p.h"
13#include <kio/listjob.h>
14#include <kio/statjob.h>
15
16#include <KLocalizedString>
17#include <KStringHandler>
18
19#include <QCollator>
20#include <QKeyEvent>
21#include <QMimeData>
22#include <QPainter>
23#include <QStyleOption>
24#include <QTimer>
25
26namespace KDEPrivate
27{
28QPointer<KUrlNavigatorMenu> KUrlNavigatorButton::m_subDirsMenu;
29
30KUrlNavigatorButton::KUrlNavigatorButton(const QUrl &url, KUrlNavigator *parent)
31 : KUrlNavigatorButtonBase(parent)
32 , m_hoverArrow(false)
33 , m_pendingTextChange(false)
34 , m_replaceButton(false)
35 , m_showMnemonic(false)
36 , m_wheelSteps(0)
37 , m_url(url)
38 , m_subDir()
39 , m_openSubDirsTimer(nullptr)
40 , m_subDirsJob(nullptr)
41{
42 setAcceptDrops(true);
43 setUrl(url);
44 setMouseTracking(true);
45
46 m_openSubDirsTimer = new QTimer(this);
47 m_openSubDirsTimer->setSingleShot(true);
48 m_openSubDirsTimer->setInterval(300);
49 connect(m_openSubDirsTimer, &QTimer::timeout, this, &KUrlNavigatorButton::startSubDirsJob);
50
51 connect(this, &QAbstractButton::pressed, this, &KUrlNavigatorButton::requestSubDirs);
52}
53
54KUrlNavigatorButton::~KUrlNavigatorButton()
55{
56}
57
58void KUrlNavigatorButton::setUrl(const QUrl &url)
59{
60 m_url = url;
61
62 // Doing a text-resolving with KIO::stat() for all non-local
63 // URLs leads to problems for protocols where a limit is given for
64 // the number of parallel connections. A black-list
65 // is given where KIO::stat() should not be used:
66 static const QSet<QString> protocolBlacklist = QSet<QString>{
67 QStringLiteral("nfs"),
68 QStringLiteral("fish"),
69 QStringLiteral("ftp"),
70 QStringLiteral("sftp"),
71 QStringLiteral("smb"),
72 QStringLiteral("webdav"),
73 QStringLiteral("mtp"),
74 };
75
76 const bool startTextResolving = m_url.isValid() && !m_url.isLocalFile() && !protocolBlacklist.contains(m_url.scheme());
77
78 if (startTextResolving) {
79 m_pendingTextChange = true;
81 connect(job, &KJob::result, this, &KUrlNavigatorButton::statFinished);
82 Q_EMIT startedTextResolving();
83 } else {
84 setText(m_url.fileName().replace(QLatin1Char('&'), QLatin1String("&&")));
85 }
86}
87
88QUrl KUrlNavigatorButton::url() const
89{
90 return m_url;
91}
92
93void KUrlNavigatorButton::setText(const QString &text)
94{
95 QString adjustedText = text;
96 if (adjustedText.isEmpty()) {
97 adjustedText = m_url.scheme();
98 }
99 // Assure that the button always consists of one line
100 adjustedText.remove(QLatin1Char('\n'));
101
102 KUrlNavigatorButtonBase::setText(adjustedText);
103 updateMinimumWidth();
104
105 // Assure that statFinished() does not overwrite a text that has been
106 // set by a client of the URL navigator button
107 m_pendingTextChange = false;
108}
109
110void KUrlNavigatorButton::setActiveSubDirectory(const QString &subDir)
111{
112 m_subDir = subDir;
113
114 // We use a different (bold) font on active, so the size hint changes
115 updateGeometry();
116 update();
117}
118
119QString KUrlNavigatorButton::activeSubDirectory() const
120{
121 return m_subDir;
122}
123
124QSize KUrlNavigatorButton::sizeHint() const
125{
126 QFont adjustedFont(font());
127 adjustedFont.setBold(m_subDir.isEmpty());
128 // the minimum size is textWidth + arrowWidth() + 2 * BorderWidth; for the
129 // preferred size we add the BorderWidth 2 times again for having an uncluttered look
130 const int width = QFontMetrics(adjustedFont).size(Qt::TextSingleLine, plainText()).width() + arrowWidth() + 4 * BorderWidth;
131 return QSize(width, KUrlNavigatorButtonBase::sizeHint().height());
132}
133
134void KUrlNavigatorButton::setShowMnemonic(bool show)
135{
136 if (m_showMnemonic != show) {
137 m_showMnemonic = show;
138 update();
139 }
140}
141
142bool KUrlNavigatorButton::showMnemonic() const
143{
144 return m_showMnemonic;
145}
146
147void KUrlNavigatorButton::paintEvent(QPaintEvent *event)
148{
149 Q_UNUSED(event);
150
151 QPainter painter(this);
152
153 QFont adjustedFont(font());
154 adjustedFont.setBold(m_subDir.isEmpty());
155 painter.setFont(adjustedFont);
156
157 int buttonWidth = width();
158 int preferredWidth = sizeHint().width();
159 if (preferredWidth < minimumWidth()) {
160 preferredWidth = minimumWidth();
161 }
162 if (buttonWidth > preferredWidth) {
163 buttonWidth = preferredWidth;
164 }
165 const int buttonHeight = height();
166
167 const QColor fgColor = foregroundColor();
168 drawHoverBackground(&painter);
169
170 int textLeft = 0;
171 int textWidth = buttonWidth;
172
173 const bool leftToRight = (layoutDirection() == Qt::LeftToRight);
174
175 if (!m_subDir.isEmpty()) {
176 // draw arrow
177 const int arrowSize = arrowWidth();
178 const int arrowX = leftToRight ? (buttonWidth - arrowSize) - BorderWidth : BorderWidth;
179 const int arrowY = (buttonHeight - arrowSize) / 2;
180
181 QStyleOption option;
182 option.initFrom(this);
183 option.rect = QRect(arrowX, arrowY, arrowSize, arrowSize);
184 option.palette = palette();
185 option.palette.setColor(QPalette::Text, fgColor);
186 option.palette.setColor(QPalette::WindowText, fgColor);
187 option.palette.setColor(QPalette::ButtonText, fgColor);
188
189 if (m_hoverArrow) {
190 // highlight the background of the arrow to indicate that the directories
191 // popup can be opened by a mouse click
192 QColor hoverColor = palette().color(QPalette::HighlightedText);
193 hoverColor.setAlpha(96);
194 painter.setPen(Qt::NoPen);
195 painter.setBrush(hoverColor);
196
197 int hoverX = arrowX;
198 if (!leftToRight) {
199 hoverX -= BorderWidth;
200 }
201 painter.drawRect(QRect(hoverX, 0, arrowSize + BorderWidth, buttonHeight));
202 }
203
204 if (leftToRight) {
205 style()->drawPrimitive(QStyle::PE_IndicatorArrowRight, &option, &painter, this);
206 } else {
207 style()->drawPrimitive(QStyle::PE_IndicatorArrowLeft, &option, &painter, this);
208 textLeft += arrowSize + 2 * BorderWidth;
209 }
210
211 textWidth -= arrowSize + 2 * BorderWidth;
212 }
213
214 painter.setPen(fgColor);
215 const bool clipped = isTextClipped();
216 const QRect textRect(textLeft, 0, textWidth, buttonHeight);
217 if (clipped) {
218 QColor bgColor = fgColor;
219 bgColor.setAlpha(0);
220 QLinearGradient gradient(textRect.topLeft(), textRect.topRight());
221 if (leftToRight) {
222 gradient.setColorAt(0.8, fgColor);
223 gradient.setColorAt(1.0, bgColor);
224 } else {
225 gradient.setColorAt(0.0, bgColor);
226 gradient.setColorAt(0.2, fgColor);
227 }
228
229 QPen pen;
230 pen.setBrush(QBrush(gradient));
231 painter.setPen(pen);
232 }
233
234 int textFlags = clipped ? Qt::AlignVCenter : Qt::AlignCenter;
235 if (m_showMnemonic) {
236 textFlags |= Qt::TextShowMnemonic;
237 painter.drawText(textRect, textFlags, text());
238 } else {
239 painter.drawText(textRect, textFlags, plainText());
240 }
241}
242
243void KUrlNavigatorButton::enterEvent(QEnterEvent *event)
244{
245 KUrlNavigatorButtonBase::enterEvent(event);
246
247 // if the text is clipped due to a small window width, the text should
248 // be shown as tooltip
249 if (isTextClipped()) {
250 setToolTip(plainText());
251 }
252}
253
254void KUrlNavigatorButton::leaveEvent(QEvent *event)
255{
256 KUrlNavigatorButtonBase::leaveEvent(event);
257 setToolTip(QString());
258
259 if (m_hoverArrow) {
260 m_hoverArrow = false;
261 update();
262 }
263}
264
265void KUrlNavigatorButton::keyPressEvent(QKeyEvent *event)
266{
267 switch (event->key()) {
268 case Qt::Key_Enter:
269 case Qt::Key_Return:
270 Q_EMIT navigatorButtonActivated(m_url, Qt::LeftButton, event->modifiers());
271 break;
272 case Qt::Key_Down:
273 case Qt::Key_Space:
274 startSubDirsJob();
275 break;
276 default:
277 KUrlNavigatorButtonBase::keyPressEvent(event);
278 }
279}
280
281void KUrlNavigatorButton::dropEvent(QDropEvent *event)
282{
283 if (event->mimeData()->hasUrls()) {
284 setDisplayHintEnabled(DraggedHint, true);
285
286 Q_EMIT urlsDroppedOnNavButton(m_url, event);
287
288 setDisplayHintEnabled(DraggedHint, false);
289 update();
290 }
291}
292
293void KUrlNavigatorButton::dragEnterEvent(QDragEnterEvent *event)
294{
295 if (event->mimeData()->hasUrls()) {
296 setDisplayHintEnabled(DraggedHint, true);
297 event->acceptProposedAction();
298
299 update();
300 }
301}
302
303void KUrlNavigatorButton::dragMoveEvent(QDragMoveEvent *event)
304{
305 QRect rect = event->answerRect();
306 if (isAboveArrow(rect.center().x())) {
307 m_hoverArrow = true;
308 update();
309
310 if (m_subDirsMenu == nullptr) {
311 requestSubDirs();
312 } else if (m_subDirsMenu->parent() != this) {
313 m_subDirsMenu->close();
314 m_subDirsMenu->deleteLater();
315 m_subDirsMenu = nullptr;
316
317 requestSubDirs();
318 }
319 } else {
320 if (m_openSubDirsTimer->isActive()) {
321 cancelSubDirsRequest();
322 }
323 m_subDirsMenu->deleteLater();
324 m_subDirsMenu = nullptr;
325 m_hoverArrow = false;
326 update();
327 }
328}
329
330void KUrlNavigatorButton::dragLeaveEvent(QDragLeaveEvent *event)
331{
332 KUrlNavigatorButtonBase::dragLeaveEvent(event);
333
334 m_hoverArrow = false;
335 setDisplayHintEnabled(DraggedHint, false);
336 update();
337}
338
339void KUrlNavigatorButton::mousePressEvent(QMouseEvent *event)
340{
341 if (isAboveArrow(qRound(event->position().x())) && (event->button() == Qt::LeftButton)) {
342 // the mouse is pressed above the [>] button
343 startSubDirsJob();
344 }
345 KUrlNavigatorButtonBase::mousePressEvent(event);
346}
347
348void KUrlNavigatorButton::mouseReleaseEvent(QMouseEvent *event)
349{
350 if (!isAboveArrow(qRound(event->position().x())) || (event->button() != Qt::LeftButton)) {
351 // the mouse has been released above the text area and not
352 // above the [>] button
353 Q_EMIT navigatorButtonActivated(m_url, event->button(), event->modifiers());
354 cancelSubDirsRequest();
355 }
356 KUrlNavigatorButtonBase::mouseReleaseEvent(event);
357}
358
359void KUrlNavigatorButton::mouseMoveEvent(QMouseEvent *event)
360{
361 KUrlNavigatorButtonBase::mouseMoveEvent(event);
362
363 const bool hoverArrow = isAboveArrow(qRound(event->position().x()));
364 if (hoverArrow != m_hoverArrow) {
365 m_hoverArrow = hoverArrow;
366 update();
367 }
368}
369
370void KUrlNavigatorButton::wheelEvent(QWheelEvent *event)
371{
372 if (event->angleDelta().y() != 0) {
373 m_wheelSteps = event->angleDelta().y() / 120;
374 m_replaceButton = true;
375 startSubDirsJob();
376 }
377
378 KUrlNavigatorButtonBase::wheelEvent(event);
379}
380
381void KUrlNavigatorButton::requestSubDirs()
382{
383 if (!m_openSubDirsTimer->isActive() && (m_subDirsJob == nullptr)) {
384 m_openSubDirsTimer->start();
385 }
386}
387
388void KUrlNavigatorButton::startSubDirsJob()
389{
390 if (m_subDirsJob != nullptr) {
391 return;
392 }
393
394 const QUrl url = m_replaceButton ? KIO::upUrl(m_url) : m_url;
395 const KUrlNavigator *urlNavigator = qobject_cast<KUrlNavigator *>(parent());
396 Q_ASSERT(urlNavigator);
397 m_subDirsJob =
399 m_subDirs.clear(); // just to be ++safe
400
401 connect(m_subDirsJob, &KIO::ListJob::entries, this, &KUrlNavigatorButton::addEntriesToSubDirs);
402
403 if (m_replaceButton) {
404 connect(m_subDirsJob, &KJob::result, this, &KUrlNavigatorButton::replaceButton);
405 } else {
406 connect(m_subDirsJob, &KJob::result, this, &KUrlNavigatorButton::openSubDirsMenu);
407 }
408}
409
410void KUrlNavigatorButton::addEntriesToSubDirs(KIO::Job *job, const KIO::UDSEntryList &entries)
411{
412 Q_ASSERT(job == m_subDirsJob);
413 Q_UNUSED(job);
414
415 for (const KIO::UDSEntry &entry : entries) {
416 if (entry.isDir()) {
417 const QString name = entry.stringValue(KIO::UDSEntry::UDS_NAME);
419 if (displayName.isEmpty()) {
421 }
422 if (name != QLatin1String(".") && name != QLatin1String("..")) {
423 m_subDirs.push_back({name, displayName});
424 }
425 }
426 }
427}
428
429void KUrlNavigatorButton::slotUrlsDropped(QAction *action, QDropEvent *event)
430{
431 const int result = action->data().toInt();
432 QUrl url(m_url);
433 url.setPath(Utils::concatPaths(url.path(), m_subDirs.at(result).name));
434 Q_EMIT urlsDroppedOnNavButton(url, event);
435}
436
437void KUrlNavigatorButton::slotMenuActionClicked(QAction *action, Qt::MouseButton button)
438{
439 const int result = action->data().toInt();
440 QUrl url(m_url);
441 url.setPath(Utils::concatPaths(url.path(), m_subDirs.at(result).name));
442 Q_EMIT navigatorButtonActivated(url, button, Qt::NoModifier);
443}
444
445void KUrlNavigatorButton::statFinished(KJob *job)
446{
447 if (m_pendingTextChange) {
448 m_pendingTextChange = false;
449
450 const KIO::UDSEntry entry = static_cast<KIO::StatJob *>(job)->statResult();
452 if (name.isEmpty()) {
453 name = m_url.fileName();
454 }
455 setText(name);
456
457 Q_EMIT finishedTextResolving();
458 }
459}
460
461/**
462 * Helper struct for sorting folder names
463 */
464struct FolderNameNaturalLessThan {
465 FolderNameNaturalLessThan(bool sortHiddenLast)
466 : m_sortHiddenLast(sortHiddenLast)
467 {
468 m_collator.setCaseSensitivity(Qt::CaseInsensitive);
469 m_collator.setNumericMode(true);
470 }
471
472 bool operator()(const KUrlNavigatorButton::SubDirInfo &a, const KUrlNavigatorButton::SubDirInfo &b)
473 {
474 if (m_sortHiddenLast) {
475 const bool isHiddenA = a.name.startsWith(QLatin1Char('.'));
476 const bool isHiddenB = b.name.startsWith(QLatin1Char('.'));
477 if (isHiddenA && !isHiddenB) {
478 return false;
479 }
480 if (!isHiddenA && isHiddenB) {
481 return true;
482 }
483 }
484 return m_collator.compare(a.name, b.name) < 0;
485 }
486
487private:
488 QCollator m_collator;
489 bool m_sortHiddenLast;
490};
491
492void KUrlNavigatorButton::openSubDirsMenu(KJob *job)
493{
494 Q_ASSERT(job == m_subDirsJob);
495 m_subDirsJob = nullptr;
496
497 if (job->error() || m_subDirs.empty()) {
498 // clear listing
499 return;
500 }
501
502 const KUrlNavigator *urlNavigator = qobject_cast<KUrlNavigator *>(parent());
503 Q_ASSERT(urlNavigator);
504 FolderNameNaturalLessThan less(urlNavigator->showHiddenFolders() && urlNavigator->sortHiddenFoldersLast());
505 std::sort(m_subDirs.begin(), m_subDirs.end(), less);
506 setDisplayHintEnabled(PopupActiveHint, true);
507 update(); // ensure the button is drawn highlighted
508
509 if (m_subDirsMenu != nullptr) {
510 m_subDirsMenu->close();
511 m_subDirsMenu->deleteLater();
512 m_subDirsMenu = nullptr;
513 }
514
515 m_subDirsMenu = new KUrlNavigatorMenu(this);
516 initMenu(m_subDirsMenu, 0);
517
518 const bool leftToRight = (layoutDirection() == Qt::LeftToRight);
519 const int popupX = leftToRight ? width() - arrowWidth() - BorderWidth : 0;
520 const QPoint popupPos = parentWidget()->mapToGlobal(geometry().bottomLeft() + QPoint(popupX, 0));
521
522 QPointer<QObject> guard(this);
523
524 m_subDirsMenu->exec(popupPos);
525
526 // If 'this' has been deleted in the menu's nested event loop, we have to return
527 // immediately because any access to a member variable might cause a crash.
528 if (!guard) {
529 return;
530 }
531
532 m_subDirs.clear();
533 delete m_subDirsMenu;
534 m_subDirsMenu = nullptr;
535
536 setDisplayHintEnabled(PopupActiveHint, false);
537}
538
539void KUrlNavigatorButton::replaceButton(KJob *job)
540{
541 Q_ASSERT(job == m_subDirsJob);
542 m_subDirsJob = nullptr;
543 m_replaceButton = false;
544
545 if (job->error() || m_subDirs.empty()) {
546 return;
547 }
548
549 const KUrlNavigator *urlNavigator = qobject_cast<KUrlNavigator *>(parent());
550 Q_ASSERT(urlNavigator);
551 FolderNameNaturalLessThan less(urlNavigator->showHiddenFolders() && urlNavigator->sortHiddenFoldersLast());
552 std::sort(m_subDirs.begin(), m_subDirs.end(), less);
553
554 // Get index of the directory that is shown currently in the button
555 const QString currentDir = m_url.fileName();
556 int currentIndex = 0;
557 const int subDirsCount = m_subDirs.size();
558 while (currentIndex < subDirsCount) {
559 if (m_subDirs[currentIndex].name == currentDir) {
560 break;
561 }
562 ++currentIndex;
563 }
564
565 // Adjust the index by respecting the wheel steps and
566 // trigger a replacing of the button content
567 int targetIndex = currentIndex - m_wheelSteps;
568 if (targetIndex < 0) {
569 targetIndex = 0;
570 } else if (targetIndex >= subDirsCount) {
571 targetIndex = subDirsCount - 1;
572 }
573
574 QUrl url(KIO::upUrl(m_url));
575 url.setPath(Utils::concatPaths(url.path(), m_subDirs[targetIndex].name));
576 Q_EMIT navigatorButtonActivated(url, Qt::LeftButton, Qt::NoModifier);
577
578 m_subDirs.clear();
579}
580
581void KUrlNavigatorButton::cancelSubDirsRequest()
582{
583 m_openSubDirsTimer->stop();
584 if (m_subDirsJob != nullptr) {
585 m_subDirsJob->kill();
586 m_subDirsJob = nullptr;
587 }
588}
589
590QString KUrlNavigatorButton::plainText() const
591{
592 // Replace all "&&" by '&' and remove all single
593 // '&' characters
594 const QString source = text();
595 const int sourceLength = source.length();
596
597 QString dest;
598 dest.resize(sourceLength);
599
600 int sourceIndex = 0;
601 int destIndex = 0;
602 while (sourceIndex < sourceLength) {
603 if (source.at(sourceIndex) == QLatin1Char('&')) {
604 ++sourceIndex;
605 if (sourceIndex >= sourceLength) {
606 break;
607 }
608 }
609 dest[destIndex] = source.at(sourceIndex);
610 ++sourceIndex;
611 ++destIndex;
612 }
613
614 dest.resize(destIndex);
615
616 return dest;
617}
618
619int KUrlNavigatorButton::arrowWidth() const
620{
621 // if there isn't arrow then return 0
622 int width = 0;
623 if (!m_subDir.isEmpty()) {
624 width = height() / 2;
625 if (width < 4) {
626 width = 4;
627 }
628 }
629
630 return width;
631}
632
633bool KUrlNavigatorButton::isAboveArrow(int x) const
634{
635 const bool leftToRight = (layoutDirection() == Qt::LeftToRight);
636 return leftToRight ? (x >= width() - arrowWidth()) : (x < arrowWidth());
637}
638
639bool KUrlNavigatorButton::isTextClipped() const
640{
641 int availableWidth = width() - 2 * BorderWidth;
642 if (!m_subDir.isEmpty()) {
643 availableWidth -= arrowWidth() - BorderWidth;
644 }
645
646 QFont adjustedFont(font());
647 adjustedFont.setBold(m_subDir.isEmpty());
648 return QFontMetrics(adjustedFont).size(Qt::TextSingleLine, plainText()).width() >= availableWidth;
649}
650
651void KUrlNavigatorButton::updateMinimumWidth()
652{
653 const int oldMinWidth = minimumWidth();
654
655 int minWidth = sizeHint().width();
656 if (minWidth < 40) {
657 minWidth = 40;
658 } else if (minWidth > 150) {
659 // don't let an overlong path name waste all the URL navigator space
660 minWidth = 150;
661 }
662 if (oldMinWidth != minWidth) {
663 setMinimumWidth(minWidth);
664 }
665}
666
667void KUrlNavigatorButton::initMenu(KUrlNavigatorMenu *menu, int startIndex)
668{
669 connect(menu, &KUrlNavigatorMenu::mouseButtonClicked, this, &KUrlNavigatorButton::slotMenuActionClicked);
670 connect(menu, &KUrlNavigatorMenu::urlsDropped, this, &KUrlNavigatorButton::slotUrlsDropped);
671
672 // So that triggering a menu item with the keyboard works
673 connect(menu, &QMenu::triggered, this, [this](QAction *act) {
674 slotMenuActionClicked(act, Qt::LeftButton);
675 });
676
677 menu->setLayoutDirection(Qt::LeftToRight);
678
679 const int maxIndex = startIndex + 30; // Don't show more than 30 items in a menu
680 const int subDirsSize = m_subDirs.size();
681 const int lastIndex = std::min(subDirsSize - 1, maxIndex);
682 for (int i = startIndex; i <= lastIndex; ++i) {
683 const auto &[subDirName, subDirDisplayName] = m_subDirs[i];
684 QString text = KStringHandler::csqueeze(subDirDisplayName, 60);
685 text.replace(QLatin1Char('&'), QLatin1String("&&"));
686 QAction *action = new QAction(text, this);
687 if (m_subDir == subDirName) {
688 QFont font(action->font());
689 font.setBold(true);
690 action->setFont(font);
691 }
692 action->setData(i);
693 menu->addAction(action);
694 }
695 if (subDirsSize > maxIndex) {
696 // If too much items are shown, move them into a sub menu
697 menu->addSeparator();
698 KUrlNavigatorMenu *subDirsMenu = new KUrlNavigatorMenu(menu);
699 subDirsMenu->setTitle(i18nc("@action:inmenu", "More"));
700 initMenu(subDirsMenu, maxIndex);
701 menu->addMenu(subDirsMenu);
702 }
703}
704
705} // namespace KDEPrivate
706
707#include "moc_kurlnavigatorbutton_p.cpp"
The base class for all jobs.
Definition job_base.h:45
@ IncludeHidden
Include hidden files in the listing.
void entries(KIO::Job *job, const KIO::UDSEntryList &list)
This signal emits the entry found by the job while listing.
A KIO job that retrieves information about a file or directory.
Definition statjob.h:26
Universal Directory Service.
Definition udsentry.h:78
QString stringValue(uint field) const
Definition udsentry.cpp:365
@ UDS_DISPLAY_NAME
If set, contains the label to display instead of the 'real name' in UDS_NAME.
Definition udsentry.h:272
@ UDS_NAME
Filename - as displayed in directory listings etc.
Definition udsentry.h:224
int error() const
void result(KJob *job)
Widget that allows to navigate through the paths of an URL.
bool showHiddenFolders() const
Returns whether to show hidden folders in the subdirectories popup.
bool sortHiddenFoldersLast() const
Returns whether to sort hidden folders in the subdirectories popup last.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
AKONADI_CALENDAR_EXPORT QString displayName(Akonadi::ETMCalendar *calendar, const Akonadi::Collection &collection)
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
void update(Part *part, const QByteArray &data, qint64 dataSize)
A namespace for KIO globals.
KIOCORE_EXPORT StatJob * stat(const QUrl &url, JobFlags flags=DefaultFlags)
Find all details for one file or directory.
Definition statjob.cpp:203
KIOCORE_EXPORT ListJob * listDir(const QUrl &url, JobFlags flags=DefaultFlags, ListJob::ListFlags listFlags=ListJob::ListFlag::IncludeHidden)
List the contents of url, which is assumed to be a directory.
Definition listjob.cpp:239
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
QString name(StandardShortcut id)
KCOREADDONS_EXPORT QString csqueeze(const QString &str, int maxlen=40)
QVariant data() const const
void setData(const QVariant &data)
void setAlpha(int alpha)
QSize size(int flags, const QString &text, int tabStops, int *tabArray) const const
void triggered(QAction *action)
void setBrush(const QBrush &brush)
int x() const const
QPoint center() const const
bool contains(const QSet< T > &other) const const
int width() const const
const QChar at(qsizetype position) const const
bool isEmpty() const const
qsizetype length() const const
void push_back(QChar ch)
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
void resize(qsizetype newSize, QChar fillChar)
qsizetype size() const const
PE_IndicatorArrowRight
void initFrom(const QWidget *widget)
AlignVCenter
CaseInsensitive
Key_Enter
NoModifier
LeftToRight
LeftButton
TextSingleLine
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void timeout()
QString path(ComponentFormattingOptions options) const const
void setPath(const QString &path, ParsingMode mode)
int toInt(bool *ok) const const
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.