diff --git a/src/fm/fm.cpp b/src/fm/fm.cpp index a86666c..9f1629e 100644 --- a/src/fm/fm.cpp +++ b/src/fm/fm.cpp @@ -1,949 +1,949 @@ /* * Copyright 2018 Camilo Higuita * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "fm.h" #include "utils.h" #include "tagging.h" #include "syncing.h" #include #include #include #include #include #include #include #include #include #include #include #include #if defined(Q_OS_ANDROID) #include "mauiandroid.h" #else #include "mauikde.h" #include #include #include #include #include #include #include #endif /* * FM *FM::instance = nullptr; * * FM* FM::getInstance() * { * if(!instance) * { * instance = new FM(); * qDebug() << "getInstance(): First instance\n"; * instance->init(); * return instance; * } else * { * qDebug()<< "getInstance(): previous instance\n"; * return instance; * } * }*/ #ifdef Q_OS_ANDROID FM::FM(QObject *parent) : FMDB(parent), sync(new Syncing(this)), tag(Tagging::getInstance()) #else FM::FM(QObject *parent) : FMDB(parent), sync(new Syncing(this)), tag(Tagging::getInstance()), dirLister(new KCoreDirLister(this)) #endif { #if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) this->dirLister->setAutoUpdate(true); connect(dirLister, static_cast(&KCoreDirLister::completed), [&](QUrl url) { qDebug()<< "PATH CONTENT READY" << url; FMH::PATH_CONTENT res; FMH::MODEL_LIST content; for(const auto &kfile : dirLister->items()) { qDebug() << kfile.url() << kfile.name() << kfile.isDir(); - content << FMH::MODEL{ {FMH::MODEL_KEY::LABEL, kfile.name()}, - {FMH::MODEL_KEY::NAME, kfile.name()}, - {FMH::MODEL_KEY::DATE, kfile.time(KFileItem::FileTimes::CreationTime).toString(Qt::TextDate)}, - {FMH::MODEL_KEY::MODIFIED, kfile.time(KFileItem::FileTimes::ModificationTime).toString(Qt::TextDate)}, - {FMH::MODEL_KEY::PATH, kfile.url().toString()}, - {FMH::MODEL_KEY::THUMBNAIL, kfile.localPath()}, - {FMH::MODEL_KEY::MIME, kfile.mimetype()}, - {FMH::MODEL_KEY::GROUP, kfile.group()}, - {FMH::MODEL_KEY::ICON, kfile.iconName()}, - {FMH::MODEL_KEY::SIZE, QString::number(kfile.size())}, - {FMH::MODEL_KEY::THUMBNAIL, kfile.mostLocalUrl().toString()}, - {FMH::MODEL_KEY::OWNER, kfile.user()}, - {FMH::MODEL_KEY::COUNT, kfile.isLocalFile() && kfile.isDir() ? QString::number(QDir(kfile.localPath()).count() - 2) : "0"} + content << FMH::MODEL{ {KEYS::LABEL, kfile.name()}, + {KEYS::NAME, kfile.name()}, + {KEYS::DATE, kfile.time(KFileItem::FileTimes::CreationTime).toString(Qt::TextDate)}, + {KEYS::MODIFIED, kfile.time(KFileItem::FileTimes::ModificationTime).toString(Qt::TextDate)}, + {KEYS::PATH, kfile.url().toString()}, + {KEYS::THUMBNAIL, kfile.localPath()}, + {KEYS::MIME, kfile.mimetype()}, + {KEYS::GROUP, kfile.group()}, + {KEYS::ICON, kfile.iconName()}, + {KEYS::SIZE, QString::number(kfile.size())}, + {KEYS::THUMBNAIL, kfile.mostLocalUrl().toString()}, + {KEYS::OWNER, kfile.user()}, + {KEYS::COUNT, kfile.isLocalFile() && kfile.isDir() ? QString::number(QDir(kfile.localPath()).count() - 2) : "0"} }; } res.path = url.toString(); res.content = content; emit this->pathContentReady(res); }); connect(dirLister, static_cast(&KCoreDirLister::itemsAdded), [&]() { qDebug()<< "MORE ITEMS WERE ADDED"; emit this->pathContentChanged(dirLister->url()); }); connect(dirLister, static_cast(&KCoreDirLister::newItems), [&]() { qDebug()<< "MORE NEW ITEMS WERE ADDED"; emit this->pathContentChanged(dirLister->url()); }); connect(dirLister, static_cast(&KCoreDirLister::itemsDeleted), [&]() { qDebug()<< "ITEMS WERE DELETED"; dirLister->updateDirectory(dirLister->url()); // emit this->pathContentChanged(dirLister->url()); // changes when dleted items are not that important? }); connect(dirLister, static_cast > &items)>(&KCoreDirLister::refreshItems), [&]() { qDebug()<< "ITEMS WERE REFRESHED"; dirLister->updateDirectory(dirLister->url()); emit this->pathContentChanged(dirLister->url()); }); #endif connect(this->sync, &Syncing::listReady, [this](const FMH::MODEL_LIST &list, const QString &url) { emit this->cloudServerContentReady(list, url); }); connect(this->sync, &Syncing::itemReady, [this](const FMH::MODEL &item, const QString &url, const Syncing::SIGNAL_TYPE &signalType) { switch(signalType) { case Syncing::SIGNAL_TYPE::OPEN: - this->openUrl(item[FMH::MODEL_KEY::PATH]); + this->openUrl(item[KEYS::PATH]); break; case Syncing::SIGNAL_TYPE::DOWNLOAD: emit this->cloudItemReady(item, url); break; case Syncing::SIGNAL_TYPE::COPY: { QVariantMap data; for(auto key : item.keys()) - data.insert(FMH::MODEL_NAME[key], item[key]); + data.insert(KEYS::_N[key], item[key]); this->copy(QVariantList {data}, this->sync->getCopyTo()); break; } default: return; } }); connect(this->sync, &Syncing::error, [this](const QString &message) { emit this->warningMessage(message); }); connect(this->sync, &Syncing::progress, [this](const int &percent) { emit this->loadProgress(percent); }); connect(this->sync, &Syncing::dirCreated, [this](const FMH::MODEL &dir, const QString &url) { emit this->newItem(dir, url); }); connect(this->sync, &Syncing::uploadReady, [this](const FMH::MODEL &item, const QString &url) { emit this->newItem(item, url); }); } FM::~FM() {} QVariantMap FM::toMap(const FMH::MODEL& model) { QVariantMap map; for(const auto &key : model.keys()) - map.insert(FMH::MODEL_NAME[key], model[key]); + map.insert(KEYS::_N[key], model[key]); return map; } FMH::MODEL FM::toModel(const QVariantMap& map) { FMH::MODEL model; for(const auto &key : map.keys()) - model.insert(FMH::MODEL_NAME_KEY[key], map[key].toString()); + model.insert(KEYS::_K[key], map[key].toString()); return model; } FMH::MODEL_LIST FM::packItems(const QStringList &items, const QString &type) { FMH::MODEL_LIST data; for(const auto &path : items) if(FMH::fileExists(path)) { auto model = FMH::getFileInfoModel(path); - model.insert(FMH::MODEL_KEY::TYPE, type); + model.insert(KEYS::TYPE, type); data << model; } return data; } QVariantList FM::get(const QString &queryTxt) { QVariantList mapList; auto query = this->getQuery(queryTxt); if(query.exec()) { while(query.next()) { QVariantMap data; - for(auto key : FMH::MODEL_NAME.keys()) - if(query.record().indexOf(FMH::MODEL_NAME[key]) > -1) - data[FMH::MODEL_NAME[key]] = query.value(FMH::MODEL_NAME[key]).toString(); + for(const auto nameKey : KEYS::_NAMES()) + if(query.record().indexOf(nameKey) > -1) + data[nameKey] = query.value(nameKey).toString(); mapList<< data; } }else qDebug()<< query.lastError()<< query.lastQuery(); return mapList; } void FM::getPathContent(const QUrl& path, const bool &hidden, const bool &onlyDirs, const QStringList& filters, const QDirIterator::IteratorFlags &iteratorFlags) { qDebug()<< "Getting async path contents"; #ifdef Q_OS_ANDROID QFutureWatcher *watcher = new QFutureWatcher; connect(watcher, &QFutureWatcher::finished, [this, watcher = std::move(watcher)]() { emit this->pathContentReady(watcher->future().result()); watcher->deleteLater(); }); QFuture t1 = QtConcurrent::run([=]() -> FMH::PATH_CONTENT { FMH::PATH_CONTENT res; res.path = path.toString(); FMH::MODEL_LIST content; if (FM::isDir(path)) { QDir::Filters dirFilter; dirFilter = (onlyDirs ? QDir::AllDirs | QDir::NoDotDot | QDir::NoDot : QDir::Files | QDir::AllDirs | QDir::NoDotDot | QDir::NoDot); if(hidden) dirFilter = dirFilter | QDir::Hidden | QDir::System; QDirIterator it (path.toLocalFile(), filters, dirFilter, iteratorFlags); while (it.hasNext()) content << FMH::getFileInfoModel(QUrl::fromLocalFile(it.next())); } res.content = content; return res; }); watcher->setFuture(t1); #else this->dirLister->setShowingDotFiles(hidden); this->dirLister->setDirOnlyMode(onlyDirs); this->dirLister->setNameFilter(filters.join(" ")); // if(this->dirLister->url() == path) // { // this->dirLister->emitChanges(); // return; // } if(this->dirLister->openUrl(path)) qDebug()<< "GETTING PATH CONTENT" << path; #endif } void FM::getTrashContent() { #if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) if(this->dirLister->openUrl(QUrl("trash://"))) qDebug()<< "TRASH CONTENT"; #endif } FMH::MODEL_LIST FM::getAppsContent(const QString& path) { FMH::MODEL_LIST res; #if (defined (Q_OS_LINUX) && !defined (Q_OS_ANDROID)) QUrl __url(path); // if(__url.scheme() == FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::APPS_PATH]) return MAUIKDE::getApps(QString(path).replace("apps://", "")); #endif return res; } FMH::MODEL_LIST FM::getDefaultPaths() { return packItems(FMH::defaultPaths, FMH::PATHTYPE_LABEL[FMH::PATHTYPE_KEY::PLACES_PATH]); } FMH::MODEL_LIST FM::getAppsPath() { #ifdef Q_OS_ANDROID return FMH::MODEL_LIST(); #endif return FMH::MODEL_LIST { FMH::MODEL { - {FMH::MODEL_KEY::ICON, "system-run"}, - {FMH::MODEL_KEY::LABEL, FMH::PATHTYPE_LABEL[FMH::PATHTYPE_KEY::APPS_PATH]}, - {FMH::MODEL_KEY::PATH, FMH::PATHTYPE_URI[FMH::PATHTYPE_KEY::APPS_PATH]}, - {FMH::MODEL_KEY::TYPE, FMH::PATHTYPE_LABEL[FMH::PATHTYPE_KEY::PLACES_PATH]} + {KEYS::ICON, "system-run"}, + {KEYS::LABEL, FMH::PATHTYPE_LABEL[FMH::PATHTYPE_KEY::APPS_PATH]}, + {KEYS::PATH, FMH::PATHTYPE_URI[FMH::PATHTYPE_KEY::APPS_PATH]}, + {KEYS::TYPE, FMH::PATHTYPE_LABEL[FMH::PATHTYPE_KEY::PLACES_PATH]} } }; } FMH::MODEL_LIST FM::search(const QString& query, const QUrl &path, const bool &hidden, const bool &onlyDirs, const QStringList &filters) { FMH::MODEL_LIST content; if(!path.isLocalFile()) { qWarning() << "URL recived is not a local file. FM::search" << path; return content; } if (FM::isDir(path)) { QDir::Filters dirFilter; dirFilter = (onlyDirs ? QDir::AllDirs | QDir::NoDotDot | QDir::NoDot : QDir::Files | QDir::AllDirs | QDir::NoDotDot | QDir::NoDot); if(hidden) dirFilter = dirFilter | QDir::Hidden | QDir::System; QDirIterator it (path.toLocalFile(), filters, dirFilter, QDirIterator::Subdirectories); while (it.hasNext()) { auto url = it.next(); auto info = it.fileInfo(); if(info.completeBaseName().contains(query, Qt::CaseInsensitive)) { content << FMH::getFileInfoModel(QUrl::fromLocalFile(url)); } } }else qWarning() << "Search path does not exists" << path; qDebug()<< content; return content; } // FMH::MODEL_LIST FM::getDevices() // { // FMH::MODEL_LIST drives; // // #if defined(Q_OS_ANDROID) // drives << packItems({MAUIAndroid::sdDir()}, FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::DRIVES_PATH]); // return drives; // #else // KFilePlacesModel model; // for(const auto &i : model.groupIndexes(KFilePlacesModel::GroupType::RemoteType)) // { // drives << FMH::MODEL{ -// {FMH::MODEL_KEY::NAME, model.text(i)}, -// {FMH::MODEL_KEY::LABEL, model.text(i)}, -// {FMH::MODEL_KEY::PATH, model.url(i).toString()}, -// {FMH::MODEL_KEY::ICON, model.icon(i).name()}, -// {FMH::MODEL_KEY::TYPE, FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::DRIVES_PATH]}, +// {KEYS::NAME, model.text(i)}, +// {KEYS::LABEL, model.text(i)}, +// {KEYS::PATH, model.url(i).toString()}, +// {KEYS::ICON, model.icon(i).name()}, +// {KEYS::TYPE, FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::DRIVES_PATH]}, // }; // } // // #endif // // // auto devices = QStorageInfo::mountedVolumes(); // // for(auto device : devices) // // { // // if(device.isValid() && !device.isReadOnly()) // // { // // QVariantMap drive = // // { -// // {FMH::MODEL_NAME[FMH::MODEL_KEY::ICON], "drive-harddisk"}, -// // {FMH::MODEL_NAME[FMH::MODEL_KEY::LABEL], device.displayName()}, -// // {FMH::MODEL_NAME[FMH::MODEL_KEY::PATH], device.rootPath()}, -// // {FMH::MODEL_NAME[FMH::MODEL_KEY::TYPE], FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::DRIVES]} +// // {KEYS::_N[KEYS::ICON], "drive-harddisk"}, +// // {KEYS::_N[KEYS::LABEL], device.displayName()}, +// // {KEYS::_N[KEYS::PATH], device.rootPath()}, +// // {KEYS::_N[KEYS::TYPE], FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::DRIVES]} // // }; // // // // drives << drive; // // } // // } // // // for(auto device : QDir::drives()) // // { // // QVariantMap drive = // // { // // {"iconName", "drive-harddisk"}, // // {"label", device.baseName()}, // // {"path", device.absoluteFilePath()}, // // {"type", "Drives"} // // }; // // // drives << drive; // // } // // return drives; // } FMH::MODEL_LIST FM::getTags(const int &limit) { Q_UNUSED(limit); FMH::MODEL_LIST data; if(this->tag) { for(const auto &tag : this->tag->getUrlsTags(false)) { qDebug()<< "TAG << "<< tag; const auto label = tag.toMap().value(TAG::KEYMAP[TAG::KEYS::TAG]).toString(); data << FMH::MODEL { - {FMH::MODEL_KEY::PATH, FMH::PATHTYPE_URI[FMH::PATHTYPE_KEY::TAGS_PATH]+label}, - {FMH::MODEL_KEY::ICON, "tag"}, - {FMH::MODEL_KEY::LABEL, label}, - {FMH::MODEL_KEY::TYPE, FMH::PATHTYPE_LABEL[FMH::PATHTYPE_KEY::TAGS_PATH]} + {KEYS::PATH, FMH::PATHTYPE_URI[FMH::PATHTYPE_KEY::TAGS_PATH]+label}, + {KEYS::ICON, "tag"}, + {KEYS::LABEL, label}, + {KEYS::TYPE, FMH::PATHTYPE_LABEL[FMH::PATHTYPE_KEY::TAGS_PATH]} }; } } return data; } bool FM::getCloudServerContent(const QString &path, const QStringList &filters, const int &depth) { const auto __list = QString(path).replace("cloud://", "/").split("/"); if(__list.isEmpty() || __list.size() < 2) { qWarning()<< "Could not parse username to get cloud server content"; return false; } auto user = __list[1]; auto data = this->get(QString("select * from clouds where user = '%1'").arg(user)); if(data.isEmpty()) return false; auto map = data.first().toMap(); - user = map[FMH::MODEL_NAME[FMH::MODEL_KEY::USER]].toString(); - auto server = map[FMH::MODEL_NAME[FMH::MODEL_KEY::SERVER]].toString(); - auto password = map[FMH::MODEL_NAME[FMH::MODEL_KEY::PASSWORD]].toString(); + user = map[KEYS::_N[KEYS::USER]].toString(); + auto server = map[KEYS::_N[KEYS::SERVER]].toString(); + auto password = map[KEYS::_N[KEYS::PASSWORD]].toString(); this->sync->setCredentials(server, user, password); this->sync->listContent(path, filters, depth); return true; } FMH::MODEL_LIST FM::getCloudAccounts() { auto accounts = this->get("select * from clouds"); FMH::MODEL_LIST res; for(const auto &account : accounts) { auto map = account.toMap(); res << FMH::MODEL { - {FMH::MODEL_KEY::PATH, FMH::PATHTYPE_URI[FMH::PATHTYPE_KEY::CLOUD_PATH]+map[FMH::MODEL_NAME[FMH::MODEL_KEY::USER]].toString()}, - {FMH::MODEL_KEY::ICON, "folder-cloud"}, - {FMH::MODEL_KEY::LABEL, map[FMH::MODEL_NAME[FMH::MODEL_KEY::USER]].toString()}, - {FMH::MODEL_KEY::USER, map[FMH::MODEL_NAME[FMH::MODEL_KEY::USER]].toString()}, - {FMH::MODEL_KEY::SERVER, map[FMH::MODEL_NAME[FMH::MODEL_KEY::SERVER]].toString()}, - {FMH::MODEL_KEY::PASSWORD, map[FMH::MODEL_NAME[FMH::MODEL_KEY::PASSWORD]].toString()}, - {FMH::MODEL_KEY::TYPE, FMH::PATHTYPE_LABEL[FMH::PATHTYPE_KEY::CLOUD_PATH]}}; + {KEYS::PATH, FMH::PATHTYPE_URI[FMH::PATHTYPE_KEY::CLOUD_PATH]+map[KEYS::_N[KEYS::USER]].toString()}, + {KEYS::ICON, "folder-cloud"}, + {KEYS::LABEL, map[KEYS::_N[KEYS::USER]].toString()}, + {KEYS::USER, map[KEYS::_N[KEYS::USER]].toString()}, + {KEYS::SERVER, map[KEYS::_N[KEYS::SERVER]].toString()}, + {KEYS::PASSWORD, map[KEYS::_N[KEYS::PASSWORD]].toString()}, + {KEYS::TYPE, FMH::PATHTYPE_LABEL[FMH::PATHTYPE_KEY::CLOUD_PATH]}}; } return res; } void FM::createCloudDir(const QString &path, const QString &name) { qDebug()<< "trying to create folder at"<< path; this->sync->createDir(path, name); } void FM::openCloudItem(const QVariantMap &item) { qDebug()<< item; FMH::MODEL data; for(const auto &key : item.keys()) - data.insert(FMH::MODEL_NAME_KEY[key], item[key].toString()); + data.insert(KEYS::_K[key], item[key].toString()); this->sync->resolveFile(data, Syncing::SIGNAL_TYPE::OPEN); } void FM::getCloudItem(const QVariantMap &item) { qDebug()<< item; FMH::MODEL data; for(const auto &key : item.keys()) - data.insert(FMH::MODEL_NAME_KEY[key], item[key].toString()); + data.insert(KEYS::_K[key], item[key].toString()); this->sync->resolveFile(data, Syncing::SIGNAL_TYPE::DOWNLOAD); } QVariantList FM::getCloudAccountsList() { QVariantList res; const auto data = this->getCloudAccounts(); for(const auto &item : data) res << FM::toMap(item); return res; } bool FM::addCloudAccount(const QString &server, const QString &user, const QString &password) { const QVariantMap account = { - {FMH::MODEL_NAME[FMH::MODEL_KEY::SERVER], server}, - {FMH::MODEL_NAME[FMH::MODEL_KEY::USER], user}, - {FMH::MODEL_NAME[FMH::MODEL_KEY::PASSWORD], password} + {KEYS::_N[KEYS::SERVER], server}, + {KEYS::_N[KEYS::USER], user}, + {KEYS::_N[KEYS::PASSWORD], password} }; if(this->insert(FMH::TABLEMAP[FMH::TABLE::CLOUDS], account)) { emit this->cloudAccountInserted(user); return true; } return false; } bool FM::removeCloudAccount(const QString &server, const QString &user) { FMH::DB account = { - {FMH::MODEL_KEY::SERVER, server}, - {FMH::MODEL_KEY::USER, user}, + {KEYS::SERVER, server}, + {KEYS::USER, user}, }; if(this->remove(FMH::TABLEMAP[FMH::TABLE::CLOUDS], account)) { emit this->cloudAccountRemoved(user); return true; } return false; } QString FM::resolveUserCloudCachePath(const QString &server, const QString &user) { return FMH::CloudCachePath+"opendesktop/"+user; } QString FM::resolveLocalCloudPath(const QString& path) { return QString(path).replace(FMH::PATHTYPE_URI[FMH::PATHTYPE_KEY::CLOUD_PATH]+this->sync->getUser(), ""); } FMH::MODEL_LIST FM::getTagContent(const QString &tag) { FMH::MODEL_LIST content; qDebug()<< "TAG CONTENT FOR TAG"<< tag; for(const auto &data : this->tag->getUrls(tag, false)) { const auto url = data.toMap().value(TAG::KEYMAP[TAG::KEYS::URL]).toString(); auto item = FMH::getFileInfoModel(QUrl::fromLocalFile(url)); content << item; } return content; } QVariantMap FM::getDirInfo(const QUrl &path, const QString &type) { return FMH::getDirInfo(path, type); } QVariantMap FM::getFileInfo(const QUrl &path) { return FMH::getFileInfo(path); } bool FM::isDefaultPath(const QString &path) { return FMH::defaultPaths.contains(path); } QUrl FM::parentDir(const QUrl &path) { if(!path.isLocalFile()) { qWarning() << "URL recived is not a local file, FM::parentDir" << path; return path; } QDir dir(path.toLocalFile()); dir.cdUp(); return QUrl::fromLocalFile(dir.absolutePath()); } bool FM::isDir(const QUrl &path) { if(!path.isLocalFile()) { qWarning() << "URL recived is not a local file. FM::isDir" << path; return false; } QFileInfo file(path.toLocalFile()); return file.isDir(); } bool FM::isApp(const QString& path) { return /*QFileInfo(path).isExecutable() ||*/ path.endsWith(".desktop"); } bool FM::isCloud(const QUrl &path) { return path.scheme() == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::CLOUD_PATH]; } bool FM::fileExists(const QUrl &path) { return FMH::fileExists(path); } void FM::saveSettings(const QString &key, const QVariant &value, const QString &group) { UTIL::saveSettings(key, value, group); } QVariant FM::loadSettings(const QString &key, const QString &group, const QVariant &defaultValue) { return UTIL::loadSettings(key, group, defaultValue); } QString FM::formatSize(const int &size) { QLocale locale; return locale.formattedDataSize(size); } QString FM::formatDate(const QString &dateStr, const QString &format, const QString &initFormat) { QDateTime date; if( initFormat.isEmpty() ) date = QDateTime::fromString(dateStr, Qt::TextDate); else date = QDateTime::fromString(dateStr, initFormat); return date.toString(format); } QString FM::homePath() { return FMH::HomePath; } bool FM::cut(const QVariantList &data, const QString &where) { FMH::MODEL_LIST items; for(const auto &k : data) items << FM::toModel(k.toMap()); for(const auto &item : items) { - const auto path = item[FMH::MODEL_KEY::PATH]; + const auto path = item[KEYS::PATH]; if(this->isCloud(path)) { this->sync->setCopyTo(where); this->sync->resolveFile(item, Syncing::SIGNAL_TYPE::COPY); }else if(FMH::fileExists(path)) { #ifdef Q_OS_ANDROID QFile file(QUrl(path).toLocalFile()); file.rename(where+"/"+QFileInfo(QUrl(path).toLocalFile()).fileName()); #else - auto job = KIO::move(QUrl(path), QUrl(where+"/"+FMH::getFileInfoModel(path)[FMH::MODEL_KEY::LABEL])); + auto job = KIO::move(QUrl(path), QUrl(where+"/"+FMH::getFileInfoModel(path)[KEYS::LABEL])); job->start(); #endif } } return true; } bool FM::copy(const QVariantList &data, const QString &where) { FMH::MODEL_LIST items; for(const auto &k : data) items << FM::toModel(k.toMap()); QStringList cloudPaths; for(const auto &item : items) { - const auto path = item[FMH::MODEL_KEY::PATH]; + const auto path = item[KEYS::PATH]; if(this->isDir(path)) { return FM::copyPath(path, where+"/"+QFileInfo(path).fileName(), false); }else if(this->isCloud(path)) { this->sync->setCopyTo(where); this->sync->resolveFile(item, Syncing::SIGNAL_TYPE::COPY); }else if(FMH::fileExists(path)) { if(this->isCloud(where)) cloudPaths << path; else - FM::copyPath(path, where+"/"+FMH::getFileInfoModel(path)[FMH::MODEL_KEY::LABEL], false); + FM::copyPath(path, where+"/"+FMH::getFileInfoModel(path)[KEYS::LABEL], false); } } if(!cloudPaths.isEmpty()) { qDebug()<<"UPLOAD QUEUE" << cloudPaths; const auto firstPath = cloudPaths.takeLast(); this->sync->setUploadQueue(cloudPaths); if(where.split("/").last().contains(".")) { QStringList whereList = where.split("/"); whereList.removeLast(); auto whereDir = whereList.join("/"); qDebug()<< "Trying ot copy to cloud" << where << whereDir; this->sync->upload(this->resolveLocalCloudPath(whereDir), firstPath); } else this->sync->upload(this->resolveLocalCloudPath(where), firstPath); } return true; } bool FM::copyPath(QUrl sourceDir, QUrl destinationDir, bool overWriteDirectory) { #ifdef Q_OS_ANDROID QFileInfo fileInfo(sourceDir.toLocalFile()); if(fileInfo.isFile()) QFile::copy(sourceDir.toLocalFile(), destinationDir.toLocalFile()); QDir originDirectory(sourceDir.toLocalFile()); if (!originDirectory.exists()) return false; QDir destinationDirectory(destinationDir.toLocalFile()); if(destinationDirectory.exists() && !overWriteDirectory) return false; else if(destinationDirectory.exists() && overWriteDirectory) destinationDirectory.removeRecursively(); originDirectory.mkpath(destinationDir.toLocalFile()); foreach(QString directoryName, originDirectory.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { QString destinationPath = destinationDir.toLocalFile() + "/" + directoryName; originDirectory.mkpath(destinationPath); copyPath(sourceDir.toLocalFile() + "/" + directoryName, destinationPath, overWriteDirectory); } foreach (QString fileName, originDirectory.entryList(QDir::Files)) { QFile::copy(sourceDir.toLocalFile() + "/" + fileName, destinationDir.toLocalFile() + "/" + fileName); } /*! Possible race-condition mitigation? */ QDir finalDestination(destinationDir.toLocalFile()); finalDestination.refresh(); if(finalDestination.exists()) return true; return false; #else qDebug()<< "TRYING TO COPY" << sourceDir.toLocalFile() << destinationDir.toLocalFile(); auto job = KIO::copy(QUrl(sourceDir), QUrl(destinationDir)); job->start(); return true; #endif } bool FM::removeFile(const QUrl &path) { if(!path.isLocalFile()) qWarning() << "URL recived is not a local file, FM::removeFile" << path; #ifdef Q_OS_ANDROID if(QFileInfo(path.toLocalFile()).isDir()) return removeDir(path); else return QFile(path.toLocalFile()).remove(); #else auto job = KIO::del(path); job->start(); return true; #endif } void FM::moveToTrash(const QUrl &path) { if(!path.isLocalFile()) qWarning() << "URL recived is not a local file, FM::moveToTrash" << path; #ifdef Q_OS_ANDROID #else auto job = KIO::trash(path); job->start(); #endif } void FM::emptyTrash() { #ifdef Q_OS_ANDROID #else auto job = KIO::emptyTrash(); job->start(); #endif } bool FM::removeDir(const QUrl &path) { bool result = true; QDir dir(path.toLocalFile()); qDebug()<< "TRYING TO REMOVE DIR" << path << path.toLocalFile(); if (dir.exists()) { Q_FOREACH(QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst)) { if (info.isDir()) { result = removeDir(QUrl::fromLocalFile(info.absoluteFilePath())); } else { result = QFile::remove(info.absoluteFilePath()); } if (!result) { return result; } } result = dir.rmdir(path.toLocalFile()); } return result; } bool FM::rename(const QUrl &path, const QString &name) { QFile file(path.toLocalFile()); const auto url = QFileInfo(path.toLocalFile()).dir().absolutePath(); return file.rename(url+"/"+name); } bool FM::createDir(const QUrl &path, const QString &name) { return QDir(path.toLocalFile()).mkdir(name); } bool FM::createFile(const QUrl &path, const QString &name) { QFile file(path.toLocalFile() + "/" + name); if(file.open(QIODevice::ReadWrite)) { file.close(); return true; } return false; } bool FM::openUrl(const QString &url) { return QDesktopServices::openUrl(QUrl::fromUserInput(url)); } void FM::openLocation(const QStringList &urls) { for(auto url : urls) QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(url).dir().absolutePath())); } void FM::runApplication(const QString& exec) { #if (defined (Q_OS_LINUX) && !defined (Q_OS_ANDROID)) return MAUIKDE::launchApp(exec); #endif } QVariantMap FM::dirConf(const QUrl &path) { return FMH::dirConf(path); } void FM::setDirConf(const QUrl &path, const QString &group, const QString &key, const QVariant &value) { FMH::setDirConf(path, group, key, value); } diff --git a/src/fm/fmdb.cpp b/src/fm/fmdb.cpp index f3de2b5..418cd71 100644 --- a/src/fm/fmdb.cpp +++ b/src/fm/fmdb.cpp @@ -1,223 +1,223 @@ #include "fmdb.h" #include"utils.h" #include FMDB::FMDB(QObject *parent) : QObject(parent) { QDir collectionDBPath_dir(FMH::FMPath); if (!collectionDBPath_dir.exists()) collectionDBPath_dir.mkpath("."); this->name = QUuid::createUuid().toString(); if(!UTIL::fileExists(FMH::FMPath + FMH::DBName)) { this->openDB(this->name); this->prepareCollectionDB(); }else this->openDB(this->name); } FMDB::~FMDB() { this->m_db.close(); } void FMDB::openDB(const QString &name) { if(!QSqlDatabase::contains(name)) { this->m_db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), name); this->m_db.setDatabaseName(FMH::FMPath + FMH::DBName); } if (!this->m_db.isOpen()) { if(!this->m_db.open()) qDebug()<<"ERROR OPENING DB"<m_db.lastError().text()<getQuery("PRAGMA synchronous=OFF"); query.exec(); } void FMDB::prepareCollectionDB() const { QSqlQuery query(this->m_db); QFile file(":/fm/script.sql"); if (!file.exists()) { QString log = QStringLiteral("Fatal error on build database. The file '"); log.append(file.fileName() + QStringLiteral("' for database and tables creation query cannot be not found!")); qDebug()<getQuery(queryStr); if (query.exec()) { if (query.next()) return true; }else qDebug()<getQuery(queryStr); if (query.exec()) { if (query.next()) return true; }else qDebug()<m_db); return query; } bool FMDB::insert(const QString &tableName, const QVariantMap &insertData) { if (tableName.isEmpty()) { qDebug()<m_db); query.prepare(sqlQueryString); int k = 0; foreach (const QVariant &value, values) query.bindValue(k++, value); return query.exec(); } bool FMDB::update(const QString &tableName, const FMH::DB &updateData, const QVariantMap &where) { if (tableName.isEmpty()) { qDebug()<getQuery(sqlQueryString); qDebug()<getQuery(queryStr); return query.exec(); } bool FMDB::remove(const QString &tableName, const FMH::DB &removeData) { if (tableName.isEmpty()) { qDebug()< 1 && igetQuery(sqlQueryString).exec(); } diff --git a/src/fm/fmh.h b/src/fm/fmh.h index 569d157..d3c0f91 100644 --- a/src/fm/fmh.h +++ b/src/fm/fmh.h @@ -1,1115 +1,944 @@ /* * Copyright 2018 Camilo Higuita * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef FMH_H #define FMH_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(Q_OS_ANDROID) #include "mauiandroid.h" #elif defined(Q_OS_LINUX) #include #include #include #include #endif - - /** *base key implementation model */ namespace PRIV { template struct __KEY { T value; QString n; QString label; uint operator[](std::string) { return value; } T operator()() { return value; } bool operator==(const __KEY &other) const { return (value == other.value && n == other.n); } + + inline operator uint()const + { + return value; + } }; typedef struct { QString n; QString label; } PUBLIC_KEY; // boilerplate code for custom qhash keys to work with qt inline uint qHash(const __KEY &key) { return qHash(key.n) ^ key.value; } // anon struct that holds the static list of keys on a keyring static struct { QHash> values; __KEY& operator << (const PUBLIC_KEY &__val) { if(values.contains(__val.n)) { - values[__val.n] = {static_cast(static_cast(values[__val.n].value)), __val.n, __val.label}; + values[__val.n].n = __val.n; + values[__val.n].label = __val.label; } - else { + else { + values[__val.n] = {static_cast(values.size()), __val.n, __val.label}; } + return (values[__val.n]); - // return std::forward<__KEY>(__k); } __KEY& operator[] (const QString &n) { return values[n]; } } KEYDB; } namespace KEYS { //type aliases typedef QHash> KEYRING; // the keyring containing the registered keys typedef PRIV::__KEY KEY; // alias to the wanted type of key with uint inline static const KEY& _SET (const QString &value) { return PRIV::KEYDB << PRIV::PUBLIC_KEY {value , QString()}; } inline static const KEY& _SET (const PRIV::PUBLIC_KEY &value) { return PRIV::KEYDB << value; } - inline static const QString& (_N)(const KEY & k) - { - return k.n; - } - - inline static const KEY& _K (const KEYRING::key_type &n) - { - return PRIV::KEYDB[n]; - } - - inline static const KEY& _K (const decltype(KEY::value) &value) - { - const auto res = std::find_if(PRIV::KEYDB.values.constBegin(), PRIV::KEYDB.values.constEnd(), [&value](const KEY &key) -> bool - { - return key.value == value; - }); - - return res.value(); - } inline static const KEYRING& _VALUES() { return PRIV::KEYDB.values; } inline static const QStringList _NAMES() { return std::accumulate(PRIV::KEYDB.values.constBegin(), PRIV::KEYDB.values.constEnd(), QStringList(), [](QStringList &res, const KEY &key) { res << key.n; return res; }); } inline static const QVector _KEYS() { return std::accumulate(PRIV::KEYDB.values.constBegin(), PRIV::KEYDB.values.constEnd(), QVector(), [](QVector &res, const KEY &key) { res << key.value; return res; }); } inline static uint _COUNT() { return uint (KEYS::_VALUES().count()); } + static struct + { + inline const decltype(KEY::n)& operator()(const KEY & k) + { + return k.n; + } + + inline const decltype(KEY::n)& operator[](const KEY & k) + { + return this->operator()(k); + } + } _N; + + static struct + { + inline const KEY& operator()(const KEYRING::key_type &n) + { + return PRIV::KEYDB[n]; + } + + inline const KEY& operator()(const decltype(KEY::value) &value) + { + const auto res = std::find_if(PRIV::KEYDB.values.constBegin(), PRIV::KEYDB.values.constEnd(), [&value](const KEY &key) -> bool + { + return key.value == value; + }); + + return res.value(); + } + + inline const KEY& operator[](const KEYRING::key_type &n) + { + return this->operator()(n); + } + + inline const KEY& operator[](const decltype(KEY::value) &value) + { + return this->operator()(value); + } + } _K; + static const auto &ICON= _SET("icon"); static const auto &LABEL = _SET("label"); static const auto &PATH = _SET("path"); static const auto &URL = _SET("url"); static const auto &TYPE = _SET("type"); static const auto &GROUP = _SET("group"); static const auto &OWNER = _SET("owner"); static const auto &SUFFIX = _SET("suffix"); static const auto &NAME = _SET("name"); static const auto &DATE = _SET("date"); static const auto &MODIFIED = _SET("modified"); static const auto &MIME = _SET("mime"); static const auto &SIZE = _SET("size"); static const auto &TAG = _SET("tag"); static const auto &PERMISSIONS = _SET("permissions"); static const auto &THUMBNAIL = _SET("thumbnail"); static const auto &THUMBNAIL_1 = _SET("thumbnail_1"); static const auto &THUMBNAIL_2 = _SET("thumbnail_2"); static const auto &THUMBNAIL_3 = _SET("thumbnail_3"); static const auto &ICONSIZE = _SET("iconsize"); static const auto &HIDDEN = _SET("hidden"); static const auto &DETAILVIEW = _SET("detailview"); static const auto &SHOWTERMINAL = _SET("showterminal"); static const auto &SHOWTHUMBNAIL = _SET("showthumbnail"); static const auto &COUNT = _SET("count"); static const auto &SORTBY = _SET("sortby"); static const auto &USER = _SET("user"); static const auto &PASSWORD = _SET("password"); static const auto &SERVER = _SET("server"); static const auto &FOLDERSFIRST = _SET("foldersfirst"); static const auto &VIEWTYPE = _SET("viewtype"); static const auto &ADDDATE = _SET("adddate"); static const auto &FAV = _SET("fav"); static const auto &FAVORITE = _SET("favorite"); static const auto &COLOR = _SET("color"); static const auto &RATE = _SET("rate"); static const auto &FORMAT = _SET("format"); static const auto &PLACE = _SET("place"); static const auto &LOCATION = _SET("location"); static const auto &ALBUM = _SET("album"); static const auto &DURATION = _SET("duration"); static const auto &RELEASEDATE = _SET("releasedate"); static const auto &ARTIST = _SET("artist"); static const auto &LYRICS = _SET("lyrics"); static const auto &TRACK = _SET("track"); static const auto &GENRE = _SET("genre"); static const auto &WIKI = _SET("wiki"); static const auto &CONTEXT = _SET("context"); static const auto &SOURCETYPE = _SET("sourcetype"); static const auto &ARTWORK= _SET("artwork"); static const auto &NOTE = _SET("note"); static const auto &MOOD = _SET("mood"); static const auto &COMMENT = _SET("comment"); static const auto &PLAYLIST = _SET("playlist"); static const auto &SOURCE = _SET("source"); static const auto &TITLE = _SET("title"); static const auto &ID = _SET("id"); static const auto &LICENSE = _SET("license"); static const auto &DESCRIPTION = _SET("description"); static const auto &BOOKMARK = _SET("bookmark"); static const auto &ACCOUNT = _SET("account"); static const auto &ACCOUNTTYPE= _SET("accounttype"); static const auto &VERSION = _SET("version"); static const auto &DOMAIN = _SET("domain"); static const auto &CATEGORY = _SET("category"); static const auto &CONTENT = _SET("content"); static const auto &PIN = _SET("pin"); static const auto &IMG = _SET("img"); static const auto &PREVIEW = _SET("preview"); static const auto &LINK = _SET("link"); static const auto &STAMP = _SET("stamp"); /** ccdav keys **/ static const auto &N = _SET("n"); static const auto &IM = _SET("im"); static const auto &PHOTO = _SET("photo"); static const auto &GENDER = _SET("gender"); static const auto &ADR = _SET("adr"); static const auto &ADR_2 = _SET("adr2"); static const auto &ADR_3 = _SET("adr3"); static const auto &EMAIL= _SET("email"); static const auto &EMAIL_2 = _SET("email2"); static const auto &EMAIL_3 = _SET("email3"); static const auto &LANG= _SET("lang"); static const auto &NICKNAME = _SET("nickname"); static const auto &ORG = _SET("org"); static const auto &PROFILE = _SET("profile"); static const auto &TZ = _SET("tz"); static const auto &TEL = _SET("tel"); static const auto &TEL_2 = _SET("tel2"); static const auto &TEL_3 = _SET("tel3"); static const auto &CITY = _SET("city"); static const auto &STATE = _SET("state"); static const auto &COUNTRY = _SET("country"); }; namespace MODELS { typedef QHash MODEL; typedef QVector MODEL_LIST; } // boilerplate code for custom qhash keys to work with qt inline uint qHash(const KEYS::KEY &key) { return qHash(key.n) ^ key.value; } + namespace FMH { inline bool isAndroid() { #if defined(Q_OS_ANDROID) return true; #elif defined(Q_OS_LINUX) return false; #elif defined(Q_OS_WIN32) return false; #elif defined(Q_OS_WIN64) return false; #elif defined(Q_OS_MACOS) return false; #elif defined(Q_OS_IOS) return false; #elif defined(Q_OS_HAIKU) return false; #endif } enum FILTER_TYPE : int { AUDIO, VIDEO, TEXT, IMAGE, DOCUMENT, NONE }; static const QHash FILTER_LIST = { {FILTER_TYPE::AUDIO, QStringList {"*.mp3", "*.mp4", "*.wav", "*.ogg", "*.flac"}}, {FILTER_TYPE::VIDEO, QStringList {"*.mp4", "*.mkv", "*.mov", "*.avi", "*.flv"}}, {FILTER_TYPE::TEXT, QStringList {"*.txt", "*.cpp", "*.js", "*.doc", "*.h", "*.json", "*.html", "*.rtf"}}, {FILTER_TYPE::DOCUMENT, QStringList {"*.pdf", "*.txt", "*.cbz", "*.cbr", "*.epub", "*.cbt", "*.cba", "*.cb7"}}, {FILTER_TYPE::IMAGE, QStringList {"*.png", "*.jpg", "*.jpeg", "*.gif", "*.svg", "*.bmp"}}, {FILTER_TYPE::NONE, QStringList()} }; - - - static const QHash MODEL_NAME = - { - {MODEL_KEY::ICON, "icon"}, - {MODEL_KEY::LABEL, "label"}, - {MODEL_KEY::PATH, "path"}, - {MODEL_KEY::URL, "url"}, - {MODEL_KEY::TYPE, "type"}, - {MODEL_KEY::GROUP, "group"}, - {MODEL_KEY::OWNER, "owner"}, - {MODEL_KEY::SUFFIX, "suffix"}, - {MODEL_KEY::NAME, "name"}, - {MODEL_KEY::DATE, "date"}, - {MODEL_KEY::MODIFIED, "modified"}, - {MODEL_KEY::MIME, "mime"}, - {MODEL_KEY::SIZE, "size"}, - {MODEL_KEY::TAG, "tag"}, - {MODEL_KEY::PERMISSIONS, "permissions"}, - {MODEL_KEY::THUMBNAIL, "thumbnail"}, - {MODEL_KEY::THUMBNAIL_1, "thumbnail_1"}, - {MODEL_KEY::THUMBNAIL_2, "thumbnail_2"}, - {MODEL_KEY::THUMBNAIL_3, "thumbnail_3"}, - {MODEL_KEY::ICONSIZE, "iconsize"}, - {MODEL_KEY::HIDDEN, "hidden"}, - {MODEL_KEY::DETAILVIEW, "detailview"}, - {MODEL_KEY::SHOWTERMINAL, "showterminal"}, - {MODEL_KEY::SHOWTHUMBNAIL, "showthumbnail"}, - {MODEL_KEY::COUNT, "count"}, - {MODEL_KEY::SORTBY, "sortby"}, - {MODEL_KEY::USER, "user"}, - {MODEL_KEY::PASSWORD, "password"}, - {MODEL_KEY::SERVER, "server"}, - {MODEL_KEY::FOLDERSFIRST, "foldersfirst"}, - {MODEL_KEY::VIEWTYPE, "viewtype"}, - {MODEL_KEY::ADDDATE, "adddate"}, - {MODEL_KEY::FAV, "fav"}, - {MODEL_KEY::FAVORITE, "favorite"}, - {MODEL_KEY::COLOR, "color"}, - {MODEL_KEY::RATE, "rate"}, - {MODEL_KEY::FORMAT, "format"}, - {MODEL_KEY::PLACE, "place"}, - {MODEL_KEY::LOCATION, "location"}, - {MODEL_KEY::ALBUM, "album"}, - {MODEL_KEY::DURATION, "duration"}, - {MODEL_KEY::RELEASEDATE, "releasedate"}, - {MODEL_KEY::ARTIST, "artist"}, - {MODEL_KEY::LYRICS, "lyrics"}, - {MODEL_KEY::TRACK, "track"}, - {MODEL_KEY::GENRE, "genre"}, - {MODEL_KEY::WIKI, "wiki"}, - {MODEL_KEY::CONTEXT, "context"}, - {MODEL_KEY::SOURCETYPE, "sourcetype"}, - {MODEL_KEY::ARTWORK, "artwork"}, - {MODEL_KEY::NOTE, "note"}, - {MODEL_KEY::MOOD, "mood"}, - {MODEL_KEY::COMMENT, "comment"}, - {MODEL_KEY::PLAYLIST, "playlist"}, - {MODEL_KEY::SOURCE, "source"}, - {MODEL_KEY::TITLE, "title"}, - {MODEL_KEY::ID, "id"}, - {MODEL_KEY::LICENSE, "license"}, - {MODEL_KEY::DESCRIPTION, "description"}, - {MODEL_KEY::BOOKMARK, "bookmark"}, - {MODEL_KEY::ACCOUNT, "account"}, - {MODEL_KEY::ACCOUNTTYPE, "accounttype"}, - {MODEL_KEY::VERSION, "version"}, - {MODEL_KEY::DOMAIN, "domain"}, - {MODEL_KEY::CATEGORY, "category"}, - {MODEL_KEY::CONTENT, "content"}, - {MODEL_KEY::PIN, "pin"}, - {MODEL_KEY::IMG, "img"}, - {MODEL_KEY::PREVIEW, "preview"}, - {MODEL_KEY::LINK, "link"}, - {MODEL_KEY::STAMP, "stamp"}, - - /** ccdav keys **/ - {MODEL_KEY::N, "n"}, - {MODEL_KEY::IM, "im"}, - {MODEL_KEY::PHOTO, "photo"}, - {MODEL_KEY::GENDER, "gender"}, - {MODEL_KEY::ADR, "adr"}, - {MODEL_KEY::ADR_2, "adr2"}, - {MODEL_KEY::ADR_3, "adr3"}, - {MODEL_KEY::EMAIL, "email"}, - {MODEL_KEY::EMAIL_2, "email2"}, - {MODEL_KEY::EMAIL_3, "email3"}, - {MODEL_KEY::LANG, "lang"}, - {MODEL_KEY::NICKNAME, "nickname"}, - {MODEL_KEY::ORG, "org"}, - {MODEL_KEY::PROFILE, "profile"}, - {MODEL_KEY::TZ, "tz"}, - {MODEL_KEY::TEL, "tel"}, - {MODEL_KEY::TEL_2, "tel2"}, - {MODEL_KEY::TEL_3, "tel3"}, - - {MODEL_KEY::CITY, "city"}, - {MODEL_KEY::STATE, "state"}, - {MODEL_KEY::COUNTRY, "country"} - }; - - static const QHash MODEL_NAME_KEY = - { - {MODEL_NAME[MODEL_KEY::ICON], MODEL_KEY::ICON}, - {MODEL_NAME[MODEL_KEY::LABEL], MODEL_KEY::LABEL}, - {MODEL_NAME[MODEL_KEY::PATH], MODEL_KEY::PATH}, - {MODEL_NAME[MODEL_KEY::URL], MODEL_KEY::URL}, - {MODEL_NAME[MODEL_KEY::TYPE], MODEL_KEY::TYPE}, - {MODEL_NAME[MODEL_KEY::GROUP], MODEL_KEY::GROUP}, - {MODEL_NAME[MODEL_KEY::OWNER], MODEL_KEY::OWNER}, - {MODEL_NAME[MODEL_KEY::SUFFIX], MODEL_KEY::SUFFIX}, - {MODEL_NAME[MODEL_KEY::NAME], MODEL_KEY::NAME}, - {MODEL_NAME[MODEL_KEY::DATE], MODEL_KEY::DATE}, - {MODEL_NAME[MODEL_KEY::MODIFIED], MODEL_KEY::MODIFIED}, - {MODEL_NAME[MODEL_KEY::MIME], MODEL_KEY::MIME}, - {MODEL_NAME[MODEL_KEY::SIZE], MODEL_KEY::SIZE,}, - {MODEL_NAME[MODEL_KEY::TAG], MODEL_KEY::TAG}, - {MODEL_NAME[MODEL_KEY::PERMISSIONS], MODEL_KEY::PERMISSIONS}, - {MODEL_NAME[MODEL_KEY::THUMBNAIL], MODEL_KEY::THUMBNAIL}, - {MODEL_NAME[MODEL_KEY::THUMBNAIL_1], MODEL_KEY::THUMBNAIL_1}, - {MODEL_NAME[MODEL_KEY::THUMBNAIL_2], MODEL_KEY::THUMBNAIL_2}, - {MODEL_NAME[MODEL_KEY::THUMBNAIL_3], MODEL_KEY::THUMBNAIL_3}, - {MODEL_NAME[MODEL_KEY::ICONSIZE], MODEL_KEY::ICONSIZE}, - {MODEL_NAME[MODEL_KEY::HIDDEN], MODEL_KEY::HIDDEN}, - {MODEL_NAME[MODEL_KEY::DETAILVIEW], MODEL_KEY::DETAILVIEW}, - {MODEL_NAME[MODEL_KEY::SHOWTERMINAL], MODEL_KEY::SHOWTERMINAL}, - {MODEL_NAME[MODEL_KEY::SHOWTHUMBNAIL], MODEL_KEY::SHOWTHUMBNAIL}, - {MODEL_NAME[MODEL_KEY::COUNT], MODEL_KEY::COUNT}, - {MODEL_NAME[MODEL_KEY::SORTBY], MODEL_KEY::SORTBY}, - {MODEL_NAME[MODEL_KEY::USER], MODEL_KEY::USER}, - {MODEL_NAME[MODEL_KEY::PASSWORD], MODEL_KEY::PASSWORD}, - {MODEL_NAME[MODEL_KEY::SERVER], MODEL_KEY::SERVER}, - {MODEL_NAME[MODEL_KEY::VIEWTYPE], MODEL_KEY::VIEWTYPE}, - {MODEL_NAME[MODEL_KEY::ADDDATE], MODEL_KEY::ADDDATE}, - {MODEL_NAME[MODEL_KEY::FAV], MODEL_KEY::FAV}, - {MODEL_NAME[MODEL_KEY::FAVORITE], MODEL_KEY::FAVORITE}, - {MODEL_NAME[MODEL_KEY::COLOR], MODEL_KEY::COLOR}, - {MODEL_NAME[MODEL_KEY::RATE], MODEL_KEY::RATE}, - {MODEL_NAME[MODEL_KEY::FORMAT], MODEL_KEY::FORMAT}, - {MODEL_NAME[MODEL_KEY::PLACE], MODEL_KEY::PLACE}, - {MODEL_NAME[MODEL_KEY::LOCATION], MODEL_KEY::LOCATION}, - {MODEL_NAME[MODEL_KEY::ALBUM], MODEL_KEY::ALBUM}, - {MODEL_NAME[MODEL_KEY::ARTIST], MODEL_KEY::ARTIST}, - {MODEL_NAME[MODEL_KEY::DURATION], MODEL_KEY::DURATION}, - {MODEL_NAME[MODEL_KEY::TRACK], MODEL_KEY::TRACK}, - {MODEL_NAME[MODEL_KEY::GENRE], MODEL_KEY::GENRE}, - {MODEL_NAME[MODEL_KEY::LYRICS], MODEL_KEY::LYRICS}, - {MODEL_NAME[MODEL_KEY::RELEASEDATE], MODEL_KEY::RELEASEDATE}, - {MODEL_NAME[MODEL_KEY::FORMAT], MODEL_KEY::FORMAT}, - {MODEL_NAME[MODEL_KEY::WIKI], MODEL_KEY::WIKI}, - {MODEL_NAME[MODEL_KEY::SOURCETYPE], MODEL_KEY::SOURCETYPE}, - {MODEL_NAME[MODEL_KEY::ARTWORK], MODEL_KEY::ARTWORK}, - {MODEL_NAME[MODEL_KEY::NOTE], MODEL_KEY::NOTE}, - {MODEL_NAME[MODEL_KEY::MOOD], MODEL_KEY::MOOD}, - {MODEL_NAME[MODEL_KEY::COMMENT], MODEL_KEY::COMMENT}, - {MODEL_NAME[MODEL_KEY::CONTEXT], MODEL_KEY::CONTEXT}, - {MODEL_NAME[MODEL_KEY::SOURCE], MODEL_KEY::SOURCE}, - {MODEL_NAME[MODEL_KEY::TITLE], MODEL_KEY::TITLE}, - {MODEL_NAME[MODEL_KEY::ID], MODEL_KEY::ID}, - {MODEL_NAME[MODEL_KEY::LICENSE], MODEL_KEY::LICENSE}, - {MODEL_NAME[MODEL_KEY::DESCRIPTION], MODEL_KEY::DESCRIPTION}, - {MODEL_NAME[MODEL_KEY::BOOKMARK], MODEL_KEY::BOOKMARK}, - {MODEL_NAME[MODEL_KEY::ACCOUNT], MODEL_KEY::ACCOUNT}, - {MODEL_NAME[MODEL_KEY::ACCOUNTTYPE], MODEL_KEY::ACCOUNTTYPE}, - {MODEL_NAME[MODEL_KEY::VERSION], MODEL_KEY::VERSION}, - {MODEL_NAME[MODEL_KEY::DOMAIN], MODEL_KEY::DOMAIN}, - {MODEL_NAME[MODEL_KEY::CATEGORY], MODEL_KEY::CATEGORY}, - {MODEL_NAME[MODEL_KEY::CONTENT], MODEL_KEY::CONTENT}, - {MODEL_NAME[MODEL_KEY::PIN], MODEL_KEY::PIN}, - {MODEL_NAME[MODEL_KEY::IMG], MODEL_KEY::IMG}, - {MODEL_NAME[MODEL_KEY::PREVIEW], MODEL_KEY::PREVIEW}, - {MODEL_NAME[MODEL_KEY::LINK], MODEL_KEY::LINK}, - {MODEL_NAME[MODEL_KEY::STAMP], MODEL_KEY::STAMP}, - - /** ccdav keys **/ - {MODEL_NAME[MODEL_KEY::N], MODEL_KEY::N}, - {MODEL_NAME[MODEL_KEY::IM], MODEL_KEY::IM}, - {MODEL_NAME[MODEL_KEY::PHOTO], MODEL_KEY::PHOTO}, - {MODEL_NAME[MODEL_KEY::GENDER], MODEL_KEY::GENDER}, - {MODEL_NAME[MODEL_KEY::ADR], MODEL_KEY::ADR}, - {MODEL_NAME[MODEL_KEY::ADR_2], MODEL_KEY::ADR_2}, - {MODEL_NAME[MODEL_KEY::ADR_3], MODEL_KEY::ADR_3}, - {MODEL_NAME[MODEL_KEY::EMAIL], MODEL_KEY::EMAIL}, - {MODEL_NAME[MODEL_KEY::EMAIL_2], MODEL_KEY::EMAIL_2}, - {MODEL_NAME[MODEL_KEY::EMAIL_3], MODEL_KEY::EMAIL_3}, - {MODEL_NAME[MODEL_KEY::LANG], MODEL_KEY::LANG}, - {MODEL_NAME[MODEL_KEY::NICKNAME], MODEL_KEY::NICKNAME}, - {MODEL_NAME[MODEL_KEY::ORG], MODEL_KEY::ORG}, - {MODEL_NAME[MODEL_KEY::PROFILE], MODEL_KEY::PROFILE}, - {MODEL_NAME[MODEL_KEY::TZ], MODEL_KEY::TZ}, - {MODEL_NAME[MODEL_KEY::TEL], MODEL_KEY::TEL}, - {MODEL_NAME[MODEL_KEY::TEL_2], MODEL_KEY::TEL_2}, - {MODEL_NAME[MODEL_KEY::TEL_3], MODEL_KEY::TEL_3}, - - {MODEL_NAME[MODEL_KEY::CITY], MODEL_KEY::CITY}, - {MODEL_NAME[MODEL_KEY::STATE], MODEL_KEY::STATE}, - {MODEL_NAME[MODEL_KEY::COUNTRY], MODEL_KEY::COUNTRY} - }; - - typedef QHash MODEL; - typedef QVector MODEL_LIST; + typedef MODELS::MODEL MODEL; + typedef MODELS::MODEL_LIST MODEL_LIST; struct PATH_CONTENT { QString path; FMH::MODEL_LIST content; }; #ifdef Q_OS_ANDROID enum PATHTYPE_KEY : int { PLACES_PATH, REMOTE_PATH, DRIVES_PATH, REMOVABLE_PATH, TAGS_PATH, UNKNOWN_TYPE, APPS_PATH, TRASH_PATH, SEARCH_PATH, CLOUD_PATH, FISH_PATH, MTP_PATH }; #else enum PATHTYPE_KEY : int { PLACES_PATH = KFilePlacesModel::GroupType::PlacesType, REMOTE_PATH = KFilePlacesModel::GroupType::RemoteType, DRIVES_PATH = KFilePlacesModel::GroupType::DevicesType, REMOVABLE_PATH = KFilePlacesModel::GroupType::RemovableDevicesType, TAGS_PATH = KFilePlacesModel::GroupType::TagsType, UNKNOWN_TYPE = KFilePlacesModel::GroupType::UnknownType, APPS_PATH = 9, TRASH_PATH = 10, SEARCH_PATH = 11, CLOUD_PATH = 12, FISH_PATH = 13, MTP_PATH = 14, }; #endif static const QHash PATHTYPE_SCHEME = { {PATHTYPE_KEY::PLACES_PATH, "file"}, {PATHTYPE_KEY::DRIVES_PATH, "drives"}, {PATHTYPE_KEY::APPS_PATH, "apps"}, {PATHTYPE_KEY::REMOTE_PATH, "remote"}, {PATHTYPE_KEY::REMOVABLE_PATH, "removable"}, {PATHTYPE_KEY::UNKNOWN_TYPE, "Unkown"}, {PATHTYPE_KEY::TRASH_PATH, "trash"}, {PATHTYPE_KEY::TAGS_PATH, "tags"}, {PATHTYPE_KEY::SEARCH_PATH, "search"}, {PATHTYPE_KEY::CLOUD_PATH, "cloud"}, {PATHTYPE_KEY::FISH_PATH, "fish"}, {PATHTYPE_KEY::MTP_PATH, "mtp"} }; static const QHash PATHTYPE_URI = { {PATHTYPE_KEY::PLACES_PATH, PATHTYPE_SCHEME[PATHTYPE_KEY::PLACES_PATH] + "://"}, {PATHTYPE_KEY::DRIVES_PATH, PATHTYPE_SCHEME[PATHTYPE_KEY::DRIVES_PATH] + "://"}, {PATHTYPE_KEY::APPS_PATH, PATHTYPE_SCHEME[PATHTYPE_KEY::APPS_PATH] + "://"}, {PATHTYPE_KEY::REMOTE_PATH, PATHTYPE_SCHEME[PATHTYPE_KEY::REMOTE_PATH] + "://"}, {PATHTYPE_KEY::REMOVABLE_PATH, PATHTYPE_SCHEME[PATHTYPE_KEY::REMOVABLE_PATH] + "://"}, {PATHTYPE_KEY::UNKNOWN_TYPE, PATHTYPE_SCHEME[PATHTYPE_KEY::UNKNOWN_TYPE] + "://"}, {PATHTYPE_KEY::TRASH_PATH, PATHTYPE_SCHEME[PATHTYPE_KEY::TRASH_PATH] + "://"}, {PATHTYPE_KEY::TAGS_PATH, PATHTYPE_SCHEME[PATHTYPE_KEY::TAGS_PATH] + "://"}, {PATHTYPE_KEY::SEARCH_PATH, PATHTYPE_SCHEME[PATHTYPE_KEY::SEARCH_PATH] + "://"}, {PATHTYPE_KEY::CLOUD_PATH, PATHTYPE_SCHEME[PATHTYPE_KEY::CLOUD_PATH] + "://"}, {PATHTYPE_KEY::FISH_PATH, PATHTYPE_SCHEME[PATHTYPE_KEY::FISH_PATH] + "://"}, {PATHTYPE_KEY::MTP_PATH, PATHTYPE_SCHEME[PATHTYPE_KEY::MTP_PATH] + "://"} }; static const QHash PATHTYPE_LABEL = { {PATHTYPE_KEY::PLACES_PATH, ("Places")}, {PATHTYPE_KEY::DRIVES_PATH, ("Drives")}, {PATHTYPE_KEY::APPS_PATH, ("Apps")}, {PATHTYPE_KEY::REMOTE_PATH, ("Remote")}, {PATHTYPE_KEY::REMOVABLE_PATH, ("Removable")}, {PATHTYPE_KEY::UNKNOWN_TYPE, ("Unknown")}, {PATHTYPE_KEY::TRASH_PATH, ("Trash")}, {PATHTYPE_KEY::TAGS_PATH, ("Tags")}, {PATHTYPE_KEY::SEARCH_PATH, ("Search")}, {PATHTYPE_KEY::CLOUD_PATH, ("Cloud")}, {PATHTYPE_KEY::FISH_PATH, ("Remote")}, {PATHTYPE_KEY::MTP_PATH, ("Drives")} }; const QString DataPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); const QString CloudCachePath = FMH::DataPath+"/Cloud/"; #if defined(Q_OS_ANDROID) const QString PicturesPath = QUrl::fromLocalFile(PATHS::PicturesPath).toString(); const QString DownloadsPath = QUrl::fromLocalFile(PATHS::DownloadsPath).toString(); const QString DocumentsPath = QUrl::fromLocalFile(PATHS::DocumentsPath).toString(); const QString HomePath = QUrl::fromLocalFile(PATHS::HomePath).toString(); const QString MusicPath = QUrl::fromLocalFile(PATHS::MusicPath).toString(); const QString VideosPath = QUrl::fromLocalFile(PATHS::VideosPath).toString(); const QStringList defaultPaths = { FMH::HomePath, FMH::DocumentsPath, FMH::PicturesPath, FMH::MusicPath, FMH::VideosPath, FMH::DownloadsPath }; const QMap folderIcon { {PicturesPath, "folder-pictures"}, {DownloadsPath, "folder-download"}, {DocumentsPath, "folder-documents"}, {HomePath, "user-home"}, {MusicPath, "folder-music"}, {VideosPath, "folder-videos"}, }; #else const QString PicturesPath = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)).toString(); const QString DownloadsPath = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)).toString(); const QString DocumentsPath = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)).toString(); const QString HomePath = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).toString(); const QString MusicPath = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MusicLocation)).toString(); const QString VideosPath = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MoviesLocation)).toString(); const QString DesktopPath = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)).toString(); const QString AppsPath = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation)).toString(); const QString RootPath = "file:///"; const QStringList defaultPaths = { FMH::HomePath, FMH::DesktopPath, FMH::DocumentsPath, FMH::PicturesPath, FMH::MusicPath, FMH::VideosPath, FMH::DownloadsPath, FMH::RootPath }; const QMap folderIcon { {PicturesPath, "folder-pictures"}, {DownloadsPath, "folder-download"}, {DocumentsPath, "folder-documents"}, {HomePath, "user-home"}, {MusicPath, "folder-music"}, {VideosPath, "folder-videos"}, {DesktopPath, "user-desktop"}, {AppsPath, "system-run"}, {RootPath, "folder-root"} }; #endif /** * Checks if a local file exists. * The URL must represent a local file path, by using the scheme file:// **/ inline bool fileExists(const QUrl &path) { if(!path.isLocalFile()) { qWarning() << "URL recived is not a local file" << path; return false; } return QFileInfo::exists(path.toLocalFile()); } /** * Return the configuration of a single directory represented * by a QVariantMap. * The passed path must be a local file URL. **/ inline QVariantMap dirConf(const QUrl &path) { if(!path.isLocalFile()) { qWarning() << "URL recived is not a local file" << path; return QVariantMap(); } if(!FMH::fileExists(path)) return QVariantMap(); QString icon, iconsize, hidden, detailview, showthumbnail, showterminal; - uint count = 0, sortby = FMH::MODEL_KEY::MODIFIED, viewType = 0; + uint count = 0, sortby = KEYS::MODIFIED, viewType = 0; bool foldersFirst = false; #ifdef Q_OS_ANDROID QSettings file(path.toLocalFile(), QSettings::Format::NativeFormat); file.beginGroup(QString("Desktop Entry")); icon = file.value("Icon").toString(); file.endGroup(); file.beginGroup(QString("Settings")); hidden = file.value("HiddenFilesShown").toString(); file.endGroup(); file.beginGroup(QString("MAUIFM")); iconsize = file.value("IconSize").toString(); detailview = file.value("DetailView").toString(); showthumbnail = file.value("ShowThumbnail").toString(); showterminal = file.value("ShowTerminal").toString(); count = file.value("Count").toInt(); sortby = file.value("SortBy").toInt(); foldersFirst = file.value("FoldersFirst").toBool(); viewType = file.value("ViewType").toInt(); file.endGroup(); #else KConfig file(path.toLocalFile()); icon = file.entryMap(QString("Desktop Entry"))["Icon"]; hidden = file.entryMap(QString("Settings"))["HiddenFilesShown"]; iconsize = file.entryMap(QString("MAUIFM"))["IconSize"]; detailview = file.entryMap(QString("MAUIFM"))["DetailView"]; showthumbnail = file.entryMap(QString("MAUIFM"))["ShowThumbnail"]; showterminal = file.entryMap(QString("MAUIFM"))["ShowTerminal"]; count = file.entryMap(QString("MAUIFM"))["Count"].toInt(); sortby = file.entryMap(QString("MAUIFM"))["SortBy"].toInt(); foldersFirst = file.entryMap(QString("MAUIFM"))["FoldersFirst"] == "true" ? true : false; viewType = file.entryMap(QString("MAUIFM"))["ViewType"].toInt(); #endif return QVariantMap({ - {FMH::MODEL_NAME[FMH::MODEL_KEY::ICON], icon.isEmpty() ? "folder" : icon}, - {FMH::MODEL_NAME[FMH::MODEL_KEY::ICONSIZE], iconsize}, - {FMH::MODEL_NAME[FMH::MODEL_KEY::COUNT], count}, - {FMH::MODEL_NAME[FMH::MODEL_KEY::SHOWTERMINAL], showterminal.isEmpty() ? "false" : showterminal}, - {FMH::MODEL_NAME[FMH::MODEL_KEY::SHOWTHUMBNAIL], showthumbnail.isEmpty() ? "false" : showthumbnail}, - {FMH::MODEL_NAME[FMH::MODEL_KEY::DETAILVIEW], detailview.isEmpty() ? "false" : detailview}, - {FMH::MODEL_NAME[FMH::MODEL_KEY::HIDDEN], hidden.isEmpty() ? false : (hidden == "true" ? true : false)}, - {FMH::MODEL_NAME[FMH::MODEL_KEY::SORTBY], sortby}, - {FMH::MODEL_NAME[FMH::MODEL_KEY::FOLDERSFIRST], foldersFirst}, - {FMH::MODEL_NAME[FMH::MODEL_KEY::VIEWTYPE], viewType} + {KEYS::_N[KEYS::ICON], icon.isEmpty() ? "folder" : icon}, + {KEYS::_N[KEYS::ICONSIZE], iconsize}, + {KEYS::_N[KEYS::COUNT], count}, + {KEYS::_N[KEYS::SHOWTERMINAL], showterminal.isEmpty() ? "false" : showterminal}, + {KEYS::_N[KEYS::SHOWTHUMBNAIL], showthumbnail.isEmpty() ? "false" : showthumbnail}, + {KEYS::_N[KEYS::DETAILVIEW], detailview.isEmpty() ? "false" : detailview}, + {KEYS::_N[KEYS::HIDDEN], hidden.isEmpty() ? false : (hidden == "true" ? true : false)}, + {KEYS::_N[KEYS::SORTBY], sortby}, + {KEYS::_N[KEYS::FOLDERSFIRST], foldersFirst}, + {KEYS::_N[KEYS::VIEWTYPE], viewType} }); } inline void setDirConf(const QUrl &path, const QString &group, const QString &key, const QVariant &value) { if(!path.isLocalFile()) { qWarning() << "URL recived is not a local file" << path; return; } #ifdef Q_OS_ANDROID QSettings file(path.toLocalFile(), QSettings::Format::IniFormat); file.beginGroup(group); file.setValue(key, value); file.endGroup(); file.sync(); #else KConfig file(path.toLocalFile(), KConfig::SimpleConfig); auto kgroup = file.group(group); kgroup.writeEntry(key, value); // file.reparseConfiguration(); file.sync(); #endif } /** * Returns the icon name for certain file. * The file path must be represented as a local file URL. * It also looks into the directory config file to get custom set icons **/ inline QString getIconName(const QUrl &path) { if(!path.isLocalFile()) { qWarning() << "URL recived is not a local file. FMH::getIconName" << path; } if(path.isLocalFile() && QFileInfo(path.toLocalFile()).isDir()) { if(folderIcon.contains(path.toString())) return folderIcon[path.toString()]; else { - auto icon = FMH::dirConf(QString(path.toString()+"/%1").arg(".directory"))[FMH::MODEL_NAME[FMH::MODEL_KEY::ICON]].toString(); + auto icon = FMH::dirConf(QString(path.toString()+"/%1").arg(".directory"))[KEYS::_N[KEYS::ICON]].toString(); return icon.isEmpty() ? "folder" : icon; } }else { #if defined(Q_OS_ANDROID) QMimeDatabase mime; auto type = mime.mimeTypeForFile(path.toLocalFile()); return type.iconName(); #else KFileItem mime(path); return mime.iconName(); #endif } } inline QString getMime(const QUrl &path) { if(!path.isLocalFile()) { qWarning() << "URL recived is not a local file" << path; return QString(); } const QMimeDatabase mimedb; return mimedb.mimeTypeForFile(path.toLocalFile()).name(); } enum class TABLE : uint { BOOKMARKS, CLOUDS }; static const QMap TABLEMAP = { {TABLE::BOOKMARKS, "bookmarks"}, {TABLE::CLOUDS, "clouds"} }; - typedef QMap DB; + typedef QMap DB; const QString FMPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)+"/maui/fm/"; const QString DBName = "fm.db"; inline FMH::MODEL getDirInfoModel(const QUrl &path, const QString &type = QString()) { if(!path.isLocalFile()) { qWarning() << "URL recived is not a local file" << path; return FMH::MODEL(); } const QDir dir (path.toLocalFile()); if(!dir.exists()) return FMH::MODEL(); return FMH::MODEL { - {FMH::MODEL_KEY::ICON, FMH::getIconName(path)}, - {FMH::MODEL_KEY::LABEL, dir.dirName()}, - {FMH::MODEL_KEY::PATH, path.toString()}, - {FMH::MODEL_KEY::TYPE, type} + {KEYS::ICON, FMH::getIconName(path)}, + {KEYS::LABEL, dir.dirName()}, + {KEYS::PATH, path.toString()}, + {KEYS::TYPE, type} }; } inline QVariantMap getDirInfo(const QUrl &path, const QString &type = QString()) { if(!path.isLocalFile()) { qWarning() << "URL recived is not a local file" << path; return QVariantMap(); } const QFileInfo file(path.toLocalFile()); if(!file.exists()) return QVariantMap(); const auto data = FMH::getDirInfoModel(path); QVariantMap res; for(const auto &key : data.keys()) - res.insert(FMH::MODEL_NAME[key], data[key]); + res.insert(KEYS::_N[key], data[key]); return res; } inline FMH::MODEL getFileInfoModel(const QUrl &path) { if(!path.isLocalFile()) { qWarning() << "URL recived is not a local file" << path; return FMH::MODEL(); } const QFileInfo file(path.toLocalFile()); if(!file.exists()) return FMH::MODEL(); qDebug()<< "trying to get path info model. exists"; const auto mime = FMH::getMime(path); return FMH::MODEL { - {FMH::MODEL_KEY::GROUP, file.group()}, - {FMH::MODEL_KEY::OWNER, file.owner()}, - {FMH::MODEL_KEY::SUFFIX, file.completeSuffix()}, - {FMH::MODEL_KEY::LABEL, /*file.isDir() ? file.baseName() :*/ path == FMH::HomePath ? QStringLiteral("Home") : file.fileName()}, - {FMH::MODEL_KEY::NAME, file.fileName()}, - {FMH::MODEL_KEY::DATE, file.birthTime().toString(Qt::TextDate)}, - {FMH::MODEL_KEY::MODIFIED, file.lastModified().toString(Qt::TextDate)}, - {FMH::MODEL_KEY::MIME, mime }, - {FMH::MODEL_KEY::ICON, FMH::getIconName(path)}, - {FMH::MODEL_KEY::SIZE, QString::number(file.size()) /*locale.formattedDataSize(file.size())*/}, - {FMH::MODEL_KEY::PATH, path.toString()}, - {FMH::MODEL_KEY::THUMBNAIL, path.toLocalFile()}, - {FMH::MODEL_KEY::COUNT, file.isDir() ? QString::number(QDir(path.toLocalFile()).count() - 2) : "0"} + {KEYS::GROUP, file.group()}, + {KEYS::OWNER, file.owner()}, + {KEYS::SUFFIX, file.completeSuffix()}, + {KEYS::LABEL, /*file.isDir() ? file.baseName() :*/ path == FMH::HomePath ? QStringLiteral("Home") : file.fileName()}, + {KEYS::NAME, file.fileName()}, + {KEYS::DATE, file.birthTime().toString(Qt::TextDate)}, + {KEYS::MODIFIED, file.lastModified().toString(Qt::TextDate)}, + {KEYS::MIME, mime }, + {KEYS::ICON, FMH::getIconName(path)}, + {KEYS::SIZE, QString::number(file.size()) /*locale.formattedDataSize(file.size())*/}, + {KEYS::PATH, path.toString()}, + {KEYS::THUMBNAIL, path.toLocalFile()}, + {KEYS::COUNT, file.isDir() ? QString::number(QDir(path.toLocalFile()).count() - 2) : "0"} }; } inline QVariantMap getFileInfo(const QUrl &path) { if(!path.isLocalFile()) { qWarning() << "URL recived is not a local file" << path; return QVariantMap(); } const QFileInfo file(path.toLocalFile()); if(!file.exists()) return QVariantMap(); const auto data = FMH::getFileInfoModel(path); qDebug()<< "getting item info model" << data; QVariantMap res; for(const auto &key : data.keys()) - res.insert(FMH::MODEL_NAME[key], data[key]); + res.insert(KEYS::_N[key], data[key]); return res; } #ifndef STATIC_MAUIKIT #include "mauikit_export.h" #endif #ifdef STATIC_MAUIKIT class Downloader : public QObject #else class MAUIKIT_EXPORT Downloader : public QObject #endif { Q_OBJECT public: explicit Downloader(QObject *parent = 0) : QObject(parent), manager(new QNetworkAccessManager) {} virtual ~Downloader() { qDebug()<< "DELETEING DOWNLOADER"; this->manager->deleteLater(); // this->reply->deleteLater(); } void setFile(const QString &fileURL, const QString &fileName = QString()) { QString filePath = fileURL; if(fileName.isEmpty() || fileURL.isEmpty()) return; QNetworkRequest request; request.setUrl(QUrl(fileURL)); reply = manager->get(request); file = new QFile; file->setFileName(fileName); file->open(QIODevice::WriteOnly); connect(reply, SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(onDownloadProgress(qint64,qint64))); connect(manager, SIGNAL(finished(QNetworkReply*)),this,SLOT(onFinished(QNetworkReply*))); connect(reply, SIGNAL(readyRead()),this,SLOT(onReadyRead())); connect(reply, SIGNAL(finished()),this,SLOT(onReplyFinished())); } void getArray(const QString &fileURL, const QMap &headers = {}) { qDebug() << fileURL << headers; if(fileURL.isEmpty()) return; QNetworkRequest request; request.setUrl(QUrl(fileURL)); if(!headers.isEmpty()) { for(auto key: headers.keys()) request.setRawHeader(key.toLocal8Bit(), headers[key].toLocal8Bit()); } reply = manager->get(request); connect(reply, &QNetworkReply::readyRead, [this]() { switch(reply->error()) { case QNetworkReply::NoError: { this->array = reply->readAll(); break; } default: { qDebug() << reply->errorString(); emit this->warning(reply->errorString()); }; } }); connect(reply, &QNetworkReply::finished, [=]() { qDebug() << "Array reply is now finished"; emit this->dataReady(this->array); emit this->done(); }); } private: QNetworkAccessManager *manager; QNetworkReply *reply; QFile *file; QByteArray array; signals: void progress(int percent); void downloadReady(); void fileSaved(QString path); void warning(QString warning); void dataReady(QByteArray array); void done(); private slots: void onDownloadProgress(qint64 bytesRead, qint64 bytesTotal) { emit this->progress((bytesRead * bytesTotal) / 100); } void onFinished(QNetworkReply* reply) { switch(reply->error()) { case QNetworkReply::NoError: { qDebug("file is downloaded successfully."); emit this->downloadReady(); break; } default: { emit this->warning(reply->errorString()); }; } if(file->isOpen()) { file->close(); emit this->fileSaved(file->fileName()); file->deleteLater(); } } void onReadyRead() { file->write(reply->readAll()); // emit this->fileSaved(file->fileName()); } void onReplyFinished() { if(file->isOpen()) { file->close(); // emit this->fileSaved(file->fileName()); file->deleteLater(); } emit done(); } }; } #endif // FMH_H diff --git a/src/fm/fmlist.cpp b/src/fm/fmlist.cpp index 48f1305..6619ae4 100644 --- a/src/fm/fmlist.cpp +++ b/src/fm/fmlist.cpp @@ -1,883 +1,883 @@ /* * * Copyright (C) 2018 camilo * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "fmlist.h" #include "fm.h" #include "utils.h" #include #include #include #include #include #include #include FMList::FMList(QObject *parent) : MauiList(parent), fm(new FM(this)), watcher(new QFileSystemWatcher(this)) { connect(this->fm, &FM::cloudServerContentReady, [&](const FMH::MODEL_LIST &list, const QString &url) { if(this->path == url) { this->pre(); this->list = list; this->pathEmpty = this->list.isEmpty(); emit this->pathEmptyChanged(); this->pos(); this->setContentReady(true); } }); connect(this->fm, &FM::trashContentReady, [&](const FMH::MODEL_LIST &list) { if(this->path == "trash://") { this->pre(); this->list = list; this->pathEmpty = this->list.isEmpty(); emit this->pathEmptyChanged(); this->pos(); this->setContentReady(true); } }); connect(this->fm, &FM::pathContentReady, [&](const FMH::PATH_CONTENT &res) { qDebug()<< "PATHCN ONTEN READY" << res.path << this->path << res.content; // if(this->pathType != FMList::PATHTYPE::PLACES_PATH) // return; if(res.path != this->path) return; emit this->preListChanged(); this->list = res.content; this->pathEmpty = this->list.isEmpty() /*&& FM::fileExists(this->path)*/; emit this->pathEmptyChanged(); this->sortList(); emit this->postListChanged(); this->setContentReady(true); }); connect(this->fm, &FM::warningMessage, [&](const QString &message) { emit this->warning(message); }); connect(this->fm, &FM::loadProgress, [&](const int &percent) { emit this->progress(percent); }); // with kio based on android it watches the directory itself, so better relay on that #ifdef Q_OS_ANDROID connect(this->watcher, &QFileSystemWatcher::directoryChanged, [&](const QString &path) { qDebug()<< "FOLDER PATH CHANGED" << path; this->reset(); }); #else connect(this->fm, &FM::pathContentChanged, [&](const QUrl &path) { qDebug()<< "FOLDER PATH CHANGED" << path; if(path.toString() != this->path) return; this->sortList(); }); #endif connect(this->fm, &FM::newItem, [&] (const FMH::MODEL &item, const QString &url) { if(this->path == url) { emit this->preItemAppended(); this->list << item; this->pathEmpty = this->list.isEmpty(); emit this->pathEmptyChanged(); emit this->postListChanged(); } }); connect(this, &FMList::pathChanged, this, &FMList::reset); // connect(this, &FMList::hiddenChanged, this, &FMList::setList); // connect(this, &FMList::onlyDirsChanged, this, &FMList::setList); // connect(this, &FMList::filtersChanged, this, &FMList::setList); const auto value = UTIL::loadSettings("SaveDirProps", "SETTINGS", this->saveDirProps).toBool(); this->setSaveDirProps(value); } FMList::~FMList() {} void FMList::pre() { emit this->preListChanged(); // this->setContentReady(false); } void FMList::pos() { // this->setContentReady(true); emit this->postListChanged(); } void FMList::watchPath(const QString& path, const bool& clear) { #ifdef Q_OS_ANDROID if(!this->watcher->directories().isEmpty() && clear) this->watcher->removePaths(this->watcher->directories()); if(path.isEmpty() || !FMH::fileExists(path)) return; this->watcher->addPath(QString(path).replace("file://", "")); qDebug()<< "WATCHING PATHS" << this->watcher->directories(); #else Q_UNUSED(path) Q_UNUSED(clear) #endif } void FMList::setList() { this->setContentReady(true); switch(this->pathType) { case FMList::PATHTYPE::FISH_PATH: case FMList::PATHTYPE::MTP_PATH: case FMList::PATHTYPE::DRIVES_PATH: case FMList::PATHTYPE::REMOTE_PATH: case FMList::PATHTYPE::PLACES_PATH: this->list.clear(); this->setContentReady(false); this->fm->getPathContent(this->path, this->hidden, this->onlyDirs, this->filters); return; //ASYNC case FMList::PATHTYPE::TRASH_PATH: this->list.clear(); this->setContentReady(false); this->fm->getTrashContent(); break;//ASYNC case FMList::PATHTYPE::SEARCH_PATH: this->list.clear(); this->setContentReady(false); this->search(QString(this->path).right(this->path.length()- 1 - this->path.lastIndexOf("/")), this->searchPath, this->hidden, this->onlyDirs, this->filters); return; //ASYNC case FMList::PATHTYPE::APPS_PATH: this->list = FM::getAppsContent(this->path); break; case FMList::PATHTYPE::TAGS_PATH: this->list = this->fm->getTagContent(QString(this->path).right(this->path.length()- 1 - this->path.lastIndexOf("/"))); break; case FMList::PATHTYPE::CLOUD_PATH: this->list.clear(); if(this->fm->getCloudServerContent(this->path, this->filters, this->cloudDepth)) { this->setContentReady(false); return; }else break; } this->pathEmpty = this->list.isEmpty() && FM::fileExists(this->path); emit this->pathEmptyChanged(); this->sortList(); } void FMList::reset() { this->pre(); switch(this->pathType) { case FMList::PATHTYPE::APPS_PATH: this->hidden = false; this->preview = false; break; case FMList::PATHTYPE::CLOUD_PATH: case FMList::PATHTYPE::SEARCH_PATH: case FMList::PATHTYPE::TAGS_PATH: this->hidden = false; this->preview = true; break; case FMList::PATHTYPE::PLACES_PATH: { if(this->saveDirProps) { auto conf = FMH::dirConf(this->path+"/.directory"); - this->hidden = conf[FMH::MODEL_NAME[FMH::MODEL_KEY::HIDDEN]].toBool(); - this->preview = conf[FMH::MODEL_NAME[FMH::MODEL_KEY::SHOWTHUMBNAIL]].toBool(); - this->foldersFirst = conf[FMH::MODEL_NAME[FMH::MODEL_KEY::FOLDERSFIRST]].toBool(); + this->hidden = conf[KEYS::_N[KEYS::HIDDEN]].toBool(); + this->preview = conf[KEYS::_N[KEYS::SHOWTHUMBNAIL]].toBool(); + this->foldersFirst = conf[KEYS::_N[KEYS::FOLDERSFIRST]].toBool(); }else { this->hidden = UTIL::loadSettings("HiddenFilesShown", "SETTINGS", this->hidden).toBool(); this->preview = UTIL::loadSettings("ShowThumbnail", "SETTINGS", this->preview).toBool(); this->foldersFirst = UTIL::loadSettings("FoldersFirst", "SETTINGS", this->foldersFirst).toBool(); } break; } default: break; } if(this->saveDirProps) { auto conf = FMH::dirConf(this->path+"/.directory"); - this->sort = static_cast(conf[FMH::MODEL_NAME[FMH::MODEL_KEY::SORTBY]].toInt()); - this->viewType = static_cast(conf[FMH::MODEL_NAME[FMH::MODEL_KEY::VIEWTYPE]].toInt()); + this->sort = static_cast(conf[KEYS::_N[KEYS::SORTBY]].toInt()); + this->viewType = static_cast(conf[KEYS::_N[KEYS::VIEWTYPE]].toInt()); }else { this->sort = static_cast(UTIL::loadSettings("SortBy", "SETTINGS", this->sort).toInt()); this->viewType = static_cast(UTIL::loadSettings("ViewType", "SETTINGS", this->viewType).toInt()); } emit this->sortByChanged(); emit this->viewTypeChanged(); emit this->hiddenChanged(); emit this->previewChanged(); qDebug()<< "RESETING PATH CONTENTE" << this->path; this->setList(); this->pos(); } FMH::MODEL_LIST FMList::items() const { return this->list; } FMList::SORTBY FMList::getSortBy() const { return this->sort; } void FMList::setSortBy(const FMList::SORTBY &key) { if(this->sort == key) return; this->pre(); this->sort = key; this->sortList(); if(this->pathType == FMList::PATHTYPE::PLACES_PATH && this->trackChanges && this->saveDirProps) FMH::setDirConf(this->path+"/.directory", "MAUIFM", "SortBy", this->sort); else UTIL::saveSettings("SortBy", this->sort, "SETTINGS"); emit this->sortByChanged(); this->pos(); } void FMList::sortList() { - FMH::MODEL_KEY key = static_cast(this->sort); + KEYS key = static_cast(this->sort); auto index = 0; if(this->foldersFirst) { qSort(this->list.begin(), this->list.end(), [](const FMH::MODEL& e1, const FMH::MODEL& e2) -> bool { Q_UNUSED(e2) - const auto key = FMH::MODEL_KEY::MIME; + const auto key = KEYS::MIME; if(e1[key] == "inode/directory") return true; return false; }); for(auto item : this->list) - if(item[FMH::MODEL_KEY::MIME] == "inode/directory") + if(item[KEYS::MIME] == "inode/directory") index++; else break; qSort(this->list.begin(),this->list.begin() + index, [key](const FMH::MODEL& e1, const FMH::MODEL& e2) -> bool { auto role = key; switch(role) { - case FMH::MODEL_KEY::SIZE: + case KEYS::SIZE: { if(e1[role].toDouble() > e2[role].toDouble()) return true; break; } - case FMH::MODEL_KEY::MODIFIED: - case FMH::MODEL_KEY::DATE: + case KEYS::MODIFIED: + case KEYS::DATE: { auto currentTime = QDateTime::currentDateTime(); auto date1 = QDateTime::fromString(e1[role], Qt::TextDate); auto date2 = QDateTime::fromString(e2[role], Qt::TextDate); if(date1.secsTo(currentTime) < date2.secsTo(currentTime)) return true; break; } - case FMH::MODEL_KEY::LABEL: + case KEYS::LABEL: { const auto str1 = QString(e1[role]).toLower(); const auto str2 = QString(e2[role]).toLower(); if(str1 < str2) return true; break; } default: if(e1[role] < e2[role]) return true; } return false; }); } qSort(this->list.begin() + index, this->list.end(), [key](const FMH::MODEL& e1, const FMH::MODEL& e2) -> bool { auto role = key; switch(role) { - case FMH::MODEL_KEY::MIME: + case KEYS::MIME: if(e1[role] == "inode/directory") return true; break; - case FMH::MODEL_KEY::SIZE: + case KEYS::SIZE: { if(e1[role].toDouble() > e2[role].toDouble()) return true; break; } - case FMH::MODEL_KEY::MODIFIED: - case FMH::MODEL_KEY::DATE: + case KEYS::MODIFIED: + case KEYS::DATE: { auto currentTime = QDateTime::currentDateTime(); auto date1 = QDateTime::fromString(e1[role], Qt::TextDate); auto date2 = QDateTime::fromString(e2[role], Qt::TextDate); if(date1.secsTo(currentTime) < date2.secsTo(currentTime)) return true; break; } - case FMH::MODEL_KEY::LABEL: + case KEYS::LABEL: { const auto str1 = QString(e1[role]).toLower(); const auto str2 = QString(e2[role]).toLower(); if(str1 < str2) return true; break; } default: if(e1[role] < e2[role]) return true; } return false; }); } QString FMList::getPath() const { return this->path; } void FMList::setPath(const QString &path) { if(this->path == path) return; if(this->pathType == FMList::PATHTYPE::PLACES_PATH) this->searchPath = this->path; this->path = path; this->setPreviousPath(this->path); qDebug()<< "Prev History" << this->prevHistory; const auto __scheme = QUrl(this->path).scheme(); qDebug()<< "CurrentPath" <<__scheme; // if(path.startsWith(FMH::PATHTYPE_NAME[FMH::PATHTYPE_KEY::SEARCH_PATH]+"/")) if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::SEARCH_PATH]) { this->pathExists = true; this->pathType = FMList::PATHTYPE::SEARCH_PATH; emit this->pathExistsChanged(); emit this->pathTypeChanged(); this->watchPath(QString()); }else if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::CLOUD_PATH]) { this->pathExists = true; this->pathType = FMList::PATHTYPE::CLOUD_PATH; emit this->pathExistsChanged(); emit this->pathTypeChanged(); this->watchPath(QString()); }else if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::APPS_PATH]) { qDebug()<< "GET APPS" ; this->pathExists = true; this->pathType = FMList::PATHTYPE::APPS_PATH; emit this->pathExistsChanged(); emit this->pathTypeChanged(); this->watchPath(QString()); }else if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::TAGS_PATH]) { this->pathExists = true; this->pathType = FMList::PATHTYPE::TAGS_PATH; emit this->pathExistsChanged(); emit this->pathTypeChanged(); this->watchPath(QString()); }else if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::TRASH_PATH]) { this->pathExists = true; this->pathType = FMList::PATHTYPE::TRASH_PATH; emit this->pathExistsChanged(); emit this->pathTypeChanged(); this->watchPath(QString()); }else if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::PLACES_PATH]) { this->watchPath(this->path); this->pathExists = FMH::fileExists(this->path); this->pathType = FMList::PATHTYPE::PLACES_PATH; emit this->pathExistsChanged(); emit this->pathTypeChanged(); }else if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::MTP_PATH]) { this->pathExists = true; this->pathType = FMList::PATHTYPE::MTP_PATH; emit this->pathExistsChanged(); emit this->pathTypeChanged(); }else if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::FISH_PATH] ) { this->pathExists = true; this->pathType = FMList::PATHTYPE::FISH_PATH; emit this->pathExistsChanged(); emit this->pathTypeChanged(); }else if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::REMOTE_PATH] ) { this->pathExists = true; this->pathType = FMList::PATHTYPE::REMOTE_PATH; emit this->pathExistsChanged(); emit this->pathTypeChanged(); }else if(__scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::DRIVES_PATH] ) { this->pathExists = true; this->pathType = FMList::PATHTYPE::DRIVES_PATH; emit this->pathExistsChanged(); emit this->pathTypeChanged(); } qDebug() << "PATHTYPE IS" << this->pathType << FMH::PATHTYPE_SCHEME[static_cast(this->pathType)]; emit this->pathChanged(); } FMList::PATHTYPE FMList::getPathType() const { return this->pathType; } QStringList FMList::getFilters() const { return this->filters; } void FMList::setFilters(const QStringList &filters) { if(this->filters == filters) return; this->filters = filters; emit this->filtersChanged(); this->reset(); } FMList::FILTER FMList::getFilterType() const { return this->filterType; } void FMList::setFilterType(const FMList::FILTER &type) { this->filterType = type; this->filters = FMH::FILTER_LIST[static_cast(this->filterType)]; emit this->filtersChanged(); emit this->filterTypeChanged(); this->reset(); } bool FMList::getHidden() const { return this->hidden; } void FMList::setHidden(const bool &state) { if(this->hidden == state) return; this->hidden = state; if(this->pathType == FMList::PATHTYPE::PLACES_PATH && this->trackChanges && this->saveDirProps) FMH::setDirConf(this->path+"/.directory", "Settings", "HiddenFilesShown", this->hidden); else UTIL::saveSettings("HiddenFilesShown", this->hidden, "SETTINGS"); emit this->hiddenChanged(); this->reset(); } bool FMList::getPreview() const { return this->preview; } void FMList::setPreview(const bool &state) { if(this->preview == state) return; this->preview = state; if(this->pathType == FMList::PATHTYPE::PLACES_PATH && this->trackChanges && this->saveDirProps) FMH::setDirConf(this->path+"/.directory", "MAUIFM", "ShowThumbnail", this->preview); else UTIL::saveSettings("ShowThumbnail", this->preview, "SETTINGS"); emit this->previewChanged(); } bool FMList::getOnlyDirs() const { return this->onlyDirs; } void FMList::setOnlyDirs(const bool &state) { if(this->onlyDirs == state) return; this->onlyDirs = state; emit this->onlyDirsChanged(); this->reset(); } QVariantMap FMList::get(const int &index) const { if(index >= this->list.size() || index < 0) return QVariantMap(); const auto model = this->list.at(index); return FM::toMap(model); } void FMList::refresh() { emit this->pathChanged(); } void FMList::createDir(const QString& name) { if(this->pathType == FMList::PATHTYPE::PLACES_PATH) this->fm->createDir(this->path, name); else if(this->pathType == FMList::PATHTYPE::CLOUD_PATH) { this->fm->createCloudDir(QString(this->path).replace(FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::CLOUD_PATH]+"/"+this->fm->sync->getUser(), ""), name); } } void FMList::copyInto(const QVariantList& files) { if(this->pathType == FMList::PATHTYPE::PLACES_PATH || this->pathType == FMList::PATHTYPE::CLOUD_PATH) this->fm->copy(files, this->path); } void FMList::cutInto(const QVariantList& files) { if(this->pathType == FMList::PATHTYPE::PLACES_PATH) this->fm->cut(files, this->path); // else if(this->pathType == FMList::PATHTYPE::CLOUD_PATH) // { // this->fm->createCloudDir(QString(this->path).replace(FMH::PATHTYPE_NAME[FMList::PATHTYPE::CLOUD_PATH]+"/"+this->fm->sync->getUser(), ""), name); // } } void FMList::setDirIcon(const int &index, const QString &iconName) { if(index >= this->list.size() || index < 0) return; - const auto path = QUrl(this->list.at(index)[FMH::MODEL_KEY::PATH]); + const auto path = QUrl(this->list.at(index)[KEYS::PATH]); if(!FM::isDir(path)) return; FMH::setDirConf(path.toString()+"/.directory", "Desktop Entry", "Icon", iconName); - this->list[index][FMH::MODEL_KEY::ICON] = iconName; - emit this->updateModel(index, QVector {FMH::MODEL_KEY::ICON}); + this->list[index][KEYS::ICON] = iconName; + emit this->updateModel(index, QVector {KEYS::ICON}); } QString FMList::getParentPath() { switch(this->pathType) { case FMList::PATHTYPE::PLACES_PATH: return FM::parentDir(this->path).toString(); default: return this->getPreviousPath(); } } QString FMList::getPosteriorPath() { if(this->postHistory.isEmpty()) return this->path; return this->postHistory.takeAt(this->postHistory.length()-1); } void FMList::setPosteriorPath(const QString& path) { this->postHistory.append(path); } QString FMList::getPreviousPath() { if(this->prevHistory.isEmpty()) return this->path; if(this->prevHistory.length() < 2) return this->prevHistory.at(0); auto post = this->prevHistory.takeAt(this->prevHistory.length()-1); this->setPosteriorPath(post); return this->prevHistory.takeAt(this->prevHistory.length()-1); } void FMList::setPreviousPath(const QString& path) { this->prevHistory.append(path); } bool FMList::getPathEmpty() const { return this->pathEmpty; } bool FMList::getPathExists() const { return this->pathExists; } bool FMList::getTrackChanges() const { return this->trackChanges; } void FMList::setTrackChanges(const bool& value) { if(this->trackChanges == value) return; this->trackChanges = value; emit this->trackChangesChanged(); } bool FMList::getFoldersFirst() const { return this->foldersFirst; } void FMList::setFoldersFirst(const bool &value) { if(this->foldersFirst == value) return; this->pre(); this->foldersFirst = value; if(this->pathType == FMList::PATHTYPE::PLACES_PATH && this->trackChanges && this->saveDirProps) FMH::setDirConf(this->path+"/.directory", "MAUIFM", "FoldersFirst", this->foldersFirst); else UTIL::saveSettings("FoldersFirst", this->foldersFirst, "SETTINGS"); emit this->foldersFirstChanged(); this->sortList(); this->pos(); } void FMList::setSaveDirProps(const bool& value) { if(this->saveDirProps == value) return; this->saveDirProps = value; UTIL::saveSettings("SaveDirProps", this->saveDirProps, "SETTINGS"); emit this->saveDirPropsChanged(); } bool FMList::getSaveDirProps() const { return this->saveDirProps; } void FMList::setContentReady(const bool& value) { this->contentReady = value; emit this->contentReadyChanged(); } bool FMList::getContentReady() const { return this->contentReady; } FMList::VIEW_TYPE FMList::getViewType() const { return this->viewType; } void FMList::setViewType(const FMList::VIEW_TYPE& value) { if(this->viewType == value) return; this->viewType = value; if(this->trackChanges && this->saveDirProps) FMH::setDirConf(this->path+"/.directory", "MAUIFM", "ViewType", this->viewType); else UTIL::saveSettings("ViewType", this->viewType, "SETTINGS"); emit this->viewTypeChanged(); } void FMList::search(const QString& query, const QUrl &path, const bool &hidden, const bool &onlyDirs, const QStringList &filters) { qDebug()<< "SEARCHING FOR" << query << path; if(!path.isLocalFile()) { qWarning() << "URL recived is not a local file. search" << path; return; } QFutureWatcher *watcher = new QFutureWatcher; connect(watcher, &QFutureWatcher::finished, [=]() { if(this->pathType != FMList::PATHTYPE::SEARCH_PATH) return; const auto res = watcher->future().result(); if(res.path != this->searchPath) return; emit this->preListChanged(); this->list = res.content; emit this->postListChanged(); emit this->searchResultReady(); this->pathEmpty = this->list.isEmpty() && FM::fileExists(this->path); emit this->pathEmptyChanged(); this->sortList(); this->setContentReady(true); watcher->deleteLater(); }); QFuture t1 = QtConcurrent::run([=]() -> FMH::PATH_CONTENT { FMH::PATH_CONTENT res; res.path = path.toString(); res.content = FM::search(query, path, hidden, onlyDirs, filters); return res; }); watcher->setFuture(t1); } int FMList::getCloudDepth() const { return this->cloudDepth; } void FMList::setCloudDepth(const int& value) { if(this->cloudDepth == value) return; this->cloudDepth = value; emit this->cloudDepthChanged(); this->reset(); } diff --git a/src/fm/fmlist.h b/src/fm/fmlist.h index 4cdb8fc..9297b93 100644 --- a/src/fm/fmlist.h +++ b/src/fm/fmlist.h @@ -1,245 +1,245 @@ /* * * Copyright (C) 2018 Camilo Higuita * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef FMLIST_H #define FMLIST_H #include #include "fmh.h" #include "mauilist.h" struct PathContent { QString path; FMH::MODEL_LIST content; }; class FM; class QFileSystemWatcher; class FMList : public MauiList { Q_OBJECT Q_PROPERTY(QString path READ getPath WRITE setPath NOTIFY pathChanged()) Q_PROPERTY(bool hidden READ getHidden WRITE setHidden NOTIFY hiddenChanged()) Q_PROPERTY(bool onlyDirs READ getOnlyDirs WRITE setOnlyDirs NOTIFY onlyDirsChanged()) Q_PROPERTY(bool preview READ getPreview WRITE setPreview NOTIFY previewChanged()) Q_PROPERTY(FMList::VIEW_TYPE viewType READ getViewType WRITE setViewType NOTIFY viewTypeChanged()) Q_PROPERTY(int cloudDepth READ getCloudDepth WRITE setCloudDepth NOTIFY cloudDepthChanged()) Q_PROPERTY(bool contentReady READ getContentReady NOTIFY contentReadyChanged()) Q_PROPERTY(QStringList filters READ getFilters WRITE setFilters NOTIFY filtersChanged()) Q_PROPERTY(FMList::FILTER filterType READ getFilterType WRITE setFilterType NOTIFY filterTypeChanged()) Q_PROPERTY(FMList::SORTBY sortBy READ getSortBy WRITE setSortBy NOTIFY sortByChanged()) Q_PROPERTY(bool foldersFirst READ getFoldersFirst WRITE setFoldersFirst NOTIFY foldersFirstChanged()) Q_PROPERTY(FMList::PATHTYPE pathType READ getPathType NOTIFY pathTypeChanged()) Q_PROPERTY(bool trackChanges READ getTrackChanges WRITE setTrackChanges NOTIFY trackChangesChanged()) Q_PROPERTY(bool saveDirProps READ getSaveDirProps WRITE setSaveDirProps NOTIFY saveDirPropsChanged()) Q_PROPERTY(bool pathExists READ getPathExists NOTIFY pathExistsChanged()) Q_PROPERTY(bool pathEmpty READ getPathEmpty NOTIFY pathEmptyChanged()) Q_PROPERTY(QString previousPath READ getPreviousPath) Q_PROPERTY(QString posteriorPath READ getPosteriorPath) Q_PROPERTY(QString parentPath READ getParentPath) public: - enum SORTBY : uint_fast8_t + enum SORTBY : uint { - SIZE = FMH::MODEL_KEY::SIZE, - MODIFIED = FMH::MODEL_KEY::MODIFIED, - DATE = FMH::MODEL_KEY::DATE, - LABEL = FMH::MODEL_KEY::LABEL, - MIME = FMH::MODEL_KEY::MIME, - ADDDATE = FMH::MODEL_KEY::MIME, - TITLE = FMH::MODEL_KEY::TITLE, - PLACE = FMH::MODEL_KEY::PLACE, - FORMAT = FMH::MODEL_KEY::FORMAT + SIZE = KEYS::SIZE, + MODIFIED = KEYS::MODIFIED, + DATE = KEYS::DATE, + LABEL = KEYS::LABEL, + MIME = KEYS::MIME, + ADDDATE = KEYS::MIME, + TITLE = KEYS::TITLE, + PLACE = KEYS::PLACE, + FORMAT = KEYS::FORMAT }; Q_ENUM(SORTBY) - enum FILTER : uint_fast8_t + enum FILTER : uint { AUDIO = FMH::FILTER_TYPE::AUDIO, VIDEO= FMH::FILTER_TYPE::VIDEO, TEXT = FMH::FILTER_TYPE::TEXT, IMAGE = FMH::FILTER_TYPE::IMAGE, NONE = FMH::FILTER_TYPE::NONE }; Q_ENUM(FILTER) - enum PATHTYPE : uint_fast8_t + enum PATHTYPE : uint { PLACES_PATH = FMH::PATHTYPE_KEY::PLACES_PATH, FISH_PATH = FMH::PATHTYPE_KEY::FISH_PATH, MTP_PATH = FMH::PATHTYPE_KEY::MTP_PATH, REMOTE_PATH = FMH::PATHTYPE_KEY::REMOTE_PATH, DRIVES_PATH = FMH::PATHTYPE_KEY::DRIVES_PATH, REMOVABLE_PATH = FMH::PATHTYPE_KEY::REMOVABLE_PATH, TAGS_PATH = FMH::PATHTYPE_KEY::TAGS_PATH, APPS_PATH = FMH::PATHTYPE_KEY::APPS_PATH, TRASH_PATH = FMH::PATHTYPE_KEY::TRASH_PATH, SEARCH_PATH = FMH::PATHTYPE_KEY::SEARCH_PATH, CLOUD_PATH = FMH::PATHTYPE_KEY::CLOUD_PATH }; Q_ENUM(PATHTYPE) - enum VIEW_TYPE : uint_fast8_t + enum VIEW_TYPE : uint { ICON_VIEW, LIST_VIEW, MILLERS_VIEW }; Q_ENUM(VIEW_TYPE) FMList(QObject *parent = nullptr); ~FMList(); FMH::MODEL_LIST items() const override; FMList::SORTBY getSortBy() const; void setSortBy(const FMList::SORTBY &key); QString getPath() const; void setPath(const QString &path); FMList::PATHTYPE getPathType() const; QStringList getFilters() const; void setFilters(const QStringList &filters); FMList::FILTER getFilterType() const; void setFilterType(const FMList::FILTER &type); bool getHidden() const; void setHidden(const bool &state); bool getPreview() const; void setPreview(const bool &state); bool getOnlyDirs() const; void setOnlyDirs(const bool &state); QString getParentPath(); QString getPreviousPath(); void setPreviousPath(const QString &path); QString getPosteriorPath(); void setPosteriorPath(const QString &path); bool getPathEmpty() const; bool getPathExists() const; bool getTrackChanges() const; void setTrackChanges(const bool &value); bool getFoldersFirst() const; void setFoldersFirst(const bool &value); bool getSaveDirProps() const; void setSaveDirProps(const bool &value); bool getContentReady() const; void setContentReady(const bool &value); VIEW_TYPE getViewType() const; void setViewType(const VIEW_TYPE &value); int getCloudDepth() const; void setCloudDepth(const int &value); private: FM *fm; QFileSystemWatcher *watcher; void pre(); void pos(); void reset(); void setList(); void sortList(); void watchPath(const QString &path, const bool &clear = true); void search(const QString &query, const QUrl &path, const bool &hidden = false, const bool &onlyDirs = false, const QStringList &filters = QStringList()); FMH::MODEL_LIST list = {{}}; QString path = QString(); QStringList filters = {}; bool onlyDirs = false; bool hidden = false; bool preview = false; bool pathExists = false; bool pathEmpty = true; bool trackChanges = true; bool foldersFirst = false; bool saveDirProps = false; bool contentReady = false; int cloudDepth = 1; QString searchPath; VIEW_TYPE viewType = VIEW_TYPE::ICON_VIEW; FMList::SORTBY sort = FMList::SORTBY::MODIFIED; FMList::FILTER filterType = FMList::FILTER::NONE; FMList::PATHTYPE pathType = FMList::PATHTYPE::PLACES_PATH; QStringList prevHistory = {}; QStringList postHistory = {}; public slots: QVariantMap get(const int &index) const; void refresh(); void createDir(const QString &name); void copyInto(const QVariantList &files); void cutInto(const QVariantList &files); void setDirIcon(const int &index, const QString &iconName); signals: void pathChanged(); void pathTypeChanged(); void filtersChanged(); void filterTypeChanged(); void hiddenChanged(); void previewChanged(); void onlyDirsChanged(); void sortByChanged(); void trackChangesChanged(); void foldersFirstChanged(); void saveDirPropsChanged(); void contentReadyChanged(); void viewTypeChanged(); void cloudDepthChanged(); void pathEmptyChanged(); void pathExistsChanged(); void warning(QString message); void progress(int percent); void searchResultReady(); }; #endif // FMLIST_H diff --git a/src/fm/pathlist.cpp b/src/fm/pathlist.cpp index 613da36..eef6f71 100644 --- a/src/fm/pathlist.cpp +++ b/src/fm/pathlist.cpp @@ -1,99 +1,99 @@ /* * * Copyright (C) 2019 camilo * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "pathlist.h" #include "fm.h" PathList::PathList(QObject *parent) : MauiList(parent) { } PathList::~PathList() {} QVariantMap PathList::get(const int& index) const { if(this->list.isEmpty() || index >= this->list.size() || index < 0) { return QVariantMap(); } const auto model = this->list.at(index); return FM::toMap(model); } QString PathList::getPath() const { return this->m_path; } FMH::MODEL_LIST PathList::items() const { return this->list; } void PathList::setPath(const QString& path) { if(path == this->m_path) return; if(!this->list.isEmpty() && FM::parentDir(path) == this->m_path) { - // qDebug() << "APPENDING PATHS TO MODEL << "<< FM::parentDir(this->m_path) << this->list.last()[FMH::MODEL_KEY::PATH]; + // qDebug() << "APPENDING PATHS TO MODEL << "<< FM::parentDir(this->m_path) << this->list.last()[KEYS::PATH]; emit this->preItemAppended(); this->list << FMH::getDirInfoModel(path); emit this->postItemAppended(); }else{ emit this->preListChanged(); this->list.clear(); this->list << PathList::splitPath(path); emit this->postListChanged(); } this->m_path = path; emit this->pathChanged(); } FMH::MODEL_LIST PathList::splitPath(const QString& path) { auto __url = QUrl(path); const auto scheme = __url.scheme(); __url.setScheme(""); const auto m_url = __url.toString(); const auto paths = m_url.split("/", QString::SplitBehavior::SkipEmptyParts); qDebug()<< "PATHBAR LIST"<< m_url << paths; return std::accumulate(paths.constBegin(), paths.constEnd(), FMH::MODEL_LIST(), [scheme](FMH::MODEL_LIST &list, const QString &part) -> FMH::MODEL_LIST { - const auto url = list.isEmpty() ? QString(scheme + (scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::PLACES_PATH] ? ":///" : "://") +part) : list.last()[FMH::MODEL_KEY::PATH] + QString("/"+part); + const auto url = list.isEmpty() ? QString(scheme + (scheme == FMH::PATHTYPE_SCHEME[FMH::PATHTYPE_KEY::PLACES_PATH] ? ":///" : "://") +part) : list.last()[KEYS::PATH] + QString("/"+part); if(!url.isEmpty()) list << FMH::MODEL { - {FMH::MODEL_KEY::LABEL, part}, - {FMH::MODEL_KEY::PATH, url} + {KEYS::LABEL, part}, + {KEYS::PATH, url} }; return list; }); } diff --git a/src/fm/placeslist.cpp b/src/fm/placeslist.cpp index 412e626..e759da7 100644 --- a/src/fm/placeslist.cpp +++ b/src/fm/placeslist.cpp @@ -1,259 +1,259 @@ /* * * Copyright (C) 2018 camilo * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "placeslist.h" #include "fm.h" #include #include #include #include #ifdef Q_OS_ANDROID #else #include #endif #ifdef Q_OS_ANDROID PlacesList::PlacesList(QObject *parent) : MauiList(parent), fm(new FM(this)), model(nullptr), watcher(new QFileSystemWatcher(this)) #else PlacesList::PlacesList(QObject *parent) : MauiList(parent), fm(new FM(this)), model(new KFilePlacesModel(this)), watcher(new QFileSystemWatcher(this)) #endif { connect(watcher, &QFileSystemWatcher::directoryChanged, [this](const QString &path) { if(this->count.contains(path)) { const auto oldCount = this->count[path]; const auto index = this->indexOf(path); - const auto newCount = FMH::getFileInfoModel(path)[FMH::MODEL_KEY::COUNT].toInt(); + const auto newCount = FMH::getFileInfoModel(path)[KEYS::COUNT].toInt(); const auto count = newCount - oldCount; - this->list[index][FMH::MODEL_KEY::COUNT] = QString::number(count); - emit this->updateModel(index, {FMH::MODEL_KEY::COUNT}); + this->list[index][KEYS::COUNT] = QString::number(count); + emit this->updateModel(index, {KEYS::COUNT}); } }); connect(fm, &FM::cloudAccountInserted, this, &PlacesList::reset); connect(fm, &FM::cloudAccountRemoved, this, &PlacesList::reset); connect(this, &PlacesList::groupsChanged, this, &PlacesList::reset); this->setList(); } void PlacesList::watchPath(const QString& path) { if(path.isEmpty() || !FMH::fileExists(path)) return; this->watcher->addPath(path); } PlacesList::~PlacesList() {} FMH::MODEL_LIST PlacesList::items() const { return this->list; } #ifdef Q_OS_ANDROID #else static FMH::MODEL modelPlaceInfo(const KFilePlacesModel &model, const QModelIndex &index, const FMH::PATHTYPE_KEY &type) { return FMH::MODEL { - {FMH::MODEL_KEY::PATH, model.url(index).toString()}, - {FMH::MODEL_KEY::URL, model.url(index).toString()}, - {FMH::MODEL_KEY::ICON, model.icon(index).name()}, - {FMH::MODEL_KEY::LABEL, model.text(index)}, - {FMH::MODEL_KEY::NAME, model.text(index)}, - {FMH::MODEL_KEY::TYPE, FMH::PATHTYPE_LABEL[type]} + {KEYS::PATH, model.url(index).toString()}, + {KEYS::URL, model.url(index).toString()}, + {KEYS::ICON, model.icon(index).name()}, + {KEYS::LABEL, model.text(index)}, + {KEYS::NAME, model.text(index)}, + {KEYS::TYPE, FMH::PATHTYPE_LABEL[type]} }; } #endif static FMH::MODEL_LIST getGroup(const KFilePlacesModel &model, const FMH::PATHTYPE_KEY &type) { #ifdef Q_OS_ANDROID Q_UNUSED(model) FMH::MODEL_LIST res; if(type == FMH::PATHTYPE_KEY::PLACES_PATH) res = FM::getDefaultPaths(); return res; #else const auto group = model.groupIndexes(static_cast(type)); return std::accumulate(group.begin(), group.end(), FMH::MODEL_LIST(), [&model, &type](FMH::MODEL_LIST &list, const QModelIndex &index) -> FMH::MODEL_LIST { list << modelPlaceInfo(model, index, type); return list; }); #endif } void PlacesList::setList() { this->list.clear(); for(const auto &group : this->groups) switch(group) { case FMH::PATHTYPE_KEY::PLACES_PATH: this->list << getGroup(*this->model, FMH::PATHTYPE_KEY::PLACES_PATH); break; case FMH::PATHTYPE_KEY::APPS_PATH: this->list << FM::getAppsPath(); break; case FMH::PATHTYPE_KEY::DRIVES_PATH: this->list << getGroup(*this->model, FMH::PATHTYPE_KEY::DRIVES_PATH); break; case FMH::PATHTYPE_KEY::REMOTE_PATH: this->list << getGroup(*this->model, FMH::PATHTYPE_KEY::REMOTE_PATH); break; case FMH::PATHTYPE_KEY::REMOVABLE_PATH: this->list << getGroup(*this->model, FMH::PATHTYPE_KEY::REMOVABLE_PATH); break; case FMH::PATHTYPE_KEY::TAGS_PATH: this->list << this->fm->getTags(); break; case FMH::PATHTYPE_KEY::CLOUD_PATH: this->list << this->fm->getCloudAccounts(); break; } this->setCount(); } void PlacesList::setCount() { this->watcher->removePaths(this->watcher->directories()); for(auto &data : this->list) { - const auto path = data[FMH::MODEL_KEY::PATH]; + const auto path = data[KEYS::PATH]; if(FM::isDir(path)) { - data.insert(FMH::MODEL_KEY::COUNT, "0"); - const auto count = FMH::getFileInfoModel(path)[FMH::MODEL_KEY::COUNT]; + data.insert(KEYS::COUNT, "0"); + const auto count = FMH::getFileInfoModel(path)[KEYS::COUNT]; this->count.insert(path, count.toInt()); this->watchPath(path); } } } int PlacesList::indexOf(const QString& path) { const auto index = std::find_if(this->list.begin(), this->list.end(), [&path](const FMH::MODEL &item) -> bool { - return item[FMH::MODEL_KEY::PATH] == path; + return item[KEYS::PATH] == path; }); return std::distance(this->list.begin(), index); } void PlacesList::reset() { emit this->preListChanged(); this->setList(); emit this->postListChanged(); } QList PlacesList::getGroups() const { return this->groups; } void PlacesList::setGroups(const QList &value) { if(this->groups == value) return; this->groups = value; emit this->groupsChanged(); } QVariantMap PlacesList::get(const int& index) const { if(index >= this->list.size() || index < 0) return QVariantMap(); const auto model = this->list.at(index); return FM::toMap(model); } void PlacesList::refresh() { this->reset(); } void PlacesList::clearBadgeCount(const int& index) { - this->list[index][FMH::MODEL_KEY::COUNT] = "0"; - emit this->updateModel(index, {FMH::MODEL_KEY::COUNT}); + this->list[index][KEYS::COUNT] = "0"; + emit this->updateModel(index, {KEYS::COUNT}); } void PlacesList::addPlace(const QString& path) { const auto it = std::find_if(this->list.rbegin(), this->list.rend(), [](const FMH::MODEL &item) -> bool{ - return item[FMH::MODEL_KEY::TYPE] == FMH::PATHTYPE_LABEL[FMH::PATHTYPE_KEY::PLACES_PATH]; + return item[KEYS::TYPE] == FMH::PATHTYPE_LABEL[FMH::PATHTYPE_KEY::PLACES_PATH]; }); const auto index = std::distance(it, this->list.rend()); qDebug()<< "trying to add path to places" << path<< QDir(path).dirName(); emit this->preItemAppendedAt(index); #ifdef Q_OS_ANDROID //do android stuff until cmake works with android this->list.insert(index, FMH::getDirInfoModel(path)); #else // const auto url = QStringLiteral("file://")+path; this->model->addPlace(QDir(path).dirName(), path); this->list.insert(index, modelPlaceInfo(*this->model, this->model->closestItem(path), FMH::PATHTYPE_KEY::PLACES_PATH)); #endif emit this->postItemAppended(); } void PlacesList::removePlace(const int& index) { emit this->preItemRemoved(index); #ifdef Q_OS_ANDROID //do android stuff until cmake works with android #else this->model->removePlace(this->model->index(index, 0)); #endif this->list.removeAt(index); emit this->postItemRemoved(); } diff --git a/src/kde/mauikde.cpp b/src/kde/mauikde.cpp index 3da5851..e8d13fa 100644 --- a/src/kde/mauikde.cpp +++ b/src/kde/mauikde.cpp @@ -1,320 +1,320 @@ /* * Copyright 2018 Camilo Higuita * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "mauikde.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kdeconnect.h" Q_DECLARE_METATYPE(QList) MAUIKDE::MAUIKDE(QObject *parent) : QObject(parent) { } MAUIKDE::~MAUIKDE() { } static QVariantMap createActionItem(const QString &label, const QString &actionId, const QVariant &argument = QVariant()) { QVariantMap map; map["label"] = label; map["actionId"] = actionId; if (argument.isValid()) map["actionArgument"] = argument; return map; } QVariantList MAUIKDE::services(const QUrl &url) { qDebug()<<"trying to get mimes"; QVariantList list; if (url.isValid()) { auto fileItem = new KFileItem(url); fileItem->determineMimeType(); KService::List services = KMimeTypeTrader::self()->query(fileItem->mimetype(), "Application"); if (!services.isEmpty()) foreach (const KService::Ptr service, services) { const QString text = service->name().replace('&', "&&"); QVariantMap item = createActionItem(text, "_kicker_fileItem_openWith", service->entryPath()); item["icon"] = service->icon(); item["serviceExec"] = service->exec(); list << item; } list << createActionItem(i18n("Properties"), "_kicker_fileItem_properties"); return list; } else return list; } bool MAUIKDE::sendToDevice(const QString &device, const QString &id, const QStringList &urls) { for(auto url : urls) KdeConnect::sendToDevice(device, id, url); return true; } QVariantList MAUIKDE::devices() { return KdeConnect::getDevices(); } void MAUIKDE::openWithApp(const QString &exec, const QStringList &urls) { KService service(exec); KRun::runApplication(service, QUrl::fromStringList(urls), nullptr); } void MAUIKDE::attachEmail(const QStringList &urls) { if(urls.isEmpty()) return; QFileInfo file(urls[0]); KToolInvocation::invokeMailer("", "", "", file.baseName(), "Files shared... ", "", urls); // QDesktopServices::openUrl(QUrl("mailto:?subject=test&body=test&attachment;=" // + url)); } void MAUIKDE::email(const QString &to, const QString &cc, const QString &bcc, const QString &subject, const QString &body, const QString &messageFile, const QStringList &urls) { KToolInvocation::invokeMailer(to, cc, bcc, subject, body, messageFile, urls); // QDesktopServices::openUrl(QUrl("mailto:?subject=test&body=test&attachment;=" // + url)); } void MAUIKDE::setColorScheme(const QString &schemeName, const QString &bg, const QString &fg) { const QString colorSchemeDir = FMH::DataPath+"/color-schemes/"; const QString colorsFile = colorSchemeDir+schemeName+".colors"; if(!FMH::fileExists(colorSchemeDir)) QDir(colorSchemeDir).mkpath("."); if(!FMH::fileExists(colorsFile)) { QFile color_scheme_file(":/assets/maui-app.colors"); if(color_scheme_file.copy(colorsFile)) { QFile copied_scheme_file(colorsFile); copied_scheme_file.setPermissions(QFile::ReadOwner|QFile::WriteOwner|QFile::ExeOwner|QFile::ReadGroup|QFile::ExeGroup|QFile::ReadOther|QFile::ExeOther); KConfig new_scheme_file(colorsFile); auto new_scheme_name = new_scheme_file.group("General"); new_scheme_name.writeEntry("Name", QVariant(schemeName)); new_scheme_name.writeEntry("ColorScheme", QVariant(schemeName)); } } KColorSchemeManager manager; auto schemeModel = manager.indexForScheme(schemeName); if(!schemeModel.isValid() && FMH::fileExists(colorsFile)) { qDebug()<< "COLROS FILE EXISTS BUT IS INVALID"; KConfig scheme_file(colorsFile); auto scheme_name = scheme_file.group("General"); scheme_name.writeEntry("Name", QVariant(schemeName)); scheme_name.writeEntry("ColorScheme", QVariant(schemeName)); } schemeModel = manager.indexForScheme(schemeName); if(schemeModel.isValid()) { qDebug()<<"COLRO SCHEME IS VALID"; if(!bg.isEmpty() || !fg.isEmpty()) { qDebug()<<"COLRO SCHEME FILE EXISTS"<< colorsFile; KConfig file(colorsFile); auto group = file.group("WM"); QColor color; if(!bg.isEmpty()) { color.setNamedColor(bg); QVariantList rgb = {color.red(), color.green(), color.blue()}; group.writeEntry("activeBackground", QVariant::fromValue(rgb)); group.writeEntry("inactiveBackground", QVariant::fromValue(rgb)); } if(!fg.isEmpty()) { color.setNamedColor(fg); QVariantList rgb = {color.red(), color.green(), color.blue()}; group.writeEntry("activeForeground", QVariant::fromValue(rgb)); group.writeEntry("inactiveForeground", QVariant::fromValue(rgb)); } file.group("Colors:Window"); if(!bg.isEmpty()) { color.setNamedColor(bg); QVariantList rgb = {color.red(), color.green(), color.blue()}; group.writeEntry("BackgroundNormal", QVariant::fromValue(rgb)); group.writeEntry("BackgroundAlternate", QVariant::fromValue(rgb)); } if(!fg.isEmpty()) { color.setNamedColor(fg); QVariantList rgb = {color.red(), color.green(), color.blue()}; group.writeEntry("ForegroundActive", QVariant::fromValue(rgb)); group.writeEntry("ForegroundInactive", QVariant::fromValue(rgb)); } } manager.activateScheme(schemeModel); } } FMH::MODEL_LIST MAUIKDE::getApps() { FMH::MODEL_LIST res; KServiceGroup::Ptr group = KServiceGroup::root(); bool sortByGenericName = false; KServiceGroup::List list = group->entries(true /* sorted */, true /* excludeNoDisplay */, true /* allowSeparators */, sortByGenericName /* sortByGenericName */); for (KServiceGroup::List::ConstIterator it = list.constBegin(); it != list.constEnd(); it++) { const KSycocaEntry::Ptr p = (*it); if (p->isType(KST_KServiceGroup)) { KServiceGroup::Ptr s(static_cast(p.data())); if (!s->noDisplay() && s->childCount() > 0) { qDebug()<< "Getting app"<icon(); res << FMH::MODEL { - {FMH::MODEL_KEY::ICON, s->icon()}, - {FMH::MODEL_KEY::LABEL, s->name()}, - {FMH::MODEL_KEY::PATH, FMH::PATHTYPE_URI[FMH::PATHTYPE_KEY::APPS_PATH]+s->entryPath()} + {KEYS::ICON, s->icon()}, + {KEYS::LABEL, s->name()}, + {KEYS::PATH, FMH::PATHTYPE_URI[FMH::PATHTYPE_KEY::APPS_PATH]+s->entryPath()} }; } } } return res; } FMH::MODEL_LIST MAUIKDE::getApps(const QString &groupStr) { const auto grp = QString(groupStr).replace("/", "")+"/"; qDebug() << "APP GROUDP" << groupStr<< grp; if(grp.isEmpty()) return getApps(); FMH::MODEL_LIST res; // const KServiceGroup::Ptr group(static_cast(groupStr)); auto group = new KServiceGroup(grp); KServiceGroup::List list = group->entries(true /* sorted */, true /* excludeNoDisplay */, false /* allowSeparators */, true /* sortByGenericName */); for (KServiceGroup::List::ConstIterator it = list.constBegin(); it != list.constEnd(); it++) { const KSycocaEntry::Ptr p = (*it); if (p->isType(KST_KService)) { const KService::Ptr s(static_cast(p.data())); if (s->noDisplay()) continue; res << FMH::MODEL { - {FMH::MODEL_KEY::ICON, s->icon()}, - {FMH::MODEL_KEY::LABEL, s->name()}, - {FMH::MODEL_KEY::PATH, s->entryPath()} + {KEYS::ICON, s->icon()}, + {KEYS::LABEL, s->name()}, + {KEYS::PATH, s->entryPath()} }; } else if (p->isType(KST_KServiceSeparator)) { qDebug()<< "separator wtf"; } else if (p->isType(KST_KServiceGroup)) { const KServiceGroup::Ptr s(static_cast(p.data())); if (s->childCount() == 0) continue; res << FMH::MODEL { - {FMH::MODEL_KEY::ICON, s->icon()}, - {FMH::MODEL_KEY::LABEL, s->name()}, - {FMH::MODEL_KEY::PATH, FMH::PATHTYPE_URI[FMH::PATHTYPE_KEY::APPS_PATH]+s->entryPath()} + {KEYS::ICON, s->icon()}, + {KEYS::LABEL, s->name()}, + {KEYS::PATH, FMH::PATHTYPE_URI[FMH::PATHTYPE_KEY::APPS_PATH]+s->entryPath()} }; } } return res; } void MAUIKDE::launchApp(const QString &app) { KService service(app); KRun::runApplication(service,{}, nullptr); } diff --git a/src/utils/handy.cpp b/src/utils/handy.cpp index db8f2e8..55ac3e4 100644 --- a/src/utils/handy.cpp +++ b/src/utils/handy.cpp @@ -1,99 +1,99 @@ /* * Copyright 2018 Camilo Higuita * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "handy.h" #include "utils.h" #include #include #include #include #include #include #include "fmh.h" Handy::Handy(QObject *parent) : QObject(parent) {} Handy::~Handy() {} QVariantMap Handy::appInfo() { auto app = UTIL::app; - auto res = QVariantMap({{FMH::MODEL_NAME[FMH::MODEL_KEY::NAME], app->applicationName()}, - {FMH::MODEL_NAME[FMH::MODEL_KEY::VERSION], app->applicationVersion()}, - {FMH::MODEL_NAME[FMH::MODEL_KEY::ORG], app->organizationName()}, - {FMH::MODEL_NAME[FMH::MODEL_KEY::DOMAIN], app->organizationDomain()}, + auto res = QVariantMap({{KEYS::_N[KEYS::NAME], app->applicationName()}, + {KEYS::_N[KEYS::VERSION], app->applicationVersion()}, + {KEYS::_N[KEYS::ORG], app->organizationName()}, + {KEYS::_N[KEYS::DOMAIN], app->organizationDomain()}, {"mauikit_version", MAUIKIT_VERSION_STR}, {"qt_version", QT_VERSION_STR} }); #ifdef Q_OS_ANDROID - res.insert(FMH::MODEL_NAME[FMH::MODEL_KEY::ICON], QGuiApplication::windowIcon().name()); + res.insert(KEYS::_N[KEYS::ICON], QGuiApplication::windowIcon().name()); #else - res.insert(FMH::MODEL_NAME[FMH::MODEL_KEY::ICON], QApplication::windowIcon().name()); + res.insert(KEYS::_N[KEYS::ICON], QApplication::windowIcon().name()); #endif return res; } QVariantMap Handy::userInfo() { QString name = qgetenv("USER"); if (name.isEmpty()) name = qgetenv("USERNAME"); - auto res = QVariantMap({{FMH::MODEL_NAME[FMH::MODEL_KEY::NAME], name}}); + auto res = QVariantMap({{KEYS::_N[KEYS::NAME], name}}); return res; } QString Handy::getClipboard() { #ifdef Q_OS_ANDROID auto clipbopard = QGuiApplication::clipboard(); #else auto clipbopard = QApplication::clipboard(); #endif auto mime = clipbopard->mimeData(); if(mime->hasText()) return clipbopard->text(); return QString(); } bool Handy::copyToClipboard(const QString &text) { #ifdef Q_OS_ANDROID auto clipbopard = QGuiApplication::clipboard(); #else auto clipbopard = QApplication::clipboard(); #endif clipbopard->setText(text); return true; } int Handy::version() { auto current = QOperatingSystemVersion::current(); return current.majorVersion(); } diff --git a/src/utils/mauiapp.h b/src/utils/mauiapp.h index 39e6b31..109f3e9 100644 --- a/src/utils/mauiapp.h +++ b/src/utils/mauiapp.h @@ -1,104 +1,104 @@ /* * * Copyright (C) 2019 camilo * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MAUIAPP_H #define MAUIAPP_H #include #include #include /** * @todo write docs */ class MauiApp : public QObject { Q_OBJECT Q_PROPERTY(QString name READ getName) Q_PROPERTY(QString version READ getVersion) Q_PROPERTY(QString org READ getOrg) Q_PROPERTY(QString domain READ getDomain) Q_PROPERTY(QString iconName READ getIconName WRITE setIconName) Q_PROPERTY(QString description READ getDomain WRITE setDescription) Q_PROPERTY(QString mauikitVersion READ getMauikitVersion) Q_PROPERTY(QString qtVersion READ getQtVersion) public: static MauiApp *instance(); static QString getName() { - return Handy::appInfo().value(FMH::MODEL_NAME[FMH::MODEL_KEY::NAME]).toString(); + return Handy::appInfo().value(KEYS::_N[KEYS::NAME]).toString(); } static QString getVersion() { - return Handy::appInfo().value(FMH::MODEL_NAME[FMH::MODEL_KEY::VERSION]).toString(); + return Handy::appInfo().value(KEYS::_N[KEYS::VERSION]).toString(); } static QString getOrg() { - return Handy::appInfo().value(FMH::MODEL_NAME[FMH::MODEL_KEY::ORG]).toString(); + return Handy::appInfo().value(KEYS::_N[KEYS::ORG]).toString(); } static QString getDomain() { - return Handy::appInfo().value(FMH::MODEL_NAME[FMH::MODEL_KEY::DOMAIN]).toString(); + return Handy::appInfo().value(KEYS::_N[KEYS::DOMAIN]).toString(); } static QString getMauikitVersion() { return Handy::appInfo().value("mauikit_version").toString(); } static QString getQtVersion() { return Handy::appInfo().value("qt_version").toString(); } QString getDescription() const { return description; } void setDescription(const QString &value) { description = value; } QString getIconName() const { return iconName; } void setIconName(const QString &value) { iconName = value; } ~MauiApp(); private: static MauiApp *m_instance; MauiApp(QObject *parent = nullptr); MauiApp(const MauiApp &other) = delete; QString description; QString iconName; }; #endif // MAUIAPP_H diff --git a/src/utils/model_template/mauimodel.cpp b/src/utils/model_template/mauimodel.cpp index a61e7b8..33de80f 100644 --- a/src/utils/model_template/mauimodel.cpp +++ b/src/utils/model_template/mauimodel.cpp @@ -1,132 +1,132 @@ /* * * Copyright (C) 2019 camilo * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mauimodel.h" #include "mauilist.h" MauiModel::~MauiModel() { } MauiModel::MauiModel(QObject *parent) : QAbstractListModel(parent), list(nullptr) {} int MauiModel::rowCount(const QModelIndex &parent) const { if (parent.isValid() || !list) return 0; return list->items().size(); } QVariant MauiModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || !list) return QVariant(); - return list->items().at(index.row())[static_cast(role)]; + return list->items().at(index.row())[static_cast(role)]; } bool MauiModel::setData(const QModelIndex &index, const QVariant &value, int role) { Q_UNUSED(index); Q_UNUSED(value); Q_UNUSED(role); return false; } Qt::ItemFlags MauiModel::flags(const QModelIndex &index) const { if (!index.isValid()) return Qt::NoItemFlags; return Qt::ItemIsEditable; // FIXME: Implement me! } QHash MauiModel::roleNames() const { QHash names; - for(auto key : FMH::MODEL_NAME.keys()) - names[key] = QString(FMH::MODEL_NAME[key]).toUtf8(); + for(auto key : KEYS::_N.keys()) + names[key] = QString(KEYS::_N[key]).toUtf8(); return names; } MauiList *MauiModel::getList() const { return this->list; } void MauiModel::setList(MauiList *value) { beginResetModel(); if(list) list->disconnect(this); list = value; if(list) { connect(this->list, &MauiList::preItemAppendedAt, this, [=](int index) { beginInsertRows(QModelIndex(), index, index); }); connect(this->list, &MauiList::preItemAppended, this, [=]() { const int index = list->items().size(); beginInsertRows(QModelIndex(), index, index); }); connect(this->list, &MauiList::postItemAppended, this, [=]() { endInsertRows(); }); connect(this->list, &MauiList::preItemRemoved, this, [=](int index) { beginRemoveRows(QModelIndex(), index, index); }); connect(this->list, &MauiList::postItemRemoved, this, [=]() { endRemoveRows(); }); connect(this->list, &MauiList::updateModel, this, [=](int index, QVector roles) { emit this->dataChanged(this->index(index), this->index(index), roles); }); connect(this->list, &MauiList::preListChanged, this, [=]() { beginResetModel(); }); connect(this->list, &MauiList::postListChanged, this, [=]() { endResetModel(); }); } endResetModel(); } diff --git a/src/utils/store/store.cpp b/src/utils/store/store.cpp index 3c67642..f4717d1 100644 --- a/src/utils/store/store.cpp +++ b/src/utils/store/store.cpp @@ -1,387 +1,387 @@ /* * * Copyright (C) 2018 camilo * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "store.h" #include "fmh.h" #include #include Store::Store(QObject *parent) : QObject(parent) { } Store::~Store() { } void Store::start() { qDebug()<< "Setting up Store backend"; if(!FMH::fileExists(FMH::DataPath+"/Store/providers.xml")) { QDir store_dir(FMH::DataPath+"/Store/"); if (!store_dir.exists()) store_dir.mkpath("."); QFile providersFile(":/store/providers.xml"); providersFile.copy(FMH::DataPath+"/Store/providers.xml"); } connect(&m_manager, SIGNAL(defaultProvidersLoaded()), SLOT(providersChanged())); // qDebug()<< "provider local file exists?"<< FMH::fileExists(FMH::DataPath+"/Store/providers.xml"); m_manager.addProviderFile(QUrl::fromLocalFile(FMH::DataPath+"/Store/providers.xml")); m_manager.addProviderFile(QUrl("https://autoconfig.kde.org/ocs/providers.xml")); m_manager.addProviderFile(QUrl("https://share.krita.org/ocs/providers.xml")); // m_manager.loadDefaultProviders(); } void Store::setProvider(const STORE::PROVIDER &provider) { this->provider = provider; } void Store::setCategory(const STORE::CATEGORY_KEY& categoryKey) { qDebug()<< "SETTING CATEGORY OFR STORE"; this->m_category = categoryKey; this->listCategories(); } void Store::searchFor(const STORE::CATEGORY_KEY& categoryKey, const QString &query, const int &limit, const int &page, const Attica::Provider::SortMode &sortBy) { this->query = query; this->limit = limit; this->page = page; this->sortBy = sortBy; // qDebug() << "CATEGORY LIST" << STORE::CATEGORIES[this->m_category]; // if(this->m_category == categoryKey) // { // qDebug()<< "SEARCHIGN WITHIN SAME CATEGORY" << this->m_category; // this->perfomSearch(); // return; // } // connect(this, &Store::categoryIDsReady, this, &Store::perfomSearch); this->setCategory(categoryKey); } void Store::perfomSearch() { Attica::Category::List categories; qDebug()<< "GOT THE CATEGORY IDS" << this->categoryID; for(auto key : this->categoryID.keys()) { Attica::Category category; category.setId(this->categoryID[key]); category.setName(key); category.setDisplayName(key); categories << category; qDebug()<< category.name() << this->categoryID[key]; } Attica::ListJob *job = this->m_provider.searchContents(categories, this->query, this->sortBy, this->page, this->limit); connect(job, SIGNAL(finished(Attica::BaseJob*)), SLOT(contentListResult(Attica::BaseJob*))); job->start(); } void Store::contentListResult(Attica::BaseJob* j) { qDebug() << "Content list job returned"; FMH::MODEL_LIST list; if (j->metadata().error() == Attica::Metadata::NoError) { Attica::ListJob *listJob = static_cast *>(j); foreach (const Attica::Content &p, listJob->itemList()) { const auto att = p.attributes(); list << FMH::MODEL { - {FMH::MODEL_KEY::ID, p.id()}, - {FMH::MODEL_KEY::URL, att[STORE::ATTRIBUTE[STORE::ATTRIBUTE_KEY::DOWNLOAD_LINK]]}, - {FMH::MODEL_KEY::THUMBNAIL, att[STORE::ATTRIBUTE[STORE::ATTRIBUTE_KEY::PREVIEW_SMALL_1]]}, - {FMH::MODEL_KEY::THUMBNAIL_1, att[STORE::ATTRIBUTE[STORE::ATTRIBUTE_KEY::PREVIEW_1]]}, - {FMH::MODEL_KEY::THUMBNAIL_2, att[STORE::ATTRIBUTE[STORE::ATTRIBUTE_KEY::PREVIEW_2]]}, - {FMH::MODEL_KEY::THUMBNAIL_3, att[STORE::ATTRIBUTE[STORE::ATTRIBUTE_KEY::DOWNLOAD_LINK]]}, - {FMH::MODEL_KEY::LABEL, p.name()}, - {FMH::MODEL_KEY::OWNER, p.author()}, - {FMH::MODEL_KEY::LICENSE, p.license()}, - {FMH::MODEL_KEY::DESCRIPTION, p.description()}, - {FMH::MODEL_KEY::RATE, QString::number(p.rating())}, - {FMH::MODEL_KEY::DATE, p.created().toString()}, - {FMH::MODEL_KEY::MODIFIED, p.updated().toString()}, - {FMH::MODEL_KEY::TAG, p.tags().join(",")}, - {FMH::MODEL_KEY::COUNT, QString::number(p.downloads())}, - {FMH::MODEL_KEY::SOURCE, p.detailpage().toString()} + {KEYS::ID, p.id()}, + {KEYS::URL, att[STORE::ATTRIBUTE[STORE::ATTRIBUTE_KEY::DOWNLOAD_LINK]]}, + {KEYS::THUMBNAIL, att[STORE::ATTRIBUTE[STORE::ATTRIBUTE_KEY::PREVIEW_SMALL_1]]}, + {KEYS::THUMBNAIL_1, att[STORE::ATTRIBUTE[STORE::ATTRIBUTE_KEY::PREVIEW_1]]}, + {KEYS::THUMBNAIL_2, att[STORE::ATTRIBUTE[STORE::ATTRIBUTE_KEY::PREVIEW_2]]}, + {KEYS::THUMBNAIL_3, att[STORE::ATTRIBUTE[STORE::ATTRIBUTE_KEY::DOWNLOAD_LINK]]}, + {KEYS::LABEL, p.name()}, + {KEYS::OWNER, p.author()}, + {KEYS::LICENSE, p.license()}, + {KEYS::DESCRIPTION, p.description()}, + {KEYS::RATE, QString::number(p.rating())}, + {KEYS::DATE, p.created().toString()}, + {KEYS::MODIFIED, p.updated().toString()}, + {KEYS::TAG, p.tags().join(",")}, + {KEYS::COUNT, QString::number(p.downloads())}, + {KEYS::SOURCE, p.detailpage().toString()} }; } emit this->contentReady(list); if (listJob->itemList().isEmpty()) { emit this->warning(QLatin1String("No Content found.")); } } else if (j->metadata().error() == Attica::Metadata::OcsError) { emit this->warning(QString(QLatin1String("OCS Error: %1")).arg(j->metadata().message())); } else if (j->metadata().error() == Attica::Metadata::NetworkError) { emit this->warning(QString(QLatin1String("Network Error: %1")).arg(j->metadata().message())); } else { emit this->warning(QString(QLatin1String("Unknown Error: %1")).arg(j->metadata().message())); } } void Store::providersChanged() { if (!m_manager.providers().isEmpty()) { qDebug()<< "Providers names:"; for(auto prov : m_manager.providers()) qDebug() << prov.name() << prov.baseUrl(); this->m_provider = m_manager.providerByUrl(QUrl(this->provider)); // this->m_provider = m_manager.providerByUrl(QUrl(STORE::OPENDESKTOP_API)); if (!this->m_provider.isValid()) { qDebug() << "Could not find "<< this->provider << "provider."; return; }else { qDebug()<< "Found the Store provider for" << m_provider.name(); qDebug()<< "Has content service" << m_provider.hasContentService(); emit this->storeReady(); } }else qDebug() << "Could not find any provider."; } void Store::categoryListResult(Attica::BaseJob* j) { qDebug() << "Category list job returned"; if (j->metadata().error() == Attica::Metadata::NoError) { Attica::ListJob *listJob = static_cast *>(j); qDebug() << "Yay, no errors ..."; QStringList projectIds; foreach (const Attica::Category &p, listJob->itemList()) { if(STORE::CATEGORIES[this->m_category].contains(p.name())) this->categoryID[p.name()] = p.id(); projectIds << p.id(); qDebug()<< p.name() << p.id(); } if (listJob->itemList().isEmpty()) { emit this->warning(QLatin1String("No Categories found.")); } } else if (j->metadata().error() == Attica::Metadata::OcsError) { emit this->warning(QString(QLatin1String("OCS Error: %1")).arg(j->metadata().message())); } else if (j->metadata().error() == Attica::Metadata::NetworkError) { emit this->warning(QString(QLatin1String("Network Error: %1")).arg(j->metadata().message())); } else { emit this->warning(QString(QLatin1String("Unknown Error: %1")).arg(j->metadata().message())); } qDebug()<< "CATEGORY IDS " << this->categoryID; emit this->categoryIDsReady(); } void Store::getPersonInfo(const QString& nick) { Attica::ItemJob* job = m_provider.requestPerson(nick); // connect that job connect(job, &Attica::BaseJob::finished, [](Attica::BaseJob* doneJob) { Attica::ItemJob *personJob = static_cast< Attica::ItemJob * >( doneJob ); // check if the request actually worked if( personJob->metadata().error() == Attica::Metadata::NoError ) { // use the data to fill the labels Attica::Person p(personJob->result()); qDebug() << (p.firstName() + ' ' + p.lastName()); qDebug() << p.city(); } else { qDebug() << ("Could not fetch information."); } }); // start the job job->start(); } void Store::listProjects() { if(!this->m_provider.isValid()) return; Attica::ListJob *job = m_provider.requestProjects(); connect(job, SIGNAL(finished(Attica::BaseJob*)), SLOT(projectListResult(Attica::BaseJob*))); job->start(); } void Store::listCategories() { if(!this->m_provider.isValid()) return; Attica::ListJob *job = m_provider.requestCategories(); connect(job, SIGNAL(finished(Attica::BaseJob*)), SLOT(categoryListResult(Attica::BaseJob*))); job->start(); } void Store::download(const QString& id) { if(!this->m_provider.isValid()) return; Attica::ItemJob *job = m_provider.downloadLink(id); connect(job, SIGNAL(finished(Attica::BaseJob*)), SLOT(contentDownloadReady(Attica::BaseJob*))); job->start(); } void Store::download(const FMH::MODEL &item) { - this->downloadLink(item[FMH::MODEL_KEY::URL], item[FMH::MODEL_KEY::LABEL]); + this->downloadLink(item[KEYS::URL], item[KEYS::LABEL]); } void Store::contentDownloadReady(Attica::BaseJob* j) { if (j->metadata().error() == Attica::Metadata::NoError) { Attica::ItemJob *res = static_cast *>(j); auto job = res->result(); auto url = job.url().toString(); auto fileName = job.packageName(); this->downloadLink(url, fileName); } else if (j->metadata().error() == Attica::Metadata::OcsError) { emit this->warning(QString(QLatin1String("OCS Error: %1")).arg(j->metadata().message())); } else if (j->metadata().error() == Attica::Metadata::NetworkError) { emit this->warning(QString(QLatin1String("Network Error: %1")).arg(j->metadata().message())); } else { emit this->warning(QString(QLatin1String("Unknown Error: %1")).arg(j->metadata().message())); } } void Store::downloadLink(const QString& url, const QString &fileName) { const auto downloader = new FMH::Downloader; // QString _fileName = fileName; qDebug()<< "DOWNLOADING CONTENT FROM "<< url << fileName; QStringList filePathList = url.split('/'); auto _fileName = filePathList.at(filePathList.count() - 1); connect(downloader, &FMH::Downloader::warning, [this](const QString &warning) { emit this->warning(warning); }); connect(downloader, &FMH::Downloader::fileSaved, [this](const QString &fileName) { emit this->downloadReady(FMH::getFileInfoModel(fileName)); }); connect(downloader, &FMH::Downloader::done, [=]() { downloader->deleteLater(); }); // connect(downloader, &FMH::Downloader::downloadReady, [this]() // { // // }); // downloader->setFile(url, FMH::DownloadsPath + "/" + _fileName); } void Store::projectListResult(Attica::BaseJob *j) { qDebug() << "Project list job returned"; QString output = QLatin1String("Projects:"); if (j->metadata().error() == Attica::Metadata::NoError) { Attica::ListJob *listJob = static_cast *>(j); qDebug() << "Yay, no errors ..."; QStringList projectIds; foreach (const Attica::Project &p, listJob->itemList()) { qDebug() << "New project:" << p.id() << p.name(); output.append(QString(QLatin1String("
%1 (%2)")).arg(p.name(), p.id())); projectIds << p.id(); // TODO: start project jobs here } if (listJob->itemList().isEmpty()) { output.append(QLatin1String("No Projects found.")); } } else if (j->metadata().error() == Attica::Metadata::OcsError) { output.append(QString(QLatin1String("OCS Error: %1")).arg(j->metadata().message())); } else if (j->metadata().error() == Attica::Metadata::NetworkError) { output.append(QString(QLatin1String("Network Error: %1")).arg(j->metadata().message())); } else { output.append(QString(QLatin1String("Unknown Error: %1")).arg(j->metadata().message())); } qDebug() << output; } QHash Store::getCategoryIDs() { return this->categoryID; } // #include "store.moc" diff --git a/src/utils/store/storelist.cpp b/src/utils/store/storelist.cpp index 3c96439..7ff6dcb 100644 --- a/src/utils/store/storelist.cpp +++ b/src/utils/store/storelist.cpp @@ -1,334 +1,334 @@ /* * * Copyright (C) 2018 camilo * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "storelist.h" #include "fm.h" StoreList::StoreList(QObject *parent) : QObject(parent) { this->store = new Store(this); this->store->setProvider(STORE::KDELOOK_API); this->store->start(); connect(this->store, &Store::contentReady, [this](const FMH::MODEL_LIST &list) { emit this->preListChanged(); this->list = list; this->sortList(); qDebug()<< "STORE LIST READY" << list; emit this->postListChanged(); this->contentReady = true; emit this->contentReadyChanged(); this->contentEmpty = this->list.isEmpty(); emit this->contentEmptyChanged(); }); connect(this->store, &Store::warning, [this](const QString warning) { emit this->warning(warning); }); connect(this->store, &Store::downloadReady, [this] (const FMH::MODEL &item) { emit this->downloadReady(FM::toMap(item)); }); connect(this->store, &Store::storeReady, this, &StoreList::setList); } QVariantMap StoreList::get(const int& index) const { if(index >= this->list.size() || index < 0) return QVariantMap(); QVariantMap res; const auto model = this->list.at(index); for(auto key : model.keys()) - res.insert(FMH::MODEL_NAME[key], model[key]); + res.insert(KEYS::_N[key], model[key]); return res; } void StoreList::download(const int& index) { if(index >= this->list.size() || index < 0) return; - // this->store->download(this->list[index][FMH::MODEL_KEY::ID]); + // this->store->download(this->list[index][KEYS::ID]); this->store->download(this->list[index]); } FMH::MODEL_LIST StoreList::items() const { return this->list; } void StoreList::getPersonInfo(const QString& nick) { this->store->getPersonInfo(nick); } void StoreList::setList() { emit this->preListChanged(); this->list.clear(); emit this->postListChanged(); this->contentEmpty = this->list.isEmpty(); emit this->contentEmptyChanged(); this->contentReady = false; emit this->contentReadyChanged(); this->store->searchFor(static_cast(this->category), this->query, this->limit, this->page, static_cast(this->sortBy)); } StoreList::CATEGORY StoreList::getCategory() const { return this->category; } void StoreList::setCategory(const StoreList::CATEGORY& value) { if(this->category == value) return; this->category = value; emit this->categoryChanged(); this->setList(); } int StoreList::getLimit() const { return this->limit; } void StoreList::setLimit(const int& value) { if(this->limit == value) return; this->limit = value; emit this->limitChanged(); this->setList(); } int StoreList::getPage() const { return this->page; } void StoreList::setPage(const int& value) { if(this->page == value) return; this->page = value; emit this->pageChanged(); this->setList(); } StoreList::ORDER StoreList::getOrder() const { return this->order; } void StoreList::setOrder(const StoreList::ORDER& value) { if(this->order == value) return; this->order = value; emit this->orderChanged(); } QString StoreList::getQuery() const { return this->query; } void StoreList::setQuery(const QString& value) { if(this->query == value) return; this->query = value; emit this->queryChanged(); this->page = 0; emit this->pageChanged(); this->setList(); } QVariantList StoreList::getCategoryList() { QVariantList res; auto data = STORE::CATEGORIES[static_cast(this->category)]; for(auto category : data) - res << QVariantMap {{FMH::MODEL_NAME[FMH::MODEL_KEY::LABEL], category}}; + res << QVariantMap {{KEYS::_N[KEYS::LABEL], category}}; return res; } bool StoreList::getContentReady() const { return this->contentReady; } bool StoreList::getContentEmpty() const { return this->contentEmpty; } StoreList::SORTBY StoreList::getSortBy() const { return this->sortBy; } void StoreList::setSortBy(const StoreList::SORTBY& key) { if(this->sortBy == key) return; this->sortBy = key; emit this->sortByChanged(); this->setList(); } void StoreList::sortList() { qDebug()<< "TRYING TO SORT LIST" << this->list.size(); qSort(this->list.begin(), this->list.begin(), [this](const FMH::MODEL& e1, const FMH::MODEL& e2) -> bool { qDebug()<< "TRYIT LIST"; - auto role = static_cast(this->sortBy);; + auto role = static_cast(this->sortBy);; switch(role) { - case FMH::MODEL_KEY::RATE: - case FMH::MODEL_KEY::COUNT: + case KEYS::RATE: + case KEYS::COUNT: { if(e1[role].toDouble() > e2[role].toDouble()) return true; break; } - case FMH::MODEL_KEY::MODIFIED: - case FMH::MODEL_KEY::DATE: + case KEYS::MODIFIED: + case KEYS::DATE: { auto currentTime = QDateTime::currentDateTime(); auto date1 = QDateTime::fromString(e1[role], Qt::TextDate); auto date2 = QDateTime::fromString(e2[role], Qt::TextDate); if(date1.secsTo(currentTime) < date2.secsTo(currentTime)) return true; break; } - case FMH::MODEL_KEY::LABEL: - case FMH::MODEL_KEY::USER: - case FMH::MODEL_KEY::OWNER: + case KEYS::LABEL: + case KEYS::USER: + case KEYS::OWNER: { const auto str1 = QString(e1[role]).toLower(); const auto str2 = QString(e2[role]).toLower(); if(str1 < str2) return true; break; } default: if(e1[role] < e2[role]) return true; } return false; }); } StoreList::PROVIDER StoreList::getProvider() const { return this->provider; } void StoreList::setProvider(const StoreList::PROVIDER &key) { if(this->provider == key) return; this->provider = key; STORE::PROVIDER value; switch(this->provider) { case StoreList::PROVIDER::KDELOOK: value = STORE::KDELOOK_API; break; case StoreList::PROVIDER::OPENDESKTOP: value = STORE::OPENDESKTOP_API; break; case StoreList::PROVIDER::OPENDESKTOPCC: value = STORE::OPENDESKTOPCC_API; break; case StoreList::PROVIDER::KRITA: value = STORE::KRITA_API; break; } this->store->setProvider(value); emit this->providerChanged(); } bool StoreList::fileExists(const int &index) { if(index >= this->list.size() || index < 0) return false; - const auto url = this->list[index][FMH::MODEL_KEY::URL]; + const auto url = this->list[index][KEYS::URL]; const QStringList filePathList = url.split('/'); const auto fileName = filePathList.at(filePathList.count() - 1); qDebug() << "Check if file exists" << FMH::DownloadsPath+"/"+fileName; return FMH::fileExists(FMH::DownloadsPath+"/"+fileName); } QString StoreList::itemLocalPath(const int &index) { if(!this->fileExists(index)) return QString(); - const auto url = this->list[index][FMH::MODEL_KEY::URL]; + const auto url = this->list[index][KEYS::URL]; const QStringList filePathList = url.split('/'); const auto fileName = filePathList.at(filePathList.count() - 1); return FMH::DownloadsPath+"/"+fileName; } diff --git a/src/utils/store/storemodel.cpp b/src/utils/store/storemodel.cpp index 456397c..764f215 100644 --- a/src/utils/store/storemodel.cpp +++ b/src/utils/store/storemodel.cpp @@ -1,122 +1,122 @@ /* * * Copyright (C) 2018 camilo * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "storemodel.h" #include "storelist.h" #include "fmh.h" StoreModel::StoreModel(QObject *parent) : QAbstractListModel(parent), mList(nullptr) {} int StoreModel::rowCount(const QModelIndex &parent) const { if (parent.isValid() || !mList) return 0; return mList->items().size(); } QVariant StoreModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || !mList) return QVariant(); - return mList->items().at(index.row())[static_cast(role)]; + return mList->items().at(index.row())[static_cast(role)]; } bool StoreModel::setData(const QModelIndex &index, const QVariant &value, int role) { return false; } Qt::ItemFlags StoreModel::flags(const QModelIndex &index) const { if (!index.isValid()) return Qt::NoItemFlags; return Qt::ItemIsEditable; // FIXME: Implement me! } QHash StoreModel::roleNames() const { QHash names; - for(auto key : FMH::MODEL_NAME.keys()) - names[key] = QString(FMH::MODEL_NAME[key]).toUtf8(); + for(auto key : KEYS::_N.keys()) + names[key] = QString(KEYS::_N[key]).toUtf8(); return names; } StoreList *StoreModel::getList() const { return this->mList; } void StoreModel::setList(StoreList *value) { beginResetModel(); if(mList) mList->disconnect(this); mList = value; if(mList) { connect(this->mList, &StoreList::preItemAppended, this, [=]() { const int index = mList->items().size(); beginInsertRows(QModelIndex(), index, index); }); connect(this->mList, &StoreList::postItemAppended, this, [=]() { endInsertRows(); }); connect(this->mList, &StoreList::preItemRemoved, this, [=](int index) { beginRemoveRows(QModelIndex(), index, index); }); connect(this->mList, &StoreList::postItemRemoved, this, [=]() { endRemoveRows(); }); connect(this->mList, &StoreList::updateModel, this, [=](int index, QVector roles) { emit this->dataChanged(this->index(index), this->index(index), roles); }); connect(this->mList, &StoreList::preListChanged, this, [=]() { beginResetModel(); }); connect(this->mList, &StoreList::postListChanged, this, [=]() { endResetModel(); }); } endResetModel(); } diff --git a/src/utils/syncing/syncing.cpp b/src/utils/syncing/syncing.cpp index 923aeba..99ce549 100644 --- a/src/utils/syncing/syncing.cpp +++ b/src/utils/syncing/syncing.cpp @@ -1,405 +1,405 @@ #include "syncing.h" #include "fm.h" #include #include #include #include "WebDAVClient.hpp" #include "WebDAVItem.hpp" #include "WebDAVReply.hpp" Syncing::Syncing(QObject *parent) : QObject(parent) { this->setCredentials(this->host, this->user, this->password); } void Syncing::listContent(const QString &path, const QStringList &filters, const int &depth) { this->currentPath = path; auto url = QUrl(path).path().replace(user, ""); this->listDirOutputHandler(this->client->listDir(url, static_cast(depth)), filters); } void Syncing::setCredentials(const QString &server, const QString &user, const QString &password) { this->host = server; this->user = user; this->password = password; this->client = new WebDAVClient(this->host, this->user, this->password); } void Syncing::listDirOutputHandler(WebDAVReply *reply, const QStringList &filters) { connect(reply, &WebDAVReply::listDirResponse, [=](QNetworkReply *listDirReply, QList items) { // qDebug() << "URL :" << listDirReply->url(); // qDebug() << "Received List of" << items.length() << "items"; // qDebug() << endl << "---------------------------------------"; FMH::MODEL_LIST list; for (WebDAVItem item : items) { const auto url = QUrl(item.getHref()).toString(); auto path = QString(FMH::PATHTYPE_URI[FMH::PATHTYPE_KEY::CLOUD_PATH]+this->user+"/")+QString(url).replace("/remote.php/webdav/", ""); auto displayName = item.getContentType().isEmpty() ? QString(url).replace("/remote.php/webdav/", "").replace("/", "") : QString(path).right(path.length()-path.lastIndexOf("/")-1); // qDebug()<< "PATHS:" << path << this->currentPath; if(QString(url).replace("/remote.php/webdav/", "").isEmpty() || path == this->currentPath) continue; // qDebug()<< "FILTERING "<< filters << QString(displayName).right(displayName.length() - displayName.lastIndexOf(".")); if(!filters.isEmpty() && !filters.contains("*"+QString(displayName).right(displayName.length() - displayName.lastIndexOf(".")))) continue; - list << FMH::MODEL { {FMH::MODEL_KEY::LABEL, displayName}, - {FMH::MODEL_KEY::NAME, item.getDisplayName()}, - {FMH::MODEL_KEY::DATE, item.getCreationDate().toString(Qt::TextDate)}, - {FMH::MODEL_KEY::MODIFIED, item.getLastModified()}, - {FMH::MODEL_KEY::MIME, item.getContentType().isEmpty() ? "inode/directory" : item.getContentType()}, - {FMH::MODEL_KEY::ICON, FMH::getIconName(url)}, - {FMH::MODEL_KEY::SIZE, QString::number(item.getContentLength())}, - {FMH::MODEL_KEY::PATH, path}, - {FMH::MODEL_KEY::URL, url}, - {FMH::MODEL_KEY::THUMBNAIL, item.getContentType().isEmpty() ? url : this->getCacheFile(url)}}; + list << FMH::MODEL { {KEYS::LABEL, displayName}, + {KEYS::NAME, item.getDisplayName()}, + {KEYS::DATE, item.getCreationDate().toString(Qt::TextDate)}, + {KEYS::MODIFIED, item.getLastModified()}, + {KEYS::MIME, item.getContentType().isEmpty() ? "inode/directory" : item.getContentType()}, + {KEYS::ICON, FMH::getIconName(url)}, + {KEYS::SIZE, QString::number(item.getContentLength())}, + {KEYS::PATH, path}, + {KEYS::URL, url}, + {KEYS::THUMBNAIL, item.getContentType().isEmpty() ? url : this->getCacheFile(url)}}; } emit this->listReady(list, this->currentPath); }); connect(reply, &WebDAVReply::error, [=](QNetworkReply::NetworkError err) { // qDebug() << "ERROR" << err; this->emitError(err); }); } QString Syncing::getCacheFile(const QString& path) { const auto directory = FM::resolveUserCloudCachePath(this->host, this->user); const auto file = directory + QString(path).replace("remote.php/webdav/", ""); qDebug()<< "resolving file"<< file; if(FMH::fileExists(file)) return file; else return path; } void Syncing::download(const QString& path) { QString url = QString(path).replace("remote.php/webdav/", ""); WebDAVReply *reply = this->client->downloadFrom(url); qDebug()<< "CURRENT CREDENTIALS"<< this->host << this->user; connect(reply, &WebDAVReply::downloadResponse, [=](QNetworkReply *reply) { if (!reply->error()) { qDebug() << "\nDownload Success" << "\nURL :" << reply->url() << "\nSize :" << reply->size(); auto file = reply->readAll(); const auto directory = FMH::CloudCachePath+"opendesktop/"+this->user; QDir dir(directory); if (!dir.exists()) dir.mkpath("."); this->saveTo(file, directory+url); } else { qDebug() << "ERROR(DOWNLOAD)" << reply->error() << reply->url() <error(reply->errorString()); } }); connect(reply, &WebDAVReply::downloadProgressResponse, [=](qint64 bytesReceived, qint64 bytesTotal) { int percent = ((float)bytesReceived / bytesTotal) * 100; qDebug() << "\nReceived : " << bytesReceived << "\nTotal : " << bytesTotal << "\nPercent : " << percent; emit this->progress(percent); }); connect(reply, &WebDAVReply::error, [=](QNetworkReply::NetworkError err) { qDebug() << "ERROR" << err; }); } void Syncing::upload(const QString &path, const QString &filePath) { if(!FMH::fileExists(filePath)) return; qDebug()<< "Copy to cloud. File exists" << path << filePath; this->mFile.setFileName(filePath); if(this->mFile.open(QIODevice::ReadOnly)) { qDebug()<< "Copy to cloud. File could be opened"; WebDAVReply *reply = this->client->uploadTo(path, QFileInfo(filePath).fileName(), &this->mFile); connect(reply, &WebDAVReply::uploadFinished, [=](QNetworkReply *reply) { if (!reply->error()) { qDebug() << "\nUpload Success" << "\nURL :" << reply->url() << "\nSize :" << reply->size(); auto cachePath = this->saveToCache(filePath, path); auto item = FMH::getFileInfoModel(cachePath); -// item[FMH::MODEL_KEY::PATH] = this->currentPath+"/"+QFileInfo(filePath).fileName()+"/"; +// item[KEYS::PATH] = this->currentPath+"/"+QFileInfo(filePath).fileName()+"/"; emit this->uploadReady(item, this->currentPath); } else { qDebug() << "ERROR(UPLOAD)" << reply->error(); emit this->error(reply->errorString()); } if(!this->uploadQueue.isEmpty()) { qDebug()<<"UPLOAD QUEUE" << this->uploadQueue; this->upload(path, this->uploadQueue.takeLast()); } }); connect(reply, &WebDAVReply::error, [=](QNetworkReply::NetworkError err) { qDebug() << "ERROR" << err; this->emitError(err); });} } void Syncing::createDir(const QString &path, const QString &name) { WebDAVReply *reply = this->client->createDir(path, name); connect(reply, &WebDAVReply::createDirFinished, [=](QNetworkReply *reply) { if (!reply->error()) { qDebug() << "\nDir Created" << "\nURL :" << reply->url(); FMH::MODEL dir = { - {FMH::MODEL_KEY::LABEL, name}, - {FMH::MODEL_KEY::DATE, QDateTime::currentDateTime().toString(Qt::TextDate)}, - {FMH::MODEL_KEY::MIME, "inode/directory"}, - {FMH::MODEL_KEY::ICON, "folder"}, - {FMH::MODEL_KEY::PATH, this->currentPath+"/"+name+"/"} + {KEYS::LABEL, name}, + {KEYS::DATE, QDateTime::currentDateTime().toString(Qt::TextDate)}, + {KEYS::MIME, "inode/directory"}, + {KEYS::ICON, "folder"}, + {KEYS::PATH, this->currentPath+"/"+name+"/"} }; emit this->dirCreated(dir, this->currentPath); } else { qDebug() << "ERROR(CREATE DIR)" << reply->error(); emit this->error(reply->errorString()); } }); connect(reply, &WebDAVReply::error, [=](QNetworkReply::NetworkError err) { qDebug() << "ERROR" << err; this->emitError(err); }); } void Syncing::emitError(const QNetworkReply::NetworkError &err) { switch(err) { case QNetworkReply::AuthenticationRequiredError: emit this->error("The remote server requires authentication to serve the content but the credentials provided were not accepted (if any)"); break; case QNetworkReply::ConnectionRefusedError: emit this->error("the remote server refused the connection (the server is not accepting requests)"); break; case QNetworkReply::RemoteHostClosedError: emit this->error("the remote server closed the connection prematurely, before the entire reply was received and processed"); break; case QNetworkReply::HostNotFoundError: emit this->error("the remote host name was not found (invalid hostname)"); break; case QNetworkReply::TimeoutError: emit this->error("the connection to the remote server timed out"); break; case QNetworkReply::OperationCanceledError: emit this->error("the operation was canceled via calls to abort() or close() before it was finished."); break; case QNetworkReply::SslHandshakeFailedError: emit this->error("the SSL/TLS handshake failed and the encrypted channel could not be established. The sslErrors() signal should have been emitted."); break; case QNetworkReply::TemporaryNetworkFailureError: emit this->error("the connection was broken due to disconnection from the network, however the system has initiated roaming to another access point. The request should be resubmitted and will be processed as soon as the connection is re-established."); break; case QNetworkReply::NetworkSessionFailedError: emit this->error("the connection was broken due to disconnection from the network or failure to start the network."); break; case QNetworkReply::BackgroundRequestNotAllowedError: emit this->error("the background request is not currently allowed due to platform policy."); break; case QNetworkReply::TooManyRedirectsError: emit this->error("while following redirects, the maximum limit was reached. The limit is by default set to 50 or as set by QNetworkRequest::setMaxRedirectsAllowed(). (This value was introduced in 5.6.)"); break; case QNetworkReply::InsecureRedirectError: emit this->error("while following redirects, the network access API detected a redirect from a encrypted protocol (https) to an unencrypted one (http)."); break; case QNetworkReply::ProxyConnectionRefusedError: emit this->error("the connection to the proxy server was refused (the proxy server is not accepting requests)"); break; case QNetworkReply::ProxyConnectionClosedError: emit this->error("the proxy server closed the connection prematurely, before the entire reply was received and processed"); break; case QNetworkReply::ProxyNotFoundError: emit this->error("the proxy host name was not found (invalid proxy hostname)"); break; case QNetworkReply::ProxyTimeoutError: emit this->error("the connection to the proxy timed out or the proxy did not reply in time to the request sent"); break; case QNetworkReply::ProxyAuthenticationRequiredError: emit this->error("the proxy requires authentication in order to honour the request but did not accept any credentials offered (if any)"); break; case QNetworkReply::ContentAccessDenied: emit this->error("the access to the remote content was denied (similar to HTTP error 403)"); break; case QNetworkReply::ContentOperationNotPermittedError: emit this->error("the operation requested on the remote content is not permitted"); break; case QNetworkReply::ContentNotFoundError: emit this->error("the remote content was not found at the server (similar to HTTP error 404)"); break; case QNetworkReply::ContentReSendError: emit this->error("the request needed to be sent again, but this failed for example because the upload data could not be read a second time."); break; case QNetworkReply::ServiceUnavailableError: emit this->error("the server is unable to handle the request at this time."); break; default: emit this->error("There was an unknown error with the remote server or your internet connection."); } } void Syncing::saveTo(const QByteArray &array, const QString& path) { QFile file(path); if(!file.exists()) { QDir dir; uint cut = path.length()- path.lastIndexOf("/") -1; auto newPath = QString(path).right(cut); dir.mkdir(QString(path).replace(newPath, "")); qDebug()<< newPath << cut; }else file.remove(); file.open(QIODevice::WriteOnly); file.write(array); file.close(); emit this->itemReady(FMH::getFileInfoModel(path), this->currentPath, this->signalType); // emit this->itemReady(FMH::getFileInfoModel(path)); } QString Syncing::saveToCache(const QString& file, const QString &where) { auto directory = FMH::CloudCachePath+"opendesktop/"+this->user+"/"+where; QDir dir(directory); if (!dir.exists()) dir.mkpath("."); const auto newPath = directory+"/"+QFileInfo(file).fileName(); if(QFile::copy(file, newPath)) return newPath; return QString(); } void Syncing::resolveFile(const FMH::MODEL& item, const Syncing::SIGNAL_TYPE &signalType) { this->signalType = signalType; - const auto url = item[FMH::MODEL_KEY::URL]; + const auto url = item[KEYS::URL]; const auto file = this->getCacheFile(url); if(FMH::fileExists(file)) { const auto cacheFile = FMH::getFileInfoModel(file); - const auto dateCacheFile = QDateTime::fromString(cacheFile[FMH::MODEL_KEY::DATE], Qt::TextDate); - const auto dateCloudFile = QDateTime::fromString(QString(item[FMH::MODEL_KEY::MODIFIED]).replace("GMT", "").simplified(), "ddd, dd MMM yyyy hh:mm:ss"); + const auto dateCacheFile = QDateTime::fromString(cacheFile[KEYS::DATE], Qt::TextDate); + const auto dateCloudFile = QDateTime::fromString(QString(item[KEYS::MODIFIED]).replace("GMT", "").simplified(), "ddd, dd MMM yyyy hh:mm:ss"); - qDebug()<<"FILE EXISTS ON CACHE" << dateCacheFile << dateCloudFile<< QString(item[FMH::MODEL_KEY::MODIFIED]).replace("GMT", "").simplified()<< file; + qDebug()<<"FILE EXISTS ON CACHE" << dateCacheFile << dateCloudFile<< QString(item[KEYS::MODIFIED]).replace("GMT", "").simplified()<< file; if(dateCloudFile > dateCacheFile) this->download(url); else emit this->itemReady(cacheFile, this->currentPath, this->signalType); } else this->download(url); } void Syncing::setCopyTo(const QString &path) { if(this->copyTo == path) return; this->copyTo = path; } QString Syncing::getCopyTo() const { return this->copyTo; } QString Syncing::getUser() const { return this->user; } void Syncing::setUploadQueue(const QStringList& list) { this->uploadQueue = list; } QString Syncing::localToAbstractCloudPath(const QString& url) { return QString(url).replace(FMH::CloudCachePath+"opendesktop", FMH::PATHTYPE_URI[FMH::PATHTYPE_KEY::CLOUD_PATH]); } diff --git a/src/utils/syncing/syncinglist.cpp b/src/utils/syncing/syncinglist.cpp index 327879c..347fbda 100644 --- a/src/utils/syncing/syncinglist.cpp +++ b/src/utils/syncing/syncinglist.cpp @@ -1,75 +1,75 @@ #include "syncinglist.h" #include "fm.h" SyncingList::SyncingList(QObject *parent) : QObject(parent) { this->fm = new FM(this); this->setList(); } void SyncingList::setList() { emit this->preListChanged(); this->list = this->fm->getCloudAccounts(); qDebug()<< "SYNCIGN LIST"<< list; emit this->postListChanged(); } QVariantMap SyncingList::get(const int &index) const { if(index >= this->list.size() || index < 0) return QVariantMap(); const auto folder = this->list.at(index); QVariantMap res; for(auto key : folder.keys()) - res.insert(FMH::MODEL_NAME[key], folder[key]); + res.insert(KEYS::_N[key], folder[key]); return res; } void SyncingList::refresh() { this->setList(); } void SyncingList::insert(const QVariantMap& data) { FMH::MODEL model; for(auto key : data.keys()) - model.insert(FMH::MODEL_NAME_KEY[key], data[key].toString()); + model.insert(KEYS::_N_KEY[key], data[key].toString()); - if(this->fm->addCloudAccount(model[FMH::MODEL_KEY::SERVER], model[FMH::MODEL_KEY::USER], model[FMH::MODEL_KEY::PASSWORD])) + if(this->fm->addCloudAccount(model[KEYS::SERVER], model[KEYS::USER], model[KEYS::PASSWORD])) { this->setList(); } } void SyncingList::removeAccount(const QString &server, const QString &user) { if(this->fm->removeCloudAccount(server, user)) { this->refresh(); } } void SyncingList::removeAccountAndFiles(const QString &server, const QString &user) { if(this->fm->removeCloudAccount(server, user)) { this->refresh(); } this->fm->removeDir(FM::resolveUserCloudCachePath(server, user)); } FMH::MODEL_LIST SyncingList::items() const { return this->list; } diff --git a/src/utils/syncing/syncingmodel.cpp b/src/utils/syncing/syncingmodel.cpp index 1f25bfd..bfd4277 100644 --- a/src/utils/syncing/syncingmodel.cpp +++ b/src/utils/syncing/syncingmodel.cpp @@ -1,105 +1,105 @@ #include "syncingmodel.h" #include "syncinglist.h" #include "fmh.h" SyncingModel::SyncingModel(QObject *parent) : QAbstractListModel(parent), mList(nullptr) {} int SyncingModel::rowCount(const QModelIndex &parent) const { if (parent.isValid() || !mList) return 0; return mList->items().size(); } QVariant SyncingModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || !mList) return QVariant(); - return mList->items().at(index.row())[static_cast(role)]; + return mList->items().at(index.row())[static_cast(role)]; } bool SyncingModel::setData(const QModelIndex &index, const QVariant &value, int role) { return false; } Qt::ItemFlags SyncingModel::flags(const QModelIndex &index) const { if (!index.isValid()) return Qt::NoItemFlags; return Qt::ItemIsEditable; // FIXME: Implement me! } QHash SyncingModel::roleNames() const { QHash names; - for(auto key : FMH::MODEL_NAME.keys()) - names[key] = QString(FMH::MODEL_NAME[key]).toUtf8(); + for(auto key : KEYS::_N.keys()) + names[key] = QString(KEYS::_N[key]).toUtf8(); return names; } SyncingList *SyncingModel::getList() const { return this->mList; } void SyncingModel::setList(SyncingList *value) { beginResetModel(); if(mList) mList->disconnect(this); mList = value; if(mList) { connect(this->mList, &SyncingList::preItemAppended, this, [=]() { const int index = mList->items().size(); beginInsertRows(QModelIndex(), index, index); }); connect(this->mList, &SyncingList::postItemAppended, this, [=]() { endInsertRows(); }); connect(this->mList, &SyncingList::preItemRemoved, this, [=](int index) { beginRemoveRows(QModelIndex(), index, index); }); connect(this->mList, &SyncingList::postItemRemoved, this, [=]() { endRemoveRows(); }); connect(this->mList, &SyncingList::updateModel, this, [=](int index, QVector roles) { emit this->dataChanged(this->index(index), this->index(index), roles); }); connect(this->mList, &SyncingList::preListChanged, this, [=]() { beginResetModel(); }); connect(this->mList, &SyncingList::postListChanged, this, [=]() { endResetModel(); }); } endResetModel(); }