8#include "freebusymanager.h"
11#include "calendarsettings.h"
12#include "freebusydownloadjob_p.h"
13#include "freebusymanager_p.h"
14#include "mailscheduler_p.h"
15#include "publishdialog.h"
18#include <Akonadi/AgentInstance>
19#include <Akonadi/AgentManager>
20#include <Akonadi/ContactSearchJob>
22#include <KCalendarCore/Event>
23#include <KCalendarCore/FreeBusy>
24#include <KCalendarCore/Person>
26#include "akonadicalendar_debug.h"
29#include <KIO/FileCopyJob>
31#include <KIO/TransferJob>
32#include <KLocalizedString>
38#include <QRegularExpression>
39#include <QStandardPaths>
40#include <QTemporaryFile>
57 emailName = email.
left(atPos);
58 emailHost = email.
mid(atPos + 1);
67 retUrl.setPath(saveStr);
77 , mUrlsToCheck(urlsToCheck)
81void FbCheckerJob::start()
86void FbCheckerJob::checkNextUrl()
88 if (mUrlsToCheck.isEmpty()) {
89 qCDebug(AKONADICALENDAR_LOG) <<
"No fb file found";
90 setError(KJob::UserDefinedError);
94 const QUrl url = mUrlsToCheck.takeFirst();
99 connect(job, &KIO::TransferJob::result,
this, &FbCheckerJob::onGetJobFinished);
107void FbCheckerJob::onGetJobFinished(
KJob *job)
110 if (mData.contains(
"BEGIN:VCALENDAR")) {
111 qCDebug(AKONADICALENDAR_LOG) <<
"found freebusy";
112 mValidUrl = transferJob->url();
119QUrl FbCheckerJob::validUrl()
const
126FreeBusyManagerPrivate::FreeBusyProviderRequest::FreeBusyProviderRequest(
const QString &provider)
127 : mRequestStatus(NotStarted)
128 , mInterface(nullptr)
131 QStringLiteral(
"/FreeBusyProvider"),
132 QStringLiteral(
"org.freedesktop.Akonadi.Resource.FreeBusyProvider")));
137FreeBusyManagerPrivate::FreeBusyProvidersRequestsQueue::FreeBusyProvidersRequestsQueue()
138 : mResultingFreeBusy(nullptr)
142 mEndTime = mStartTime.addDays(14);
146FreeBusyManagerPrivate::FreeBusyProvidersRequestsQueue::FreeBusyProvidersRequestsQueue(
const QDateTime &
start,
const QDateTime &end)
147 : mResultingFreeBusy(nullptr)
156FreeBusyManagerPrivate::FreeBusyManagerPrivate(FreeBusyManager *q)
159 , mParentWidgetForRetrieval(nullptr)
161 connect(
this, &FreeBusyManagerPrivate::freeBusyUrlRetrieved,
this, &FreeBusyManagerPrivate::finishProcessRetrieveQueue);
164QString FreeBusyManagerPrivate::freeBusyDir()
const
169void FreeBusyManagerPrivate::checkFreeBusyUrl()
171 const QUrl targetURL(CalendarSettings::self()->freeBusyPublishUrl());
172 mBrokenUrl = targetURL.isEmpty() || !targetURL.isValid();
181void FreeBusyManagerPrivate::fetchFreeBusyUrl(
const QString &email)
188 qCDebug(AKONADICALENDAR_LOG) <<
"Found cached url:" << url;
190 if (Akonadi::CalendarUtils::thatIsMe(email)) {
191 cachedUrl.setUserName(CalendarSettings::self()->freeBusyRetrieveUser());
192 cachedUrl.setPassword(CalendarSettings::self()->freeBusyRetrievePassword());
194 Q_EMIT freeBusyUrlRetrieved(email, replaceVariablesUrl(cachedUrl, email));
201 connect(job, &Akonadi::ContactSearchJob::result,
this, &FreeBusyManagerPrivate::contactSearchJobFinished);
205void FreeBusyManagerPrivate::contactSearchJobFinished(
KJob *_job)
210 qCritical() <<
"Error while searching for contact: " << _job->
errorString() <<
", email = " << email;
211 Q_EMIT freeBusyUrlRetrieved(email,
QUrl());
215 auto job = qobject_cast<Akonadi::ContactSearchJob *>(_job);
222 const QString pref = contact.preferredEmail();
223 if (!pref.
isEmpty() && pref != email) {
224 group = cfg.
group(pref);
226 qCDebug(AKONADICALENDAR_LOG) <<
"Preferred email of" << email <<
"is" << pref;
228 qCDebug(AKONADICALENDAR_LOG) <<
"Taken url from preferred email:" << url;
229 Q_EMIT freeBusyUrlRetrieved(email, replaceVariablesUrl(
QUrl(url), email));
235 if (!CalendarSettings::self()->freeBusyRetrieveAuto()) {
237 qCDebug(AKONADICALENDAR_LOG) <<
"No automatic retrieving";
238 Q_EMIT freeBusyUrlRetrieved(email,
QUrl());
245 if (emailpos == -1) {
246 qCWarning(AKONADICALENDAR_LOG) <<
"No '@' found in" << email;
247 Q_EMIT freeBusyUrlRetrieved(email,
QUrl());
251 const QString emailHost = email.
mid(emailpos + 1);
254 if (CalendarSettings::self()->freeBusyCheckHostname()) {
257 const QString hostDomain =
QUrl(CalendarSettings::self()->freeBusyRetrieveUrl()).
host();
260 qCDebug(AKONADICALENDAR_LOG) <<
"Host '" << hostDomain <<
"' doesn't match email '" << email <<
'\'';
261 Q_EMIT freeBusyUrlRetrieved(email,
QUrl());
266 if (CalendarSettings::self()->freeBusyRetrieveUrl().contains(
QRegularExpression(QStringLiteral(
"\\.[xiv]fb$")))) {
269 const QUrl sourceUrl(CalendarSettings::self()->freeBusyRetrieveUrl());
270 QUrl fullpathURL = replaceVariablesUrl(sourceUrl, email);
273 fullpathURL.
setUserName(CalendarSettings::self()->freeBusyRetrieveUser());
274 fullpathURL.
setPassword(CalendarSettings::self()->freeBusyRetrievePassword());
278 qCDebug(AKONADICALENDAR_LOG) <<
"Found url. email=" << email <<
"; url=" << fullpathURL;
279 Q_EMIT freeBusyUrlRetrieved(email, fullpathURL);
286 extensions << QStringLiteral(
"xfb");
287 extensions << QStringLiteral(
"ifb");
288 extensions << QStringLiteral(
"vfb");
294 for (ext = extensions.
constBegin(); ext != extEnd; ++ext) {
296 const QUrl sourceUrl =
QUrl(CalendarSettings::self()->freeBusyRetrieveUrl());
297 QUrl dirURL = replaceVariablesUrl(sourceUrl, email);
298 if (CalendarSettings::self()->freeBusyFullDomainRetrieval()) {
307 dirURL.
setUserName(CalendarSettings::self()->freeBusyRetrieveUser());
308 dirURL.
setPassword(CalendarSettings::self()->freeBusyRetrievePassword());
309 urlsToCheck << dirURL;
311 KJob *checkerJob =
new FbCheckerJob(urlsToCheck,
this);
317void FreeBusyManagerPrivate::fbCheckerJobFinished(
KJob *job)
321 auto checkerJob =
static_cast<FbCheckerJob *
>(job);
322 const QUrl dirURL = checkerJob->validUrl();
328 qCDebug(AKONADICALENDAR_LOG) <<
"Found url email=" << email <<
"; url=" << dirURL;
330 Q_EMIT freeBusyUrlRetrieved(email, dirURL);
332 qCDebug(AKONADICALENDAR_LOG) <<
"Returning invalid url";
333 Q_EMIT freeBusyUrlRetrieved(email,
QUrl());
348 qCDebug(AKONADICALENDAR_LOG) <<
"Error parsing free/busy";
349 qCDebug(AKONADICALENDAR_LOG) << freeBusyVCal;
358 const QDateTime end =
start.addDays(CalendarSettings::self()->freeBusyPublishDays());
362 freebusy->setOrganizer(
KCalendarCore::Person(Akonadi::CalendarUtils::fullName(), Akonadi::CalendarUtils::email()));
366QString FreeBusyManagerPrivate::ownerFreeBusyAsString()
368 return freeBusyToIcal(ownerFreeBusy());
371void FreeBusyManagerPrivate::processFreeBusyDownloadResult(
KJob *_job)
373 Q_Q(FreeBusyManager);
375 auto job = qobject_cast<FreeBusyDownloadJob *>(_job);
378 qCritical() <<
"Error downloading freebusy" << _job->
errorString();
380 i18n(
"Failed to download free/busy data from: %1\nReason: %2", job->url().toDisplayString(), job->
errorText()),
381 i18nc(
"@title:window",
"Free/Busy Retrieval Error"));
386 mFreeBusyUrlEmailMap.take(job->url());
390 Q_ASSERT(mFreeBusyUrlEmailMap.contains(job->url()));
391 const QString email = mFreeBusyUrlEmailMap.take(job->url());
397 q->saveFreeBusy(fb, p);
398 qCDebug(AKONADICALENDAR_LOG) <<
"Freebusy retrieved for " << email;
399 Q_EMIT q->freeBusyRetrieved(fb, email);
401 qCritical() <<
"Error downloading freebusy, invalid fb.";
403 i18n(
"Failed to parse free/busy information that was retrieved from: %1", job->url().toDisplayString()),
404 i18nc(
"@title:window",
"Free/Busy Retrieval Error"));
410 processRetrieveQueue();
413void FreeBusyManagerPrivate::processFreeBusyUploadResult(
KJob *_job)
418 i18n(
"<qt><p>The software could not upload your free/busy list to "
419 "the URL '%1'. There might be a problem with the access "
420 "rights, or you specified an incorrect URL. The system said: "
422 "<p>Please check the URL or contact your system administrator."
424 job->destUrl().toString(),
428 QUrl src = job->srcUrl();
433 mUploadingFreeBusy =
false;
436void FreeBusyManagerPrivate::processRetrieveQueue()
438 if (mRetrieveQueue.isEmpty()) {
442 const QString email = mRetrieveQueue.takeFirst();
446 qCDebug(AKONADICALENDAR_LOG) <<
"Got the following FreeBusy providers: " <<
providers;
451 queryFreeBusyProviders(providers, email);
453 fetchFreeBusyUrl(email);
457void FreeBusyManagerPrivate::finishProcessRetrieveQueue(
const QString &email,
const QUrl &freeBusyUrlForEmail)
459 Q_Q(FreeBusyManager);
461 if (!freeBusyUrlForEmail.
isValid()) {
462 qCDebug(AKONADICALENDAR_LOG) <<
"Invalid FreeBusy URL" << freeBusyUrlForEmail.
toDisplayString() << email;
466 if (mFreeBusyUrlEmailMap.contains(freeBusyUrlForEmail)) {
467 qCDebug(AKONADICALENDAR_LOG) <<
"Download already in progress for " << freeBusyUrlForEmail;
471 mFreeBusyUrlEmailMap.insert(freeBusyUrlForEmail, email);
473 auto job =
new FreeBusyDownloadJob(freeBusyUrlForEmail, mParentWidgetForRetrieval);
474 q->connect(job, &FreeBusyDownloadJob::result,
this, [
this](
KJob *job) {
475 processFreeBusyDownloadResult(job);
480void FreeBusyManagerPrivate::uploadFreeBusy()
482 Q_Q(FreeBusyManager);
485 if (!CalendarSettings::self()->freeBusyPublishAuto() || CalendarSettings::self()->freeBusyPublishUrl().isEmpty()) {
496 int eta =
static_cast<int>(mNextUploadTime.toSecsSinceEpoch()) - now;
498 if (!mUploadingFreeBusy) {
500 if (mNextUploadTime.isNull() || currentDateTime > mNextUploadTime) {
502 q->publishFreeBusy();
509 q->publishFreeBusy();
515 qCDebug(AKONADICALENDAR_LOG) <<
"This shouldn't happen! eta <= 0";
521 mTimerID = q->startTimer(eta * 1000);
525 q->publishFreeBusy();
529QStringList FreeBusyManagerPrivate::getFreeBusyProviders()
const
534 if (agent.type().capabilities().contains(
"FreeBusyProvider"_L1)) {
541void FreeBusyManagerPrivate::queryFreeBusyProviders(
const QStringList &providers,
const QString &email)
543 if (!mProvidersRequestsByEmail.contains(email)) {
544 mProvidersRequestsByEmail[email] = FreeBusyProvidersRequestsQueue();
547 for (
const QString &provider : providers) {
548 FreeBusyProviderRequest request(provider);
551 connect(request.mInterface.data(), SIGNAL(handlesFreeBusy(
QString,
bool)),
this, SLOT(onHandlesFreeBusy(
QString,
bool)));
553 request.mInterface->call(QStringLiteral(
"canHandleFreeBusy"), email);
554 request.mRequestStatus = FreeBusyProviderRequest::HandlingRequested;
555 mProvidersRequestsByEmail[email].mRequests << request;
561 if (!mProvidersRequestsByEmail.contains(email)) {
562 mProvidersRequestsByEmail[email] = FreeBusyProvidersRequestsQueue(
start, end);
565 queryFreeBusyProviders(providers, email);
568void FreeBusyManagerPrivate::onHandlesFreeBusy(
const QString &email,
bool handles)
570 if (!mProvidersRequestsByEmail.contains(email)) {
574 auto iface = qobject_cast<QDBusInterface *>(sender());
579 FreeBusyProvidersRequestsQueue *queue = &mProvidersRequestsByEmail[email];
580 QString respondingService = iface->service();
581 qCDebug(AKONADICALENDAR_LOG) << respondingService <<
"responded to our FreeBusy request:" << handles;
582 int requestIndex = -1;
584 const int requestsSize(queue->mRequests.size());
585 for (
int i = 0; i < requestsSize; ++i) {
586 if (queue->mRequests.at(i).mInterface->service() == respondingService) {
591 if (requestIndex == -1) {
595 disconnect(iface, SIGNAL(handlesFreeBusy(
QString,
bool)),
this, SLOT(onHandlesFreeBusy(
QString,
bool)));
598 queue->mRequests.removeAt(requestIndex);
601 if (queue->mRequests.isEmpty() && queue->mHandlersCount == 0) {
602 mProvidersRequestsByEmail.remove(email);
603 fetchFreeBusyUrl(email);
606 ++queue->mHandlersCount;
610 iface->call(QStringLiteral(
"retrieveFreeBusy"), email, queue->mStartTime, queue->mEndTime);
611 queue->mRequests[requestIndex].mRequestStatus = FreeBusyProviderRequest::FreeBusyRequested;
615void FreeBusyManagerPrivate::processMailSchedulerResult(Akonadi::Scheduler::Result result,
const QString &errorMsg)
617 if (result == Scheduler::ResultSuccess) {
619 i18n(
"The free/busy information was successfully sent."),
620 i18nc(
"@title:window",
"Sending Free/Busy"),
621 QStringLiteral(
"FreeBusyPublishSuccess"));
626 sender()->deleteLater();
629void FreeBusyManagerPrivate::onFreeBusyRetrieved(
const QString &email,
const QString &freeBusy,
bool success,
const QString &errorText)
631 Q_Q(FreeBusyManager);
634 if (!mProvidersRequestsByEmail.contains(email)) {
643 FreeBusyProvidersRequestsQueue *queue = &mProvidersRequestsByEmail[email];
644 QString respondingService = iface->service();
645 int requestIndex = -1;
647 const int requestsSize(queue->mRequests.size());
648 for (
int i = 0; i < requestsSize; ++i) {
649 if (queue->mRequests.at(i).mInterface->service() == respondingService) {
654 if (requestIndex == -1) {
660 queue->mRequests.removeAt(requestIndex);
665 --queue->mHandlersCount;
667 queue->mResultingFreeBusy->merge(fb);
671 if (queue->mRequests.isEmpty()) {
672 if (queue->mHandlersCount == 0) {
673 fetchFreeBusyUrl(email);
675 Q_EMIT q->freeBusyRetrieved(queue->mResultingFreeBusy, email);
677 mProvidersRequestsByEmail.remove(email);
685class FreeBusyManagerStatic
688 FreeBusyManager instance;
692Q_GLOBAL_STATIC(FreeBusyManagerStatic, sManagerInstance)
694FreeBusyManager::FreeBusyManager()
695 : d_ptr(new FreeBusyManagerPrivate(this))
697 setObjectName(
"FreeBusyManager"_L1);
698 connect(CalendarSettings::self(), SIGNAL(configChanged()), SLOT(checkFreeBusyUrl()));
701FreeBusyManager::~FreeBusyManager() =
default;
703FreeBusyManager *FreeBusyManager::self()
705 return &sManagerInstance->instance;
710 Q_D(FreeBusyManager);
713 disconnect(d->mCalendar.data(), SIGNAL(calendarChanged()));
718 d->mFormat.setTimeZone(d->mCalendar->timeZone());
719 connect(d->mCalendar.data(), SIGNAL(calendarChanged()), SLOT(uploadFreeBusy()));
730void FreeBusyManager::publishFreeBusy(
QWidget *parentWidget)
732 Q_D(FreeBusyManager);
734 if (d->mUploadingFreeBusy) {
744 QUrl targetURL(CalendarSettings::self()->freeBusyPublishUrl());
745 if (targetURL.isEmpty()) {
747 i18n(
"<qt><p>No URL configured for uploading your free/busy list. "
748 "Please set it in KOrganizer's configuration dialog, on the "
749 "\"Free/Busy\" page.</p>"
750 "<p>Contact your system administrator for the exact URL and the "
751 "account details.</p></qt>"),
752 i18nc(
"@title:window",
"No Free/Busy Upload URL"));
760 if (!targetURL.isValid()) {
762 i18n(
"<qt>The target URL '%1' provided is invalid.</qt>", targetURL.toDisplayString()),
763 i18nc(
"@title:window",
"Invalid URL"));
764 d->mBrokenUrl =
true;
767 targetURL.setUserName(CalendarSettings::self()->freeBusyPublishUser());
768 targetURL.setPassword(CalendarSettings::self()->freeBusyPublishPassword());
770 d->mUploadingFreeBusy =
true;
773 if (d->mTimerID != 0) {
780 if (CalendarSettings::self()->freeBusyPublishDelay() > 0) {
781 d->mNextUploadTime = d->mNextUploadTime.addSecs(CalendarSettings::self()->freeBusyPublishDelay() * 60);
784 QString messageText = d->ownerFreeBusyAsString();
793 if (tempFile.
open()) {
795 textStream << messageText;
799 QString defaultEmail = KOCore()
805 if (CalendarSettings::self()->publishKolab()) {
808 if (CalendarSettings::self()->publishKolabServer() ==
"%SERVER%"_L1
809 || CalendarSettings::self()->publishKolabServer().isEmpty()) {
812 server = CalendarSettings::self()->publishKolabServer();
815 targetURL.setScheme(
"webdavs");
816 targetURL.setHost(server);
818 QString fbname = CalendarSettings::self()->publishUserName();
820 if (at > 1 && fbname.
length() > (uint)at) {
823 targetURL.setPath(
"/freebusy/" + fbname +
".ifb");
824 targetURL.setUserName(CalendarSettings::self()->publishUserName());
825 targetURL.setPassword(CalendarSettings::self()->publishPassword());
828 targetURL = CalendarSettings::self()->+publishAnyURL().replace(
"%SERVER%", emailHost);
829 targetURL.setUserName(CalendarSettings::self()->publishUserName());
830 targetURL.setPassword(CalendarSettings::self()->publishPassword());
837 qCDebug(AKONADICALENDAR_LOG) << targetURL;
848void FreeBusyManager::mailFreeBusy(
int daysToPublish,
QWidget *parentWidget)
850 Q_D(FreeBusyManager);
862 freebusy->setOrganizer(
Person(Akonadi::CalendarUtils::fullName(), Akonadi::CalendarUtils::email()));
867 auto scheduler =
new MailScheduler(
nullptr,
this);
868 connect(scheduler, &Scheduler::transactionFinished, d, &FreeBusyManagerPrivate::processMailSchedulerResult);
869 d->mParentWidgetForMailling = parentWidget;
871 scheduler->publish(freebusy, publishdlg->addresses());
876bool FreeBusyManager::retrieveFreeBusy(
const QString &email,
bool forceDownload,
QWidget *parentWidget)
878 Q_D(FreeBusyManager);
880 qCDebug(AKONADICALENDAR_LOG) << email;
882 qCDebug(AKONADICALENDAR_LOG) <<
"Email is empty";
886 d->mParentWidgetForRetrieval = parentWidget;
888 if (Akonadi::CalendarUtils::thatIsMe(email)) {
890 qCDebug(AKONADICALENDAR_LOG) <<
"freebusy of owner, not downloading";
891 Q_EMIT freeBusyRetrieved(d->ownerFreeBusy(), email);
898 qCDebug(AKONADICALENDAR_LOG) <<
"Found a cached copy for " << email;
899 Q_EMIT freeBusyRetrieved(fb, email);
904 if (!CalendarSettings::self()->freeBusyRetrieveAuto() && !forceDownload) {
905 qCDebug(AKONADICALENDAR_LOG) <<
"Not downloading freebusy";
909 d->mRetrieveQueue.append(email);
911 if (d->mRetrieveQueue.count() > 1) {
913 qCWarning(AKONADICALENDAR_LOG) <<
"Returning true without Q_EMIT, is this correct?";
922 d->processRetrieveQueue();
928void FreeBusyManager::cancelRetrieval()
930 Q_D(FreeBusyManager);
931 d->mRetrieveQueue.clear();
936 Q_D(FreeBusyManager);
937 const QString fbd = d->freeBusyDir();
941 qCDebug(AKONADICALENDAR_LOG) << f.fileName() <<
"doesn't exist.";
946 qCDebug(AKONADICALENDAR_LOG) <<
"Unable to open file" << f.fileName();
953 return d->iCalToFreeBusy(str.
toUtf8());
958 Q_D(FreeBusyManager);
959 qCDebug(AKONADICALENDAR_LOG) << person.
fullName();
961 QString fbd = d->freeBusyDir();
963 QDir freeBusyDirectory(fbd);
964 if (!freeBusyDirectory.exists()) {
965 qCDebug(AKONADICALENDAR_LOG) <<
"Directory" << fbd <<
" does not exist!";
966 qCDebug(AKONADICALENDAR_LOG) <<
"Creating directory:" << fbd;
968 if (!freeBusyDirectory.mkpath(fbd)) {
969 qCDebug(AKONADICALENDAR_LOG) <<
"Could not create directory:" << fbd;
976 filename += person.
email();
977 filename += QStringLiteral(
".ifb");
980 qCDebug(AKONADICALENDAR_LOG) <<
"filename:" << filename;
982 freebusy->clearAttendees();
983 freebusy->setOrganizer(person);
988 qCDebug(AKONADICALENDAR_LOG) <<
"acceptFreeBusy: Can't open:" << filename <<
"for writing";
998void FreeBusyManager::timerEvent(
QTimerEvent *event)
1004#include "moc_freebusymanager.cpp"
1005#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 setPassword(const QString &password, ParsingMode mode)
void setPath(const QString &path, ParsingMode mode)
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