KIO

kfileplacesitem.cpp
1/*
2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 2007 Kevin Ottens <ervin@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-only
6*/
7
8#include "kfileplacesitem_p.h"
9
10#include <QDateTime>
11#include <QDir>
12#include <QIcon>
13
14#include <KBookmarkManager>
15#include <KConfig>
16#include <KConfigGroup>
17#include <KIconUtils>
18#include <KLocalizedString>
19#include <KMountPoint>
20#include <kprotocolinfo.h>
21#include <solid/block.h>
22#include <solid/genericinterface.h>
23#include <solid/networkshare.h>
24#include <solid/opticaldisc.h>
25#include <solid/opticaldrive.h>
26#include <solid/portablemediaplayer.h>
27#include <solid/storageaccess.h>
28#include <solid/storagedrive.h>
29#include <solid/storagevolume.h>
30
31static bool isTrash(const KBookmark &bk)
32{
33 return bk.url().toString() == QLatin1String("trash:/");
34}
35
36KFilePlacesItem::KFilePlacesItem(KBookmarkManager *manager, const QString &address, const QString &udi, KFilePlacesModel *parent)
37 : QObject(static_cast<QObject *>(parent))
38 , m_manager(manager)
39 , m_folderIsEmpty(true)
40 , m_isCdrom(false)
41 , m_isAccessible(false)
42 , m_isTeardownAllowed(false)
43 , m_isTeardownOverlayRecommended(false)
44 , m_isTeardownInProgress(false)
45 , m_isSetupInProgress(false)
46 , m_isEjectInProgress(false)
47 , m_isReadOnly(false)
48{
49 updateDeviceInfo(udi);
50
51 setBookmark(m_manager->findByAddress(address));
52
53 if (udi.isEmpty() && m_bookmark.metaDataItem(QStringLiteral("ID")).isEmpty()) {
54 m_bookmark.setMetaDataItem(QStringLiteral("ID"), generateNewId());
55 } else if (udi.isEmpty()) {
56 if (isTrash(m_bookmark)) {
57 KConfig cfg(QStringLiteral("trashrc"), KConfig::SimpleConfig);
58 const KConfigGroup group = cfg.group(QStringLiteral("Status"));
59 m_folderIsEmpty = group.readEntry("Empty", true);
60 }
61 }
62
63 // Hide SSHFS network device mounted by kdeconnect, since we already have the kdeconnect:// place.
64 if (isDevice() && m_access && device().vendor() == QLatin1String("fuse.sshfs")) {
65 const QString storageFilePath = m_access->filePath();
66 // Not using findByPath() as it resolves symlinks, potentially blocking,
67 // but here we know we query for an existing actual mount point.
68 const auto mountPoints = KMountPoint::currentMountPoints();
69 auto it = std::find_if(mountPoints.cbegin(), mountPoints.cend(), [&storageFilePath](const KMountPoint::Ptr &mountPoint) {
70 return mountPoint->mountPoint() == storageFilePath;
71 });
72 if (it != mountPoints.cend()) {
73 if ((*it)->mountedFrom().startsWith(QLatin1String("kdeconnect@"))) {
74 // Hide only if the user never set the "Hide" checkbox on the device.
75 if (m_bookmark.metaDataItem(QStringLiteral("IsHidden")).isEmpty()) {
76 setHidden(true);
77 }
78 }
79 }
80 }
81}
82
83KFilePlacesItem::~KFilePlacesItem()
84{
85}
86
87QString KFilePlacesItem::id() const
88{
89 if (isDevice()) {
90 return bookmark().metaDataItem(QStringLiteral("UDI"));
91 } else {
92 return bookmark().metaDataItem(QStringLiteral("ID"));
93 }
94}
95
96bool KFilePlacesItem::hasSupportedScheme(const QStringList &schemes) const
97{
98 if (schemes.isEmpty()) {
99 return true;
100 }
101
102 // StorageAccess is always local, doesn't need to be accessible to know this
103 if (m_access && schemes.contains(QLatin1String("file"))) {
104 return true;
105 }
106
107 if (m_networkShare && schemes.contains(m_networkShare->url().scheme())) {
108 return true;
109 }
110
111 if (m_player) {
112 const QStringList protocols = m_player->supportedProtocols();
113 for (const QString &protocol : protocols) {
114 if (schemes.contains(protocol)) {
115 return true;
116 }
117 }
118 }
119
120 return false;
121}
122
123bool KFilePlacesItem::isDevice() const
124{
125 return !bookmark().metaDataItem(QStringLiteral("UDI")).isEmpty();
126}
127
128KFilePlacesModel::DeviceAccessibility KFilePlacesItem::deviceAccessibility() const
129{
130 if (m_isTeardownInProgress || m_isEjectInProgress) {
131 return KFilePlacesModel::TeardownInProgress;
132 } else if (m_isSetupInProgress) {
133 return KFilePlacesModel::SetupInProgress;
134 } else if (m_isAccessible) {
135 return KFilePlacesModel::Accessible;
136 } else {
137 return KFilePlacesModel::SetupNeeded;
138 }
139}
140
141bool KFilePlacesItem::isTeardownAllowed() const
142{
143 return m_isTeardownAllowed;
144}
145
146bool KFilePlacesItem::isTeardownOverlayRecommended() const
147{
148 return m_isTeardownOverlayRecommended;
149}
150
151bool KFilePlacesItem::isEjectAllowed() const
152{
153 return m_isCdrom;
154}
155
156KBookmark KFilePlacesItem::bookmark() const
157{
158 return m_bookmark;
159}
160
161void KFilePlacesItem::setBookmark(const KBookmark &bookmark)
162{
163 m_bookmark = bookmark;
164
165 if (m_device.isValid()) {
166 m_bookmark.setMetaDataItem(QStringLiteral("UDI"), m_device.udi());
167 if (m_volume && !m_volume->uuid().isEmpty()) {
168 m_bookmark.setMetaDataItem(QStringLiteral("uuid"), m_volume->uuid());
169 }
170 }
171
172 if (bookmark.metaDataItem(QStringLiteral("isSystemItem")) == QLatin1String("true")) {
173 // This context must stay as it is - the translated system bookmark names
174 // are created with 'KFile System Bookmarks' as their context, so this
175 // ensures the right string is picked from the catalog.
176 // (coles, 13th May 2009)
177
178 m_text = i18nc("KFile System Bookmarks", bookmark.text().toUtf8().data());
179 } else {
180 m_text = bookmark.text();
181 }
182
183 if (!isDevice()) {
184 const QString protocol = bookmark.url().scheme();
185 if (protocol == QLatin1String("timeline") || protocol == QLatin1String("recentlyused")) {
187 } else if (protocol.contains(QLatin1String("search"))) {
189 } else if (protocol == QLatin1String("bluetooth") || protocol == QLatin1String("obexftp") || protocol == QLatin1String("kdeconnect")) {
190 m_groupType = KFilePlacesModel::DevicesType;
191 } else if (protocol == QLatin1String("tags")) {
192 m_groupType = KFilePlacesModel::TagsType;
193 } else if (protocol == QLatin1String("remote") || KProtocolInfo::protocolClass(protocol) != QLatin1String(":local")) {
194 m_groupType = KFilePlacesModel::RemoteType;
195 } else {
196 m_groupType = KFilePlacesModel::PlacesType;
197 }
198 } else {
199 if (m_drive && (m_drive->isHotpluggable() || m_drive->isRemovable())) {
201 } else if (m_networkShare) {
202 m_groupType = KFilePlacesModel::RemoteType;
203 } else {
204 m_groupType = KFilePlacesModel::DevicesType;
205 }
206 }
207
208 switch (m_groupType) {
210 m_groupName = i18nc("@item", "Places");
211 break;
213 m_groupName = i18nc("@item", "Remote");
214 break;
216 m_groupName = i18nc("@item The place group section name for recent dynamic lists", "Recent");
217 break;
219 m_groupName = i18nc("@item", "Search For");
220 break;
222 m_groupName = i18nc("@item", "Devices");
223 break;
225 m_groupName = i18nc("@item", "Removable Devices");
226 break;
228 m_groupName = i18nc("@item", "Tags");
229 break;
231 Q_UNREACHABLE();
232 break;
233 }
234}
235
236Solid::Device KFilePlacesItem::device() const
237{
238 return m_device;
239}
240
241QVariant KFilePlacesItem::data(int role) const
242{
243 if (role == KFilePlacesModel::GroupRole) {
244 return QVariant(m_groupName);
245 } else if (role != KFilePlacesModel::HiddenRole && role != Qt::BackgroundRole && isDevice()) {
246 return deviceData(role);
247 } else {
248 return bookmarkData(role);
249 }
250}
251
252KFilePlacesModel::GroupType KFilePlacesItem::groupType() const
253{
254 return m_groupType;
255}
256
257bool KFilePlacesItem::isHidden() const
258{
259 return m_bookmark.metaDataItem(QStringLiteral("IsHidden")) == QLatin1String("true");
260}
261
262void KFilePlacesItem::setHidden(bool hide)
263{
264 if (m_bookmark.isNull() || isHidden() == hide) {
265 return;
266 }
267 m_bookmark.setMetaDataItem(QStringLiteral("IsHidden"), hide ? QStringLiteral("true") : QStringLiteral("false"));
268}
269
270QVariant KFilePlacesItem::bookmarkData(int role) const
271{
272 KBookmark b = bookmark();
273
274 if (b.isNull()) {
275 return QVariant();
276 }
277
278 switch (role) {
279 case Qt::DisplayRole:
280 return m_text;
282 return QIcon::fromTheme(iconNameForBookmark(b));
283 case Qt::ToolTipRole: {
284 const KFilePlacesModel::GroupType type = groupType();
285 // Don't display technical gibberish in the URL, particularly search.
288 }
289 return QString();
290 }
292 if (isHidden()) {
293 return QColor(Qt::lightGray);
294 } else {
295 return QVariant();
296 }
298 return b.url();
300 return false;
302 return isHidden();
304 return iconNameForBookmark(b);
305 default:
306 return QVariant();
307 }
308}
309
310QVariant KFilePlacesItem::deviceData(int role) const
311{
312 Solid::Device d = device();
313
314 if (d.isValid()) {
315 switch (role) {
316 case Qt::DisplayRole:
317 if (m_deviceDisplayName.isEmpty()) {
318 m_deviceDisplayName = d.displayName();
319 }
320 return m_deviceDisplayName;
322 // qDebug() << "adding emblems" << m_emblems << "to device icon" << m_deviceIconName;
323 return KIconUtils::addOverlays(m_deviceIconName, m_emblems);
324 case Qt::ToolTipRole: {
325 if (m_access && m_isAccessible) {
326 // For loop devices, show backing file path rather than /dev/loop123.
327 QString mountedFrom = m_backingFile;
328 if (mountedFrom.isEmpty() && m_block) {
329 mountedFrom = m_block->device();
330 }
331
332 if (!mountedFrom.isEmpty()) {
333 return i18nc("@info:tooltip path (mounted from)", "%1 (from %2)", m_access->filePath(), mountedFrom);
334 }
335 } else if (!m_backingFile.isEmpty()) {
336 return m_backingFile;
337 } else if (m_block) {
338 return m_block->device();
339 }
340 return QString();
341 }
343 if (m_access) {
344 const QString path = m_access->filePath();
345 return path.isEmpty() ? QUrl() : QUrl::fromLocalFile(path);
346 } else if (m_disc && (m_disc->availableContent() & Solid::OpticalDisc::Audio) != 0) {
347 Solid::Block *block = d.as<Solid::Block>();
348 if (block) {
349 QString device = block->device();
350 return QUrl(QStringLiteral("audiocd:/?device=%1").arg(device));
351 }
352 // We failed to get the block device. Assume audiocd:/ can
353 // figure it out, but cannot handle multiple disc drives.
354 // See https://bugs.kde.org/show_bug.cgi?id=314544#c40
355 return QUrl(QStringLiteral("audiocd:/"));
356 } else if (m_player) {
357 const QStringList protocols = m_player->supportedProtocols();
358 if (!protocols.isEmpty()) {
359 const QString protocol = protocols.first();
360 if (protocol == QLatin1String("mtp")) {
361 return QUrl(QStringLiteral("%1:udi=%2").arg(protocol, d.udi()));
362 } else {
363 QUrl url;
364 url.setScheme(protocol);
365 url.setHost(d.udi().section(QLatin1Char('/'), -1));
366 url.setPath(QStringLiteral("/"));
367 return url;
368 }
369 }
370 return QVariant();
371 } else {
372 return QVariant();
373 }
375 if (m_access) {
376 return !m_isAccessible;
377 } else {
378 return QVariant();
379 }
380
382 if (m_access) {
383 return m_isTeardownAllowed;
384 } else {
385 return QVariant();
386 }
387
389 return m_isAccessible && m_isCdrom;
390
392 return m_isTeardownOverlayRecommended;
393
395 return deviceAccessibility();
396
398 if (m_drive != nullptr) {
399 return !m_drive->isHotpluggable() && !m_drive->isRemovable();
400 }
401 return true;
402 }
403
405 return m_isAccessible && !m_isCdrom && !m_networkShare && !m_isReadOnly;
406
408 return m_deviceIconName;
409
410 default:
411 return QVariant();
412 }
413 } else {
414 return QVariant();
415 }
416}
417
418KBookmark KFilePlacesItem::createBookmark(KBookmarkManager *manager, const QString &label, const QUrl &url, const QString &iconName, KFilePlacesItem *after)
419{
420 KBookmarkGroup root = manager->root();
421 if (root.isNull()) {
422 return KBookmark();
423 }
424 QString empty_icon = iconName;
425 if (url.toString() == QLatin1String("trash:/")) {
426 if (empty_icon.endsWith(QLatin1String("-full"))) {
427 empty_icon.chop(5);
428 } else if (empty_icon.isEmpty()) {
429 empty_icon = QStringLiteral("user-trash");
430 }
431 }
432 KBookmark bookmark = root.addBookmark(label, url, empty_icon);
433 bookmark.setMetaDataItem(QStringLiteral("ID"), generateNewId());
434
435 if (after) {
436 root.moveBookmark(bookmark, after->bookmark());
437 }
438
439 return bookmark;
440}
441
442KBookmark KFilePlacesItem::createSystemBookmark(KBookmarkManager *manager,
443 const char *untranslatedLabel,
444 const QUrl &url,
445 const QString &iconName,
446 const KBookmark &after)
447{
448 KBookmark bookmark = createBookmark(manager, QString::fromUtf8(untranslatedLabel), url, iconName);
449 if (!bookmark.isNull()) {
450 bookmark.setMetaDataItem(QStringLiteral("isSystemItem"), QStringLiteral("true"));
451 }
452 if (!after.isNull()) {
453 manager->root().moveBookmark(bookmark, after);
454 }
455 return bookmark;
456}
457
458KBookmark KFilePlacesItem::createDeviceBookmark(KBookmarkManager *manager, const Solid::Device &device)
459{
460 KBookmarkGroup root = manager->root();
461 if (root.isNull()) {
462 return KBookmark();
463 }
464 KBookmark bookmark = root.createNewSeparator();
465 bookmark.setMetaDataItem(QStringLiteral("UDI"), device.udi());
466 bookmark.setMetaDataItem(QStringLiteral("isSystemItem"), QStringLiteral("true"));
467
468 const auto storage = device.as<Solid::StorageVolume>();
469 if (storage) {
470 bookmark.setMetaDataItem(QStringLiteral("uuid"), storage->uuid());
471 }
472 return bookmark;
473}
474
475KBookmark KFilePlacesItem::createTagBookmark(KBookmarkManager *manager, const QString &tag)
476{
477 // TODO: Currently KFilePlacesItem::setBookmark() only decides by the "isSystemItem" property
478 // if the label text should be looked up for translation. So there is a small risk that
479 // labelTexts which match existing untranslated system labels accidentally get translated.
480 KBookmark bookmark = createBookmark(manager, tag, QUrl(QLatin1String("tags:/") + tag), QStringLiteral("tag"));
481 if (!bookmark.isNull()) {
482 bookmark.setMetaDataItem(QStringLiteral("tag"), tag);
483 bookmark.setMetaDataItem(QStringLiteral("isSystemItem"), QStringLiteral("true"));
484 }
485
486 return bookmark;
487}
488
489QString KFilePlacesItem::generateNewId()
490{
491 static int count = 0;
492
493 // return QString::number(count++);
494
496
497 // return QString::number(QDateTime::currentSecsSinceEpoch())
498 // + '/' + QString::number(qrand());
499}
500
501bool KFilePlacesItem::updateDeviceInfo(const QString &udi)
502{
503 if (m_device.udi() == udi) {
504 return false;
505 }
506
507 if (m_access) {
508 m_access->disconnect(this);
509 }
510
511 if (m_opticalDrive) {
512 m_opticalDrive->disconnect(this);
513 }
514
515 m_device = Solid::Device(udi);
516 if (m_device.isValid()) {
517 m_access = m_device.as<Solid::StorageAccess>();
518 m_volume = m_device.as<Solid::StorageVolume>();
519 m_block = m_device.as<Solid::Block>();
520 m_disc = m_device.as<Solid::OpticalDisc>();
521 m_player = m_device.as<Solid::PortableMediaPlayer>();
522 m_networkShare = m_device.as<Solid::NetworkShare>();
523 m_deviceIconName = m_device.icon();
524 m_emblems = m_device.emblems();
525
526 if (auto *genericIface = m_device.as<Solid::GenericInterface>()) {
527 m_backingFile = genericIface->property(QStringLiteral("BackingFile")).toString();
528 }
529
530 m_drive = nullptr;
531 m_opticalDrive = nullptr;
532
533 Solid::Device parentDevice = m_device;
534 while (parentDevice.isValid() && !m_drive) {
535 m_drive = parentDevice.as<Solid::StorageDrive>();
536 m_opticalDrive = parentDevice.as<Solid::OpticalDrive>();
537 parentDevice = parentDevice.parent();
538 }
539
540 if (m_access) {
541 connect(m_access.data(), &Solid::StorageAccess::setupRequested, this, [this] {
542 m_isSetupInProgress = true;
543 Q_EMIT itemChanged(id(), {KFilePlacesModel::DeviceAccessibilityRole});
544 });
545 connect(m_access.data(), &Solid::StorageAccess::setupDone, this, [this] {
546 m_isSetupInProgress = false;
547 Q_EMIT itemChanged(id(), {KFilePlacesModel::DeviceAccessibilityRole});
548 });
549
550 connect(m_access.data(), &Solid::StorageAccess::teardownRequested, this, [this] {
551 m_isTeardownInProgress = true;
552 Q_EMIT itemChanged(id(), {KFilePlacesModel::DeviceAccessibilityRole});
553 });
554 connect(m_access.data(), &Solid::StorageAccess::teardownDone, this, [this] {
555 m_isTeardownInProgress = false;
556 Q_EMIT itemChanged(id(), {KFilePlacesModel::DeviceAccessibilityRole});
557 });
558
559 connect(m_access.data(), &Solid::StorageAccess::accessibilityChanged, this, &KFilePlacesItem::onAccessibilityChanged);
560 onAccessibilityChanged(m_access->isAccessible());
561 }
562
563 if (m_opticalDrive) {
564 connect(m_opticalDrive.data(), &Solid::OpticalDrive::ejectRequested, this, [this] {
565 m_isEjectInProgress = true;
566 Q_EMIT itemChanged(id(), {KFilePlacesModel::DeviceAccessibilityRole});
567 });
568 connect(m_opticalDrive.data(), &Solid::OpticalDrive::ejectDone, this, [this] {
569 m_isEjectInProgress = false;
570 Q_EMIT itemChanged(id(), {KFilePlacesModel::DeviceAccessibilityRole});
571 });
572 }
573 } else {
574 m_access = nullptr;
575 m_volume = nullptr;
576 m_disc = nullptr;
577 m_player = nullptr;
578 m_drive = nullptr;
579 m_opticalDrive = nullptr;
580 m_networkShare = nullptr;
581 m_deviceIconName.clear();
582 m_emblems.clear();
583 }
584
585 return true;
586}
587
588void KFilePlacesItem::onAccessibilityChanged(bool isAccessible)
589{
590 m_isAccessible = isAccessible;
591 m_isCdrom = m_device.is<Solid::OpticalDrive>() || m_opticalDrive || (m_volume && m_volume->fsType() == QLatin1String("iso9660"));
592 m_emblems = m_device.emblems();
593
594 if (auto generic = m_device.as<Solid::GenericInterface>()) {
595 // TODO add Solid API for this.
596 m_isReadOnly = generic->property(QStringLiteral("ReadOnly")).toBool();
597 }
598
599 m_isTeardownAllowed = isAccessible;
600 if (m_isTeardownAllowed) {
601 if (m_access->filePath() == QDir::rootPath()) {
602 m_isTeardownAllowed = false;
603 } else {
604 const auto homeDevice = Solid::Device::storageAccessFromPath(QDir::homePath());
605 const auto *homeAccess = homeDevice.as<Solid::StorageAccess>();
606 if (homeAccess && m_access->filePath() == homeAccess->filePath()) {
607 m_isTeardownAllowed = false;
608 }
609 }
610 }
611
612 m_isTeardownOverlayRecommended = m_isTeardownAllowed && !m_networkShare;
613 if (m_isTeardownOverlayRecommended) {
614 if (m_drive && !m_drive->isHotpluggable() && !m_drive->isRemovable()) {
615 m_isTeardownOverlayRecommended = false;
616 }
617 }
618
619 Q_EMIT itemChanged(id());
620}
621
622QString KFilePlacesItem::iconNameForBookmark(const KBookmark &bookmark) const
623{
624 if (!m_folderIsEmpty && isTrash(bookmark)) {
625 return bookmark.icon() + QLatin1String("-full");
626 } else {
627 return bookmark.icon();
628 }
629}
630
631#include "moc_kfileplacesitem_p.cpp"
bool moveBookmark(const KBookmark &bookmark, const KBookmark &after)
KBookmark createNewSeparator()
KBookmark addBookmark(const KBookmark &bm)
KBookmarkGroup root() const
QString text() const
QString icon() const
void setMetaDataItem(const QString &key, const QString &value, MetaDataOverwriteMode mode=OverwriteMetaData)
bool isNull() const
QUrl url() const
QString metaDataItem(const QString &key) const
KConfigGroup group(const QString &group)
QString readEntry(const char *key, const char *aDefault=nullptr) const
This class is a list view model.
GroupType
Describes the available group types used in this model.
@ PlacesType
"Places" section
@ RemoteType
"Remote" section
@ RemovableDevicesType
"Removable Devices" section
@ RecentlySavedType
"Recent" section
@ DevicesType
"Devices" section
@ UnknownType
Unknown GroupType.
@ TagsType
"Tags" section.
@ SearchForType
"Search for" section
@ EjectAllowedRole
roleName is "isEjectAllowed".
@ GroupRole
The name of the group, for example "Remote" or "Devices".
@ IconNameRole
roleName is "iconName".
@ HiddenRole
roleName is "isHidden".
@ TeardownOverlayRecommendedRole
roleName is "isTeardownOverlayRecommended".
@ CapacityBarRecommendedRole
Whether the place should have its free space displayed in a capacity bar.
@ FixedDeviceRole
Whether the place is a fixed device (neither hotpluggable nor removable).
@ SetupNeededRole
roleName is "isSetupNeeded".
@ TeardownAllowedRole
roleName is "isTeardownAllowed".
@ DeviceAccessibilityRole
roleName is "deviceAccessibility".
@ UrlRole
roleName is "url".
static List currentMountPoints(DetailsNeededFlags infoNeeded=BasicInfoNeeded)
Returns a list of all current mountpoints.
static QString protocolClass(const QString &protocol)
Returns the protocol class for the specified protocol.
QString device() const
QString udi() const
QString displayName() const
static Device storageAccessFromPath(const QString &path)
bool isValid() const
DevIface * as()
void ejectDone(Solid::ErrorType error, QVariant errorData, const QString &udi)
void ejectRequested(const QString &udi)
void setupRequested(const QString &udi)
void accessibilityChanged(bool accessible, const QString &udi)
void teardownRequested(const QString &udi)
void teardownDone(Solid::ErrorType error, QVariant errorData, const QString &udi)
void setupDone(Solid::ErrorType error, QVariant errorData, const QString &udi)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
Type type(const QSqlDatabase &db)
QIcon addOverlays(const QIcon &icon, const QHash< Qt::Corner, QIcon > &overlays)
QString path(const QString &relativePath)
char * data()
qint64 currentSecsSinceEpoch()
QString homePath()
QString rootPath()
QIcon fromTheme(const QString &name)
T & first()
bool isEmpty() const const
QObject * parent() const const
void chop(qsizetype n)
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
QString fromUtf8(QByteArrayView str)
bool isEmpty() const const
QString number(double n, char format, int precision)
QString section(QChar sep, qsizetype start, qsizetype end, SectionFlags flags) const const
QByteArray toUtf8() const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
lightGray
BackgroundRole
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
PreferLocalFile
QString scheme() const const
void setHost(const QString &host, 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
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:16:28 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.