Commit c1cc4a3b authored by Camilo Higuita's avatar Camilo Higuita

solve sh*tload of problems on initial scan and move away from kirigami desktop...

solve sh*tload of problems on initial scan and move away from kirigami desktop style to material ultil issues get solved
parent a9189460
......@@ -119,9 +119,8 @@ HEADERS += \
#TAGLIB
linux:unix:!android {
linux:unix:!macx:!android {
message(Searching local TagLib lib)
LIBS += -ltag
} else:android {
......
......@@ -52,9 +52,9 @@ Babe::Babe(QObject *parent) : CollectionDB(parent)
connect(bDebug::Instance(), SIGNAL(debug(QString)), this, SLOT(debug(QString)));
connect(settings, &BabeSettings::refreshTables, [this](QVariantMap tables)
connect(settings, &BabeSettings::refreshTables, [this](int size)
{
emit this->refreshTables(tables);
emit this->refreshTables(size);
});
#if (defined (Q_OS_LINUX) && !defined (Q_OS_ANDROID))
......@@ -113,7 +113,6 @@ void Babe::set(const QString &table, const QVariantList &wheres)
this->thread->start(table, wheres);
}
void Babe::trackPlaylist(const QStringList &urls, const QString &playlist)
{
QVariantList data;
......@@ -693,24 +692,16 @@ QVariantMap Babe::getParentDir(const QString &path)
return {{"url", path}, {"name", QFileInfo(path).dir().dirName()}};
}
void Babe::registerTypes()
QStringList Babe::defaultSources()
{
qmlRegisterUncreatableType<Babe>("Babe", 1, 0, "Babe", "ERROR ABE");
return BAE::defaultSources;
}
uint Babe::sizeHint(const uint &hint)
void Babe::registerTypes()
{
if(hint>=BAE::BIG_ALBUM_FACTOR)
return BAE::getWidgetSizeHint(BAE::AlbumSizeHint::BIG_ALBUM);
else if(hint>=BAE::MEDIUM_ALBUM_FACTOR)
return BAE::getWidgetSizeHint(BAE::AlbumSizeHint::MEDIUM_ALBUM);
else if(hint>=BAE::SMALL_ALBUM_FACTOR)
return BAE::getWidgetSizeHint(BAE::AlbumSizeHint::SMALL_ALBUM);
else return hint;
qmlRegisterUncreatableType<Babe>("Babe", 1, 0, "Babe", "ERROR ABE");
}
QString Babe::loadCover(const QString &url)
{
auto map = getDBData(QStringList() << url);
......
......@@ -104,8 +104,9 @@ public:
Q_INVOKABLE static QVariantList getDirs(const QString &pathUrl);
Q_INVOKABLE static QVariantMap getParentDir(const QString &path);
Q_INVOKABLE static QStringList defaultSources();
static void registerTypes();
Q_INVOKABLE static uint sizeHint(const uint &hint);
/*USEFUL*/
Q_INVOKABLE QString loadCover(const QString &url);
......@@ -144,7 +145,7 @@ private:
void fetchTrackLyrics(DB &song);
signals:
void refreshTables(QVariantMap tables);
void refreshTables(int size);
void trackLyricsReady(QString lyrics, QString url);
void skipTrack();
void babeIt();
......
......@@ -833,23 +833,27 @@ QSqlQuery CollectionDB::getQuery(const QString &queryTxt)
return QSqlQuery(queryTxt, this->m_db);
}
bool CollectionDB::removeSource(const QString &path)
bool CollectionDB::removeSource(const QString &url)
{
auto path = url.endsWith("/") ? url.chopped(1) : url;
auto queryTxt = QString("DELETE FROM %1 WHERE %2 LIKE \"%3%\"").arg(TABLEMAP[TABLE::TRACKS],
KEYMAP[KEY::SOURCES_URL],path);
qDebug() << queryTxt;
auto query = this->getQuery(queryTxt);
if(query.exec())
{
{
queryTxt = QString("DELETE FROM %1 WHERE %2 LIKE \"%3%\"").arg(TABLEMAP[TABLE::SOURCES],
KEYMAP[KEY::URL],path);
query.prepare(queryTxt);
if(query.exec())
{
this->removeFolder(path);
if(cleanAlbums()) cleanArtists();
return true;
}
}
return false;
}
......@@ -930,6 +934,16 @@ bool CollectionDB::removePlaylist(const QString &playlist)
return query.exec();
}
void CollectionDB::removeMissingTracks()
{
auto tracks = this->getDBData("select url from tracks");
for(auto track : tracks)
if(!BAE::fileExists(track[BAE::KEY::URL]))
this->removeTrack(track[BAE::KEY::URL]);
}
bool CollectionDB::removeArtist(const QString &artist)
{
auto queryTxt = QString("DELETE FROM %1 WHERE %2 = \"%3\" ").arg(TABLEMAP[TABLE::ARTISTS],
......@@ -954,6 +968,18 @@ bool CollectionDB::cleanArtists()
return query.exec();
}
bool CollectionDB::removeFolder(const QString &url)
{
auto queryTxt=QString("DELETE FROM %1 WHERE %2 LIKE \"%3%\"").arg(
TABLEMAP[TABLE::FOLDERS],
KEYMAP[KEY::URL], url);
qDebug()<<queryTxt;
auto query = this->getQuery(queryTxt);
return query.exec();
}
bool CollectionDB::removeAlbum(const QString &album, const QString &artist)
{
auto queryTxt = QString("DELETE FROM %1 WHERE %2 = \"%3\" AND %4 = \"%5\"").arg(TABLEMAP[TABLE::ALBUMS],
......
......@@ -67,6 +67,7 @@ public:
Q_INVOKABLE bool addPlaylist(const QString &title);
bool addFolder(const QString &url);
bool removeFolder(const QString &url);
BAE::DB_LIST getDBData(const QStringList &urls);
BAE::DB_LIST getDBData(const QString &queryTxt);
......@@ -95,11 +96,12 @@ public:
Q_INVOKABLE bool removePlaylistTrack(const QString &url, const QString &playlist);
Q_INVOKABLE bool removePlaylist(const QString &playlist);
Q_INVOKABLE void removeMissingTracks();
bool removeArtist(const QString &artist);
bool cleanArtists();
bool removeAlbum(const QString &album, const QString &artist);
bool cleanAlbums();
Q_INVOKABLE bool removeSource(const QString &path);
Q_INVOKABLE bool removeSource(const QString &url);
Q_INVOKABLE bool removeTrack(const QString &path);
QSqlQuery getQuery(const QString &queryTxt);
/*useful tools*/
......
......@@ -48,25 +48,28 @@ int main(int argc, char *argv[])
return 0;
}
Player player;
Babe bae;
QFontDatabase::addApplicationFont(":/utils/materialdesignicons-webfont.ttf");
// QQuickStyle::setStyle("org.kde.desktop");
QQuickStyle::setStyle("Material");
QQmlApplicationEngine engine;
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, [&]()
{
qDebug()<<"FINISHED LOADING QML APP";
bae.refreshCollection();
});
auto context = engine.rootContext();
context->setContextProperty("player", &player);
context->setContextProperty("bae", &bae);
#ifdef Q_OS_ANDROID
// NotificationClient *notificationClient = new NotificationClient(&engine);
// context->setContextProperty(QLatin1String("notificationClient"), notificationClient);
#ifdef Q_OS_ANDROID
KirigamiPlugin::getInstance().registerTypes();
#endif
Babe bae;
Player player;
context->setContextProperty("bae", &bae);
context->setContextProperty("player", &player);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
......
......@@ -20,6 +20,7 @@ import "view_models/BabeDialog"
import "db/Queries.js" as Q
import "utils/Player.js" as Player
import "utils/Help.js" as H
Kirigami.ApplicationWindow
{
......@@ -186,13 +187,6 @@ Kirigami.ApplicationWindow
missingDialog.open()
}
Component.onCompleted:
{
if(isMobile) settingsDrawer.switchColorScheme(bae.loadSetting("THEME", "BABE", "Dark"))
settingsDrawer.close()
}
/*COMPONENTS*/
BabeNotify { id: babeNotify }
......@@ -207,49 +201,7 @@ Kirigami.ApplicationWindow
mainPlaylist.table.model.remove(mainPlaylist.table.currentIndex)
}
}
/*CONNECTIONS*/
Connections
{
target: player
onPos: progressBar.value = pos
onTiming: progressTimeLabel = time
onDurationChanged: durationTimeLabel = time
onFinished:
{
bae.playedTrack(currentTrack.url)
Player.nextTrack()
}
onIsPlaying: isPlaying = playing
}
Connections
{
target: bae
onRefreshTables:
{
console.log("Clearing tables")
tracksView.clearTable()
albumsView.clearGrid()
artistsView.clearGrid()
tracksView.populate()
albumsView.populate()
artistsView.populate()
}
onTrackLyricsReady:
{
if(url === currentTrack.url)
Player.setLyrics(lyrics)
}
onSkipTrack: Player.nextTrack()
onBabeIt: Player.babeTrack()
}
}
/* UI */
header: BabeBar
......@@ -723,7 +675,7 @@ Kirigami.ApplicationWindow
width: parent.width
height: parent.height
Component.onCompleted: contentItem.interactive = root.isMobile
Component.onCompleted: contentItem.interactive = isMobile
currentIndex: currentView
......@@ -887,4 +839,41 @@ Kirigami.ApplicationWindow
animTxt.running = true
}
Component.onCompleted:
{
if(isMobile) settingsDrawer.switchColorScheme(bae.loadSetting("THEME", "BABE", "Dark"))
}
/*CONNECTIONS*/
Connections
{
target: player
onPos: progressBar.value = pos
onTiming: progressTimeLabel = time
onDurationChanged: durationTimeLabel = time
onFinished:
{
bae.playedTrack(currentTrack.url)
Player.nextTrack()
}
onIsPlaying: isPlaying = playing
}
Connections
{
target: bae
onRefreshTables: H.refreshCollection(size)
onTrackLyricsReady:
{
if(url === currentTrack.url)
Player.setLyrics(lyrics)
}
onSkipTrack: Player.nextTrack()
onBabeIt: Player.babeTrack()
}
}
#include "player.h"
#include <QMediaMetaData>
#include "../../utils/bae.h"
Player::Player(QObject *parent) : QObject(parent)
{
this->player = new QMediaPlayer(this);
connect(player, &QMediaPlayer::durationChanged, this, [&](qint64 dur) {
connect(player, &QMediaPlayer::durationChanged, this, [&](qint64 dur)
{
emit this->durationChanged(BAE::transformTime(dur/1000));
});
......@@ -18,7 +20,12 @@ Player::Player(QObject *parent) : QObject(parent)
void Player::source(const QString &url)
{
this->sourceurl = url;
this->player->setMedia(QUrl::fromLocalFile(this->sourceurl));
auto media = QMediaContent(QUrl::fromLocalFile(this->sourceurl));
qDebug()<<this->player->mediaStatus();
this->player->setMedia(media);
qDebug()<<this->player->mediaStatus();
}
bool Player::play()
......@@ -85,7 +92,7 @@ void Player::update()
}
emit this->isPlaying(this->player->state() == QMediaPlayer::PlayingState ? true : false);
if(this->player->state() == QMediaPlayer::StoppedState)
if(this->player->state() == QMediaPlayer::StoppedState)
emit this->finished();
}
......@@ -18,61 +18,48 @@
#include "taginfo.h"
#include "../../utils/bae.h"
#if (defined (Q_OS_LINUX) && !defined (Q_OS_ANDROID))
#include <taglib/tag.h>
#include <taglib/fileref.h>
#endif
#if defined(Q_OS_ANDROID)
#include <./3rdparty/taglib/tag.h>
#include <./3rdparty/taglib/fileref.h>
#endif
using namespace BAE;
TagInfo::TagInfo(QObject *parent) : QObject(parent)
{}
TagInfo::~TagInfo()
{
}
{}
void TagInfo::feed(const QString &url)
bool TagInfo::feed(const QString &url)
{
this->path = url;
this->file = new TagLib::FileRef(path.toUtf8());
this->file = TagLib::FileRef(path.toUtf8());
return !file.isNull();
}
QString TagInfo::getAlbum() const
{
return !QString::fromStdWString(file->tag()->album().toWString()).isEmpty()
? QString::fromStdWString(file->tag()->album().toWString())
return !QString::fromStdWString(file.tag()->album().toWString()).isEmpty()
? QString::fromStdWString(file.tag()->album().toWString())
: SLANG[W::UNKNOWN];
}
QString TagInfo::getTitle() const
{
return !QString::fromStdWString(file->tag()->title().toWString()).isEmpty()
? QString::fromStdWString(file->tag()->title().toWString())
return !QString::fromStdWString(file.tag()->title().toWString()).isEmpty()
? QString::fromStdWString(file.tag()->title().toWString())
: fileName();
}
QString TagInfo::getArtist() const
{
return QString::fromStdWString(file->tag()->artist().toWString()).size() > 0
? QString::fromStdWString(file->tag()->artist().toWString())
return QString::fromStdWString(file.tag()->artist().toWString()).size() > 0
? QString::fromStdWString(file.tag()->artist().toWString())
: SLANG[W::UNKNOWN];
}
int TagInfo::getTrack() const { return static_cast<signed int>(file->tag()->track()); }
int TagInfo::getTrack() const { return static_cast<signed int>(file.tag()->track()); }
QString TagInfo::getGenre() const
{
return QString::fromStdWString(file->tag()->genre().toWString()).size() > 0
? QString::fromStdWString(file->tag()->genre().toWString())
return QString::fromStdWString(file.tag()->genre().toWString()).size() > 0
? QString::fromStdWString(file.tag()->genre().toWString())
: SLANG[W::UNKNOWN];
}
......@@ -84,20 +71,20 @@ QString TagInfo::fileName() const
uint TagInfo::getYear() const
{
//return BAE::getNameFromLocation(path);
return file->tag()->year();
return file.tag()->year();
}
int TagInfo::getDuration() const
{
return file->audioProperties()->length();
return file.audioProperties()->length();
}
QString TagInfo::getComment() const
{
return QString::fromStdWString(file->tag()->comment().toWString()).size() > 0
? QString::fromStdWString(file->tag()->genre().toWString())
return QString::fromStdWString(file.tag()->comment().toWString()).size() > 0
? QString::fromStdWString(file.tag()->genre().toWString())
: SLANG[W::UNKNOWN];
}
......@@ -116,38 +103,38 @@ void TagInfo::setCover(const QByteArray &array)
void TagInfo::setComment(const QString &comment)
{
this->file->tag()->setComment(comment.toStdString());
this->file->save();
this->file.tag()->setComment(comment.toStdString());
this->file.save();
}
void TagInfo::setAlbum(const QString &album)
{
this->file->tag()->setAlbum(album.toStdString());
this->file->save();
this->file.tag()->setAlbum(album.toStdString());
this->file.save();
}
void TagInfo::setTitle(const QString &title)
{
this->file->tag()->setTitle(title.toStdString());
this->file->save();
this->file.tag()->setTitle(title.toStdString());
this->file.save();
}
void TagInfo::setTrack(const int &track)
{
this->file->tag()->setTrack(static_cast<unsigned int>(track));
this->file->save();
this->file.tag()->setTrack(static_cast<unsigned int>(track));
this->file.save();
}
void TagInfo::setArtist(const QString &artist)
{
this->file->tag()->setArtist(artist.toStdString());
this->file->save();
this->file.tag()->setArtist(artist.toStdString());
this->file.save();
}
void TagInfo::setGenre(const QString &genre)
{
this->file->tag()->setGenre(genre.toStdString());
this->file->save();
this->file.tag()->setGenre(genre.toStdString());
this->file.save();
}
#ifndef TAGINFO_H
#define TAGINFO_H
#include <QString>
#include <QByteArray>
#include <QObject>
#if (defined (Q_OS_LINUX) && !defined (Q_OS_ANDROID))
#include <taglib/tag.h>
#include <taglib/fileref.h>
#endif
#if defined(Q_OS_ANDROID)
#include <./3rdparty/taglib/tag.h>
#include <./3rdparty/taglib/fileref.h>
#endif
namespace TagLib {
class FileRef;
}
......@@ -18,7 +26,7 @@ class TagInfo : public QObject
public:
TagInfo(QObject *parent = nullptr);
~TagInfo();
void feed(const QString &url);
bool feed(const QString &url);
QString getAlbum() const;
QString getTitle() const;
QString getArtist() const;
......@@ -38,9 +46,8 @@ public:
void setComment(const QString &comment);
void setCover(const QByteArray &array);
private:
TagLib::FileRef *file;
TagLib::FileRef file;
QString path;
};
......
......@@ -62,15 +62,6 @@ BabeSettings::BabeSettings(QObject *parent) : QObject(parent)
if (!youtubeCache_dir.exists())
youtubeCache_dir.mkpath(".");
// if(!connection->check_existance(TABLEMAP[TABLE::SOURCES], KEYMAP[KEY::URL], BAE::MusicPath))
if(BAE::isMobile())
this->populateDB(QStringList()<<BAE::MusicPath<<BAE::DownloadsPath<<BAE::MusicPaths<<BAE::DownloadsPaths);
else
this->populateDB({BAE::MusicPath, BAE::YoutubeCachePath});
// checkCollectionBrainz(BAE::loadSettings("BRAINZ", "BABE", false).toBool());
connect(this->ytFetch, &YouTube::done, [this]()
{
this->startBrainz(true, BAE::SEG::THREE);
......@@ -91,41 +82,23 @@ BabeSettings::BabeSettings(QObject *parent) : QObject(parent)
connect(this->brainDeamon, &Brain::done, [this](const TABLE type)
{
emit this->refreshTables({{BAE::TABLEMAP[type], true}});
emit this->refreshTables(0);
});
// connect(this->fileLoader, &FileLoader::trackReady, [this]()
// {
// this->ui->progressBar->setValue(this->ui->progressBar->value()+1);
// });
connect(this->fileLoader, &FileLoader::finished,[this](int size)
{
if(size > 0)
{
this->collectionWatcher();
emit refreshTables({{BAE::TABLEMAP[TABLE::TRACKS], true},
{BAE::TABLEMAP[TABLE::ALBUMS], true},
{BAE::TABLEMAP[TABLE::ARTISTS], true},
{BAE::TABLEMAP[TABLE::PLAYLISTS], true}});
// this->startBrainz(true, BAE::SEG::ONEHALF);
bDebug::Instance()->msg("Finished inserting into DB");
this->startBrainz(true, BAE::SEG::ONEHALF);
bDebug::Instance()->msg("Finished inserting into DB "+QString::number(size)+" tracks");
bDebug::Instance()->msg("Starting Brainz with interval: " + QString::number(BAE::SEG::ONEHALF));
}else
{
this->dirs.clear();
this->collectionWatcher();
this->watcher->removePaths(watcher->directories());
this->startBrainz(BAE::loadSettings("BRAINZ", "BABE", false).toBool(), BAE::SEG::THREE);
}
emit refreshTables(size);
});
connect(this, &BabeSettings::collectionPathChanged, this, &BabeSettings::populateDB);
this->watcher = new QFileSystemWatcher(this);
connect(this->watcher, &QFileSystemWatcher::directoryChanged, this, &BabeSettings::handleDirectoryChanged);
}
BabeSettings::~BabeSettings()
......@@ -135,80 +108,12 @@ BabeSettings::~BabeSettings()
delete brainDeamon;
}
void BabeSettings::on_remove_clicked()
{
qDebug() << this->pathToRemove;
if (!this->pathToRemove.isEmpty())
{
if(this->connection->removeSource(this->pathToRemove))
{
this->refreshCollection();
this->dirs.clear();
this->collectionWatcher();
this->watcher->removePaths(watcher->directories());
emit refreshTables({{TABLEMAP[TABLE::TRACKS], true},
{TABLEMAP[TABLE::PLAYLISTS], true}});
}
}
}
void BabeSettings::refreshCollection()
{
this->populateDB(this->connection->getSourcesFolders());
}
void BabeSettings::addToWatcher(QStringList paths)
{
bDebug::Instance()->msg("Removed duplicated paths in watcher: "+paths.removeDuplicates());
if(!paths.isEmpty()) watcher->addPaths(paths);
}
void BabeSettings::collectionWatcher()
{
auto queryTxt = QString("SELECT %1 FROM %2").arg(BAE::KEYMAP[BAE::KEY::URL], BAE::TABLEMAP[BAE::TABLE::TRACKS]);
for (auto track : this->connection->getDBData(queryTxt))
{
auto location = track[BAE::KEY::URL];
if(!location.startsWith(BAE::YoutubeCachePath,Qt::CaseInsensitive)) //exclude the youtube cache folder
{
if (!this->dirs.contains(QFileInfo(location).dir().path()) && BAE::fileExists(location)) //check if parent dir isn't already in list and it exists
{
QString dir = QFileInfo(location).dir().path();
this->dirs << dir;
QDirIterator it(dir, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); // get all the subdirectories to watch
while (it.hasNext())
{
QString subDir = QFileInfo(it.next()).path();
if(QFileInfo(subDir).isDir() && !this->dirs.contains(subDir) && BAE::fileExists(subDir))
this->dirs <<subDir;
}
}
}
}
this->addToWatcher(this->dirs);
}
void BabeSettings::handleDirectoryChanged(const QString &dir)
{
bDebug::Instance()->msg("directory changed:"+dir);
auto wait = new QTimer(this);
wait->setSingleShot(true);
wait->setInterval(1500);
connect(wait, &QTimer::timeout,[=]()
{
emit collectionPathChanged({dir});
wait->deleteLater();
});
wait->start();
{
if(this->connection->getSourcesFolders().isEmpty())
this->populateDB(BAE::defaultSources);
else
this->populateDB(this->connection->getSourcesFolders());
}
void BabeSettings::checkCollectionBrainz(const bool &state)
......
......@@ -32,18 +32,12 @@ public:
explicit BabeSettings(QObject *parent = nullptr);
~BabeSettings();
void checkCollectionBrainz(const bool &state);
void collectionWatcher();
void refreshCollection();
private slots:
void handleDirectoryChanged(const QString &dir);
void on_remove_clicked();
public slots:
void startBrainz(const bool &on, const uint &speed = BAE::SEG::THREE);
void populateDB(const QStringList &paths);
private:
FileLoader *fileLoader;
CollectionDB *connection;
......@@ -51,18 +45,9 @@ private:
YouTube *ytFetch;
Socket