Correction after hatstand's review
This commit is contained in:
parent
1fc95cb7ed
commit
e484306631
|
@ -1,48 +1,23 @@
|
|||
CREATE TABLE seafile_songs(
|
||||
title TEXT,
|
||||
album TEXT,
|
||||
artist TEXT,
|
||||
albumartist TEXT,
|
||||
composer TEXT,
|
||||
track INTEGER,
|
||||
disc INTEGER,
|
||||
bpm REAL,
|
||||
year INTEGER,
|
||||
genre TEXT,
|
||||
comment TEXT,
|
||||
compilation INTEGER,
|
||||
|
||||
length INTEGER,
|
||||
bitrate INTEGER,
|
||||
samplerate INTEGER,
|
||||
|
||||
directory INTEGER NOT NULL,
|
||||
filename TEXT NOT NULL,
|
||||
mtime INTEGER NOT NULL,
|
||||
ctime INTEGER NOT NULL,
|
||||
filesize INTEGER NOT NULL,
|
||||
sampler INTEGER NOT NULL DEFAULT 0,
|
||||
art_automatic TEXT,
|
||||
art_manual TEXT,
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER,
|
||||
rating INTEGER,
|
||||
forced_compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||
forced_compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||
effective_compilation NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
score INTEGER NOT NULL DEFAULT 0,
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
cue_path TEXT,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
effective_albumartist TEXT,
|
||||
etag TEXT
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE seafile_songs_fts USING fts3 (
|
||||
CREATE VIRTUAL TABLE playlist_items_fts USING fts3(
|
||||
ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsgenre, ftscomment,
|
||||
tokenize=unicode
|
||||
);
|
||||
|
||||
DELETE FROM %allsongstables_fts;
|
||||
|
||||
DROP TABLE %allsongstables_fts;
|
||||
|
||||
ALTER TABLE %allsongstables ADD COLUMN performer TEXT;
|
||||
|
||||
ALTER TABLE %allsongstables ADD COLUMN grouping TEXT;
|
||||
|
||||
CREATE VIRTUAL TABLE %allsongstables_fts USING fts3(
|
||||
ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment,
|
||||
tokenize=unicode
|
||||
);
|
||||
|
||||
INSERT INTO %allsongstables_fts (ROWID, ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment)
|
||||
SELECT ROWID, title, album, artist, albumartist, composer, performer, grouping, genre, comment
|
||||
FROM %allsongstables;
|
||||
|
||||
UPDATE schema_version SET version=45;
|
||||
|
|
|
@ -1,24 +1,3 @@
|
|||
CREATE VIRTUAL TABLE playlist_items_fts USING fts3(
|
||||
ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsgenre, ftscomment,
|
||||
tokenize=unicode
|
||||
);
|
||||
|
||||
DELETE FROM %allsongstables_fts;
|
||||
|
||||
DROP TABLE %allsongstables_fts;
|
||||
|
||||
ALTER TABLE %allsongstables ADD COLUMN performer TEXT;
|
||||
|
||||
ALTER TABLE %allsongstables ADD COLUMN grouping TEXT;
|
||||
|
||||
CREATE VIRTUAL TABLE %allsongstables_fts USING fts3(
|
||||
ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment,
|
||||
tokenize=unicode
|
||||
);
|
||||
|
||||
INSERT INTO %allsongstables_fts (ROWID, ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment)
|
||||
SELECT ROWID, title, album, artist, albumartist, composer, performer, grouping, genre, comment
|
||||
FROM %allsongstables;
|
||||
ALTER TABLE playlists ADD COLUMN is_favorite INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
UPDATE schema_version SET version=46;
|
||||
|
||||
|
|
|
@ -1,3 +1,50 @@
|
|||
ALTER TABLE playlists ADD COLUMN is_favorite INTEGER NOT NULL DEFAULT 0;
|
||||
CREATE TABLE seafile_songs(
|
||||
title TEXT,
|
||||
album TEXT,
|
||||
artist TEXT,
|
||||
albumartist TEXT,
|
||||
composer TEXT,
|
||||
track INTEGER,
|
||||
disc INTEGER,
|
||||
bpm REAL,
|
||||
year INTEGER,
|
||||
genre TEXT,
|
||||
comment TEXT,
|
||||
compilation INTEGER,
|
||||
|
||||
length INTEGER,
|
||||
bitrate INTEGER,
|
||||
samplerate INTEGER,
|
||||
|
||||
directory INTEGER NOT NULL,
|
||||
filename TEXT NOT NULL,
|
||||
mtime INTEGER NOT NULL,
|
||||
ctime INTEGER NOT NULL,
|
||||
filesize INTEGER NOT NULL,
|
||||
sampler INTEGER NOT NULL DEFAULT 0,
|
||||
art_automatic TEXT,
|
||||
art_manual TEXT,
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER,
|
||||
rating INTEGER,
|
||||
forced_compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||
forced_compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||
effective_compilation NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
score INTEGER NOT NULL DEFAULT 0,
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
cue_path TEXT,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
effective_albumartist TEXT,
|
||||
etag TEXT,
|
||||
performer TEXT,
|
||||
grouping TEXT
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE seafile_songs_fts USING fts3 (
|
||||
ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment,
|
||||
tokenize=unicode
|
||||
);
|
||||
|
||||
UPDATE schema_version SET version=47;
|
||||
|
|
|
@ -36,11 +36,11 @@
|
|||
#cmakedefine HAVE_LIBPULSE
|
||||
#cmakedefine HAVE_MOODBAR
|
||||
#cmakedefine HAVE_QCA
|
||||
#cmakedefine HAVE_SEAFILE
|
||||
#cmakedefine HAVE_SKYDRIVE
|
||||
#cmakedefine HAVE_SPARKLE
|
||||
#cmakedefine HAVE_SPOTIFY_DOWNLOADER
|
||||
#cmakedefine HAVE_VK
|
||||
#cmakedefine HAVE_SEAFILE
|
||||
#cmakedefine HAVE_WIIMOTEDEV
|
||||
#cmakedefine TAGLIB_HAS_OPUS
|
||||
#cmakedefine USE_INSTALL_PREFIX
|
||||
|
|
|
@ -57,7 +57,6 @@
|
|||
#include "seafileservice.h"
|
||||
#endif
|
||||
|
||||
|
||||
using smart_playlists::Generator;
|
||||
using smart_playlists::GeneratorMimeData;
|
||||
using smart_playlists::GeneratorPtr;
|
||||
|
@ -99,15 +98,15 @@ InternetModel::InternetModel(Application* app, QObject* parent)
|
|||
#ifdef HAVE_GOOGLE_DRIVE
|
||||
AddService(new GoogleDriveService(app, this));
|
||||
#endif
|
||||
#ifdef HAVE_SEAFILE
|
||||
AddService(new SeafileService(app, this));
|
||||
#endif
|
||||
#ifdef HAVE_SKYDRIVE
|
||||
AddService(new SkydriveService(app, this));
|
||||
#endif
|
||||
#ifdef HAVE_VK
|
||||
AddService(new VkService(app, this));
|
||||
#endif
|
||||
#ifdef HAVE_SEAFILE
|
||||
AddService(new SeafileService(app, this));
|
||||
#endif
|
||||
|
||||
invisibleRootItem()->sortChildren(0, Qt::AscendingOrder);
|
||||
}
|
||||
|
@ -230,8 +229,9 @@ QStringList InternetModel::mimeTypes() const {
|
|||
|
||||
QMimeData* InternetModel::mimeData(const QModelIndexList& indexes) const {
|
||||
// Special case for when the user double clicked on a special item.
|
||||
if (indexes.count() == 1 && indexes[0].data(Role_PlayBehaviour).toInt() ==
|
||||
PlayBehaviour_DoubleClickAction) {
|
||||
if (indexes.count() == 1 &&
|
||||
indexes[0].data(Role_PlayBehaviour).toInt() ==
|
||||
PlayBehaviour_DoubleClickAction) {
|
||||
InternetModel::ServiceForIndex(indexes[0])
|
||||
->ItemDoubleClicked(itemFromIndex(indexes[0]));
|
||||
return nullptr;
|
||||
|
|
|
@ -10,25 +10,24 @@
|
|||
#include "library/librarybackend.h"
|
||||
#include "internet/oauthenticator.h"
|
||||
|
||||
|
||||
const char* SeafileService::kServiceName = "Seafile";
|
||||
const char* SeafileService::kSettingsGroup = "Seafile";
|
||||
|
||||
namespace {
|
||||
|
||||
static const char* kAuthToken = "/api2/auth-token/";
|
||||
static const char* kAuthTokenUrl = "/api2/auth-token/";
|
||||
|
||||
static const char* kFolderItems = "/api2/repos/%1/dir/";
|
||||
static const char* kListRepos = "/api2/repos/";
|
||||
static const char* kFolderItemsUrl = "/api2/repos/%1/dir/";
|
||||
static const char* kListReposUrl = "/api2/repos/";
|
||||
|
||||
static const char* kFileUrl = "/api2/repos/%1/file/";
|
||||
static const char* kFileContent = "/api2/repos/%1/file/detail/";
|
||||
static const char* kFileContentUrl = "/api2/repos/%1/file/detail/";
|
||||
}
|
||||
|
||||
SeafileService::SeafileService(Application* app, InternetModel* parent)
|
||||
: CloudFileService(app, parent, kServiceName, kSettingsGroup,
|
||||
QIcon(":/providers/seafile.png"), SettingsDialog::Page_Seafile) {
|
||||
|
||||
: CloudFileService(app, parent, kServiceName, kSettingsGroup,
|
||||
QIcon(":/providers/seafile.png"),
|
||||
SettingsDialog::Page_Seafile) {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
access_token_ = s.value("access_token").toString();
|
||||
|
@ -36,19 +35,19 @@ SeafileService::SeafileService(Application* app, InternetModel* parent)
|
|||
|
||||
QByteArray tree_bytes = s.value("tree").toByteArray();
|
||||
|
||||
if(!tree_bytes.isEmpty()) {
|
||||
if (!tree_bytes.isEmpty()) {
|
||||
QDataStream stream(&tree_bytes, QIODevice::ReadOnly);
|
||||
stream >> tree_;
|
||||
}
|
||||
|
||||
app->player()->RegisterUrlHandler(new SeafileUrlHandler(this, this));
|
||||
|
||||
connect(&tree_, SIGNAL(ToAdd(QString, QString, SeafileTree::Entry)), this, SLOT(AddEntry(QString, QString, SeafileTree::Entry)));
|
||||
connect(&tree_, SIGNAL(ToDelete(QString, QString, SeafileTree::Entry)), this, SLOT(DeleteEntry(QString, QString, SeafileTree::Entry)));
|
||||
connect(&tree_, SIGNAL(ToUpdate(QString, QString, SeafileTree::Entry)), this, SLOT(UpdateEntry(QString, QString, SeafileTree::Entry)));
|
||||
|
||||
library_updated_ = QString::null;
|
||||
|
||||
connect(&tree_, SIGNAL(ToAdd(QString, QString, SeafileTree::Entry)), this,
|
||||
SLOT(AddEntry(QString, QString, SeafileTree::Entry)));
|
||||
connect(&tree_, SIGNAL(ToDelete(QString, QString, SeafileTree::Entry)), this,
|
||||
SLOT(DeleteEntry(QString, QString, SeafileTree::Entry)));
|
||||
connect(&tree_, SIGNAL(ToUpdate(QString, QString, SeafileTree::Entry)), this,
|
||||
SLOT(UpdateEntry(QString, QString, SeafileTree::Entry)));
|
||||
}
|
||||
|
||||
bool SeafileService::has_credentials() const {
|
||||
|
@ -67,7 +66,8 @@ QString SeafileService::access_token() const {
|
|||
}
|
||||
|
||||
void SeafileService::AddAuthorizationHeader(QNetworkRequest* request) const {
|
||||
request->setRawHeader("Authorization", QString(QString("Token ") + QString(access_token_)).toAscii());
|
||||
request->setRawHeader("Authorization",
|
||||
QString("Token %1").arg(access_token_).toAscii());
|
||||
}
|
||||
|
||||
void SeafileService::ForgetCredentials() {
|
||||
|
@ -82,8 +82,9 @@ void SeafileService::ForgetCredentials() {
|
|||
server_.clear();
|
||||
}
|
||||
|
||||
bool SeafileService::GetToken(const QString &mail, const QString &password, const QString &server) {
|
||||
QUrl url(server + kAuthToken);
|
||||
bool SeafileService::GetToken(const QString& mail, const QString& password,
|
||||
const QString& server) {
|
||||
QUrl url(server + kAuthTokenUrl);
|
||||
QNetworkRequest request(url);
|
||||
AddAuthorizationHeader(&request);
|
||||
|
||||
|
@ -91,10 +92,9 @@ bool SeafileService::GetToken(const QString &mail, const QString &password, cons
|
|||
url.addQueryItem("password", password);
|
||||
|
||||
QNetworkReply* reply = network_->post(request, url.encodedQuery());
|
||||
reply->ignoreSslErrors();
|
||||
WaitForSignal(reply, SIGNAL(finished()));
|
||||
|
||||
if(!CheckReply(&reply)) {
|
||||
if (!CheckReply(&reply)) {
|
||||
qLog(Warning) << "Something wrong with the reply... (GetToken)";
|
||||
return false;
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ bool SeafileService::GetToken(const QString &mail, const QString &password, cons
|
|||
// Because the server responds "token"
|
||||
access_token_ = response["token"].toString().replace("\"", "");
|
||||
|
||||
if(access_token_.isEmpty()) {
|
||||
if (access_token_.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -122,19 +122,18 @@ bool SeafileService::GetToken(const QString &mail, const QString &password, cons
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SeafileService::GetLibraries() {
|
||||
QUrl url(server_ + kListRepos);
|
||||
QUrl url(server_ + kListReposUrl);
|
||||
QNetworkRequest request(url);
|
||||
AddAuthorizationHeader(&request);
|
||||
QNetworkReply *reply = network_->get(request);
|
||||
reply->ignoreSslErrors();
|
||||
QNetworkReply* reply = network_->get(request);
|
||||
|
||||
NewClosure(reply, SIGNAL(finished()), this, SLOT(GetLibrariesFinished(QNetworkReply*)), reply);
|
||||
NewClosure(reply, SIGNAL(finished()), this,
|
||||
SLOT(GetLibrariesFinished(QNetworkReply*)), reply);
|
||||
}
|
||||
|
||||
void SeafileService::GetLibrariesFinished(QNetworkReply *reply) {
|
||||
if(!CheckReply(&reply)) {
|
||||
void SeafileService::GetLibrariesFinished(QNetworkReply* reply) {
|
||||
if (!CheckReply(&reply)) {
|
||||
qLog(Warning) << "Something wrong with the reply... (GetLibraries)";
|
||||
return;
|
||||
}
|
||||
|
@ -147,13 +146,14 @@ void SeafileService::GetLibrariesFinished(QNetworkReply *reply) {
|
|||
QJson::Parser parser;
|
||||
QList<QVariant> repos = parser.parse(data).toList();
|
||||
|
||||
for (int i=0; i<repos.size(); ++i) {
|
||||
for (int i = 0; i < repos.size(); ++i) {
|
||||
QVariantMap repo = repos.at(i).toMap();
|
||||
QString repo_name = repo["name"].toString(),
|
||||
repo_id = repo["id"].toString();
|
||||
repo_id = repo["id"].toString();
|
||||
|
||||
// One library can appear several times and we don't add encrypted libraries (not supported yet)
|
||||
if(!libraries.contains(repo_id) && !repo["encrypted"].toBool()) {
|
||||
// One library can appear several times and we don't add encrypted libraries
|
||||
// (not supported yet)
|
||||
if (!libraries.contains(repo_id) && !repo["encrypted"].toBool()) {
|
||||
libraries.insert(repo_id, repo_name);
|
||||
}
|
||||
}
|
||||
|
@ -161,43 +161,38 @@ void SeafileService::GetLibrariesFinished(QNetworkReply *reply) {
|
|||
emit GetLibrariesFinishedSignal(libraries);
|
||||
}
|
||||
|
||||
|
||||
void SeafileService::ChangeLibrary(const QString &new_library) {
|
||||
|
||||
void SeafileService::ChangeLibrary(const QString& new_library) {
|
||||
// Every other libraries have to be destroyed from the tree
|
||||
if(new_library != "all") {
|
||||
|
||||
for (SeafileTree::TreeItem *library : tree_.libraries()) {
|
||||
if (new_library != "all") {
|
||||
for (SeafileTree::TreeItem* library : tree_.libraries()) {
|
||||
if (new_library != library->entry().id()) {
|
||||
DeleteEntry(library->entry().id(), "/", library->entry());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UpdateLibraries();
|
||||
}
|
||||
|
||||
void SeafileService::Connect() {
|
||||
if (is_authenticated()) {
|
||||
UpdateLibraries();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ShowSettingsDialog();
|
||||
}
|
||||
}
|
||||
|
||||
void SeafileService::UpdateLibraries() {
|
||||
|
||||
connect(this, SIGNAL(GetLibrariesFinishedSignal(QMap<QString,QString>)), this,
|
||||
SLOT(UpdateLibrariesInProgress(QMap<QString,QString>)));
|
||||
connect(this, SIGNAL(GetLibrariesFinishedSignal(QMap<QString, QString>)),
|
||||
this, SLOT(UpdateLibrariesInProgress(QMap<QString, QString>)));
|
||||
|
||||
GetLibraries();
|
||||
}
|
||||
|
||||
void SeafileService::UpdateLibrariesInProgress(const QMap<QString, QString> &libraries) {
|
||||
disconnect(this, SIGNAL(GetLibrariesFinishedSignal(QMap<QString,QString>)), this,
|
||||
SLOT(UpdateLibrariesInProgress(QMap<QString,QString>)));
|
||||
void SeafileService::UpdateLibrariesInProgress(
|
||||
const QMap<QString, QString>& libraries) {
|
||||
disconnect(this, SIGNAL(GetLibrariesFinishedSignal(QMap<QString, QString>)),
|
||||
this, SLOT(UpdateLibrariesInProgress(QMap<QString, QString>)));
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
|
@ -210,7 +205,7 @@ void SeafileService::UpdateLibrariesInProgress(const QMap<QString, QString> &lib
|
|||
|
||||
library_updated_ = library_to_update;
|
||||
|
||||
if(library_to_update == "none") {
|
||||
if (library_to_update == "none") {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -220,43 +215,49 @@ void SeafileService::UpdateLibrariesInProgress(const QMap<QString, QString> &lib
|
|||
|
||||
// Need to check this library ?
|
||||
if (library_to_update == "all" || library.key() == library_to_update) {
|
||||
|
||||
FetchAndCheckFolderItems(
|
||||
SeafileTree::Entry(library.value(), library.key(), SeafileTree::Entry::LIBRARY), "/");
|
||||
SeafileTree::Entry(library.value(), library.key(),
|
||||
SeafileTree::Entry::LIBRARY),
|
||||
"/");
|
||||
}
|
||||
// If not, we can destroy the library from the tree
|
||||
else {
|
||||
// If the library was not in the tree, it's not a problem because DeleteEntry won't do anything
|
||||
// If the library was not in the tree, it's not a problem because
|
||||
// DeleteEntry won't do anything
|
||||
DeleteEntry(library.key(), "/",
|
||||
SeafileTree::Entry(library.value(), library.key(), SeafileTree::Entry::LIBRARY));
|
||||
SeafileTree::Entry(library.value(), library.key(),
|
||||
SeafileTree::Entry::LIBRARY));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QNetworkReply* SeafileService::PrepareFetchFolderItems(const QString &library, const QString &path) {
|
||||
QUrl url(server_ + QString(kFolderItems).arg(library));
|
||||
QNetworkReply* SeafileService::PrepareFetchFolderItems(const QString& library,
|
||||
const QString& path) {
|
||||
QUrl url(server_ + QString(kFolderItemsUrl).arg(library));
|
||||
url.addQueryItem("p", path);
|
||||
|
||||
QNetworkRequest request(url);
|
||||
AddAuthorizationHeader(&request);
|
||||
QNetworkReply* reply = network_->get(request);
|
||||
reply->ignoreSslErrors();
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
void SeafileService::FetchAndCheckFolderItems(const SeafileTree::Entry &library, const QString &path) {
|
||||
QNetworkReply *reply = PrepareFetchFolderItems(library.id(), path);
|
||||
void SeafileService::FetchAndCheckFolderItems(const SeafileTree::Entry& library,
|
||||
const QString& path) {
|
||||
QNetworkReply* reply = PrepareFetchFolderItems(library.id(), path);
|
||||
NewClosure(reply, SIGNAL(finished()), this,
|
||||
SLOT(FetchAndCheckFolderItemsFinished(QNetworkReply*,SeafileTree::Entry,QString)),
|
||||
SLOT(FetchAndCheckFolderItemsFinished(
|
||||
QNetworkReply*, SeafileTree::Entry, QString)),
|
||||
reply, library, path);
|
||||
}
|
||||
|
||||
void SeafileService::FetchAndCheckFolderItemsFinished(
|
||||
QNetworkReply *reply, const SeafileTree::Entry &library, const QString &path) {
|
||||
if(!CheckReply(&reply)) {
|
||||
qLog(Warning) << "Something wrong with the reply... (FetchFolderItemsToList)";
|
||||
QNetworkReply* reply, const SeafileTree::Entry& library,
|
||||
const QString& path) {
|
||||
if (!CheckReply(&reply)) {
|
||||
qLog(Warning)
|
||||
<< "Something wrong with the reply... (FetchFolderItemsToList)";
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -268,33 +269,40 @@ void SeafileService::FetchAndCheckFolderItemsFinished(
|
|||
QList<QVariant> variant_entries = parser.parse(data).toList();
|
||||
|
||||
SeafileTree::Entries entries;
|
||||
for (const QVariant & e: variant_entries) {
|
||||
for (const QVariant& e : variant_entries) {
|
||||
QVariantMap entry = e.toMap();
|
||||
SeafileTree::Entry::Type entry_type = SeafileTree::Entry::StringToType(entry["type"].toString());
|
||||
SeafileTree::Entry::Type entry_type =
|
||||
SeafileTree::Entry::StringToType(entry["type"].toString());
|
||||
QString entry_name = entry["name"].toString();
|
||||
|
||||
// We just want libraries/directories and files which could be songs.
|
||||
if (entry_type == SeafileTree::Entry::NONE) {
|
||||
qLog(Warning) << "Type entry unknown for this entry";
|
||||
}
|
||||
else if (entry_type == SeafileTree::Entry::FILE && GuessMimeTypeForFile(entry_name).isNull()) {
|
||||
} else if (entry_type == SeafileTree::Entry::FILE &&
|
||||
GuessMimeTypeForFile(entry_name).isNull()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
entries.append(SeafileTree::Entry(entry_name, entry["id"].toString(), entry_type));
|
||||
entries.append(
|
||||
SeafileTree::Entry(entry_name, entry["id"].toString(), entry_type));
|
||||
}
|
||||
|
||||
tree_.CheckEntries(entries, library, path);
|
||||
}
|
||||
|
||||
|
||||
void SeafileService::AddRecursivelyFolderItems(const QString &library, const QString &path) {
|
||||
QNetworkReply *reply = PrepareFetchFolderItems(library, path);
|
||||
NewClosure(reply, SIGNAL(finished()), this, SLOT(AddRecursivelyFolderItemsFinished(QNetworkReply*,QString,QString)), reply, library, path);
|
||||
void SeafileService::AddRecursivelyFolderItems(const QString& library,
|
||||
const QString& path) {
|
||||
QNetworkReply* reply = PrepareFetchFolderItems(library, path);
|
||||
NewClosure(
|
||||
reply, SIGNAL(finished()), this,
|
||||
SLOT(AddRecursivelyFolderItemsFinished(QNetworkReply*, QString, QString)),
|
||||
reply, library, path);
|
||||
}
|
||||
|
||||
void SeafileService::AddRecursivelyFolderItemsFinished(QNetworkReply* reply, const QString &library, const QString &path) {
|
||||
if(!CheckReply(&reply)) {
|
||||
void SeafileService::AddRecursivelyFolderItemsFinished(QNetworkReply* reply,
|
||||
const QString& library,
|
||||
const QString& path) {
|
||||
if (!CheckReply(&reply)) {
|
||||
qLog(Warning) << "Something wrong with the reply... (FetchFolderItems)";
|
||||
return;
|
||||
}
|
||||
|
@ -307,36 +315,39 @@ void SeafileService::AddRecursivelyFolderItemsFinished(QNetworkReply* reply, con
|
|||
|
||||
for (const QVariant& e : entries) {
|
||||
QVariantMap entry_map = e.toMap();
|
||||
SeafileTree::Entry::Type entry_type = SeafileTree::Entry::StringToType(entry_map["type"].toString());
|
||||
SeafileTree::Entry::Type entry_type =
|
||||
SeafileTree::Entry::StringToType(entry_map["type"].toString());
|
||||
QString entry_name = entry_map["name"].toString();
|
||||
|
||||
// We just want libraries/directories and files which could be songs.
|
||||
if (entry_type == SeafileTree::Entry::NONE) {
|
||||
qLog(Warning) << "Type entry unknown for this entry";
|
||||
}
|
||||
else if (entry_type == SeafileTree::Entry::FILE && GuessMimeTypeForFile(entry_name).isNull()) {
|
||||
} else if (entry_type == SeafileTree::Entry::FILE &&
|
||||
GuessMimeTypeForFile(entry_name).isNull()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SeafileTree::Entry entry(entry_name, entry_map["id"].toString(), entry_type);
|
||||
SeafileTree::Entry entry(entry_name, entry_map["id"].toString(),
|
||||
entry_type);
|
||||
|
||||
// If AddEntry was not successful we stop
|
||||
// It could happen when the user changes the library to update while an update was in progress
|
||||
if(!tree_.AddEntry(library, path, entry)) {
|
||||
// It could happen when the user changes the library to update while an
|
||||
// update was in progress
|
||||
if (!tree_.AddEntry(library, path, entry)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry.is_dir()) {
|
||||
AddRecursivelyFolderItems(library, path + entry.name() + "/");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
MaybeAddFileEntry(entry.name(), library, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QNetworkReply *SeafileService::PrepareFetchContentForFile(const QString &library, const QString &filepath) {
|
||||
QUrl content_url(server_ + QString(kFileContent).arg(library));
|
||||
QNetworkReply* SeafileService::PrepareFetchContentForFile(
|
||||
const QString& library, const QString& filepath) {
|
||||
QUrl content_url(server_ + QString(kFileContentUrl).arg(library));
|
||||
content_url.addQueryItem("p", filepath);
|
||||
|
||||
QNetworkRequest request(content_url);
|
||||
|
@ -346,24 +357,26 @@ QNetworkReply *SeafileService::PrepareFetchContentForFile(const QString &library
|
|||
return reply;
|
||||
}
|
||||
|
||||
|
||||
void SeafileService::MaybeAddFileEntry(const QString &entry_name, const QString &library, const QString &path) {
|
||||
void SeafileService::MaybeAddFileEntry(const QString& entry_name,
|
||||
const QString& library,
|
||||
const QString& path) {
|
||||
QString mime_type = GuessMimeTypeForFile(entry_name);
|
||||
|
||||
if(mime_type.isNull())
|
||||
return;
|
||||
if (mime_type.isNull()) return;
|
||||
|
||||
// Get the details of the entry
|
||||
QNetworkReply *reply = PrepareFetchContentForFile(library, path + entry_name);
|
||||
QNetworkReply* reply = PrepareFetchContentForFile(library, path + entry_name);
|
||||
NewClosure(reply, SIGNAL(finished()), this,
|
||||
SLOT(MaybeAddFileEntryInProgress(QNetworkReply*,QString,QString,QString)),
|
||||
SLOT(MaybeAddFileEntryInProgress(QNetworkReply*, QString, QString,
|
||||
QString)),
|
||||
reply, library, path, mime_type);
|
||||
}
|
||||
|
||||
void SeafileService::MaybeAddFileEntryInProgress(
|
||||
QNetworkReply *reply, const QString &library, const QString &path, const QString &mime_type) {
|
||||
|
||||
if(!CheckReply(&reply)) {
|
||||
void SeafileService::MaybeAddFileEntryInProgress(QNetworkReply* reply,
|
||||
const QString& library,
|
||||
const QString& path,
|
||||
const QString& mime_type) {
|
||||
if (!CheckReply(&reply)) {
|
||||
qLog(Warning) << "Something wrong with the reply... (MaybeAddFileEntry)";
|
||||
return;
|
||||
}
|
||||
|
@ -387,12 +400,16 @@ void SeafileService::MaybeAddFileEntryInProgress(
|
|||
song.set_title(entry_detail_map["name"].toString());
|
||||
|
||||
// Get the download url of the entry
|
||||
reply = PrepareFetchContentUrlForFile(library, path + entry_detail_map["name"].toString());
|
||||
NewClosure(reply, SIGNAL(finished()), this, SLOT(FetchContentUrlForFileFinished(QNetworkReply*, Song, QString)), reply, song, mime_type);
|
||||
reply = PrepareFetchContentUrlForFile(
|
||||
library, path + entry_detail_map["name"].toString());
|
||||
NewClosure(
|
||||
reply, SIGNAL(finished()), this,
|
||||
SLOT(FetchContentUrlForFileFinished(QNetworkReply*, Song, QString)),
|
||||
reply, song, mime_type);
|
||||
}
|
||||
|
||||
|
||||
QNetworkReply* SeafileService::PrepareFetchContentUrlForFile(const QString &library, const QString &filepath) {
|
||||
QNetworkReply* SeafileService::PrepareFetchContentUrlForFile(
|
||||
const QString& library, const QString& filepath) {
|
||||
QUrl content_url(server_ + QString(kFileUrl).arg(library));
|
||||
content_url.addQueryItem("p", filepath);
|
||||
|
||||
|
@ -403,10 +420,12 @@ QNetworkReply* SeafileService::PrepareFetchContentUrlForFile(const QString &libr
|
|||
return reply;
|
||||
}
|
||||
|
||||
void SeafileService::FetchContentUrlForFileFinished(QNetworkReply* reply, const Song &song, const QString &mime_type) {
|
||||
|
||||
if(!CheckReply(&reply)) {
|
||||
qLog(Warning) << "Something wrong with the reply... (FetchContentUrlForFile)";
|
||||
void SeafileService::FetchContentUrlForFileFinished(QNetworkReply* reply,
|
||||
const Song& song,
|
||||
const QString& mime_type) {
|
||||
if (!CheckReply(&reply)) {
|
||||
qLog(Warning)
|
||||
<< "Something wrong with the reply... (FetchContentUrlForFile)";
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -415,17 +434,18 @@ void SeafileService::FetchContentUrlForFileFinished(QNetworkReply* reply, const
|
|||
// Because server response is "http://..."
|
||||
QString real_url = QString(reply->readAll()).replace("\"", "");
|
||||
|
||||
MaybeAddFileToDatabase(song, mime_type, QUrl(real_url), QString("Token %1").arg(access_token_));
|
||||
MaybeAddFileToDatabase(song, mime_type, QUrl(real_url),
|
||||
QString("Token %1").arg(access_token_));
|
||||
}
|
||||
|
||||
QUrl SeafileService::GetStreamingUrlFromSongId(const QString &library, const QString &filepath) {
|
||||
|
||||
QUrl SeafileService::GetStreamingUrlFromSongId(const QString& library,
|
||||
const QString& filepath) {
|
||||
QNetworkReply* reply = PrepareFetchContentUrlForFile(library, filepath);
|
||||
reply->ignoreSslErrors();
|
||||
WaitForSignal(reply, SIGNAL(finished()));
|
||||
|
||||
if(!CheckReply(&reply)) {
|
||||
qLog(Warning) << "Something wrong with the reply... (GetStreamingUrlFromSongId)";
|
||||
if (!CheckReply(&reply)) {
|
||||
qLog(Warning)
|
||||
<< "Something wrong with the reply... (GetStreamingUrlFromSongId)";
|
||||
return QUrl("");
|
||||
}
|
||||
reply->deleteLater();
|
||||
|
@ -435,115 +455,120 @@ QUrl SeafileService::GetStreamingUrlFromSongId(const QString &library, const QSt
|
|||
return QUrl(response);
|
||||
}
|
||||
|
||||
|
||||
void SeafileService::AddEntry(const QString &library, const QString &path, const SeafileTree::Entry &entry) {
|
||||
|
||||
void SeafileService::AddEntry(const QString& library, const QString& path,
|
||||
const SeafileTree::Entry& entry) {
|
||||
if (entry.is_library()) {
|
||||
tree_.AddLibrary(entry.name(), entry.id());
|
||||
AddRecursivelyFolderItems(library, "/");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// If AddEntry was not successful we stop
|
||||
// It could happen when the user changes the library to update while an update was in progress
|
||||
if(!tree_.AddEntry(library, path, entry)) {
|
||||
// It could happen when the user changes the library to update while an
|
||||
// update was in progress
|
||||
if (!tree_.AddEntry(library, path, entry)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry.is_file()) {
|
||||
MaybeAddFileEntry(entry.name(), library, path);
|
||||
}
|
||||
else {
|
||||
AddRecursivelyFolderItems(library, path + entry.name() + "/");
|
||||
} else {
|
||||
AddRecursivelyFolderItems(library, path + entry.name() + "/");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SeafileService::UpdateEntry(const QString & library, const QString &path, const SeafileTree::Entry &entry) {
|
||||
|
||||
void SeafileService::UpdateEntry(const QString& library, const QString& path,
|
||||
const SeafileTree::Entry& entry) {
|
||||
if (entry.is_file()) {
|
||||
DeleteEntry(library, path, entry);
|
||||
AddEntry(library, path, entry);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
QString entry_path = path;
|
||||
|
||||
if(entry.is_dir()) {
|
||||
if (entry.is_dir()) {
|
||||
entry_path += entry.name() + "/";
|
||||
}
|
||||
|
||||
FetchAndCheckFolderItems(SeafileTree::Entry("", library, SeafileTree::Entry::LIBRARY),
|
||||
entry_path);
|
||||
FetchAndCheckFolderItems(
|
||||
SeafileTree::Entry("", library, SeafileTree::Entry::LIBRARY),
|
||||
entry_path);
|
||||
}
|
||||
}
|
||||
|
||||
void SeafileService::DeleteEntry(const QString &library, const QString &path, const SeafileTree::Entry &entry) {
|
||||
|
||||
void SeafileService::DeleteEntry(const QString& library, const QString& path,
|
||||
const SeafileTree::Entry& entry) {
|
||||
// For the QPair -> 1 : path, 2 : entry
|
||||
QList<QPair<QString, SeafileTree::Entry>> files_to_delete;
|
||||
if(entry.is_library()) {
|
||||
SeafileTree::TreeItem *item = tree_.FindLibrary(library);
|
||||
if (entry.is_library()) {
|
||||
SeafileTree::TreeItem* item = tree_.FindLibrary(library);
|
||||
files_to_delete = tree_.GetRecursiveFilesOfDir("/", item);
|
||||
tree_.DeleteLibrary(library);
|
||||
}
|
||||
else {
|
||||
if(entry.is_dir()) {
|
||||
SeafileTree::TreeItem *item = tree_.FindFromAbsolutePath(library, path + entry.name() + "/");
|
||||
files_to_delete = tree_.GetRecursiveFilesOfDir(path + entry.name() + "/", item);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (entry.is_dir()) {
|
||||
SeafileTree::TreeItem* item =
|
||||
tree_.FindFromAbsolutePath(library, path + entry.name() + "/");
|
||||
files_to_delete =
|
||||
tree_.GetRecursiveFilesOfDir(path + entry.name() + "/", item);
|
||||
} else {
|
||||
files_to_delete.append(qMakePair(path, entry));
|
||||
}
|
||||
|
||||
if(!tree_.DeleteEntry(library, path, entry)) {
|
||||
if (!tree_.DeleteEntry(library, path, entry)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete songs from the library of Clementine
|
||||
for (const QPair<QString, SeafileTree::Entry> &file_to_delete : files_to_delete) {
|
||||
if(!GuessMimeTypeForFile(file_to_delete.second.name())
|
||||
.isEmpty()) {
|
||||
QUrl song_url("seafile:/" + library + file_to_delete.first + file_to_delete.second.name());
|
||||
for (const QPair<QString, SeafileTree::Entry>& file_to_delete :
|
||||
files_to_delete) {
|
||||
if (!GuessMimeTypeForFile(file_to_delete.second.name()).isEmpty()) {
|
||||
QUrl song_url("seafile:/" + library + file_to_delete.first +
|
||||
file_to_delete.second.name());
|
||||
Song song = library_backend_->GetSongByUrl(song_url);
|
||||
|
||||
if (song.is_valid()) {
|
||||
library_backend_->DeleteSongs(SongList() << song);
|
||||
}
|
||||
else {
|
||||
qLog(Warning) << "Can't delete song from the Clementine's library : " << song_url;
|
||||
} else {
|
||||
qLog(Warning) << "Can't delete song from the Clementine's library : "
|
||||
<< song_url;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SeafileService::CheckReply(QNetworkReply **reply) {
|
||||
if (!(*reply)) {
|
||||
bool SeafileService::CheckReply(QNetworkReply** reply, int tries) {
|
||||
if (!(*reply) || tries > 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant status_code_variant = (*reply)->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
||||
QVariant status_code_variant =
|
||||
(*reply)->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
||||
if (status_code_variant.isValid()) {
|
||||
int status_code = status_code_variant.toInt();
|
||||
|
||||
if (status_code == NO_ERROR) {
|
||||
return true;
|
||||
}
|
||||
else if (status_code == TOO_MANY_REQUESTS) {
|
||||
} else if (status_code == TOO_MANY_REQUESTS) {
|
||||
qLog(Debug) << "Too many requests, wait...";
|
||||
|
||||
// If there are too many requests, we just wait
|
||||
int seconds_to_wait;
|
||||
if ((*reply)->hasRawHeader("X-Throttle-Wait-Seconds")) {
|
||||
seconds_to_wait =
|
||||
((*reply)->rawHeader("X-Throttle-Wait-Seconds").toInt() + 1) * 1000;
|
||||
} else {
|
||||
seconds_to_wait = pow(tries, 2) * 1000;
|
||||
}
|
||||
|
||||
QTimer timer;
|
||||
timer.start(10000);
|
||||
timer.start(seconds_to_wait);
|
||||
WaitForSignal(&timer, SIGNAL(timeout()));
|
||||
|
||||
(*reply)->deleteLater();
|
||||
|
||||
// And we execute the reply again
|
||||
// We execute the reply again
|
||||
*reply = network_->get((*reply)->request());
|
||||
WaitForSignal(*reply, SIGNAL(finished()));
|
||||
|
||||
return CheckReply(reply);
|
||||
return CheckReply(reply, ++tries);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -552,7 +577,6 @@ bool SeafileService::CheckReply(QNetworkReply **reply) {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
SeafileService::~SeafileService() {
|
||||
// Save the tree !
|
||||
QSettings s;
|
||||
|
@ -563,6 +587,4 @@ SeafileService::~SeafileService() {
|
|||
stream << tree_;
|
||||
|
||||
s.setValue("tree", tree_byte);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -3,18 +3,23 @@
|
|||
*
|
||||
* Help :
|
||||
* - The "path" variable has to end with "/".
|
||||
* If we want to specify a filepath, the name of the variable has to be... filepath :)
|
||||
* - Seafile stores files in libraries (or repositories) so variable with the name "library" corresponds to the
|
||||
* If we want to specify a filepath, the name of the variable has to be...
|
||||
*filepath :)
|
||||
* - Seafile stores files in libraries (or repositories) so variable with the
|
||||
*name "library" corresponds to the
|
||||
* Seafile library, not to the Clementine library
|
||||
* - The authentification of Seafile's API is simply a token (REST API)
|
||||
* - Seafile stores a hash for each entry. This hash changes when the entry is modified.
|
||||
* This is the reason why we just have to compare the local hash with the server
|
||||
* - Seafile stores a hash for each entry. This hash changes when the entry is
|
||||
*modified.
|
||||
* This is the reason why we just have to compare the local hash with the
|
||||
*server
|
||||
* hash of a directory (for example) to know if the directory was modified.
|
||||
* Libraries are an exception : Seafile stores a hash that never changes.
|
||||
* This hash is called "id".
|
||||
*
|
||||
* Todo :
|
||||
* - Add ssl certificate exception (for people who generate their own certificate on their Seafile server
|
||||
* - Add ssl certificate exception (for people who generate their own
|
||||
*certificate on their Seafile server
|
||||
* - Stop Tagreader when user changes the library
|
||||
*/
|
||||
|
||||
|
@ -22,24 +27,20 @@
|
|||
#define SEAFILESERVICE_H
|
||||
|
||||
#include "cloudfileservice.h"
|
||||
#include "seafiletree.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QMutex>
|
||||
|
||||
#include "seafiletree.h"
|
||||
|
||||
class QNetworkReply;
|
||||
class QNetworkRequest;
|
||||
|
||||
// Interface between the seafile server and Clementine
|
||||
class SeafileService : public CloudFileService {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
enum ApiError {
|
||||
NO_ERROR = 200,
|
||||
NOT_FOUND = 404,
|
||||
TOO_MANY_REQUESTS = 429
|
||||
};
|
||||
enum ApiError { NO_ERROR = 200, NOT_FOUND = 404, TOO_MANY_REQUESTS = 429 };
|
||||
|
||||
SeafileService(Application* app, InternetModel* parent);
|
||||
~SeafileService();
|
||||
|
@ -48,12 +49,14 @@ class SeafileService : public CloudFileService {
|
|||
static const char* kSettingsGroup;
|
||||
|
||||
virtual bool has_credentials() const;
|
||||
QUrl GetStreamingUrlFromSongId(const QString &library, const QString &filepath);
|
||||
QUrl GetStreamingUrlFromSongId(const QString& library,
|
||||
const QString& filepath);
|
||||
// Get the token for an user (simple rest api)
|
||||
bool GetToken(const QString &mail, const QString &password, const QString &server);
|
||||
bool GetToken(const QString& mail, const QString& password,
|
||||
const QString& server);
|
||||
// Get all the libraries available for the user. Will emit a signal
|
||||
void GetLibraries();
|
||||
void ChangeLibrary(const QString &new_library);
|
||||
void ChangeLibrary(const QString& new_library);
|
||||
|
||||
public slots:
|
||||
void Connect();
|
||||
|
@ -66,25 +69,35 @@ signals:
|
|||
|
||||
private slots:
|
||||
// Will emit the signal
|
||||
void GetLibrariesFinished(QNetworkReply *reply);
|
||||
void GetLibrariesFinished(QNetworkReply* reply);
|
||||
|
||||
void FetchAndCheckFolderItemsFinished(QNetworkReply *reply, const SeafileTree::Entry &library, const QString &path);
|
||||
void FetchAndCheckFolderItemsFinished(QNetworkReply* reply,
|
||||
const SeafileTree::Entry& library,
|
||||
const QString& path);
|
||||
|
||||
// Add recursively the content of a folder from a library
|
||||
void AddRecursivelyFolderItemsFinished(QNetworkReply *reply, const QString &library, const QString &path);
|
||||
void AddRecursivelyFolderItemsFinished(QNetworkReply* reply,
|
||||
const QString& library,
|
||||
const QString& path);
|
||||
// Get the url and try to add the file to the database
|
||||
void FetchContentUrlForFileFinished(QNetworkReply* reply, const Song &song, const QString &mime_type);
|
||||
void FetchContentUrlForFileFinished(QNetworkReply* reply, const Song& song,
|
||||
const QString& mime_type);
|
||||
// Add the entry to the tree and maybe add this entry to the database
|
||||
void AddEntry(const QString &library, const QString &path, const SeafileTree::Entry &entry);
|
||||
void AddEntry(const QString& library, const QString& path,
|
||||
const SeafileTree::Entry& entry);
|
||||
// Update the entry or check recursively the directories
|
||||
void UpdateEntry(const QString &library, const QString &path, const SeafileTree::Entry &entry);
|
||||
// Delete the entry (eventually the files of its subdir) of the tree and the database
|
||||
void DeleteEntry(const QString &library, const QString &path, const SeafileTree::Entry &entry);
|
||||
void UpdateEntry(const QString& library, const QString& path,
|
||||
const SeafileTree::Entry& entry);
|
||||
// Delete the entry (eventually the files of its subdir) of the tree and the
|
||||
// database
|
||||
void DeleteEntry(const QString& library, const QString& path,
|
||||
const SeafileTree::Entry& entry);
|
||||
|
||||
void UpdateLibrariesInProgress(const QMap<QString, QString> &libraries);
|
||||
void UpdateLibrariesInProgress(const QMap<QString, QString>& libraries);
|
||||
|
||||
void MaybeAddFileEntryInProgress(QNetworkReply *reply, const QString &library,
|
||||
const QString &path, const QString &mime_type);
|
||||
void MaybeAddFileEntryInProgress(QNetworkReply* reply, const QString& library,
|
||||
const QString& path,
|
||||
const QString& mime_type);
|
||||
|
||||
private:
|
||||
QString access_token() const;
|
||||
|
@ -94,19 +107,24 @@ signals:
|
|||
|
||||
void UpdateLibraries();
|
||||
|
||||
void FetchAndCheckFolderItems(const SeafileTree::Entry &library, const QString &path);
|
||||
void AddRecursivelyFolderItems(const QString &library, const QString &path);
|
||||
void FetchAndCheckFolderItems(const SeafileTree::Entry& library,
|
||||
const QString& path);
|
||||
void AddRecursivelyFolderItems(const QString& library, const QString& path);
|
||||
|
||||
QNetworkReply* PrepareFetchFolderItems(const QString &library, const QString &path);
|
||||
QNetworkReply* PrepareFetchContentForFile(const QString &library, const QString &filepath);
|
||||
QNetworkReply* PrepareFetchContentUrlForFile(const QString &library, const QString &filepath);
|
||||
QNetworkReply* PrepareFetchFolderItems(const QString& library,
|
||||
const QString& path);
|
||||
QNetworkReply* PrepareFetchContentForFile(const QString& library,
|
||||
const QString& filepath);
|
||||
QNetworkReply* PrepareFetchContentUrlForFile(const QString& library,
|
||||
const QString& filepath);
|
||||
|
||||
void MaybeAddFileEntry(const QString &entry_name, const QString &library, const QString &path);
|
||||
void MaybeAddFileEntry(const QString& entry_name, const QString& library,
|
||||
const QString& path);
|
||||
|
||||
// False if not 200 or 429
|
||||
// If 429 (too many requests), re execute the request and put the reply in the argument
|
||||
bool CheckReply(QNetworkReply **reply);
|
||||
|
||||
// If 429 (too many requests), re execute the request and put the reply in the
|
||||
// argument
|
||||
bool CheckReply(QNetworkReply** reply, int tries = 1);
|
||||
|
||||
SeafileTree tree_;
|
||||
QString access_token_;
|
||||
|
|
|
@ -15,13 +15,7 @@
|
|||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "seafileservice.h"
|
||||
#include "seafilesettingspage.h"
|
||||
#include "internetmodel.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/network.h"
|
||||
#include "ui_seafilesettingspage.h"
|
||||
#include "ui/iconloader.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QNetworkReply>
|
||||
|
@ -29,10 +23,17 @@
|
|||
#include <QSettings>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "seafileservice.h"
|
||||
#include "internetmodel.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/network.h"
|
||||
#include "ui_seafilesettingspage.h"
|
||||
#include "ui/iconloader.h"
|
||||
|
||||
SeafileSettingsPage::SeafileSettingsPage(SettingsDialog* dialog)
|
||||
: SettingsPage(dialog),
|
||||
ui_(new Ui_SeafileSettingsPage),
|
||||
service_(InternetModel::Service<SeafileService>()) {
|
||||
: SettingsPage(dialog),
|
||||
ui_(new Ui_SeafileSettingsPage),
|
||||
service_(InternetModel::Service<SeafileService>()) {
|
||||
ui_->setupUi(this);
|
||||
|
||||
setWindowIcon(QIcon(":/providers/seafile.png"));
|
||||
|
@ -47,12 +48,11 @@ SeafileSettingsPage::SeafileSettingsPage(SettingsDialog* dialog)
|
|||
|
||||
ui_->library_box->addItem("None", "none");
|
||||
|
||||
connect(service_, SIGNAL(GetLibrariesFinishedSignal(QMap<QString,QString>)), this,
|
||||
SLOT(GetLibrariesFinished(QMap<QString,QString>)));
|
||||
connect(service_, SIGNAL(GetLibrariesFinishedSignal(QMap<QString, QString>)),
|
||||
this, SLOT(GetLibrariesFinished(QMap<QString, QString>)));
|
||||
}
|
||||
|
||||
SeafileSettingsPage::~SeafileSettingsPage() { delete ui_; }
|
||||
|
||||
SeafileSettingsPage::~SeafileSettingsPage() {}
|
||||
|
||||
void SeafileSettingsPage::Load() {
|
||||
QSettings s;
|
||||
|
@ -62,23 +62,26 @@ void SeafileSettingsPage::Load() {
|
|||
ui_->mail->setText(s.value("mail").toString());
|
||||
|
||||
if (!ui_->server->text().isEmpty() && !ui_->mail->text().isEmpty()) {
|
||||
ui_->login_state->SetLoggedIn(LoginStateWidget::LoggedIn, ui_->mail->text());
|
||||
ui_->login_state->SetLoggedIn(LoginStateWidget::LoggedIn,
|
||||
ui_->mail->text());
|
||||
|
||||
// If there is more than "none" library, that means that we already got the libraries
|
||||
if(ui_->library_box->count() <= 1) {
|
||||
service_->GetLibraries();
|
||||
// If there is more than "none" library, that means that we already got the
|
||||
// libraries
|
||||
if (ui_->library_box->count() <= 1) {
|
||||
service_->GetLibraries();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SeafileSettingsPage::GetLibrariesFinished(QMap<QString, QString> libraries) {
|
||||
void SeafileSettingsPage::GetLibrariesFinished(
|
||||
const QMap<QString, QString>& libraries) {
|
||||
ui_->library_box->clear();
|
||||
ui_->library_box->addItem("None", "none");
|
||||
ui_->library_box->addItem("All (could be slow)", "all");
|
||||
|
||||
// key : library's id, value : library's name
|
||||
QMapIterator <QString, QString> library(libraries);
|
||||
while(library.hasNext()) {
|
||||
QMapIterator<QString, QString> library(libraries);
|
||||
while (library.hasNext()) {
|
||||
library.next();
|
||||
ui_->library_box->addItem(library.value(), library.key());
|
||||
}
|
||||
|
@ -93,9 +96,9 @@ void SeafileSettingsPage::GetLibrariesFinished(QMap<QString, QString> libraries)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void SeafileSettingsPage::Save() {
|
||||
QString id = ui_->library_box->itemData(ui_->library_box->currentIndex()).toString();
|
||||
QString id =
|
||||
ui_->library_box->itemData(ui_->library_box->currentIndex()).toString();
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(SeafileService::kSettingsGroup);
|
||||
|
@ -108,21 +111,21 @@ void SeafileSettingsPage::Save() {
|
|||
service_->ChangeLibrary(id);
|
||||
}
|
||||
|
||||
|
||||
void SeafileSettingsPage::Login() {
|
||||
|
||||
ui_->login_button->setEnabled(false);
|
||||
|
||||
if(service_->GetToken(ui_->mail->text(), ui_->password->text(), ui_->server->text())) {
|
||||
if (service_->GetToken(ui_->mail->text(), ui_->password->text(),
|
||||
ui_->server->text())) {
|
||||
Save();
|
||||
|
||||
ui_->login_state->SetLoggedIn(LoginStateWidget::LoggedIn, ui_->mail->text());
|
||||
ui_->login_state->SetLoggedIn(LoginStateWidget::LoggedIn,
|
||||
ui_->mail->text());
|
||||
|
||||
service_->GetLibraries();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ui_->login_button->setEnabled(true);
|
||||
QMessageBox::warning(this, tr("Unable to connect"), tr("Unable to connect"));
|
||||
QMessageBox::warning(this, tr("Unable to connect"),
|
||||
tr("Unable to connect"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,6 +148,4 @@ void SeafileSettingsPage::Logout() {
|
|||
|
||||
ui_->login_state->SetLoggedIn(LoginStateWidget::LoggedOut);
|
||||
ui_->login_button->setEnabled(true);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -40,12 +40,11 @@ class SeafileSettingsPage : public SettingsPage {
|
|||
void Login();
|
||||
void Logout();
|
||||
// Map -> key : library's id, value : library's name
|
||||
void GetLibrariesFinished(QMap<QString, QString> libraries);
|
||||
void GetLibrariesFinished(const QMap<QString, QString>& libraries);
|
||||
|
||||
private:
|
||||
Ui_SeafileSettingsPage* ui_;
|
||||
std::unique_ptr<Ui_SeafileSettingsPage> ui_;
|
||||
SeafileService* service_;
|
||||
|
||||
};
|
||||
|
||||
#endif // SEAFILESETTINGSPAGE_H
|
||||
|
|
|
@ -3,32 +3,32 @@
|
|||
#include <QStringList>
|
||||
#include <QRegExp>
|
||||
#include <QDir>
|
||||
|
||||
#include "core/logging.h"
|
||||
|
||||
/* ############################## SeafileTree ############################## */
|
||||
SeafileTree::SeafileTree() {}
|
||||
|
||||
SeafileTree::SeafileTree() { }
|
||||
SeafileTree::SeafileTree(const SeafileTree& copy) : SeafileTree() {
|
||||
libraries_ = copy.libraries();
|
||||
}
|
||||
|
||||
SeafileTree::SeafileTree(const SeafileTree ©) : SeafileTree()
|
||||
{ libraries_ = copy.libraries(); }
|
||||
|
||||
QList<SeafileTree::TreeItem*> SeafileTree::libraries() const { return libraries_; }
|
||||
QList<SeafileTree::TreeItem*> SeafileTree::libraries() const {
|
||||
return libraries_;
|
||||
}
|
||||
|
||||
void SeafileTree::Print() const {
|
||||
qLog(Debug) << "library count : " << libraries_.count();
|
||||
|
||||
for (TreeItem *item : libraries_) {
|
||||
for (TreeItem* item : libraries_) {
|
||||
qLog(Debug) << "library : " << item->ToString(1);
|
||||
}
|
||||
}
|
||||
|
||||
void SeafileTree::AddLibrary(const QString &name, const QString &id) {
|
||||
libraries_.append(
|
||||
new TreeItem(
|
||||
Entry(name, id, Entry::Type::LIBRARY)));
|
||||
void SeafileTree::AddLibrary(const QString& name, const QString& id) {
|
||||
libraries_.append(new TreeItem(Entry(name, id, Entry::Type::LIBRARY)));
|
||||
}
|
||||
|
||||
void SeafileTree::DeleteLibrary(const QString &id) {
|
||||
void SeafileTree::DeleteLibrary(const QString& id) {
|
||||
for (int i = 0; i < libraries_.size(); ++i) {
|
||||
if (libraries_.at(i)->entry().id() == id) {
|
||||
libraries_.removeAt(i);
|
||||
|
@ -37,17 +37,17 @@ void SeafileTree::DeleteLibrary(const QString &id) {
|
|||
}
|
||||
}
|
||||
|
||||
bool SeafileTree::AddEntry(const QString& library, const QString& path,
|
||||
const Entry& entry) {
|
||||
TreeItem* dir_node = FindFromAbsolutePath(library, path);
|
||||
|
||||
bool SeafileTree::AddEntry(const QString& library, const QString &path, const Entry &entry) {
|
||||
TreeItem *dir_node = FindFromAbsolutePath(library, path);
|
||||
|
||||
if(!dir_node) {
|
||||
if (!dir_node) {
|
||||
qLog(Warning) << "Can't find the path...";
|
||||
return false;
|
||||
}
|
||||
|
||||
// If it is not a dir or a library we can't add an entry...
|
||||
if(!dir_node->entry().is_dir() && !dir_node->entry().is_library()) {
|
||||
if (!dir_node->entry().is_dir() && !dir_node->entry().is_library()) {
|
||||
qLog(Warning) << "This is not a dir or a file...";
|
||||
return false;
|
||||
}
|
||||
|
@ -57,27 +57,28 @@ bool SeafileTree::AddEntry(const QString& library, const QString &path, const En
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SeafileTree::CheckEntries(const Entries &server_entries, const Entry &library, const QString &path) {
|
||||
TreeItem *local_item = FindFromAbsolutePath(library.id(), path);
|
||||
void SeafileTree::CheckEntries(const Entries& server_entries,
|
||||
const Entry& library, const QString& path) {
|
||||
TreeItem* local_item = FindFromAbsolutePath(library.id(), path);
|
||||
|
||||
// Don't know the path
|
||||
// Have to add all entries
|
||||
if(!local_item) {
|
||||
if (!local_item) {
|
||||
emit ToAdd(library.id(), path, library);
|
||||
return;
|
||||
}
|
||||
|
||||
Entries local_entries = local_item->childs_entry();
|
||||
Entries local_entries = local_item->children_entries();
|
||||
|
||||
for (const Entry &server_entry : server_entries) {
|
||||
for (const Entry& server_entry : server_entries) {
|
||||
bool is_in_tree = false;
|
||||
|
||||
for (int i=0; i<local_entries.size(); ++i) {
|
||||
for (int i = 0; i < local_entries.size(); ++i) {
|
||||
Entry local_entry = local_entries.at(i);
|
||||
|
||||
// We found the entry in the tree
|
||||
if (local_entry.name() == server_entry.name() && local_entry.type() == server_entry.type()) {
|
||||
if (local_entry.name() == server_entry.name() &&
|
||||
local_entry.type() == server_entry.type()) {
|
||||
is_in_tree = true;
|
||||
|
||||
// Need to update
|
||||
|
@ -97,29 +98,29 @@ void SeafileTree::CheckEntries(const Entries &server_entries, const Entry &libra
|
|||
}
|
||||
|
||||
// Need to add the entry
|
||||
if (!is_in_tree){
|
||||
if (!is_in_tree) {
|
||||
emit ToAdd(library.id(), path, server_entry);
|
||||
}
|
||||
}
|
||||
|
||||
// Each entry in this list corresponds to an entry that we didn't proceed
|
||||
// So if the entry is in the tree but not on the server : we have to delete it
|
||||
for (const Entry &local_entry : local_entries) {
|
||||
for (const Entry& local_entry : local_entries) {
|
||||
emit ToDelete(library.id(), path, local_entry);
|
||||
}
|
||||
}
|
||||
|
||||
SeafileTree::TreeItem* SeafileTree::FindLibrary(const QString &library) {
|
||||
for (TreeItem *item : libraries_) {
|
||||
if (item->entry().id() == library)
|
||||
return item;
|
||||
SeafileTree::TreeItem* SeafileTree::FindLibrary(const QString& library) {
|
||||
for (TreeItem* item : libraries_) {
|
||||
if (item->entry().id() == library) return item;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SeafileTree::TreeItem* SeafileTree::FindFromAbsolutePath(const QString &library, const QString &path) {
|
||||
TreeItem *node_item = FindLibrary(library);
|
||||
SeafileTree::TreeItem* SeafileTree::FindFromAbsolutePath(const QString& library,
|
||||
const QString& path) {
|
||||
TreeItem* node_item = FindLibrary(library);
|
||||
|
||||
if (!node_item) {
|
||||
return nullptr;
|
||||
|
@ -127,10 +128,10 @@ SeafileTree::TreeItem* SeafileTree::FindFromAbsolutePath(const QString &library,
|
|||
|
||||
QStringList path_parts = path.split("/", QString::SkipEmptyParts);
|
||||
|
||||
for (const QString &part : path_parts) {
|
||||
for (const QString& part : path_parts) {
|
||||
node_item = node_item->FindChild(part);
|
||||
|
||||
if(!node_item) {
|
||||
if (!node_item) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -138,25 +139,27 @@ SeafileTree::TreeItem* SeafileTree::FindFromAbsolutePath(const QString &library,
|
|||
return node_item;
|
||||
}
|
||||
|
||||
bool SeafileTree::DeleteEntry(const QString &library, const QString &path, const Entry &entry) {
|
||||
TreeItem *item_parent = FindFromAbsolutePath(library, path);
|
||||
bool SeafileTree::DeleteEntry(const QString& library, const QString& path,
|
||||
const Entry& entry) {
|
||||
TreeItem* item_parent = FindFromAbsolutePath(library, path);
|
||||
|
||||
if(!item_parent) {
|
||||
qLog(Debug) << "Unable to delete " << library + path + entry.name()
|
||||
if (!item_parent) {
|
||||
qLog(Debug) << "Unable to delete " << library + path + entry.name()
|
||||
<< " : path " << path << " not found";
|
||||
return false;
|
||||
}
|
||||
|
||||
TreeItem *item_entry = item_parent->FindChild(entry.name());
|
||||
TreeItem* item_entry = item_parent->FindChild(entry.name());
|
||||
|
||||
if(!item_entry) {
|
||||
qLog(Debug) << "Unable to delete " << library + path + entry.name()
|
||||
if (!item_entry) {
|
||||
qLog(Debug) << "Unable to delete " << library + path + entry.name()
|
||||
<< " : entry " << entry.name() << " from path not found";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!item_parent->RemoveChild(item_entry)) {
|
||||
qLog(Debug) << "Can't remove " << item_entry->entry().name() << " from parent";
|
||||
if (!item_parent->RemoveChild(item_entry)) {
|
||||
qLog(Debug) << "Can't remove " << item_entry->entry().name()
|
||||
<< " from parent";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -170,25 +173,24 @@ void SeafileTree::Clear() {
|
|||
libraries_.clear();
|
||||
}
|
||||
|
||||
|
||||
QList<QPair<QString, SeafileTree::Entry>> SeafileTree::GetRecursiveFilesOfDir(const QString &path, const TreeItem *item) {
|
||||
QList<QPair<QString, SeafileTree::Entry>> SeafileTree::GetRecursiveFilesOfDir(
|
||||
const QString& path, const TreeItem* item) {
|
||||
// key = path, value = entry
|
||||
QList<QPair<QString, Entry>> files;
|
||||
|
||||
if(!item) {
|
||||
if (!item) {
|
||||
return files;
|
||||
}
|
||||
|
||||
if(item->entry().is_file()) {
|
||||
if (item->entry().is_file()) {
|
||||
files.append(qMakePair(path, item->entry()));
|
||||
}
|
||||
// Get files of the dir
|
||||
else {
|
||||
for (TreeItem *child_item : item->childs()) {
|
||||
if(child_item->entry().is_file()) {
|
||||
for (TreeItem* child_item : item->children()) {
|
||||
if (child_item->entry().is_file()) {
|
||||
files.append(qMakePair(path, child_item->entry()));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
QString name = child_item->entry().name() + "/";
|
||||
files.append(GetRecursiveFilesOfDir(path + name, child_item));
|
||||
}
|
||||
|
@ -200,38 +202,25 @@ QList<QPair<QString, SeafileTree::Entry>> SeafileTree::GetRecursiveFilesOfDir(co
|
|||
|
||||
SeafileTree::~SeafileTree() {}
|
||||
|
||||
|
||||
|
||||
/* ################################# Entry ################################# */
|
||||
|
||||
SeafileTree::Entry::Entry()
|
||||
: Entry("", "", Type::FILE) {}
|
||||
|
||||
SeafileTree::Entry::Entry(const SeafileTree::Entry &entry)
|
||||
: Entry(entry.name(), entry.id(), entry.type()) {}
|
||||
|
||||
SeafileTree::Entry::Entry(const QString& name, const QString& id, const Type& type) {
|
||||
name_ = name;
|
||||
id_ = id;
|
||||
type_ = type;
|
||||
}
|
||||
|
||||
QString SeafileTree::Entry::name() const { return name_; }
|
||||
QString SeafileTree::Entry::id() const { return id_; }
|
||||
SeafileTree::Entry::Type SeafileTree::Entry::type() const { return type_; }
|
||||
bool SeafileTree::Entry::is_dir() const { return (type_ == Entry::DIR); }
|
||||
bool SeafileTree::Entry::is_file() const { return (type_ == Entry::FILE); }
|
||||
bool SeafileTree::Entry::is_library() const { return (type_ == Entry::LIBRARY); }
|
||||
void SeafileTree::Entry::set_name(const QString &name) { name_ = name; }
|
||||
void SeafileTree::Entry::set_id(const QString &id) { id_ = id; }
|
||||
void SeafileTree::Entry::set_type(const Type &type) { type_ = type; }
|
||||
|
||||
bool SeafileTree::Entry::is_library() const {
|
||||
return (type_ == Entry::LIBRARY);
|
||||
}
|
||||
void SeafileTree::Entry::set_name(const QString& name) { name_ = name; }
|
||||
void SeafileTree::Entry::set_id(const QString& id) { id_ = id; }
|
||||
void SeafileTree::Entry::set_type(const Type& type) { type_ = type; }
|
||||
|
||||
QString SeafileTree::Entry::ToString() const {
|
||||
return "name : " + name_ + " id : " + id_ + " type : " + TypeToString(type_);
|
||||
}
|
||||
|
||||
SeafileTree::Entry& SeafileTree::Entry::operator =(const Entry &entry) {
|
||||
SeafileTree::Entry& SeafileTree::Entry::operator=(const Entry& entry) {
|
||||
name_ = entry.name();
|
||||
id_ = entry.id();
|
||||
type_ = entry.type();
|
||||
|
@ -239,90 +228,81 @@ SeafileTree::Entry& SeafileTree::Entry::operator =(const Entry &entry) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
bool SeafileTree::Entry::operator ==(const Entry &a) const {
|
||||
if(a.name() == name() && a.id() == id() && a.type() == type())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
bool SeafileTree::Entry::operator==(const Entry& a) const {
|
||||
return a.name() == name() && a.id() == id() && a.type() == type();
|
||||
}
|
||||
|
||||
bool SeafileTree::Entry::operator !=(const Entry &a) const {
|
||||
return !(operator ==(a));
|
||||
bool SeafileTree::Entry::operator!=(const Entry& a) const {
|
||||
return !(operator==(a));
|
||||
}
|
||||
|
||||
SeafileTree::Entry::~Entry() {}
|
||||
|
||||
|
||||
QString SeafileTree::Entry::TypeToString(const Type &type) {
|
||||
if (type == DIR) {
|
||||
return "dir";
|
||||
QString SeafileTree::Entry::TypeToString(const Type& type) {
|
||||
switch (type) {
|
||||
case DIR:
|
||||
return "dir";
|
||||
case FILE:
|
||||
return "file";
|
||||
case LIBRARY:
|
||||
return "library";
|
||||
default:
|
||||
return QString::null;
|
||||
}
|
||||
else if (type == FILE) {
|
||||
return "file";
|
||||
}
|
||||
else if (type == LIBRARY) {
|
||||
return "library";
|
||||
}
|
||||
|
||||
return QString::null;
|
||||
}
|
||||
|
||||
SeafileTree::Entry::Type SeafileTree::Entry::StringToType(const QString &type) {
|
||||
if (type == "dir") {
|
||||
return DIR;
|
||||
}
|
||||
else if (type == "file") {
|
||||
return FILE;
|
||||
}
|
||||
else if (type == "library") {
|
||||
return LIBRARY;
|
||||
}
|
||||
SeafileTree::Entry::Type SeafileTree::Entry::StringToType(const QString& type) {
|
||||
if (type == "dir") {
|
||||
return DIR;
|
||||
} else if (type == "file") {
|
||||
return FILE;
|
||||
} else if (type == "library") {
|
||||
return LIBRARY;
|
||||
}
|
||||
|
||||
return NONE;
|
||||
return NONE;
|
||||
}
|
||||
|
||||
|
||||
/* ############################### TreeItem ############################### */
|
||||
|
||||
SeafileTree::TreeItem::TreeItem() { entry_ = Entry(); }
|
||||
|
||||
SeafileTree::TreeItem::TreeItem(const TreeItem ©) { entry_ = copy.entry(); }
|
||||
|
||||
SeafileTree::TreeItem::TreeItem(const Entry &entry) { entry_ = entry; }
|
||||
|
||||
SeafileTree::TreeItem::TreeItem(const Entry &entry, QList<TreeItem *> *childs) {
|
||||
entry_ = entry;
|
||||
childs_ = *childs;
|
||||
}
|
||||
|
||||
SeafileTree::Entries SeafileTree::TreeItem::childs_entry() const {
|
||||
SeafileTree::Entries SeafileTree::TreeItem::children_entries() const {
|
||||
Entries entries;
|
||||
|
||||
for (TreeItem *item : childs_) {
|
||||
for (TreeItem* item : children_) {
|
||||
entries.append(Entry(item->entry()));
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
SeafileTree::TreeItem* SeafileTree::TreeItem::child(int i) const { return childs_.at(i); }
|
||||
QList<SeafileTree::TreeItem*> SeafileTree::TreeItem::childs() const { return childs_; }
|
||||
SeafileTree::TreeItem* SeafileTree::TreeItem::child(int i) const {
|
||||
return children_.at(i);
|
||||
}
|
||||
QList<SeafileTree::TreeItem*> SeafileTree::TreeItem::children() const {
|
||||
return children_;
|
||||
}
|
||||
SeafileTree::Entry SeafileTree::TreeItem::entry() const { return entry_; }
|
||||
void SeafileTree::TreeItem::set_entry(const Entry &entry) { entry_ = entry;}
|
||||
void SeafileTree::TreeItem::set_childs(QList<TreeItem *> *childs) { childs_ = *childs; }
|
||||
|
||||
void SeafileTree::TreeItem::AppendChild(TreeItem *child) { childs_.append(child); }
|
||||
|
||||
void SeafileTree::TreeItem::AppendChild(const Entry &entry) {
|
||||
childs_.append(new TreeItem(entry));
|
||||
void SeafileTree::TreeItem::set_entry(const Entry& entry) { entry_ = entry; }
|
||||
void SeafileTree::TreeItem::set_children(const QList<TreeItem*>& children) {
|
||||
children_ = children;
|
||||
}
|
||||
|
||||
bool SeafileTree::TreeItem::RemoveChild(TreeItem *child) { return childs_.removeOne(child); }
|
||||
void SeafileTree::TreeItem::AppendChild(TreeItem* child) {
|
||||
children_.append(child);
|
||||
}
|
||||
|
||||
SeafileTree::TreeItem* SeafileTree::TreeItem::FindChild(const QString &name) const {
|
||||
for (TreeItem *item : childs_) {
|
||||
if (item->entry().name() == name)
|
||||
return item;
|
||||
void SeafileTree::TreeItem::AppendChild(const Entry& entry) {
|
||||
children_.append(new TreeItem(entry));
|
||||
}
|
||||
|
||||
bool SeafileTree::TreeItem::RemoveChild(TreeItem* child) {
|
||||
return children_.removeOne(child);
|
||||
}
|
||||
|
||||
SeafileTree::TreeItem* SeafileTree::TreeItem::FindChild(
|
||||
const QString& name) const {
|
||||
for (TreeItem* item : children_) {
|
||||
if (item->entry().name() == name) return item;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -337,31 +317,25 @@ QString SeafileTree::TreeItem::ToString(int i) const {
|
|||
|
||||
res += entry_.ToString() + "\n";
|
||||
|
||||
for (TreeItem *item : childs_) {
|
||||
res += item->ToString( i+1 );
|
||||
for (TreeItem* item : children_) {
|
||||
res += item->ToString(i + 1);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
SeafileTree::TreeItem::~TreeItem() {
|
||||
// We need to delete childs
|
||||
for (TreeItem *item : childs_) {
|
||||
delete item;
|
||||
}
|
||||
// We need to delete children
|
||||
qDeleteAll(children_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
QDataStream & operator << (QDataStream &out, const SeafileTree::Entry &entry) {
|
||||
out << entry.name_
|
||||
<< entry.id_
|
||||
<< static_cast<quint8>(entry.type_);
|
||||
QDataStream& operator<<(QDataStream& out, const SeafileTree::Entry& entry) {
|
||||
out << entry.name_ << entry.id_ << static_cast<quint8>(entry.type_);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream & operator >> (QDataStream &in, SeafileTree::Entry &entry) {
|
||||
QDataStream& operator>>(QDataStream& in, SeafileTree::Entry& entry) {
|
||||
quint8 temp;
|
||||
|
||||
in >> entry.name_;
|
||||
|
@ -372,34 +346,31 @@ QDataStream & operator >> (QDataStream &in, SeafileTree::Entry &entry) {
|
|||
return in;
|
||||
}
|
||||
|
||||
QDataStream & operator << (QDataStream &out, SeafileTree::TreeItem *item) {
|
||||
out << item->entry_
|
||||
<< item->childs_;
|
||||
QDataStream& operator<<(QDataStream& out, SeafileTree::TreeItem* item) {
|
||||
out << item->entry_ << item->children_;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream& operator>>(QDataStream& in, SeafileTree::TreeItem*& item) {
|
||||
SeafileTree::Entry entry;
|
||||
QList<SeafileTree::TreeItem*> children;
|
||||
|
||||
QDataStream & operator >> (QDataStream &in, SeafileTree::TreeItem *&item) {
|
||||
SeafileTree::Entry *entry = new SeafileTree::Entry();
|
||||
QList<SeafileTree::TreeItem*> *childs = new QList<SeafileTree::TreeItem*>;
|
||||
in >> entry;
|
||||
in >> children;
|
||||
|
||||
in >> *entry;
|
||||
in >> *childs;
|
||||
|
||||
item = new SeafileTree::TreeItem(*entry, childs);
|
||||
item = new SeafileTree::TreeItem(entry, children);
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
QDataStream & operator << (QDataStream &out, const SeafileTree &tree) {
|
||||
QDataStream& operator<<(QDataStream& out, const SeafileTree& tree) {
|
||||
out << tree.libraries_;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream & operator >> (QDataStream &in, SeafileTree &tree) {
|
||||
QDataStream& operator>>(QDataStream& in, SeafileTree& tree) {
|
||||
in >> tree.libraries_;
|
||||
|
||||
return in;
|
||||
|
|
|
@ -17,54 +17,48 @@
|
|||
class SeafileTree : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
public:
|
||||
SeafileTree();
|
||||
SeafileTree(const SeafileTree ©);
|
||||
SeafileTree(const SeafileTree& copy);
|
||||
~SeafileTree();
|
||||
|
||||
class Entry {
|
||||
public:
|
||||
enum Type { DIR = 0, FILE = 1, LIBRARY = 2, NONE = 3 };
|
||||
|
||||
public:
|
||||
|
||||
enum Type {
|
||||
DIR = 0,
|
||||
FILE = 1,
|
||||
LIBRARY = 2,
|
||||
NONE = 3
|
||||
};
|
||||
|
||||
Entry();
|
||||
Entry(const Entry &entry);
|
||||
Entry(const QString &name, const QString &id, const Type &type);
|
||||
Entry(const QString& name = QString(), const QString& id = QString(),
|
||||
const Type& type = NONE)
|
||||
: name_(name), id_(id), type_(type) {}
|
||||
Entry(const Entry& entry) : Entry(entry.name(), entry.id(), entry.type()) {}
|
||||
~Entry();
|
||||
|
||||
QString name() const;
|
||||
void set_name(const QString &name);
|
||||
void set_name(const QString& name);
|
||||
QString id() const;
|
||||
void set_id(const QString &id);
|
||||
void set_id(const QString& id);
|
||||
Type type() const;
|
||||
void set_type(const Type &type);
|
||||
void set_type(const Type& type);
|
||||
|
||||
bool is_dir() const;
|
||||
bool is_file() const;
|
||||
bool is_library() const;
|
||||
|
||||
Entry& operator =(const Entry &entry);
|
||||
bool operator ==(const Entry &a) const;
|
||||
bool operator !=(const Entry &a) const;
|
||||
Entry& operator=(const Entry& entry);
|
||||
bool operator==(const Entry& a) const;
|
||||
bool operator!=(const Entry& a) const;
|
||||
|
||||
QString ToString() const;
|
||||
|
||||
static QString TypeToString(const Type &type);
|
||||
static Type StringToType(const QString &type);
|
||||
static QString TypeToString(const Type& type);
|
||||
static Type StringToType(const QString& type);
|
||||
|
||||
private:
|
||||
private:
|
||||
QString name_, id_;
|
||||
Type type_;
|
||||
|
||||
friend QDataStream & operator << (QDataStream &out, const SeafileTree::Entry &entry);
|
||||
friend QDataStream & operator >> (QDataStream &in, SeafileTree::Entry &entry);
|
||||
friend QDataStream& operator<<(QDataStream& out,
|
||||
const SeafileTree::Entry& entry);
|
||||
friend QDataStream& operator>>(QDataStream& in, SeafileTree::Entry& entry);
|
||||
};
|
||||
|
||||
typedef QList<Entry> Entries;
|
||||
|
@ -72,61 +66,68 @@ public:
|
|||
// Node of the tree
|
||||
// Contains an entry
|
||||
class TreeItem {
|
||||
public:
|
||||
TreeItem();
|
||||
TreeItem(const TreeItem ©);
|
||||
TreeItem(const Entry &entry);
|
||||
TreeItem(const Entry &entry, QList<TreeItem *> *childs);
|
||||
public:
|
||||
TreeItem(const Entry& entry = Entry(),
|
||||
const QList<TreeItem*>& children = QList<TreeItem*>())
|
||||
: entry_(entry), children_(children) {}
|
||||
TreeItem(const TreeItem& copy) : TreeItem(copy.entry()) {}
|
||||
~TreeItem();
|
||||
|
||||
TreeItem* child(int i) const;
|
||||
QList<TreeItem*> childs() const;
|
||||
QList<TreeItem*> children() const;
|
||||
// List of each child's entry
|
||||
Entries childs_entry() const;
|
||||
Entries children_entries() const;
|
||||
|
||||
void set_childs(QList<TreeItem*> *childs);
|
||||
void set_children(const QList<TreeItem*>& children);
|
||||
|
||||
Entry entry() const;
|
||||
void set_entry(const Entry &entry);
|
||||
void set_entry(const Entry& entry);
|
||||
|
||||
void AppendChild(TreeItem *child);
|
||||
void AppendChild(const Entry &entry);
|
||||
void AppendChild(TreeItem* child);
|
||||
void AppendChild(const Entry& entry);
|
||||
|
||||
// True if child is removed
|
||||
bool RemoveChild(TreeItem *child);
|
||||
bool RemoveChild(TreeItem* child);
|
||||
|
||||
// nullptr if we didn't find a child entry with the given name
|
||||
TreeItem* FindChild(const QString &name) const;
|
||||
TreeItem* FindChild(const QString& name) const;
|
||||
|
||||
// Convert the node in QString (for debug)
|
||||
QString ToString(int i) const;
|
||||
|
||||
private:
|
||||
private:
|
||||
Entry entry_;
|
||||
QList<TreeItem*> childs_;
|
||||
QList<TreeItem*> children_;
|
||||
|
||||
friend QDataStream & operator << (QDataStream &out, SeafileTree::TreeItem *item);
|
||||
friend QDataStream & operator >> (QDataStream &in, SeafileTree::TreeItem *&item);
|
||||
friend QDataStream& operator<<(QDataStream& out,
|
||||
SeafileTree::TreeItem* item);
|
||||
friend QDataStream& operator>>(QDataStream& in,
|
||||
SeafileTree::TreeItem*& item);
|
||||
};
|
||||
|
||||
QList<TreeItem*> libraries() const;
|
||||
|
||||
void AddLibrary(const QString &name, const QString &id);
|
||||
void DeleteLibrary(const QString &id);
|
||||
bool AddEntry(const QString &library, const QString &path, const Entry &entry);
|
||||
bool DeleteEntry(const QString &library, const QString &path, const Entry &entry);
|
||||
void AddLibrary(const QString& name, const QString& id);
|
||||
void DeleteLibrary(const QString& id);
|
||||
bool AddEntry(const QString& library, const QString& path,
|
||||
const Entry& entry);
|
||||
bool DeleteEntry(const QString& library, const QString& path,
|
||||
const Entry& entry);
|
||||
|
||||
// Get a list of pair (path, entry) corresponding to the subfiles (and recursively to the subsubfiles...) of the given item
|
||||
QList<QPair<QString, SeafileTree::Entry>> GetRecursiveFilesOfDir(const QString &path, const TreeItem *item);
|
||||
// Get a list of pair (path, entry) corresponding to the subfiles (and
|
||||
// recursively to the subsubfiles...) of the given item
|
||||
QList<QPair<QString, SeafileTree::Entry>> GetRecursiveFilesOfDir(
|
||||
const QString& path, const TreeItem* item);
|
||||
|
||||
// nullptr if we didn't find the library with the given id
|
||||
TreeItem* FindLibrary(const QString &library);
|
||||
TreeItem* FindLibrary(const QString& library);
|
||||
// nullptr if we didn't find the item
|
||||
TreeItem* FindFromAbsolutePath(const QString &library, const QString &path);
|
||||
TreeItem* FindFromAbsolutePath(const QString& library, const QString& path);
|
||||
|
||||
// Compare the server entries with the tree
|
||||
// Emit signals (ToDelete, ToAdd, ToUpdate)
|
||||
void CheckEntries(const Entries &server_entries, const Entry &library, const QString &path);
|
||||
void CheckEntries(const Entries& server_entries, const Entry& library,
|
||||
const QString& path);
|
||||
|
||||
// Destroy the tree
|
||||
void Clear();
|
||||
|
@ -136,27 +137,29 @@ public:
|
|||
|
||||
signals:
|
||||
// Entry to delete in the tree
|
||||
void ToDelete(const QString &library, const QString &path, const SeafileTree::Entry &entry);
|
||||
void ToDelete(const QString& library, const QString& path,
|
||||
const SeafileTree::Entry& entry);
|
||||
// Entry to add in the tree
|
||||
void ToAdd(const QString &library, const QString &path, const SeafileTree::Entry &entry);
|
||||
void ToAdd(const QString& library, const QString& path,
|
||||
const SeafileTree::Entry& entry);
|
||||
// Entry to update in the tree
|
||||
void ToUpdate(const QString &library, const QString &path, const SeafileTree::Entry &entry);
|
||||
void ToUpdate(const QString& library, const QString& path,
|
||||
const SeafileTree::Entry& entry);
|
||||
|
||||
private:
|
||||
private:
|
||||
QList<TreeItem*> libraries_;
|
||||
|
||||
friend QDataStream & operator << (QDataStream &out, const SeafileTree &tree);
|
||||
friend QDataStream & operator >> (QDataStream &in, SeafileTree &tree);
|
||||
friend QDataStream& operator<<(QDataStream& out, const SeafileTree& tree);
|
||||
friend QDataStream& operator>>(QDataStream& in, SeafileTree& tree);
|
||||
};
|
||||
|
||||
QDataStream & operator << (QDataStream &out, const SeafileTree &tree);
|
||||
QDataStream & operator >> (QDataStream &in, SeafileTree &tree);
|
||||
QDataStream& operator<<(QDataStream& out, const SeafileTree& tree);
|
||||
QDataStream& operator>>(QDataStream& in, SeafileTree& tree);
|
||||
|
||||
QDataStream & operator << (QDataStream &out, const SeafileTree::Entry &entry);
|
||||
QDataStream & operator >> (QDataStream &in, SeafileTree::Entry &entry);
|
||||
|
||||
QDataStream & operator << (QDataStream &out, SeafileTree::TreeItem *item);
|
||||
QDataStream & operator >> (QDataStream &in, SeafileTree::TreeItem *&item);
|
||||
QDataStream& operator<<(QDataStream& out, const SeafileTree::Entry& entry);
|
||||
QDataStream& operator>>(QDataStream& in, SeafileTree::Entry& entry);
|
||||
|
||||
QDataStream& operator<<(QDataStream& out, SeafileTree::TreeItem* item);
|
||||
QDataStream& operator>>(QDataStream& in, SeafileTree::TreeItem*& item);
|
||||
|
||||
#endif // SEAFILETREE_H
|
||||
|
|
Loading…
Reference in New Issue