8#include "freebusymanager.h"
9#include "calendarsettings.h"
10#include "freebusydownloadjob_p.h"
11#include "freebusymanager_p.h"
12#include "mailscheduler_p.h"
13#include "publishdialog.h"
16#include <Akonadi/AgentInstance>
17#include <Akonadi/AgentManager>
18#include <Akonadi/ContactSearchJob>
20#include <KCalendarCore/Event>
21#include <KCalendarCore/FreeBusy>
22#include <KCalendarCore/Person>
24#include "akonadicalendar_debug.h"
27#include <KIO/FileCopyJob>
29#include <KIO/TransferJob>
30#include <KLocalizedString>
36#include <QRegularExpression>
37#include <QStandardPaths>
38#include <QTemporaryFile>
55 emailName = email.
left(atPos);
56 emailHost = email.
mid(atPos + 1);
65 retUrl.setPath(saveStr);
75 , mUrlsToCheck(urlsToCheck)
79void FbCheckerJob::start()
84void FbCheckerJob::checkNextUrl()
86 if (mUrlsToCheck.isEmpty()) {
87 qCDebug(AKONADICALENDAR_LOG) <<
"No fb file found";
88 setError(KJob::UserDefinedError);
92 const QUrl url = mUrlsToCheck.takeFirst();
105void FbCheckerJob::onGetJobFinished(
KJob *job)
108 if (mData.contains(
"BEGIN:VCALENDAR")) {
109 qCDebug(AKONADICALENDAR_LOG) <<
"found freebusy";
110 mValidUrl = transferJob->
url();
117QUrl FbCheckerJob::validUrl()
const
124FreeBusyManagerPrivate::FreeBusyProviderRequest::FreeBusyProviderRequest(
const QString &provider)
125 : mRequestStatus(NotStarted)
126 , mInterface(nullptr)
129 QStringLiteral(
"/FreeBusyProvider"),
130 QStringLiteral(
"org.freedesktop.Akonadi.Resource.FreeBusyProvider")));
135FreeBusyManagerPrivate::FreeBusyProvidersRequestsQueue::FreeBusyProvidersRequestsQueue()
136 : mResultingFreeBusy(nullptr)
140 mEndTime = mStartTime.addDays(14);
144FreeBusyManagerPrivate::FreeBusyProvidersRequestsQueue::FreeBusyProvidersRequestsQueue(
const QDateTime &
start,
const QDateTime &end)
145 : mResultingFreeBusy(nullptr)
154FreeBusyManagerPrivate::FreeBusyManagerPrivate(FreeBusyManager *q)
157 , mParentWidgetForRetrieval(nullptr)
159 connect(
this, &FreeBusyManagerPrivate::freeBusyUrlRetrieved,
this, &FreeBusyManagerPrivate::finishProcessRetrieveQueue);
162QString FreeBusyManagerPrivate::freeBusyDir()
const
167void FreeBusyManagerPrivate::checkFreeBusyUrl()
169 const QUrl targetURL(CalendarSettings::self()->freeBusyPublishUrl());
170 mBrokenUrl = targetURL.isEmpty() || !targetURL.isValid();
179void FreeBusyManagerPrivate::fetchFreeBusyUrl(
const QString &email)
186 qCDebug(AKONADICALENDAR_LOG) <<
"Found cached url:" << url;
188 if (Akonadi::CalendarUtils::thatIsMe(email)) {
189 cachedUrl.setUserName(CalendarSettings::self()->freeBusyRetrieveUser());
190 cachedUrl.setPassword(CalendarSettings::self()->freeBusyRetrievePassword());
192 Q_EMIT freeBusyUrlRetrieved(email, replaceVariablesUrl(cachedUrl, email));
203void FreeBusyManagerPrivate::contactSearchJobFinished(
KJob *_job)
208 qCritical() <<
"Error while searching for contact: " << _job->
errorString() <<
", email = " << email;
209 Q_EMIT freeBusyUrlRetrieved(email,
QUrl());
213 auto job = qobject_cast<Akonadi::ContactSearchJob *>(_job);
220 const QString pref = contact.preferredEmail();
221 if (!pref.
isEmpty() && pref != email) {
222 group = cfg.
group(pref);
224 qCDebug(AKONADICALENDAR_LOG) <<
"Preferred email of" << email <<
"is" << pref;
226 qCDebug(AKONADICALENDAR_LOG) <<
"Taken url from preferred email:" << url;
227 Q_EMIT freeBusyUrlRetrieved(email, replaceVariablesUrl(
QUrl(url), email));
233 if (!CalendarSettings::self()->freeBusyRetrieveAuto()) {
235 qCDebug(AKONADICALENDAR_LOG) <<
"No automatic retrieving";
236 Q_EMIT freeBusyUrlRetrieved(email,
QUrl());
243 if (emailpos == -1) {
244 qCWarning(AKONADICALENDAR_LOG) <<
"No '@' found in" << email;
245 Q_EMIT freeBusyUrlRetrieved(email,
QUrl());
249 const QString emailHost = email.
mid(emailpos + 1);
252 if (CalendarSettings::self()->freeBusyCheckHostname()) {
255 const QString hostDomain =
QUrl(CalendarSettings::self()->freeBusyRetrieveUrl()).
host();
258 qCDebug(AKONADICALENDAR_LOG) <<
"Host '" << hostDomain <<
"' doesn't match email '" << email <<
'\'';
259 Q_EMIT freeBusyUrlRetrieved(email,
QUrl());
264 if (CalendarSettings::self()->freeBusyRetrieveUrl().contains(
QRegularExpression(QStringLiteral(
"\\.[xiv]fb$")))) {
267 const QUrl sourceUrl(CalendarSettings::self()->freeBusyRetrieveUrl());
268 QUrl fullpathURL = replaceVariablesUrl(sourceUrl, email);
271 fullpathURL.
setUserName(CalendarSettings::self()->freeBusyRetrieveUser());
272 fullpathURL.
setPassword(CalendarSettings::self()->freeBusyRetrievePassword());
276 qCDebug(AKONADICALENDAR_LOG) <<
"Found url. email=" << email <<
"; url=" << fullpathURL;
277 Q_EMIT freeBusyUrlRetrieved(email, fullpathURL);
284 extensions << QStringLiteral(
"xfb");
285 extensions << QStringLiteral(
"ifb");
286 extensions << QStringLiteral(
"vfb");
292 for (ext = extensions.
constBegin(); ext != extEnd; ++ext) {
294 const QUrl sourceUrl =
QUrl(CalendarSettings::self()->freeBusyRetrieveUrl());
295 QUrl dirURL = replaceVariablesUrl(sourceUrl, email);
296 if (CalendarSettings::self()->freeBusyFullDomainRetrieval()) {
305 dirURL.
setUserName(CalendarSettings::self()->freeBusyRetrieveUser());
306 dirURL.
setPassword(CalendarSettings::self()->freeBusyRetrievePassword());
307 urlsToCheck << dirURL;
309 KJob *checkerJob =
new FbCheckerJob(urlsToCheck,
this);
315void FreeBusyManagerPrivate::fbCheckerJobFinished(
KJob *job)
319 auto checkerJob =
static_cast<FbCheckerJob *
>(job);
320 const QUrl dirURL = checkerJob->validUrl();
326 qCDebug(AKONADICALENDAR_LOG) <<
"Found url email=" << email <<
"; url=" << dirURL;
328 Q_EMIT freeBusyUrlRetrieved(email, dirURL);
330 qCDebug(AKONADICALENDAR_LOG) <<
"Returning invalid url";
331 Q_EMIT freeBusyUrlRetrieved(email,
QUrl());
346 qCDebug(AKONADICALENDAR_LOG) <<
"Error parsing free/busy";
347 qCDebug(AKONADICALENDAR_LOG) << freeBusyVCal;
356 const QDateTime end =
start.addDays(CalendarSettings::self()->freeBusyPublishDays());
360 freebusy->setOrganizer(
KCalendarCore::Person(Akonadi::CalendarUtils::fullName(), Akonadi::CalendarUtils::email()));
364QString FreeBusyManagerPrivate::ownerFreeBusyAsString()
366 return freeBusyToIcal(ownerFreeBusy());
369void FreeBusyManagerPrivate::processFreeBusyDownloadResult(
KJob *_job)
371 Q_Q(FreeBusyManager);
373 auto job = qobject_cast<FreeBusyDownloadJob *>(_job);
376 qCritical() <<
"Error downloading freebusy" << _job->
errorString();
378 i18n(
"Failed to download free/busy data from: %1\nReason: %2", job->url().toDisplayString(), job->
errorText()),
379 i18nc(
"@title:window",
"Free/Busy Retrieval Error"));
384 mFreeBusyUrlEmailMap.take(job->url());
388 Q_ASSERT(mFreeBusyUrlEmailMap.contains(job->url()));
389 const QString email = mFreeBusyUrlEmailMap.take(job->url());
395 q->saveFreeBusy(fb, p);
396 qCDebug(AKONADICALENDAR_LOG) <<
"Freebusy retrieved for " << email;
397 Q_EMIT q->freeBusyRetrieved(fb, email);
399 qCritical() <<
"Error downloading freebusy, invalid fb.";
401 i18n(
"Failed to parse free/busy information that was retrieved from: %1", job->url().toDisplayString()),
402 i18nc(
"@title:window",
"Free/Busy Retrieval Error"));
408 processRetrieveQueue();
411void FreeBusyManagerPrivate::processFreeBusyUploadResult(
KJob *_job)
416 i18n(
"<qt><p>The software could not upload your free/busy list to "
417 "the URL '%1'. There might be a problem with the access "
418 "rights, or you specified an incorrect URL. The system said: "
420 "<p>Please check the URL or contact your system administrator."
422 job->destUrl().toString(),
426 QUrl src = job->srcUrl();
431 mUploadingFreeBusy =
false;
434void FreeBusyManagerPrivate::processRetrieveQueue()
436 if (mRetrieveQueue.isEmpty()) {
440 const QString email = mRetrieveQueue.takeFirst();
444 qCDebug(AKONADICALENDAR_LOG) <<
"Got the following FreeBusy providers: " <<
providers;
449 queryFreeBusyProviders(providers, email);
451 fetchFreeBusyUrl(email);
455void FreeBusyManagerPrivate::finishProcessRetrieveQueue(
const QString &email,
const QUrl &freeBusyUrlForEmail)
457 Q_Q(FreeBusyManager);
459 if (!freeBusyUrlForEmail.
isValid()) {
460 qCDebug(AKONADICALENDAR_LOG) <<
"Invalid FreeBusy URL" << freeBusyUrlForEmail.
toDisplayString() << email;
464 if (mFreeBusyUrlEmailMap.contains(freeBusyUrlForEmail)) {
465 qCDebug(AKONADICALENDAR_LOG) <<
"Download already in progress for " << freeBusyUrlForEmail;
469 mFreeBusyUrlEmailMap.insert(freeBusyUrlForEmail, email);
471 auto job =
new FreeBusyDownloadJob(freeBusyUrlForEmail, mParentWidgetForRetrieval);
472 q->connect(job, &FreeBusyDownloadJob::result,
this, [
this](
KJob *job) {
473 processFreeBusyDownloadResult(job);
478void FreeBusyManagerPrivate::uploadFreeBusy()
480 Q_Q(FreeBusyManager);
483 if (!CalendarSettings::self()->freeBusyPublishAuto() || CalendarSettings::self()->freeBusyPublishUrl().isEmpty()) {
494 int eta =
static_cast<int>(mNextUploadTime.toSecsSinceEpoch()) - now;
496 if (!mUploadingFreeBusy) {
498 if (mNextUploadTime.isNull() || currentDateTime > mNextUploadTime) {
500 q->publishFreeBusy();
507 q->publishFreeBusy();
513 qCDebug(AKONADICALENDAR_LOG) <<
"This shouldn't happen! eta <= 0";
519 mTimerID = q->startTimer(eta * 1000);
523 q->publishFreeBusy();
527QStringList FreeBusyManagerPrivate::getFreeBusyProviders()
const
532 if (agent.type().capabilities().contains(
QLatin1StringView(
"FreeBusyProvider"))) {
539void FreeBusyManagerPrivate::queryFreeBusyProviders(
const QStringList &providers,
const QString &email)
541 if (!mProvidersRequestsByEmail.contains(email)) {
542 mProvidersRequestsByEmail[email] = FreeBusyProvidersRequestsQueue();
546 FreeBusyProviderRequest request(provider);
549 connect(request.mInterface.data(), SIGNAL(handlesFreeBusy(
QString,
bool)),
this, SLOT(onHandlesFreeBusy(
QString,
bool)));
551 request.mInterface->call(QStringLiteral(
"canHandleFreeBusy"), email);
552 request.mRequestStatus = FreeBusyProviderRequest::HandlingRequested;
553 mProvidersRequestsByEmail[email].mRequests << request;
559 if (!mProvidersRequestsByEmail.contains(email)) {
560 mProvidersRequestsByEmail[email] = FreeBusyProvidersRequestsQueue(
start, end);
563 queryFreeBusyProviders(providers, email);
566void FreeBusyManagerPrivate::onHandlesFreeBusy(
const QString &email,
bool handles)
568 if (!mProvidersRequestsByEmail.contains(email)) {
572 auto iface = qobject_cast<QDBusInterface *>(sender());
577 FreeBusyProvidersRequestsQueue *queue = &mProvidersRequestsByEmail[email];
578 QString respondingService = iface->service();
579 qCDebug(AKONADICALENDAR_LOG) << respondingService <<
"responded to our FreeBusy request:" << handles;
580 int requestIndex = -1;
582 const int requestsSize(queue->mRequests.size());
583 for (
int i = 0; i < requestsSize; ++i) {
584 if (queue->mRequests.at(i).mInterface->service() == respondingService) {
589 if (requestIndex == -1) {
593 disconnect(iface, SIGNAL(handlesFreeBusy(
QString,
bool)),
this, SLOT(onHandlesFreeBusy(
QString,
bool)));
596 queue->mRequests.removeAt(requestIndex);
599 if (queue->mRequests.isEmpty() && queue->mHandlersCount == 0) {
600 mProvidersRequestsByEmail.remove(email);
601 fetchFreeBusyUrl(email);
604 ++queue->mHandlersCount;
608 iface->call(QStringLiteral(
"retrieveFreeBusy"), email, queue->mStartTime, queue->mEndTime);
609 queue->mRequests[requestIndex].mRequestStatus = FreeBusyProviderRequest::FreeBusyRequested;
613void FreeBusyManagerPrivate::processMailSchedulerResult(Akonadi::Scheduler::Result result,
const QString &errorMsg)
615 if (result == Scheduler::ResultSuccess) {
617 i18n(
"The free/busy information was successfully sent."),
618 i18nc(
"@title:window",
"Sending Free/Busy"),
619 QStringLiteral(
"FreeBusyPublishSuccess"));
624 sender()->deleteLater();
627void FreeBusyManagerPrivate::onFreeBusyRetrieved(
const QString &email,
const QString &freeBusy,
bool success,
const QString &errorText)
629 Q_Q(FreeBusyManager);
632 if (!mProvidersRequestsByEmail.contains(email)) {
641 FreeBusyProvidersRequestsQueue *queue = &mProvidersRequestsByEmail[email];
642 QString respondingService = iface->service();
643 int requestIndex = -1;
645 const int requestsSize(queue->mRequests.size());
646 for (
int i = 0; i < requestsSize; ++i) {
647 if (queue->mRequests.at(i).mInterface->service() == respondingService) {
652 if (requestIndex == -1) {
658 queue->mRequests.removeAt(requestIndex);
663 --queue->mHandlersCount;
665 queue->mResultingFreeBusy->merge(fb);
669 if (queue->mRequests.isEmpty()) {
670 if (queue->mHandlersCount == 0) {
671 fetchFreeBusyUrl(email);
673 Q_EMIT q->freeBusyRetrieved(queue->mResultingFreeBusy, email);
675 mProvidersRequestsByEmail.remove(email);
683class FreeBusyManagerStatic
686 FreeBusyManager instance;
690Q_GLOBAL_STATIC(FreeBusyManagerStatic, sManagerInstance)
692FreeBusyManager::FreeBusyManager()
693 : d_ptr(new FreeBusyManagerPrivate(this))
696 connect(CalendarSettings::self(), SIGNAL(configChanged()), SLOT(checkFreeBusyUrl()));
699FreeBusyManager::~FreeBusyManager() =
default;
701FreeBusyManager *FreeBusyManager::self()
703 return &sManagerInstance->instance;
708 Q_D(FreeBusyManager);
711 disconnect(d->mCalendar.data(), SIGNAL(calendarChanged()));
716 d->mFormat.setTimeZone(d->mCalendar->timeZone());
717 connect(d->mCalendar.data(), SIGNAL(calendarChanged()), SLOT(uploadFreeBusy()));
728void FreeBusyManager::publishFreeBusy(
QWidget *parentWidget)
730 Q_D(FreeBusyManager);
732 if (d->mUploadingFreeBusy) {
742 QUrl targetURL(CalendarSettings::self()->freeBusyPublishUrl());
743 if (targetURL.isEmpty()) {
745 i18n(
"<qt><p>No URL configured for uploading your free/busy list. "
746 "Please set it in KOrganizer's configuration dialog, on the "
747 "\"Free/Busy\" page.</p>"
748 "<p>Contact your system administrator for the exact URL and the "
749 "account details.</p></qt>"),
750 i18nc(
"@title:window",
"No Free/Busy Upload URL"));
758 if (!targetURL.isValid()) {
760 i18n(
"<qt>The target URL '%1' provided is invalid.</qt>", targetURL.toDisplayString()),
761 i18nc(
"@title:window",
"Invalid URL"));
762 d->mBrokenUrl =
true;
765 targetURL.setUserName(CalendarSettings::self()->freeBusyPublishUser());
766 targetURL.setPassword(CalendarSettings::self()->freeBusyPublishPassword());
768 d->mUploadingFreeBusy =
true;
771 if (d->mTimerID != 0) {
778 if (CalendarSettings::self()->freeBusyPublishDelay() > 0) {
779 d->mNextUploadTime = d->mNextUploadTime.addSecs(CalendarSettings::self()->freeBusyPublishDelay() * 60);
782 QString messageText = d->ownerFreeBusyAsString();
791 if (tempFile.
open()) {
793 textStream << messageText;
797 QString defaultEmail = KOCore()
803 if (CalendarSettings::self()->publishKolab()) {
806 if (CalendarSettings::self()->publishKolabServer() ==
QLatin1StringView(
"%SERVER%")
807 || CalendarSettings::self()->publishKolabServer().isEmpty()) {
810 server = CalendarSettings::self()->publishKolabServer();
816 QString fbname = CalendarSettings::self()->publishUserName();
818 if (at > 1 && fbname.
length() > (uint)at) {
821 targetURL.
setPath(
"/freebusy/" + fbname +
".ifb");
822 targetURL.
setUserName(CalendarSettings::self()->publishUserName());
823 targetURL.
setPassword(CalendarSettings::self()->publishPassword());
826 targetURL = CalendarSettings::self()->+publishAnyURL().replace(
"%SERVER%", emailHost);
827 targetURL.
setUserName(CalendarSettings::self()->publishUserName());
828 targetURL.
setPassword(CalendarSettings::self()->publishPassword());
835 qCDebug(AKONADICALENDAR_LOG) << targetURL;
846void FreeBusyManager::mailFreeBusy(
int daysToPublish,
QWidget *parentWidget)
848 Q_D(FreeBusyManager);
860 freebusy->setOrganizer(
Person(Akonadi::CalendarUtils::fullName(), Akonadi::CalendarUtils::email()));
865 auto scheduler =
new MailScheduler(
nullptr,
this);
866 connect(scheduler, &Scheduler::transactionFinished, d, &FreeBusyManagerPrivate::processMailSchedulerResult);
867 d->mParentWidgetForMailling = parentWidget;
869 scheduler->publish(freebusy, publishdlg->addresses());
874bool FreeBusyManager::retrieveFreeBusy(
const QString &email,
bool forceDownload,
QWidget *parentWidget)
876 Q_D(FreeBusyManager);
878 qCDebug(AKONADICALENDAR_LOG) << email;
880 qCDebug(AKONADICALENDAR_LOG) <<
"Email is empty";
884 d->mParentWidgetForRetrieval = parentWidget;
886 if (Akonadi::CalendarUtils::thatIsMe(email)) {
888 qCDebug(AKONADICALENDAR_LOG) <<
"freebusy of owner, not downloading";
889 Q_EMIT freeBusyRetrieved(d->ownerFreeBusy(), email);
896 qCDebug(AKONADICALENDAR_LOG) <<
"Found a cached copy for " << email;
897 Q_EMIT freeBusyRetrieved(fb, email);
902 if (!CalendarSettings::self()->freeBusyRetrieveAuto() && !forceDownload) {
903 qCDebug(AKONADICALENDAR_LOG) <<
"Not downloading freebusy";
907 d->mRetrieveQueue.append(email);
909 if (d->mRetrieveQueue.count() > 1) {
911 qCWarning(AKONADICALENDAR_LOG) <<
"Returning true without Q_EMIT, is this correct?";
920 d->processRetrieveQueue();
926void FreeBusyManager::cancelRetrieval()
928 Q_D(FreeBusyManager);
929 d->mRetrieveQueue.clear();
934 Q_D(FreeBusyManager);
935 const QString fbd = d->freeBusyDir();
939 qCDebug(AKONADICALENDAR_LOG) << f.fileName() <<
"doesn't exist.";
944 qCDebug(AKONADICALENDAR_LOG) <<
"Unable to open file" << f.fileName();
951 return d->iCalToFreeBusy(str.
toUtf8());
956 Q_D(FreeBusyManager);
957 qCDebug(AKONADICALENDAR_LOG) << person.
fullName();
959 QString fbd = d->freeBusyDir();
961 QDir freeBusyDirectory(fbd);
962 if (!freeBusyDirectory.exists()) {
963 qCDebug(AKONADICALENDAR_LOG) <<
"Directory" << fbd <<
" does not exist!";
964 qCDebug(AKONADICALENDAR_LOG) <<
"Creating directory:" << fbd;
966 if (!freeBusyDirectory.mkpath(fbd)) {
967 qCDebug(AKONADICALENDAR_LOG) <<
"Could not create directory:" << fbd;
974 filename += person.
email();
975 filename += QStringLiteral(
".ifb");
978 qCDebug(AKONADICALENDAR_LOG) <<
"filename:" << filename;
980 freebusy->clearAttendees();
981 freebusy->setOrganizer(person);
986 qCDebug(AKONADICALENDAR_LOG) <<
"acceptFreeBusy: Can't open:" << filename <<
"for writing";
996void FreeBusyManager::timerEvent(
QTimerEvent *event)
1002#include "moc_freebusymanager.cpp"
1003#include "moc_freebusymanager_p.cpp"
static AgentManager * self()
AgentInstance::List instances() const
QSharedPointer< FreeBusy > Ptr
void setEmail(const QString &email)
KConfigGroup group(const QString &group)
void writeEntry(const char *key, const char *value, WriteConfigFlags pFlags=Normal)
QString readEntry(const char *key, const char *aDefault=nullptr) const
void data(KIO::Job *job, const QByteArray &data)
virtual QString errorString() const
virtual Q_SCRIPTABLE void start()=0
QString errorText() const
Q_SCRIPTABLE Q_NOREPLY void start()
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
FreeBusyManager::Singleton.
KIOCORE_EXPORT TransferJob * get(const QUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
KIOCORE_EXPORT FileCopyJob * file_copy(const QUrl &src, const QUrl &dest, int permissions=-1, JobFlags flags=DefaultFlags)
void information(QWidget *parent, const QString &text, const QString &title=QString(), const QString &dontShowAgainName=QString(), Options options=Notify)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
const QList< QKeySequence > & end()
QCA_EXPORT ProviderList providers()
QDateTime currentDateTime()
QDateTime currentDateTimeUtc()
qint64 toSecsSinceEpoch() const const
QDateTime toTimeZone(const QTimeZone &timeZone) const const
const_iterator constBegin() const const
const_iterator constEnd() const const
qsizetype count() const const
bool isEmpty() const const
void reserve(qsizetype size)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
virtual bool event(QEvent *e)
QVariant property(const char *name) const const
bool setProperty(const char *name, QVariant &&value)
QString writableLocation(StandardLocation type)
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
QString fromUtf8(QByteArrayView str)
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString left(qsizetype n) const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
QByteArray toUtf8() const const
void truncate(qsizetype position)
virtual QString fileName() const const override
void setAutoRemove(bool b)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QUrl adjusted(FormattingOptions options) const const
QString host(ComponentFormattingOptions options) const const
bool isLocalFile() const const
bool isValid() const const
QString path(ComponentFormattingOptions options) const const
void setHost(const QString &host, ParsingMode mode)
void setPassword(const QString &password, ParsingMode mode)
void setPath(const QString &path, ParsingMode mode)
void setScheme(const QString &scheme)
void setUserName(const QString &userName, ParsingMode mode)
QString toDisplayString(FormattingOptions options) const const
QString toLocalFile() const const
QVariant fromValue(T &&value)
QString toString() const const