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 if (m_subDirsMenu) {
324 m_subDirsMenu->deleteLater();
325 m_subDirsMenu = nullptr;
326 }
327 m_hoverArrow = false;
328 update();
329 }
330}
331
332void KUrlNavigatorButton::dragLeaveEvent(QDragLeaveEvent *event)
333{
334 KUrlNavigatorButtonBase::dragLeaveEvent(event);
335
336 m_hoverArrow = false;
337 setDisplayHintEnabled(DraggedHint, false);
338 update();
339}
340
341void KUrlNavigatorButton::mousePressEvent(QMouseEvent *event)
342{
343 if (isAboveArrow(qRound(event->position().x())) && (event->button() == Qt::LeftButton)) {
344 // the mouse is pressed above the [>] button
345 startSubDirsJob();
346 }
347 KUrlNavigatorButtonBase::mousePressEvent(event);
348}
349
350void KUrlNavigatorButton::mouseReleaseEvent(QMouseEvent *event)
351{
352 if (!isAboveArrow(qRound(event->position().x())) || (event->button() != Qt::LeftButton)) {
353 // the mouse has been released above the text area and not
354 // above the [>] button
355 Q_EMIT navigatorButtonActivated(m_url, event->button(), event->modifiers());
356 cancelSubDirsRequest();
357 }
358 KUrlNavigatorButtonBase::mouseReleaseEvent(event);
359}
360
361void KUrlNavigatorButton::mouseMoveEvent(QMouseEvent *event)
362{
363 KUrlNavigatorButtonBase::mouseMoveEvent(event);
364
365 const bool hoverArrow = isAboveArrow(qRound(event->position().x()));
366 if (hoverArrow != m_hoverArrow) {
367 m_hoverArrow = hoverArrow;
368 update();
369 }
370}
371
372void KUrlNavigatorButton::wheelEvent(QWheelEvent *event)
373{
374 if (event->angleDelta().y() != 0) {
375 m_wheelSteps = event->angleDelta().y() / 120;
376 m_replaceButton = true;
377 startSubDirsJob();
378 }
379
380 KUrlNavigatorButtonBase::wheelEvent(event);
381}
382
383void KUrlNavigatorButton::requestSubDirs()
384{
385 if (!m_openSubDirsTimer->isActive() && (m_subDirsJob == nullptr)) {
386 m_openSubDirsTimer->start();
387 }
388}
389
390void KUrlNavigatorButton::startSubDirsJob()
391{
392 if (m_subDirsJob != nullptr) {
393 return;
394 }
395
396 const QUrl url = m_replaceButton ? KIO::upUrl(m_url) : m_url;
397 const KUrlNavigator *urlNavigator = qobject_cast<KUrlNavigator *>(parent());
398 Q_ASSERT(urlNavigator);
399 m_subDirsJob =
401 m_subDirs.clear(); // just to be ++safe
402
403 connect(m_subDirsJob, &KIO::ListJob::entries, this, &KUrlNavigatorButton::addEntriesToSubDirs);
404
405 if (m_replaceButton) {
406 connect(m_subDirsJob, &KJob::result, this, &KUrlNavigatorButton::replaceButton);
407 } else {
408 connect(m_subDirsJob, &KJob::result, this, &KUrlNavigatorButton::openSubDirsMenu);
409 }
410}
411
412void KUrlNavigatorButton::addEntriesToSubDirs(KIO::Job *job, const KIO::UDSEntryList &entries)
413{
414 Q_ASSERT(job == m_subDirsJob);
415 Q_UNUSED(job);
416
417 for (const KIO::UDSEntry &entry : entries) {
418 if (entry.isDir()) {
419 const QString name = entry.stringValue(KIO::UDSEntry::UDS_NAME);
421 if (displayName.isEmpty()) {
423 }
424 if (name != QLatin1String(".") && name != QLatin1String("..")) {
425 m_subDirs.push_back({name, displayName});
426 }
427 }
428 }
429}
430
431void KUrlNavigatorButton::slotUrlsDropped(QAction *action, QDropEvent *event)
432{
433 const int result = action->data().toInt();
434 QUrl url(m_url);
435 url.setPath(Utils::concatPaths(url.path(), m_subDirs.at(result).name));
436 Q_EMIT urlsDroppedOnNavButton(url, event);
437}
438
439void KUrlNavigatorButton::slotMenuActionClicked(QAction *action, Qt::MouseButton button)
440{
441 const int result = action->data().toInt();
442 QUrl url(m_url);
443 url.setPath(Utils::concatPaths(url.path(), m_subDirs.at(result).name));
444 Q_EMIT navigatorButtonActivated(url, button, Qt::NoModifier);
445}
446
447void KUrlNavigatorButton::statFinished(KJob *job)
448{
449 if (m_pendingTextChange) {
450 m_pendingTextChange = false;
451
452 const KIO::UDSEntry entry = static_cast<KIO::StatJob *>(job)->statResult();
454 if (name.isEmpty()) {
455 name = m_url.fileName();
456 }
457 setText(name);
458
459 Q_EMIT finishedTextResolving();
460 }
461}
462
463/**
464 * Helper struct for sorting folder names
465 */
466struct FolderNameNaturalLessThan {
467 FolderNameNaturalLessThan(bool sortHiddenLast)
468 : m_sortHiddenLast(sortHiddenLast)
469 {
470 m_collator.setCaseSensitivity(Qt::CaseInsensitive);
471 m_collator.setNumericMode(true);
472 }
473
474 bool operator()(const KUrlNavigatorButton::SubDirInfo &a, const KUrlNavigatorButton::SubDirInfo &b)
475 {
476 if (m_sortHiddenLast) {
477 const bool isHiddenA = a.name.startsWith(QLatin1Char('.'));
478 const bool isHiddenB = b.name.startsWith(QLatin1Char('.'));
479 if (isHiddenA && !isHiddenB) {
480 return false;
481 }
482 if (!isHiddenA && isHiddenB) {
483 return true;
484 }
485 }
486 return m_collator.compare(a.name, b.name) < 0;
487 }
488
489private:
490 QCollator m_collator;
491 bool m_sortHiddenLast;
492};
493
494void KUrlNavigatorButton::openSubDirsMenu(KJob *job)
495{
496 Q_ASSERT(job == m_subDirsJob);
497 m_subDirsJob = nullptr;
498
499 if (job->error() || m_subDirs.empty()) {
500 // clear listing
501 return;
502 }
503
504 const KUrlNavigator *urlNavigator = qobject_cast<KUrlNavigator *>(parent());
505 Q_ASSERT(urlNavigator);
506 FolderNameNaturalLessThan less(urlNavigator->showHiddenFolders() && urlNavigator->sortHiddenFoldersLast());
507 std::sort(m_subDirs.begin(), m_subDirs.end(), less);
508 setDisplayHintEnabled(PopupActiveHint, true);
509 update(); // ensure the button is drawn highlighted
510
511 if (m_subDirsMenu != nullptr) {
512 m_subDirsMenu->close();
513 m_subDirsMenu->deleteLater();
514 m_subDirsMenu = nullptr;
515 }
516
517 m_subDirsMenu = new KUrlNavigatorMenu(this);
518 initMenu(m_subDirsMenu, 0);
519
520 const bool leftToRight = (layoutDirection() == Qt::LeftToRight);
521 const int popupX = leftToRight ? width() - arrowWidth() - BorderWidth : 0;
522 const QPoint popupPos = parentWidget()->mapToGlobal(geometry().bottomLeft() + QPoint(popupX, 0));
523
524 QPointer<QObject> guard(this);
525
526 m_subDirsMenu->exec(popupPos);
527
528 // If 'this' has been deleted in the menu's nested event loop, we have to return
529 // immediately because any access to a member variable might cause a crash.
530 if (!guard) {
531 return;
532 }
533
534 m_subDirs.clear();
535 delete m_subDirsMenu;
536 m_subDirsMenu = nullptr;
537
538 setDisplayHintEnabled(PopupActiveHint, false);
539}
540
541void KUrlNavigatorButton::replaceButton(KJob *job)
542{
543 Q_ASSERT(job == m_subDirsJob);
544 m_subDirsJob = nullptr;
545 m_replaceButton = false;
546
547 if (job->error() || m_subDirs.empty()) {
548 return;
549 }
550
551 const KUrlNavigator *urlNavigator = qobject_cast<KUrlNavigator *>(parent());
552 Q_ASSERT(urlNavigator);
553 FolderNameNaturalLessThan less(urlNavigator->showHiddenFolders() && urlNavigator->sortHiddenFoldersLast());
554 std::sort(m_subDirs.begin(), m_subDirs.end(), less);
555
556 // Get index of the directory that is shown currently in the button
557 const QString currentDir = m_url.fileName();
558 int currentIndex = 0;
559 const int subDirsCount = m_subDirs.size();
560 while (currentIndex < subDirsCount) {
561 if (m_subDirs[currentIndex].name == currentDir) {
562 break;
563 }
564 ++currentIndex;
565 }
566
567 // Adjust the index by respecting the wheel steps and
568 // trigger a replacing of the button content
569 int targetIndex = currentIndex - m_wheelSteps;
570 if (targetIndex < 0) {
571 targetIndex = 0;
572 } else if (targetIndex >= subDirsCount) {
573 targetIndex = subDirsCount - 1;
574 }
575
576 QUrl url(KIO::upUrl(m_url));
577 url.setPath(Utils::concatPaths(url.path(), m_subDirs[targetIndex].name));
578 Q_EMIT navigatorButtonActivated(url, Qt::LeftButton, Qt::NoModifier);
579
580 m_subDirs.clear();
581}
582
583void KUrlNavigatorButton::cancelSubDirsRequest()
584{
585 m_openSubDirsTimer->stop();
586 if (m_subDirsJob != nullptr) {
587 m_subDirsJob->kill();
588 m_subDirsJob = nullptr;
589 }
590}
591
592QString KUrlNavigatorButton::plainText() const
593{
594 // Replace all "&&" by '&' and remove all single
595 // '&' characters
596 const QString source = text();
597 const int sourceLength = source.length();
598
599 QString dest;
600 dest.resize(sourceLength);
601
602 int sourceIndex = 0;
603 int destIndex = 0;
604 while (sourceIndex < sourceLength) {
605 if (source.at(sourceIndex) == QLatin1Char('&')) {
606 ++sourceIndex;
607 if (sourceIndex >= sourceLength) {
608 break;
609 }
610 }
611 dest[destIndex] = source.at(sourceIndex);
612 ++sourceIndex;
613 ++destIndex;
614 }
615
616 dest.resize(destIndex);
617
618 return dest;
619}
620
621int KUrlNavigatorButton::arrowWidth() const
622{
623 // if there isn't arrow then return 0
624 int width = 0;
625 if (!m_subDir.isEmpty()) {
626 width = height() / 2;
627 if (width < 4) {
628 width = 4;
629 }
630 }
631
632 return width;
633}
634
635bool KUrlNavigatorButton::isAboveArrow(int x) const
636{
637 const bool leftToRight = (layoutDirection() == Qt::LeftToRight);
638 return leftToRight ? (x >= width() - arrowWidth()) : (x < arrowWidth());
639}
640
641bool KUrlNavigatorButton::isTextClipped() const
642{
643 int availableWidth = width() - 2 * BorderWidth;
644 if (!m_subDir.isEmpty()) {
645 availableWidth -= arrowWidth() - BorderWidth;
646 }
647
648 QFont adjustedFont(font());
649 adjustedFont.setBold(m_subDir.isEmpty());
650 return QFontMetrics(adjustedFont).size(Qt::TextSingleLine, plainText()).width() >= availableWidth;
651}
652
653void KUrlNavigatorButton::updateMinimumWidth()
654{
655 const int oldMinWidth = minimumWidth();
656
657 int minWidth = sizeHint().width();
658 if (minWidth < 40) {
659 minWidth = 40;
660 } else if (minWidth > 150) {
661 // don't let an overlong path name waste all the URL navigator space
662 minWidth = 150;
663 }
664 if (oldMinWidth != minWidth) {
665 setMinimumWidth(minWidth);
666 }
667}
668
669void KUrlNavigatorButton::initMenu(KUrlNavigatorMenu *menu, int startIndex)
670{
671 connect(menu, &KUrlNavigatorMenu::mouseButtonClicked, this, &KUrlNavigatorButton::slotMenuActionClicked);
672 connect(menu, &KUrlNavigatorMenu::urlsDropped, this, &KUrlNavigatorButton::slotUrlsDropped);
673
674 // So that triggering a menu item with the keyboard works
675 connect(menu, &QMenu::triggered, this, [this](QAction *act) {
676 slotMenuActionClicked(act, Qt::LeftButton);
677 });
678
679 menu->setLayoutDirection(Qt::LeftToRight);
680
681 const int maxIndex = startIndex + 30; // Don't show more than 30 items in a menu
682 const int subDirsSize = m_subDirs.size();
683 const int lastIndex = std::min(subDirsSize - 1, maxIndex);
684 for (int i = startIndex; i <= lastIndex; ++i) {
685 const auto &[subDirName, subDirDisplayName] = m_subDirs[i];
686 QString text = KStringHandler::csqueeze(subDirDisplayName, 60);
687 text.replace(QLatin1Char('&'), QLatin1String("&&"));
688 QAction *action = new QAction(text, this);
689 if (m_subDir == subDirName) {
690 QFont font(action->font());
691 font.setBold(true);
692 action->setFont(font);
693 }
694 action->setData(i);
695 menu->addAction(action);
696 }
697 if (subDirsSize > maxIndex) {
698 // If too much items are shown, move them into a sub menu
699 menu->addSeparator();
700 KUrlNavigatorMenu *subDirsMenu = new KUrlNavigatorMenu(menu);
701 subDirsMenu->setTitle(i18nc("@action:inmenu", "More"));
702 initMenu(subDirsMenu, maxIndex);
703 menu->addMenu(subDirsMenu);
704 }
705}
706
707} // namespace KDEPrivate
708
709#include "moc_kurlnavigatorbutton_p.cpp"
The base class for all jobs.
@ 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.
Universal Directory Service.
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)
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:238
@ HideProgressInfo
Hide progress information dialog, i.e. don't show a GUI.
Definition job_base.h:251
QString name(StandardAction 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
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 Sat Dec 21 2024 16:58:45 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.