File indexing completed on 2024-05-12 05:22:19

0001 /*
0002     SPDX-FileCopyrightText: 2012 Andrius da Costa Ribas <andriusmao@gmail.com>
0003     SPDX-FileCopyrightText: 2013 Daniel Vrátil <dvratil@redhat.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0006 */
0007 
0008 #include "file.h"
0009 #include "file_p.h"
0010 #include "parentreference_p.h"
0011 #include "permission_p.h"
0012 #include "user.h"
0013 #include "utils_p.h"
0014 
0015 #include <QJsonDocument>
0016 
0017 using namespace KGAPI2;
0018 using namespace KGAPI2::Drive;
0019 
0020 ///// DriveFile::Labels
0021 
0022 class Q_DECL_HIDDEN File::Labels::Private
0023 {
0024 public:
0025     Private();
0026     Private(const Private &other);
0027 
0028     bool starred = false;
0029     bool hidden = false;
0030     bool trashed = false;
0031     bool restricted = false;
0032     bool viewed = false;
0033 };
0034 
0035 File::Labels::Private::Private()
0036 {
0037 }
0038 
0039 File::Labels::Private::Private(const Private &other)
0040     : starred(other.starred)
0041     , hidden(other.hidden)
0042     , trashed(other.trashed)
0043     , restricted(other.restricted)
0044     , viewed(other.viewed)
0045 {
0046 }
0047 
0048 File::Labels::Labels()
0049     : d(new Private)
0050 {
0051 }
0052 
0053 File::Labels::Labels(const Labels &other)
0054     : d(new Private(*(other.d)))
0055 {
0056 }
0057 
0058 File::Labels::~Labels()
0059 {
0060     delete d;
0061 }
0062 
0063 bool File::Labels::operator==(const Labels &other) const
0064 {
0065     GAPI_COMPARE(starred)
0066     GAPI_COMPARE(hidden)
0067     GAPI_COMPARE(trashed)
0068     GAPI_COMPARE(restricted)
0069     GAPI_COMPARE(viewed)
0070     return true;
0071 }
0072 
0073 bool File::Labels::starred() const
0074 {
0075     return d->starred;
0076 }
0077 
0078 void File::Labels::setStarred(bool starred)
0079 {
0080     d->starred = starred;
0081 }
0082 
0083 bool File::Labels::hidden() const
0084 {
0085     return d->hidden;
0086 }
0087 
0088 void File::Labels::setHidden(bool hidden)
0089 {
0090     d->hidden = hidden;
0091 }
0092 
0093 bool File::Labels::trashed() const
0094 {
0095     return d->trashed;
0096 }
0097 
0098 void File::Labels::setTrashed(bool trashed)
0099 {
0100     d->trashed = trashed;
0101 }
0102 
0103 bool File::Labels::restricted() const
0104 {
0105     return d->restricted;
0106 }
0107 
0108 void File::Labels::setRestricted(bool restricted)
0109 {
0110     d->restricted = restricted;
0111 }
0112 
0113 bool File::Labels::viewed() const
0114 {
0115     return d->viewed;
0116 }
0117 
0118 void File::Labels::setViewed(bool viewed)
0119 {
0120     d->viewed = viewed;
0121 }
0122 
0123 ///// DriveFile::ImageMediaMetadata
0124 
0125 class Q_DECL_HIDDEN File::IndexableText::Private
0126 {
0127 public:
0128     Private();
0129     Private(const Private &other);
0130 
0131     QString text;
0132 };
0133 
0134 File::IndexableText::Private::Private()
0135 {
0136 }
0137 
0138 File::IndexableText::Private::Private(const Private &other)
0139     : text(other.text)
0140 {
0141 }
0142 
0143 File::IndexableText::IndexableText()
0144     : d(new Private)
0145 {
0146 }
0147 
0148 File::IndexableText::IndexableText(const IndexableText &other)
0149     : d(new Private(*(other.d)))
0150 {
0151 }
0152 
0153 File::IndexableText::~IndexableText()
0154 {
0155     delete d;
0156 }
0157 
0158 bool File::IndexableText::operator==(const IndexableText &other) const
0159 {
0160     GAPI_COMPARE(text)
0161     return true;
0162 }
0163 
0164 QString File::IndexableText::text() const
0165 {
0166     return d->text;
0167 }
0168 
0169 void File::IndexableText::setText(const QString &text)
0170 {
0171     d->text = text;
0172 }
0173 
0174 ///// DriveFile::ImageMediaMetadata::Location
0175 
0176 class Q_DECL_HIDDEN File::ImageMediaMetadata::Location::Private
0177 {
0178 public:
0179     Private();
0180     Private(const Private &other);
0181 
0182     qreal latitude;
0183     qreal longitude;
0184     qreal altitude;
0185 };
0186 
0187 File::ImageMediaMetadata::Location::Private::Private()
0188     : latitude(-1)
0189     , longitude(-1)
0190     , altitude(0)
0191 {
0192 }
0193 
0194 File::ImageMediaMetadata::Location::Private::Private(const Private &other)
0195     : latitude(other.latitude)
0196     , longitude(other.longitude)
0197     , altitude(other.altitude)
0198 {
0199 }
0200 
0201 File::ImageMediaMetadata::Location::Location()
0202     : d(new Private)
0203 {
0204 }
0205 
0206 File::ImageMediaMetadata::Location::Location(const Location &other)
0207     : d(new Private(*(other.d)))
0208 {
0209 }
0210 
0211 File::ImageMediaMetadata::Location::~Location()
0212 {
0213     delete d;
0214 }
0215 
0216 bool File::ImageMediaMetadata::Location::operator==(const Location &other) const
0217 {
0218     GAPI_COMPARE(latitude)
0219     GAPI_COMPARE(longitude)
0220     GAPI_COMPARE(altitude)
0221     return true;
0222 }
0223 
0224 qreal File::ImageMediaMetadata::Location::latitude() const
0225 {
0226     return d->latitude;
0227 }
0228 
0229 qreal File::ImageMediaMetadata::Location::longitude() const
0230 {
0231     return d->longitude;
0232 }
0233 
0234 qreal File::ImageMediaMetadata::Location::altitude() const
0235 {
0236     return d->altitude;
0237 }
0238 
0239 ///// DriveFile::ImageMediaMetadata
0240 
0241 class Q_DECL_HIDDEN File::ImageMediaMetadata::Private
0242 {
0243 public:
0244     Private();
0245     Private(const Private &other);
0246 
0247     int width;
0248     int height;
0249     int rotation;
0250     LocationPtr location;
0251     QString date;
0252     QString cameraMake;
0253     QString cameraModel;
0254     float exposureTime;
0255     float aperture;
0256     bool flashUsed;
0257     float focalLength;
0258     int isoSpeed;
0259     QString meteringMode;
0260     QString sensor;
0261     QString exposureMode;
0262     QString colorSpace;
0263     QString whiteBalance;
0264     float exposureBias;
0265     float maxApertureValue;
0266     int subjectDistance;
0267     QString lens;
0268 };
0269 
0270 File::ImageMediaMetadata::Private::Private()
0271     : width(-1)
0272     , height(-1)
0273     , rotation(-1)
0274     , exposureTime(-1)
0275     , aperture(-1)
0276     , flashUsed(false)
0277     , focalLength(-1)
0278     , isoSpeed(-1)
0279     , exposureBias(-1)
0280     , maxApertureValue(-1)
0281     , subjectDistance(-1)
0282 {
0283 }
0284 
0285 File::ImageMediaMetadata::Private::Private(const Private &other)
0286     : width(other.width)
0287     , height(other.height)
0288     , rotation(other.rotation)
0289     , location(other.location)
0290     , date(other.date)
0291     , cameraMake(other.cameraMake)
0292     , cameraModel(other.cameraModel)
0293     , exposureTime(other.exposureTime)
0294     , aperture(other.aperture)
0295     , flashUsed(other.flashUsed)
0296     , focalLength(other.focalLength)
0297     , isoSpeed(other.isoSpeed)
0298     , meteringMode(other.meteringMode)
0299     , sensor(other.sensor)
0300     , exposureMode(other.exposureMode)
0301     , colorSpace(other.colorSpace)
0302     , whiteBalance(other.whiteBalance)
0303     , exposureBias(other.exposureBias)
0304     , maxApertureValue(other.maxApertureValue)
0305     , subjectDistance(other.subjectDistance)
0306     , lens(other.lens)
0307 {
0308 }
0309 
0310 File::ImageMediaMetadata::ImageMediaMetadata(const QVariantMap &map)
0311     : d(new Private)
0312 {
0313     d->width = map[QStringLiteral("width")].toInt();
0314     d->height = map[QStringLiteral("height")].toInt();
0315     d->rotation = map[QStringLiteral("rotation")].toInt();
0316     d->date = map[QStringLiteral("date")].toString();
0317     d->cameraMake = map[QStringLiteral("cameraMake")].toString();
0318     d->cameraModel = map[QStringLiteral("cameraModel")].toString();
0319     d->exposureTime = map[QStringLiteral("exposureTime")].toFloat();
0320     d->aperture = map[QStringLiteral("aperture")].toFloat();
0321     d->flashUsed = map[QStringLiteral("flashUsed")].toBool();
0322     d->focalLength = map[QStringLiteral("focalLength")].toFloat();
0323     d->isoSpeed = map[QStringLiteral("isoSpeed")].toInt();
0324     d->meteringMode = map[QStringLiteral("meteringMode")].toString();
0325     d->sensor = map[QStringLiteral("sensor")].toString();
0326     d->exposureMode = map[QStringLiteral("exposureMode")].toString();
0327     d->colorSpace = map[QStringLiteral("colorSpace")].toString();
0328     d->whiteBalance = map[QStringLiteral("whiteBalance")].toString();
0329     d->exposureBias = map[QStringLiteral("exposureBias")].toFloat();
0330     d->maxApertureValue = map[QStringLiteral("maxApertureValue")].toFloat();
0331     d->subjectDistance = map[QStringLiteral("subjectDistance")].toFloat();
0332     d->lens = map[QStringLiteral("lens")].toString();
0333 
0334     const QVariantMap locationData = map[QStringLiteral("location")].toMap();
0335     File::ImageMediaMetadata::LocationPtr location(new File::ImageMediaMetadata::Location);
0336     location->d->latitude = locationData[QStringLiteral("latitude")].toReal();
0337     location->d->longitude = locationData[QStringLiteral("longitude")].toReal();
0338     location->d->altitude = locationData[QStringLiteral("altitude")].toReal();
0339 }
0340 
0341 File::ImageMediaMetadata::ImageMediaMetadata(const ImageMediaMetadata &other)
0342     : d(new Private(*(other.d)))
0343 {
0344 }
0345 
0346 File::ImageMediaMetadata::~ImageMediaMetadata()
0347 {
0348     delete d;
0349 }
0350 
0351 bool File::ImageMediaMetadata::operator==(const ImageMediaMetadata &other) const
0352 {
0353     GAPI_COMPARE(width)
0354     GAPI_COMPARE(height)
0355     GAPI_COMPARE(rotation)
0356     GAPI_COMPARE_SHAREDPTRS(location)
0357     GAPI_COMPARE(date)
0358     GAPI_COMPARE(cameraMake)
0359     GAPI_COMPARE(cameraModel)
0360     GAPI_COMPARE(exposureTime)
0361     GAPI_COMPARE(aperture)
0362     GAPI_COMPARE(flashUsed)
0363     GAPI_COMPARE(focalLength)
0364     GAPI_COMPARE(isoSpeed)
0365     GAPI_COMPARE(meteringMode)
0366     GAPI_COMPARE(sensor)
0367     GAPI_COMPARE(exposureMode)
0368     GAPI_COMPARE(colorSpace)
0369     GAPI_COMPARE(whiteBalance)
0370     GAPI_COMPARE(exposureBias)
0371     GAPI_COMPARE(maxApertureValue)
0372     GAPI_COMPARE(subjectDistance)
0373     GAPI_COMPARE(lens)
0374     return true;
0375 }
0376 
0377 int File::ImageMediaMetadata::width() const
0378 {
0379     return d->width;
0380 }
0381 
0382 int File::ImageMediaMetadata::height() const
0383 {
0384     return d->height;
0385 }
0386 
0387 int File::ImageMediaMetadata::rotation() const
0388 {
0389     return d->rotation;
0390 }
0391 
0392 File::ImageMediaMetadata::LocationPtr File::ImageMediaMetadata::location() const
0393 {
0394     return d->location;
0395 }
0396 
0397 QString File::ImageMediaMetadata::date() const
0398 {
0399     return d->date;
0400 }
0401 
0402 QString File::ImageMediaMetadata::cameraMake() const
0403 {
0404     return d->cameraMake;
0405 }
0406 
0407 QString File::ImageMediaMetadata::cameraModel() const
0408 {
0409     return d->cameraModel;
0410 }
0411 
0412 float File::ImageMediaMetadata::exposureTime() const
0413 {
0414     return d->exposureTime;
0415 }
0416 
0417 float File::ImageMediaMetadata::aperture() const
0418 {
0419     return d->aperture;
0420 }
0421 
0422 bool File::ImageMediaMetadata::flashUsed() const
0423 {
0424     return d->flashUsed;
0425 }
0426 
0427 float File::ImageMediaMetadata::focalLength() const
0428 {
0429     return d->focalLength;
0430 }
0431 
0432 int File::ImageMediaMetadata::isoSpeed() const
0433 {
0434     return d->isoSpeed;
0435 }
0436 
0437 QString File::ImageMediaMetadata::meteringMode() const
0438 {
0439     return d->meteringMode;
0440 }
0441 
0442 QString File::ImageMediaMetadata::sensor() const
0443 {
0444     return d->sensor;
0445 }
0446 
0447 QString File::ImageMediaMetadata::exposureMode() const
0448 {
0449     return d->exposureMode;
0450 }
0451 
0452 QString File::ImageMediaMetadata::colorSpace() const
0453 {
0454     return d->colorSpace;
0455 }
0456 
0457 QString File::ImageMediaMetadata::whiteBalance() const
0458 {
0459     return d->whiteBalance;
0460 }
0461 
0462 float File::ImageMediaMetadata::exposureBias() const
0463 {
0464     return d->exposureBias;
0465 }
0466 
0467 float File::ImageMediaMetadata::maxApertureValue() const
0468 {
0469     return d->maxApertureValue;
0470 }
0471 
0472 int File::ImageMediaMetadata::subjectDistance() const
0473 {
0474     return d->subjectDistance;
0475 }
0476 
0477 QString File::ImageMediaMetadata::lens() const
0478 {
0479     return d->lens;
0480 }
0481 
0482 ////// DriveFile::Thumbnail
0483 
0484 class Q_DECL_HIDDEN File::Thumbnail::Private
0485 {
0486 public:
0487     Private();
0488     Private(const Private &other);
0489 
0490     QImage image;
0491     QString mimeType;
0492 };
0493 
0494 File::Thumbnail::Private::Private()
0495 {
0496 }
0497 
0498 File::Thumbnail::Private::Private(const Private &other)
0499     : image(other.image)
0500     , mimeType(other.mimeType)
0501 {
0502 }
0503 
0504 File::Thumbnail::Thumbnail(const QVariantMap &map)
0505     : d(new Private)
0506 {
0507     const QByteArray ba = QByteArray::fromBase64(map[QStringLiteral("image")].toByteArray());
0508     d->image = QImage::fromData(ba);
0509     d->mimeType = map[Fields::MimeType].toString();
0510 }
0511 
0512 File::Thumbnail::Thumbnail(const File::Thumbnail &other)
0513     : d(new Private(*(other.d)))
0514 {
0515 }
0516 
0517 File::Thumbnail::~Thumbnail()
0518 {
0519     delete d;
0520 }
0521 
0522 bool File::Thumbnail::operator==(const Thumbnail &other) const
0523 {
0524     GAPI_COMPARE(image)
0525     GAPI_COMPARE(mimeType)
0526     return true;
0527 }
0528 
0529 QImage File::Thumbnail::image() const
0530 {
0531     return d->image;
0532 }
0533 
0534 QString File::Thumbnail::mimeType() const
0535 {
0536     return d->mimeType;
0537 }
0538 
0539 ////// DriveFile
0540 
0541 File::Private::Private()
0542     : fileSize(-1)
0543     , version(-1)
0544     , quotaBytesUsed(-1)
0545     , editable(false)
0546     , writersCanShare(false)
0547     , explicitlyTrashed(false)
0548     , shared(false)
0549 {
0550 }
0551 
0552 File::Private::Private(const Private &other)
0553     : id(other.id)
0554     , selfLink(other.selfLink)
0555     , title(other.title)
0556     , mimeType(other.mimeType)
0557     , description(other.description)
0558     , labels(other.labels)
0559     , createdDate(other.createdDate)
0560     , modifiedDate(other.modifiedDate)
0561     , modifiedByMeDate(other.modifiedByMeDate)
0562     , downloadUrl(other.downloadUrl)
0563     , indexableText(other.indexableText)
0564     , userPermission(other.userPermission)
0565     , fileExtension(other.fileExtension)
0566     , md5Checksum(other.md5Checksum)
0567     , fileSize(other.fileSize)
0568     , alternateLink(other.alternateLink)
0569     , embedLink(other.embedLink)
0570     , version(other.version)
0571     , sharedWithMeDate(other.sharedWithMeDate)
0572     , parents(other.parents)
0573     , exportLinks(other.exportLinks)
0574     , originalFileName(other.originalFileName)
0575     , quotaBytesUsed(other.quotaBytesUsed)
0576     , ownerNames(other.ownerNames)
0577     , lastModifyingUserName(other.lastModifyingUserName)
0578     , editable(other.editable)
0579     , writersCanShare(other.writersCanShare)
0580     , thumbnailLink(other.thumbnailLink)
0581     , lastViewedByMeDate(other.lastViewedByMeDate)
0582     , webContentLink(other.webContentLink)
0583     , explicitlyTrashed(other.explicitlyTrashed)
0584     , imageMediaMetadata(other.imageMediaMetadata)
0585     , thumbnail(other.thumbnail)
0586     , webViewLink(other.webViewLink)
0587     , iconLink(other.iconLink)
0588     , shared(other.shared)
0589     , owners(other.owners)
0590     , lastModifyingUser(other.lastModifyingUser)
0591 {
0592 }
0593 
0594 bool File::operator==(const File &other) const
0595 {
0596     if (!Object::operator==(other)) {
0597         return false;
0598     }
0599     GAPI_COMPARE(id)
0600     GAPI_COMPARE(selfLink)
0601     GAPI_COMPARE(title)
0602     GAPI_COMPARE(mimeType)
0603     GAPI_COMPARE(description)
0604     GAPI_COMPARE_SHAREDPTRS(labels)
0605     GAPI_COMPARE(createdDate)
0606     GAPI_COMPARE(modifiedDate)
0607     GAPI_COMPARE(modifiedByMeDate)
0608     GAPI_COMPARE(downloadUrl)
0609     GAPI_COMPARE_SHAREDPTRS(indexableText)
0610     GAPI_COMPARE_SHAREDPTRS(userPermission)
0611     GAPI_COMPARE(fileExtension)
0612     GAPI_COMPARE(md5Checksum)
0613     GAPI_COMPARE(fileSize)
0614     GAPI_COMPARE(alternateLink)
0615     GAPI_COMPARE(embedLink)
0616     GAPI_COMPARE(version)
0617     GAPI_COMPARE(sharedWithMeDate)
0618     GAPI_COMPARE_CONTAINERS(parents)
0619     GAPI_COMPARE(exportLinks)
0620     GAPI_COMPARE(originalFileName)
0621     GAPI_COMPARE(quotaBytesUsed)
0622     GAPI_COMPARE(ownerNames)
0623     GAPI_COMPARE(lastModifyingUserName)
0624     GAPI_COMPARE(editable)
0625     GAPI_COMPARE(writersCanShare)
0626     GAPI_COMPARE(thumbnailLink)
0627     GAPI_COMPARE(lastViewedByMeDate)
0628     GAPI_COMPARE(webContentLink)
0629     GAPI_COMPARE(explicitlyTrashed)
0630     GAPI_COMPARE_SHAREDPTRS(imageMediaMetadata)
0631     GAPI_COMPARE_SHAREDPTRS(thumbnail)
0632     GAPI_COMPARE(webViewLink)
0633     GAPI_COMPARE(iconLink)
0634     GAPI_COMPARE(shared)
0635     GAPI_COMPARE_CONTAINERS(owners)
0636     GAPI_COMPARE_SHAREDPTRS(lastModifyingUser)
0637     return true;
0638 }
0639 
0640 FilePtr File::Private::fromJSON(const QVariantMap &map)
0641 {
0642     if (!map.contains(File::Fields::Kind) || map[File::Fields::Kind].toString() != QLatin1StringView("drive#file")) {
0643         return FilePtr();
0644     }
0645 
0646     FilePtr file(new File());
0647     file->setEtag(map[Fields::Etag].toString());
0648     file->d->id = map[Fields::Id].toString();
0649     file->d->selfLink = map[Fields::SelfLink].toUrl();
0650     file->d->title = map[Fields::Title].toString();
0651     file->d->mimeType = map[Fields::MimeType].toString();
0652     file->d->description = map[Fields::Description].toString();
0653 
0654     const QVariantMap labelsData = map[Fields::Labels].toMap();
0655     File::LabelsPtr labels(new File::Labels());
0656     labels->d->starred = labelsData[QStringLiteral("starred")].toBool();
0657     labels->d->hidden = labelsData[QStringLiteral("hidden")].toBool();
0658     labels->d->trashed = labelsData[QStringLiteral("trashed")].toBool();
0659     labels->d->restricted = labelsData[QStringLiteral("restricted")].toBool();
0660     labels->d->viewed = labelsData[QStringLiteral("viewed")].toBool();
0661     file->d->labels = labels;
0662 
0663     // FIXME FIXME FIXME Verify the date format
0664     file->d->createdDate = QDateTime::fromString(map[Fields::CreatedDate].toString(), Qt::ISODate);
0665     file->d->modifiedDate = QDateTime::fromString(map[Fields::ModifiedDate].toString(), Qt::ISODate);
0666     file->d->modifiedByMeDate = QDateTime::fromString(map[Fields::ModifiedByMeDate].toString(), Qt::ISODate);
0667     file->d->downloadUrl = map[Fields::DownloadUrl].toUrl();
0668 
0669     const QVariantMap indexableTextData = map[Fields::IndexableText].toMap();
0670     File::IndexableTextPtr indexableText(new File::IndexableText());
0671     indexableText->d->text = indexableTextData[QStringLiteral("text")].toString();
0672     file->d->indexableText = indexableText;
0673 
0674     const QVariantMap userPermissionData = map[Fields::UserPermission].toMap();
0675     file->d->userPermission = Permission::Private::fromJSON(userPermissionData);
0676 
0677     file->d->fileExtension = map[Fields::FileExtension].toString();
0678     file->d->md5Checksum = map[Fields::Md5Checksum].toString();
0679     file->d->fileSize = map[Fields::FileSize].toLongLong();
0680     file->d->alternateLink = map[Fields::AlternateLink].toUrl();
0681     file->d->embedLink = map[Fields::EmbedLink].toUrl();
0682     file->d->version = map[Fields::Version].toLongLong();
0683     file->d->sharedWithMeDate = QDateTime::fromString(map[Fields::SharedWithMeDate].toString(), Qt::ISODate);
0684 
0685     const QVariantList parents = map[Fields::Parents].toList();
0686     for (const QVariant &parent : parents) {
0687         file->d->parents << ParentReference::Private::fromJSON(parent.toMap());
0688     }
0689 
0690     const QVariantMap exportLinksData = map[Fields::ExportLinks].toMap();
0691     QVariantMap::ConstIterator iter = exportLinksData.constBegin();
0692     for (; iter != exportLinksData.constEnd(); ++iter) {
0693         file->d->exportLinks.insert(iter.key(), iter.value().toUrl());
0694     }
0695 
0696     file->d->originalFileName = map[QStringLiteral("originalFileName")].toString();
0697     file->d->quotaBytesUsed = map[QStringLiteral("quotaBytesUsed")].toLongLong();
0698     file->d->ownerNames = map[Fields::OwnerNames].toStringList();
0699     file->d->lastModifyingUserName = map[QStringLiteral("lastModifyingUserName")].toString();
0700     file->d->editable = map[Fields::Editable].toBool();
0701     file->d->writersCanShare = map[Fields::WritersCanShare].toBool();
0702     file->d->thumbnailLink = map[Fields::ThumbnailLink].toUrl();
0703     file->d->lastViewedByMeDate = QDateTime::fromString(map[Fields::LastViewedByMeDate].toString(), Qt::ISODate);
0704     file->d->webContentLink = map[Fields::WebContentLink].toUrl();
0705     file->d->explicitlyTrashed = map[Fields::ExplicitlyTrashed].toBool();
0706 
0707     const QVariantMap imageMetaData = map[Fields::ImageMediaMetadata].toMap();
0708     file->d->imageMediaMetadata = File::ImageMediaMetadataPtr(new File::ImageMediaMetadata(imageMetaData));
0709 
0710     const QVariantMap thumbnailData = map[Fields::Thumbnail].toMap();
0711     File::ThumbnailPtr thumbnail(new File::Thumbnail(thumbnailData));
0712     file->d->thumbnail = thumbnail;
0713 
0714     file->d->webViewLink = map[Fields::WebViewLink].toUrl();
0715     file->d->iconLink = map[Fields::IconLink].toUrl();
0716     file->d->shared = map[Fields::Shared].toBool();
0717 
0718     const QVariantList ownersList = map[Fields::Owners].toList();
0719     for (const QVariant &owner : ownersList) {
0720         file->d->owners << User::fromJSON(owner.toMap());
0721     }
0722 
0723     const QVariantMap lastModifyingUser = map[Fields::LastModifyingUser].toMap();
0724     file->d->lastModifyingUser = User::fromJSON(lastModifyingUser);
0725 
0726     return file;
0727 }
0728 
0729 File::File()
0730     : KGAPI2::Object()
0731     , d(new Private)
0732 {
0733 }
0734 
0735 File::File(const File &other)
0736     : KGAPI2::Object(other)
0737     , d(new Private(*(other.d)))
0738 {
0739 }
0740 
0741 File::~File()
0742 {
0743     delete d;
0744 }
0745 
0746 QString File::folderMimeType()
0747 {
0748     return QStringLiteral("application/vnd.google-apps.folder");
0749 }
0750 
0751 QString File::id() const
0752 {
0753     return d->id;
0754 }
0755 
0756 QUrl File::selfLink() const
0757 {
0758     return d->selfLink;
0759 }
0760 
0761 QString File::title() const
0762 {
0763     return d->title;
0764 }
0765 
0766 void File::setTitle(const QString &title)
0767 {
0768     d->title = title;
0769 }
0770 
0771 QString File::mimeType() const
0772 {
0773     return d->mimeType;
0774 }
0775 
0776 void File::setMimeType(const QString &mimeType)
0777 {
0778     d->mimeType = mimeType;
0779 }
0780 
0781 QString File::description() const
0782 {
0783     return d->description;
0784 }
0785 
0786 void File::setDescription(const QString &description)
0787 {
0788     d->description = description;
0789 }
0790 
0791 File::LabelsPtr File::labels() const
0792 {
0793     return d->labels;
0794 }
0795 
0796 void File::setLabels(const File::LabelsPtr &labels)
0797 {
0798     d->labels = labels;
0799 }
0800 
0801 QDateTime File::createdDate() const
0802 {
0803     return d->createdDate;
0804 }
0805 
0806 QDateTime File::modifiedDate() const
0807 {
0808     return d->modifiedDate;
0809 }
0810 
0811 void File::setModifiedDate(const QDateTime &modifiedDate)
0812 {
0813     d->modifiedDate = modifiedDate;
0814 }
0815 
0816 QDateTime File::modifiedByMeDate() const
0817 {
0818     return d->modifiedByMeDate;
0819 }
0820 
0821 QUrl File::downloadUrl() const
0822 {
0823     return d->downloadUrl;
0824 }
0825 
0826 File::IndexableTextPtr &File::indexableText()
0827 {
0828     return d->indexableText;
0829 }
0830 
0831 PermissionPtr File::userPermission() const
0832 {
0833     return d->userPermission;
0834 }
0835 
0836 QString File::fileExtension() const
0837 {
0838     return d->fileExtension;
0839 }
0840 
0841 QString File::md5Checksum() const
0842 {
0843     return d->md5Checksum;
0844 }
0845 
0846 qlonglong File::fileSize() const
0847 {
0848     return d->fileSize;
0849 }
0850 
0851 QUrl File::alternateLink() const
0852 {
0853     return d->alternateLink;
0854 }
0855 
0856 QUrl File::embedLink() const
0857 {
0858     return d->embedLink;
0859 }
0860 
0861 qlonglong File::version() const
0862 {
0863     return d->version;
0864 }
0865 
0866 QDateTime File::sharedWithMeDate() const
0867 {
0868     return d->sharedWithMeDate;
0869 }
0870 
0871 ParentReferencesList File::parents() const
0872 {
0873     return d->parents;
0874 }
0875 
0876 void File::setParents(const ParentReferencesList &parents)
0877 {
0878     d->parents = parents;
0879 }
0880 
0881 QMap<QString, QUrl> File::exportLinks() const
0882 {
0883     return d->exportLinks;
0884 }
0885 
0886 QString File::originalFileName() const
0887 {
0888     return d->originalFileName;
0889 }
0890 
0891 qlonglong File::quotaBytesUsed() const
0892 {
0893     return d->quotaBytesUsed;
0894 }
0895 
0896 QStringList File::ownerNames() const
0897 {
0898     return d->ownerNames;
0899 }
0900 
0901 QString File::lastModifyingUserName() const
0902 {
0903     return d->lastModifyingUserName;
0904 }
0905 
0906 bool File::editable() const
0907 {
0908     return d->editable;
0909 }
0910 
0911 bool File::writersCanShare() const
0912 {
0913     return d->writersCanShare;
0914 }
0915 
0916 QUrl File::thumbnailLink() const
0917 {
0918     return d->thumbnailLink;
0919 }
0920 
0921 QDateTime File::lastViewedByMeDate() const
0922 {
0923     return d->lastViewedByMeDate;
0924 }
0925 
0926 void File::setLastViewedByMeDate(const QDateTime &lastViewedByMeDate)
0927 {
0928     d->lastViewedByMeDate = lastViewedByMeDate;
0929 }
0930 
0931 QUrl File::webContentLink() const
0932 {
0933     return d->webContentLink;
0934 }
0935 
0936 bool File::explicitlyTrashed() const
0937 {
0938     return d->explicitlyTrashed;
0939 }
0940 
0941 File::ImageMediaMetadataPtr File::imageMediaMetadata() const
0942 {
0943     return d->imageMediaMetadata;
0944 }
0945 
0946 File::ThumbnailPtr File::thumbnail() const
0947 {
0948     return d->thumbnail;
0949 }
0950 
0951 QUrl File::webViewLink() const
0952 {
0953     return d->webViewLink;
0954 }
0955 
0956 QUrl File::iconLink() const
0957 {
0958     return d->iconLink;
0959 }
0960 
0961 bool File::shared() const
0962 {
0963     return d->shared;
0964 }
0965 
0966 UsersList File::owners() const
0967 {
0968     return d->owners;
0969 }
0970 
0971 UserPtr File::lastModifyingUser() const
0972 {
0973     return d->lastModifyingUser;
0974 }
0975 
0976 bool File::isFolder() const
0977 {
0978     return (d->mimeType == File::folderMimeType());
0979 }
0980 
0981 const QString File::Fields::Kind = QStringLiteral("kind");
0982 const QString File::Fields::Items = QStringLiteral("items");
0983 const QString File::Fields::NextLink = QStringLiteral("nextLink");
0984 const QString File::Fields::NextPageToken = QStringLiteral("nextPageToken");
0985 const QString File::Fields::SelfLink = QStringLiteral("selfLink");
0986 const QString File::Fields::Etag = QStringLiteral("etag");
0987 const QString File::Fields::Id = QStringLiteral("id");
0988 const QString File::Fields::Title = QStringLiteral("title");
0989 const QString File::Fields::MimeType = QStringLiteral("mimeType");
0990 const QString File::Fields::Description = QStringLiteral("description");
0991 const QString File::Fields::Labels = QStringLiteral("labels");
0992 const QString File::Fields::CreatedDate = QStringLiteral("createdDate");
0993 const QString File::Fields::ModifiedDate = QStringLiteral("modifiedDate");
0994 const QString File::Fields::ModifiedByMeDate = QStringLiteral("modifiedByMeDate");
0995 const QString File::Fields::DownloadUrl = QStringLiteral("downloadUrl");
0996 const QString File::Fields::IndexableText = QStringLiteral("indexableText");
0997 const QString File::Fields::UserPermission = QStringLiteral("userPermission");
0998 const QString File::Fields::FileExtension = QStringLiteral("fileExtension");
0999 const QString File::Fields::Md5Checksum = QStringLiteral("md5Checksum");
1000 const QString File::Fields::FileSize = QStringLiteral("fileSize");
1001 const QString File::Fields::AlternateLink = QStringLiteral("alternateLink");
1002 const QString File::Fields::EmbedLink = QStringLiteral("embedLink");
1003 const QString File::Fields::SharedWithMeDate = QStringLiteral("sharedWithMeDate");
1004 const QString File::Fields::Parents = QStringLiteral("parents");
1005 const QString File::Fields::ExportLinks = QStringLiteral("exportLinks");
1006 const QString File::Fields::OriginalFilename = QStringLiteral("originalFilename");
1007 const QString File::Fields::OwnerNames = QStringLiteral("ownerNames");
1008 const QString File::Fields::LastModifiedByMeDate = QStringLiteral("lastModifiedByMeDate");
1009 const QString File::Fields::Editable = QStringLiteral("editable");
1010 const QString File::Fields::WritersCanShare = QStringLiteral("writersCanShare");
1011 const QString File::Fields::ThumbnailLink = QStringLiteral("thumbnailLink");
1012 const QString File::Fields::LastViewedByMeDate = QStringLiteral("lastViewedByMeDate");
1013 const QString File::Fields::WebContentLink = QStringLiteral("webContentLink");
1014 const QString File::Fields::ExplicitlyTrashed = QStringLiteral("explicitlyTrashed");
1015 const QString File::Fields::ImageMediaMetadata = QStringLiteral("imageMediaMetadata");
1016 const QString File::Fields::Thumbnail = QStringLiteral("thumbnail");
1017 const QString File::Fields::WebViewLink = QStringLiteral("webViewLink");
1018 const QString File::Fields::IconLink = QStringLiteral("iconLink");
1019 const QString File::Fields::Shared = QStringLiteral("shared");
1020 const QString File::Fields::Owners = QStringLiteral("owners");
1021 const QString File::Fields::LastModifyingUser = QStringLiteral("lastModifyingUser");
1022 const QString File::Fields::AppDataContents = QStringLiteral("appDataContents");
1023 const QString File::Fields::OpenWithLinks = QStringLiteral("openWithLinks");
1024 const QString File::Fields::DefaultOpenWithLink = QStringLiteral("defaultOpenWithLink");
1025 const QString File::Fields::HeadRevisionId = QStringLiteral("headRevisionId");
1026 const QString File::Fields::Copyable = QStringLiteral("copyable");
1027 const QString File::Fields::Properties = QStringLiteral("properties");
1028 const QString File::Fields::MarkedViewedByMeDate = QStringLiteral("markedViewedByMeDate");
1029 const QString File::Fields::Version = QStringLiteral("version");
1030 const QString File::Fields::SharingUser = QStringLiteral("sharingUser");
1031 const QString File::Fields::Permissions = QStringLiteral("permissions");
1032 
1033 FilePtr File::fromJSON(const QByteArray &jsonData)
1034 {
1035     QJsonDocument document = QJsonDocument::fromJson(jsonData);
1036     if (document.isNull()) {
1037         return FilePtr();
1038     }
1039     const QVariant data = document.toVariant();
1040     return Private::fromJSON(data.toMap());
1041 }
1042 
1043 FilePtr File::fromJSON(const QVariantMap &jsonData)
1044 {
1045     if (jsonData.isEmpty()) {
1046         return FilePtr();
1047     }
1048     return Private::fromJSON(jsonData);
1049 }
1050 
1051 FilesList File::fromJSONFeed(const QByteArray &jsonData, FeedData &feedData)
1052 {
1053     QJsonDocument document = QJsonDocument::fromJson(jsonData);
1054     if (document.isNull()) {
1055         return FilesList();
1056     }
1057     const QVariant data = document.toVariant();
1058     const QVariantMap map = data.toMap();
1059     if (!map.contains(File::Fields::Kind) || map[Fields::Kind].toString() != QLatin1StringView("drive#fileList")) {
1060         return FilesList();
1061     }
1062 
1063     FilesList list;
1064     const QVariantList items = map[File::Fields::Items].toList();
1065     for (const QVariant &item : items) {
1066         const FilePtr file = Private::fromJSON(item.toMap());
1067 
1068         if (!file.isNull()) {
1069             list << file;
1070         }
1071     }
1072 
1073     if (map.contains(File::Fields::NextLink)) {
1074         feedData.nextPageUrl = map[File::Fields::NextLink].toUrl();
1075     }
1076 
1077     return list;
1078 }
1079 
1080 QByteArray File::toJSON(const FilePtr &file, SerializationOptions options)
1081 {
1082     QVariantMap map;
1083 
1084     map[File::Fields::Kind] = QLatin1StringView("drive#file");
1085     if (!file->description().isEmpty()) {
1086         map[Fields::Description] = file->description();
1087     }
1088 
1089     if (file->indexableText() && !file->indexableText()->text().isEmpty()) {
1090         QVariantMap indexableText;
1091         indexableText[QStringLiteral("text")] = file->indexableText()->text();
1092         map[Fields::IndexableText] = indexableText;
1093     }
1094 
1095     if (file->labels()) {
1096         QVariantMap labels;
1097         labels[QStringLiteral("hidden")] = file->labels()->hidden();
1098         labels[QStringLiteral("restricted")] = file->labels()->restricted();
1099         labels[QStringLiteral("starred")] = file->labels()->starred();
1100         labels[QStringLiteral("trashed")] = file->labels()->trashed();
1101         labels[QStringLiteral("viewed")] = file->labels()->viewed();
1102         map[Fields::Labels] = labels;
1103     }
1104 
1105     if (file->lastViewedByMeDate().isValid()) {
1106         map[Fields::LastViewedByMeDate] = file->lastViewedByMeDate().toString(Qt::ISODate);
1107     }
1108 
1109     if (!file->mimeType().isEmpty()) {
1110         map[Fields::MimeType] = file->mimeType();
1111     }
1112 
1113     if (file->modifiedDate().isValid()) {
1114         map[Fields::ModifiedDate] = file->modifiedDate().toString(Qt::ISODate);
1115     }
1116     if (file->createdDate().isValid() && !(options & ExcludeCreationDate)) {
1117         map[Fields::CreatedDate] = file->createdDate().toString(Qt::ISODate);
1118     }
1119     if (file->modifiedByMeDate().isValid()) {
1120         map[Fields::ModifiedByMeDate] = file->modifiedByMeDate().toString(Qt::ISODate);
1121     }
1122 
1123     if (file->fileSize() > 0) {
1124         map[Fields::FileSize] = file->fileSize();
1125     }
1126 
1127     if (!file->title().isEmpty()) {
1128         map[Fields::Title] = file->title();
1129     }
1130 
1131     QVariantList parents;
1132     const auto parentReferences = file->parents();
1133     parents.reserve(parentReferences.size());
1134     for (const ParentReferencePtr &parent : parentReferences) {
1135         parents << ParentReference::Private::toJSON(parent);
1136     }
1137     if (!parents.isEmpty()) {
1138         map[Fields::Parents] = parents;
1139     }
1140     if (!file->etag().isEmpty()) {
1141         map[Fields::Etag] = file->etag();
1142     }
1143     if (!file->d->id.isEmpty()) {
1144         map[Fields::Id] = file->d->id;
1145     }
1146     if (!file->d->selfLink.isEmpty()) {
1147         map[Fields::SelfLink] = file->d->selfLink;
1148     }
1149     if (!file->d->downloadUrl.isEmpty()) {
1150         map[Fields::DownloadUrl] = file->d->downloadUrl;
1151     }
1152 
1153     if (!file->d->fileExtension.isEmpty()) {
1154         map[Fields::FileExtension] = file->d->fileExtension;
1155     }
1156     if (!file->d->md5Checksum.isEmpty()) {
1157         map[Fields::Md5Checksum] = file->d->md5Checksum;
1158     }
1159     if (!file->d->alternateLink.isEmpty()) {
1160         map[Fields::AlternateLink] = file->d->alternateLink;
1161     }
1162     if (!file->d->embedLink.isEmpty()) {
1163         map[Fields::EmbedLink] = file->d->embedLink;
1164     }
1165     if (!file->d->sharedWithMeDate.isNull()) {
1166         map[Fields::SharedWithMeDate] = file->d->sharedWithMeDate.toString(Qt::ISODate);
1167     }
1168 
1169     if (!file->d->originalFileName.isEmpty()) {
1170         map[QStringLiteral("originalFileName")] = file->d->originalFileName;
1171     }
1172     if (file->d->quotaBytesUsed > 0) {
1173         map[QStringLiteral("quotaBytesUsed")] = file->d->quotaBytesUsed;
1174     }
1175     if (!file->d->ownerNames.isEmpty()) {
1176         map[Fields::OwnerNames] = QVariant(file->d->ownerNames);
1177     }
1178     if (!file->d->lastModifyingUserName.isEmpty()) {
1179         map[QStringLiteral("lastModifyingUserName")] = file->d->lastModifyingUserName;
1180     }
1181     if (!file->d->editable) { // default is true
1182         map[Fields::Editable] = file->d->editable;
1183     }
1184     if (file->d->writersCanShare) { // default is false
1185         map[Fields::WritersCanShare] = file->d->writersCanShare;
1186     }
1187     if (!file->d->thumbnailLink.isEmpty()) {
1188         map[Fields::ThumbnailLink] = file->d->thumbnailLink;
1189     }
1190     if (!file->d->lastViewedByMeDate.isNull()) {
1191         map[Fields::LastViewedByMeDate] = file->d->lastViewedByMeDate.toString(Qt::ISODate);
1192     }
1193     if (!file->d->webContentLink.isEmpty()) {
1194         map[Fields::WebContentLink] = file->d->webContentLink;
1195     }
1196     if (file->d->explicitlyTrashed) {
1197         map[Fields::ExplicitlyTrashed] = file->d->explicitlyTrashed;
1198     }
1199 
1200     if (!file->d->webViewLink.isEmpty()) {
1201         map[Fields::WebViewLink] = file->d->webViewLink;
1202     }
1203     if (!file->d->iconLink.isEmpty()) {
1204         map[Fields::IconLink] = file->d->iconLink;
1205     }
1206     if (file->d->shared) {
1207         map[Fields::Shared] = file->d->shared;
1208     }
1209 
1210 #if 0
1211     const QVariantMap userPermissionData = map[QLatin1StringView("userPermission")].toMap();
1212     file->d->userPermission = Permission::Private::fromJSON(userPermissionData);
1213 
1214     const QVariantList parents = map[QLatin1StringView("parents")].toList();
1215     for (const QVariant &parent : parents)
1216     {
1217         file->d->parents << ParentReference::Private::fromJSON(parent.toMap());
1218     }
1219 
1220     const QVariantMap exportLinksData = map[QLatin1StringView("exportLinks")].toMap();
1221     QVariantMap::ConstIterator iter = exportLinksData.constBegin();
1222     for ( ; iter != exportLinksData.constEnd(); ++iter) {
1223         file->d->exportLinks.insert(iter.key(), iter.value().toUrl());
1224     }
1225 
1226 
1227     const QVariantMap imageMetaData = map[QLatin1StringView("imageMediaMetadata")].toMap();
1228     file->d->imageMediaMetadata =
1229         File::ImageMediaMetadataPtr(new File::ImageMediaMetadata(imageMetaData));
1230 
1231     const QVariantMap thumbnailData = map[QLatin1StringView("thumbnail")].toMap();
1232     File::ThumbnailPtr thumbnail(new File::Thumbnail(thumbnailData));
1233     file->d->thumbnail = thumbnail;
1234 
1235 
1236     const QVariantList ownersList = map[QLatin1StringView("owners")].toList();
1237     for (const QVariant &owner : ownersList) {
1238         file->d->owners << User::fromJSON(owner.toMap());
1239     }
1240 
1241     const QVariantMap lastModifyingUser = map[QLatin1StringView("lastModifyingUser")].toMap();
1242     file->d->lastModifyingUser = User::fromJSON(lastModifyingUser);
1243 
1244 #endif
1245 
1246     QJsonDocument document = QJsonDocument::fromVariant(map);
1247     return document.toJson(QJsonDocument::Compact);
1248 }