2021-04-02 17:06:27 +02:00
/**
2021-04-03 19:29:40 +02:00
* SPDX - FileCopyrightText : 2021 Bart De Vries < bart @ mogwai . be >
2021-04-02 17:06:27 +02:00
*
* SPDX - License - Identifier : GPL - 2.0 - only OR GPL - 3.0 - only OR LicenseRef - KDE - Accepted - GPL
*/
2021-04-02 22:31:34 +02:00
# include <QDateTime>
# include <QDir>
# include <QSqlDatabase>
# include <QSqlError>
# include <QStandardPaths>
# include <QUrl>
# include <QXmlStreamReader>
# include <QXmlStreamWriter>
2021-04-02 17:06:27 +02:00
# include "datamanager.h"
# include "fetcher.h"
# include "database.h"
2021-04-10 08:46:14 +02:00
# include "settingsmanager.h"
2021-04-02 17:06:27 +02:00
DataManager : : DataManager ( )
{
2021-04-02 22:31:34 +02:00
connect ( & Fetcher : : instance ( ) , & Fetcher : : feedDetailsUpdated , this , [ this ] ( const QString & url , const QString & name , const QString & image , const QString & link , const QString & description , const QDateTime & lastUpdated ) {
2021-04-20 17:12:17 +02:00
//qDebug() << "Start updating feed details" << m_feeds;
2021-04-09 20:27:58 +02:00
Feed * feed = getFeed ( url ) ;
if ( feed ! = nullptr ) {
feed - > setName ( name ) ;
feed - > setImage ( image ) ;
feed - > setLink ( link ) ;
feed - > setDescription ( description ) ;
feed - > setLastUpdated ( lastUpdated ) ;
//qDebug() << "Retrieving authors";
2021-04-19 16:53:40 +02:00
feed - > updateAuthors ( ) ;
2021-04-09 20:27:58 +02:00
// TODO: signal feedmodel: Q_EMIT dataChanged(createIndex(i, 0), createIndex(i, 0));
2021-04-21 10:43:21 +02:00
// quite sure that this is actually not needed
2021-04-09 20:27:58 +02:00
}
2021-04-02 22:31:34 +02:00
} ) ;
2021-04-03 11:44:08 +02:00
connect ( & Fetcher : : instance ( ) , & Fetcher : : entryAdded , this , [ this ] ( const QString & feedurl , const QString & id ) {
// Only add the new entry to m_entries
// we will repopulate m_entrymap once all new entries have been added,
// such that m_entrymap will show all new entries in the correct order
m_entries [ id ] = nullptr ;
Q_EMIT entryAdded ( feedurl , id ) ;
} ) ;
connect ( & Fetcher : : instance ( ) , & Fetcher : : feedUpdated , this , [ this ] ( const QString & feedurl ) {
// Update m_entrymap for feedurl, such that the new and old entries show
// up in the correct order
// TODO: put this code into a separate method and re-use this in the constructor
QSqlQuery query ;
m_entrymap [ feedurl ] . clear ( ) ;
query . prepare ( QStringLiteral ( " SELECT id FROM Entries WHERE feed=:feed ORDER BY updated DESC; " ) ) ;
query . bindValue ( QStringLiteral ( " :feed " ) , feedurl ) ;
Database : : instance ( ) . execute ( query ) ;
while ( query . next ( ) ) {
m_entrymap [ feedurl ] + = query . value ( QStringLiteral ( " id " ) ) . toString ( ) ;
2021-04-05 12:43:35 +02:00
//qDebug() << m_entrymap[feedurl];
2021-04-03 11:44:08 +02:00
}
2021-04-09 21:43:29 +02:00
// Check for "new" entries
2021-04-10 08:46:14 +02:00
if ( SettingsManager : : self ( ) - > autoQueue ( ) ) {
2021-04-09 21:43:29 +02:00
query . prepare ( QStringLiteral ( " SELECT id FROM Entries WHERE feed=:feed AND new=:new; " ) ) ;
query . bindValue ( QStringLiteral ( " :feed " ) , feedurl ) ;
query . bindValue ( QStringLiteral ( " :new " ) , true ) ;
Database : : instance ( ) . execute ( query ) ;
while ( query . next ( ) ) {
2021-05-01 21:00:12 +02:00
QString id = query . value ( QStringLiteral ( " id " ) ) . toString ( ) ;
2021-04-15 23:10:40 +02:00
addToQueue ( feedurl , id ) ;
2021-04-10 08:46:14 +02:00
if ( SettingsManager : : self ( ) - > autoDownload ( ) ) {
if ( getEntry ( id ) - > hasEnclosure ( ) ) {
qDebug ( ) < < " Start downloading " < < getEntry ( id ) - > title ( ) ;
2021-04-09 23:39:41 +02:00
getEntry ( id ) - > enclosure ( ) - > download ( ) ;
2021-04-10 08:46:14 +02:00
}
2021-04-09 23:39:41 +02:00
}
2021-04-09 21:43:29 +02:00
}
}
2021-04-03 11:44:08 +02:00
Q_EMIT feedEntriesUpdated ( feedurl ) ;
2021-04-02 22:31:34 +02:00
} ) ;
2021-04-02 17:06:27 +02:00
// Only read unique feedurls and entry ids from the database.
2021-04-02 22:31:34 +02:00
// The feed and entry datastructures will be loaded lazily.
2021-04-02 17:06:27 +02:00
QSqlQuery query ;
query . prepare ( QStringLiteral ( " SELECT url FROM Feeds; " ) ) ;
Database : : instance ( ) . execute ( query ) ;
while ( query . next ( ) ) {
m_feedmap + = query . value ( QStringLiteral ( " url " ) ) . toString ( ) ;
2021-04-22 10:53:02 +02:00
m_feeds [ query . value ( QStringLiteral ( " url " ) ) . toString ( ) ] = nullptr ;
2021-04-02 17:06:27 +02:00
}
2021-04-05 12:43:35 +02:00
//qDebug() << m_feedmap;
2021-04-02 17:06:27 +02:00
for ( auto & feedurl : m_feedmap ) {
2021-04-03 11:44:08 +02:00
query . prepare ( QStringLiteral ( " SELECT id FROM Entries WHERE feed=:feed ORDER BY updated DESC; " ) ) ;
2021-04-02 17:06:27 +02:00
query . bindValue ( QStringLiteral ( " :feed " ) , feedurl ) ;
Database : : instance ( ) . execute ( query ) ;
while ( query . next ( ) ) {
m_entrymap [ feedurl ] + = query . value ( QStringLiteral ( " id " ) ) . toString ( ) ;
2021-04-03 11:44:08 +02:00
m_entries [ query . value ( QStringLiteral ( " id " ) ) . toString ( ) ] = nullptr ;
2021-04-05 12:43:35 +02:00
//qDebug() << m_entrymap[feedurl];
2021-04-02 17:06:27 +02:00
}
}
2021-04-05 12:43:35 +02:00
//qDebug() << m_entrymap;
2021-04-03 19:29:40 +02:00
query . prepare ( QStringLiteral ( " SELECT id FROM Queue ORDER BY listnr; " ) ) ;
Database : : instance ( ) . execute ( query ) ;
while ( query . next ( ) ) {
m_queuemap + = query . value ( QStringLiteral ( " id " ) ) . toString ( ) ;
}
2021-04-05 12:43:35 +02:00
//qDebug() << m_queuemap;
2021-04-02 17:06:27 +02:00
}
2021-05-01 21:00:12 +02:00
Feed * DataManager : : getFeed ( const int index ) const
2021-04-02 17:06:27 +02:00
{
return getFeed ( m_feedmap [ index ] ) ;
}
2021-05-01 21:00:12 +02:00
Feed * DataManager : : getFeed ( const QString & feedurl ) const
2021-04-02 17:06:27 +02:00
{
if ( m_feeds [ feedurl ] = = nullptr )
loadFeed ( feedurl ) ;
return m_feeds [ feedurl ] ;
}
2021-05-01 21:00:12 +02:00
Entry * DataManager : : getEntry ( const int feed_index , const int entry_index ) const
2021-04-02 22:31:34 +02:00
{
return getEntry ( m_entrymap [ m_feedmap [ feed_index ] ] [ entry_index ] ) ;
}
2021-05-01 21:00:12 +02:00
Entry * DataManager : : getEntry ( const Feed * feed , const int entry_index ) const
2021-04-02 22:31:34 +02:00
{
return getEntry ( m_entrymap [ feed - > url ( ) ] [ entry_index ] ) ;
}
2021-05-01 21:00:12 +02:00
Entry * DataManager : : getEntry ( const QString & id ) const
2021-04-02 22:31:34 +02:00
{
if ( m_entries [ id ] = = nullptr )
loadEntry ( id ) ;
return m_entries [ id ] ;
}
2021-04-17 22:54:35 +02:00
Entry * DataManager : : getEntry ( const EpisodeModel : : Type type , const int entry_index ) const
{
QSqlQuery entryQuery ;
2021-04-18 21:56:33 +02:00
if ( type = = EpisodeModel : : All | | type = = EpisodeModel : : New | | type = = EpisodeModel : : Unread | | type = = EpisodeModel : : Downloaded ) {
2021-04-17 22:54:35 +02:00
if ( type = = EpisodeModel : : New ) {
2021-04-18 21:56:33 +02:00
entryQuery . prepare ( QStringLiteral ( " SELECT id FROM Entries WHERE new=:new ORDER BY updated DESC LIMIT 1 OFFSET :index; " ) ) ;
2021-04-17 22:54:35 +02:00
entryQuery . bindValue ( QStringLiteral ( " :new " ) , true ) ;
2021-04-18 10:44:36 +02:00
} else if ( type = = EpisodeModel : : Unread ) {
2021-04-18 21:56:33 +02:00
entryQuery . prepare ( QStringLiteral ( " SELECT id FROM Entries WHERE read=:read ORDER BY updated DESC LIMIT 1 OFFSET :index; " ) ) ;
2021-04-18 10:44:36 +02:00
entryQuery . bindValue ( QStringLiteral ( " :read " ) , false ) ;
2021-04-18 21:56:33 +02:00
} else if ( type = = EpisodeModel : : All ) {
entryQuery . prepare ( QStringLiteral ( " SELECT id FROM Entries ORDER BY updated DESC LIMIT 1 OFFSET :index; " ) ) ;
} else { // i.e. EpisodeModel::Downloaded
entryQuery . prepare ( QStringLiteral ( " SELECT * FROM Enclosures INNER JOIN Entries ON Enclosures.id = Entries.id WHERE downloaded=:downloaded ORDER BY updated DESC LIMIT 1 OFFSET :index; " ) ) ;
entryQuery . bindValue ( QStringLiteral ( " :downloaded " ) , true ) ;
2021-04-17 22:54:35 +02:00
}
entryQuery . bindValue ( QStringLiteral ( " :index " ) , entry_index ) ;
Database : : instance ( ) . execute ( entryQuery ) ;
if ( ! entryQuery . next ( ) ) {
qWarning ( ) < < " No element with index " < < entry_index < < " found " ;
return nullptr ;
}
QString id = entryQuery . value ( QStringLiteral ( " id " ) ) . toString ( ) ;
return getEntry ( id ) ;
}
return nullptr ;
}
2021-04-02 22:31:34 +02:00
int DataManager : : feedCount ( ) const
{
return m_feedmap . count ( ) ;
}
int DataManager : : entryCount ( const int feed_index ) const
{
return m_entrymap [ m_feedmap [ feed_index ] ] . count ( ) ;
}
int DataManager : : entryCount ( const Feed * feed ) const
{
return m_entrymap [ feed - > url ( ) ] . count ( ) ;
}
2021-04-17 22:54:35 +02:00
int DataManager : : entryCount ( const EpisodeModel : : Type type ) const
{
QSqlQuery query ;
2021-04-18 21:56:33 +02:00
if ( type = = EpisodeModel : : All | | type = = EpisodeModel : : New | | type = = EpisodeModel : : Unread | | type = = EpisodeModel : : Downloaded ) {
2021-04-17 22:54:35 +02:00
if ( type = = EpisodeModel : : New ) {
query . prepare ( QStringLiteral ( " SELECT COUNT (id) FROM Entries WHERE new=:new; " ) ) ;
query . bindValue ( QStringLiteral ( " :new " ) , true ) ;
2021-04-18 10:44:36 +02:00
} else if ( type = = EpisodeModel : : Unread ) {
query . prepare ( QStringLiteral ( " SELECT COUNT (id) FROM Entries WHERE read=:read; " ) ) ;
query . bindValue ( QStringLiteral ( " :read " ) , false ) ;
2021-04-18 21:56:33 +02:00
} else if ( type = = EpisodeModel : : All ) {
2021-04-17 22:54:35 +02:00
query . prepare ( QStringLiteral ( " SELECT COUNT (id) FROM Entries; " ) ) ;
2021-04-18 21:56:33 +02:00
} else { // i.e. EpisodeModel::Downloaded
query . prepare ( QStringLiteral ( " SELECT COUNT (id) FROM Enclosures WHERE downloaded=:downloaded; " ) ) ;
query . bindValue ( QStringLiteral ( " :downloaded " ) , true ) ;
2021-04-17 22:54:35 +02:00
}
Database : : instance ( ) . execute ( query ) ;
if ( ! query . next ( ) )
return - 1 ;
return query . value ( 0 ) . toInt ( ) ;
}
return - 1 ;
}
2021-04-02 22:31:34 +02:00
int DataManager : : unreadEntryCount ( const Feed * feed ) const
{
QSqlQuery query ;
query . prepare ( QStringLiteral ( " SELECT COUNT (id) FROM Entries where feed=:feed AND read=0; " ) ) ;
query . bindValue ( QStringLiteral ( " :feed " ) , feed - > url ( ) ) ;
Database : : instance ( ) . execute ( query ) ;
if ( ! query . next ( ) )
return - 1 ;
return query . value ( 0 ) . toInt ( ) ;
}
2021-04-07 10:39:12 +02:00
int DataManager : : newEntryCount ( const Feed * feed ) const
{
QSqlQuery query ;
query . prepare ( QStringLiteral ( " SELECT COUNT (id) FROM Entries where feed=:feed AND new=1; " ) ) ;
query . bindValue ( QStringLiteral ( " :feed " ) , feed - > url ( ) ) ;
Database : : instance ( ) . execute ( query ) ;
if ( ! query . next ( ) )
return - 1 ;
return query . value ( 0 ) . toInt ( ) ;
}
2021-04-21 11:46:54 +02:00
void DataManager : : removeFeed ( Feed * feed )
2021-04-02 22:31:34 +02:00
{
2021-04-21 11:46:54 +02:00
qDebug ( ) < < feed - > url ( ) ;
qDebug ( ) < < " deleting feed with index " < < m_feedmap . indexOf ( feed - > url ( ) ) ;
2021-04-02 22:31:34 +02:00
removeFeed ( m_feedmap . indexOf ( feed - > url ( ) ) ) ;
}
2021-05-01 21:00:12 +02:00
void DataManager : : removeFeed ( const int index )
2021-04-02 22:31:34 +02:00
{
// Get feed pointer
2021-04-09 20:27:58 +02:00
Feed * feed = getFeed ( m_feedmap [ index ] ) ;
2021-04-03 21:39:20 +02:00
const QString feedurl = feed - > url ( ) ;
// Delete the object instances and mappings
// First delete entries in Queue
qDebug ( ) < < " delete queueentries of " < < feedurl ;
for ( auto & id : m_queuemap ) {
if ( getEntry ( id ) - > feed ( ) - > url ( ) = = feedurl ) {
removeQueueItem ( id ) ;
}
}
2021-04-02 22:31:34 +02:00
2021-04-03 21:39:20 +02:00
// Delete entries themselves
qDebug ( ) < < " delete entries of " < < feedurl ;
for ( auto & id : m_entrymap [ feedurl ] ) {
if ( getEntry ( id ) - > hasEnclosure ( ) ) getEntry ( id ) - > enclosure ( ) - > deleteFile ( ) ; // delete enclosure (if it exists)
2021-04-07 12:46:47 +02:00
if ( ! getEntry ( id ) - > image ( ) . isEmpty ( ) ) Fetcher : : instance ( ) . removeImage ( getEntry ( id ) - > image ( ) ) ; // delete entry images
2021-04-03 21:39:20 +02:00
delete m_entries [ id ] ; // delete pointer
m_entries . remove ( id ) ; // delete the hash key
}
m_entrymap . remove ( feedurl ) ; // remove all the entry mappings belonging to the feed
2021-04-07 12:46:47 +02:00
qDebug ( ) < < " Remove feed image " < < feed - > image ( ) < < " for feed " < < feedurl ;
2021-04-03 21:39:20 +02:00
if ( ! feed - > image ( ) . isEmpty ( ) ) Fetcher : : instance ( ) . removeImage ( feed - > image ( ) ) ;
m_feeds . remove ( m_feedmap [ index ] ) ; // remove from m_feeds
m_feedmap . removeAt ( index ) ; // remove from m_feedmap
2021-04-09 22:52:20 +02:00
delete feed ; // remove the pointer
2021-04-03 21:39:20 +02:00
// Then delete everything from the database
qDebug ( ) < < " delete database part of " < < feedurl ;
2021-04-02 22:31:34 +02:00
// Delete Authors
QSqlQuery query ;
query . prepare ( QStringLiteral ( " DELETE FROM Authors WHERE feed=:feed; " ) ) ;
2021-04-03 21:39:20 +02:00
query . bindValue ( QStringLiteral ( " :feed " ) , feedurl ) ;
2021-04-02 22:31:34 +02:00
Database : : instance ( ) . execute ( query ) ;
// Delete Entries
query . prepare ( QStringLiteral ( " DELETE FROM Entries WHERE feed=:feed; " ) ) ;
2021-04-03 21:39:20 +02:00
query . bindValue ( QStringLiteral ( " :feed " ) , feedurl ) ;
2021-04-02 22:31:34 +02:00
Database : : instance ( ) . execute ( query ) ;
// Delete Enclosures
query . prepare ( QStringLiteral ( " DELETE FROM Enclosures WHERE feed=:feed; " ) ) ;
2021-04-03 21:39:20 +02:00
query . bindValue ( QStringLiteral ( " :feed " ) , feedurl ) ;
2021-04-02 22:31:34 +02:00
Database : : instance ( ) . execute ( query ) ;
// Delete Feed
query . prepare ( QStringLiteral ( " DELETE FROM Feeds WHERE url=:url; " ) ) ;
2021-04-03 21:39:20 +02:00
query . bindValue ( QStringLiteral ( " :url " ) , feedurl ) ;
2021-04-02 22:31:34 +02:00
Database : : instance ( ) . execute ( query ) ;
2021-04-03 22:52:46 +02:00
Q_EMIT feedRemoved ( index ) ;
2021-04-02 22:31:34 +02:00
}
2021-04-21 10:43:21 +02:00
void DataManager : : addFeed ( const QString & url )
{
addFeed ( url , true ) ;
}
void DataManager : : addFeed ( const QString & url , const bool fetch )
2021-04-02 22:31:34 +02:00
{
2021-04-08 11:12:16 +02:00
// This method will add the relevant internal data structures, and then add
// a preliminary entry into the database. Those details (as well as entries,
// authors and enclosures) will be updated by calling Fetcher::fetch() which
// will trigger a full update of the feed and all related items.
2021-04-02 22:31:34 +02:00
qDebug ( ) < < " Adding feed " ;
if ( feedExists ( url ) ) {
qDebug ( ) < < " Feed already exists " ;
return ;
}
qDebug ( ) < < " Feed does not yet exist " ;
QUrl urlFromInput = QUrl : : fromUserInput ( url ) ;
QSqlQuery query ;
2021-04-09 17:03:02 +02:00
query . prepare ( QStringLiteral ( " INSERT INTO Feeds VALUES (:name, :url, :image, :link, :description, :deleteAfterCount, :deleteAfterType, :subscribed, :lastUpdated, :new, :notify); " ) ) ;
2021-04-02 22:31:34 +02:00
query . bindValue ( QStringLiteral ( " :name " ) , urlFromInput . toString ( ) ) ;
query . bindValue ( QStringLiteral ( " :url " ) , urlFromInput . toString ( ) ) ;
query . bindValue ( QStringLiteral ( " :image " ) , QLatin1String ( " " ) ) ;
query . bindValue ( QStringLiteral ( " :link " ) , QLatin1String ( " " ) ) ;
query . bindValue ( QStringLiteral ( " :description " ) , QLatin1String ( " " ) ) ;
query . bindValue ( QStringLiteral ( " :deleteAfterCount " ) , 0 ) ;
query . bindValue ( QStringLiteral ( " :deleteAfterType " ) , 0 ) ;
query . bindValue ( QStringLiteral ( " :subscribed " ) , QDateTime : : currentDateTime ( ) . toSecsSinceEpoch ( ) ) ;
query . bindValue ( QStringLiteral ( " :lastUpdated " ) , 0 ) ;
2021-04-09 17:03:02 +02:00
query . bindValue ( QStringLiteral ( " :new " ) , true ) ;
2021-04-02 22:31:34 +02:00
query . bindValue ( QStringLiteral ( " :notify " ) , false ) ;
Database : : instance ( ) . execute ( query ) ;
2021-04-09 20:27:58 +02:00
m_feeds [ urlFromInput . toString ( ) ] = nullptr ;
2021-04-02 22:31:34 +02:00
m_feedmap . append ( urlFromInput . toString ( ) ) ;
Q_EMIT feedAdded ( urlFromInput . toString ( ) ) ;
2021-04-20 21:14:19 +02:00
if ( fetch ) Fetcher : : instance ( ) . fetch ( urlFromInput . toString ( ) ) ;
}
void DataManager : : addFeeds ( const QStringList & urls )
{
if ( urls . count ( ) = = 0 ) return ;
for ( int i = 0 ; i < urls . count ( ) ; i + + ) {
addFeed ( urls [ i ] , false ) ; // add preliminary feed entries, but do not fetch yet
}
Fetcher : : instance ( ) . fetch ( urls ) ;
2021-04-02 22:31:34 +02:00
}
2021-05-01 21:00:12 +02:00
Entry * DataManager : : getQueueEntry ( int index ) const
2021-04-03 13:49:33 +02:00
{
return getEntry ( m_queuemap [ index ] ) ;
}
int DataManager : : queueCount ( ) const
{
return m_queuemap . count ( ) ;
}
2021-05-01 21:00:12 +02:00
QStringList DataManager : : queue ( ) const
2021-04-11 23:07:21 +02:00
{
return m_queuemap ;
}
2021-04-16 20:38:13 +02:00
bool DataManager : : entryInQueue ( const Entry * entry )
{
return entryInQueue ( entry - > feed ( ) - > url ( ) , entry - > id ( ) ) ;
}
2021-04-07 22:10:39 +02:00
bool DataManager : : entryInQueue ( const QString & feedurl , const QString & id ) const
{
Q_UNUSED ( feedurl ) ;
return m_queuemap . contains ( id ) ;
}
2021-04-15 23:10:40 +02:00
void DataManager : : addToQueue ( const Entry * entry )
{
if ( entry ! = nullptr ) {
return addToQueue ( entry - > feed ( ) - > url ( ) , entry - > id ( ) ) ;
}
}
void DataManager : : addToQueue ( const QString & feedurl , const QString & id )
2021-04-03 13:49:33 +02:00
{
2021-04-03 19:29:40 +02:00
// If item is already in queue, then stop here
if ( m_queuemap . contains ( id ) ) return ;
// Add to internal queuemap data structure
2021-04-03 13:49:33 +02:00
m_queuemap + = id ;
2021-04-05 12:43:35 +02:00
//qDebug() << m_queuemap;
2021-04-03 19:29:40 +02:00
// Get index of this entry
const int index = m_queuemap . indexOf ( id ) ; // add new entry to end of queue
// Add to Queue database
QSqlQuery query ;
2021-04-17 20:55:01 +02:00
query . prepare ( QStringLiteral ( " INSERT INTO Queue VALUES (:index, :feedurl, :id, :playing); " ) ) ;
2021-04-03 19:29:40 +02:00
query . bindValue ( QStringLiteral ( " :index " ) , index ) ;
query . bindValue ( QStringLiteral ( " :feedurl " ) , feedurl ) ;
query . bindValue ( QStringLiteral ( " :id " ) , id ) ;
2021-04-17 20:55:01 +02:00
query . bindValue ( QStringLiteral ( " :playing " ) , false ) ;
2021-04-03 19:29:40 +02:00
Database : : instance ( ) . execute ( query ) ;
// Make sure that the QueueModel is aware of the changes
Q_EMIT queueEntryAdded ( index , id ) ;
2021-04-03 13:49:33 +02:00
}
2021-05-01 21:00:12 +02:00
void DataManager : : moveQueueItem ( const int from , const int to )
2021-04-03 13:49:33 +02:00
{
2021-04-03 19:29:40 +02:00
// First move the items in the internal data structure
2021-04-03 13:49:33 +02:00
m_queuemap . move ( from , to ) ;
2021-04-03 19:29:40 +02:00
// Then make sure that the database Queue table reflects these changes
updateQueueListnrs ( ) ;
// Make sure that the QueueModel is aware of the changes so it can update
2021-04-03 13:49:33 +02:00
Q_EMIT queueEntryMoved ( from , to ) ;
}
2021-05-01 21:00:12 +02:00
void DataManager : : removeQueueItem ( const int index )
2021-04-03 19:29:40 +02:00
{
2021-04-21 11:46:54 +02:00
//qDebug() << m_queuemap;
2021-04-09 23:39:41 +02:00
// Unset "new" state
getEntry ( m_queuemap [ index ] ) - > setNew ( false ) ;
// TODO: Make sure to unset the pointer in the Audio class once it's been
// ported to c++
// Remove the item from the internal data structure
2021-04-03 19:29:40 +02:00
const QString id = m_queuemap [ index ] ;
m_queuemap . removeAt ( index ) ;
// Then make sure that the database Queue table reflects these changes
QSqlQuery query ;
query . prepare ( QStringLiteral ( " DELETE FROM Queue WHERE listnr=:listnr; " ) ) ;
query . bindValue ( QStringLiteral ( " :listnr " ) , index ) ;
Database : : instance ( ) . execute ( query ) ;
// ... and update all other listnrs in Queue table
updateQueueListnrs ( ) ;
// Make sure that the QueueModel is aware of the change so it can update
Q_EMIT queueEntryRemoved ( index , id ) ;
}
2021-04-03 21:39:20 +02:00
void DataManager : : removeQueueItem ( const QString id )
2021-04-03 19:29:40 +02:00
{
2021-04-03 21:39:20 +02:00
removeQueueItem ( m_queuemap . indexOf ( id ) ) ;
2021-04-03 19:29:40 +02:00
}
2021-04-07 22:10:39 +02:00
void DataManager : : removeQueueItem ( Entry * entry )
{
removeQueueItem ( m_queuemap . indexOf ( entry - > id ( ) ) ) ;
}
2021-04-09 23:39:41 +02:00
2021-04-17 20:55:01 +02:00
QString DataManager : : lastPlayingEntry ( )
{
QSqlQuery query ;
query . prepare ( QStringLiteral ( " SELECT id FROM Queue WHERE playing=:playing; " ) ) ;
query . bindValue ( QStringLiteral ( " :playing " ) , true ) ;
Database : : instance ( ) . execute ( query ) ;
if ( ! query . next ( ) ) return QStringLiteral ( " none " ) ;
return query . value ( QStringLiteral ( " id " ) ) . toString ( ) ;
}
void DataManager : : setLastPlayingEntry ( const QString & id )
{
QSqlQuery query ;
// First set playing to false for all Queue items
query . prepare ( QStringLiteral ( " UPDATE Queue SET playing=:playing; " ) ) ;
query . bindValue ( QStringLiteral ( " :playing " ) , false ) ;
Database : : instance ( ) . execute ( query ) ;
// Now set the correct track to playing=true
query . prepare ( QStringLiteral ( " UPDATE Queue SET playing=:playing WHERE id=:id; " ) ) ;
query . bindValue ( QStringLiteral ( " :playing " ) , true ) ;
query . bindValue ( QStringLiteral ( " :id " ) , id ) ;
Database : : instance ( ) . execute ( query ) ;
}
2021-04-02 22:31:34 +02:00
void DataManager : : importFeeds ( const QString & path )
{
QUrl url ( path ) ;
QFile file ( url . isLocalFile ( ) ? url . toLocalFile ( ) : url . toString ( ) ) ;
file . open ( QIODevice : : ReadOnly ) ;
2021-04-20 21:14:19 +02:00
QStringList urls ;
2021-04-02 22:31:34 +02:00
QXmlStreamReader xmlReader ( & file ) ;
while ( ! xmlReader . atEnd ( ) ) {
xmlReader . readNext ( ) ;
if ( xmlReader . tokenType ( ) = = 4 & & xmlReader . attributes ( ) . hasAttribute ( QStringLiteral ( " xmlUrl " ) ) ) {
2021-04-20 21:14:19 +02:00
urls + = xmlReader . attributes ( ) . value ( QStringLiteral ( " xmlUrl " ) ) . toString ( ) ;
2021-04-02 22:31:34 +02:00
}
}
2021-04-20 21:14:19 +02:00
qDebug ( ) < < urls ;
addFeeds ( urls ) ;
2021-04-02 22:31:34 +02:00
}
void DataManager : : exportFeeds ( const QString & path )
{
QUrl url ( path ) ;
QFile file ( url . isLocalFile ( ) ? url . toLocalFile ( ) : url . toString ( ) ) ;
file . open ( QIODevice : : WriteOnly ) ;
QXmlStreamWriter xmlWriter ( & file ) ;
xmlWriter . setAutoFormatting ( true ) ;
xmlWriter . writeStartDocument ( QStringLiteral ( " 1.0 " ) ) ;
xmlWriter . writeStartElement ( QStringLiteral ( " opml " ) ) ;
xmlWriter . writeEmptyElement ( QStringLiteral ( " head " ) ) ;
xmlWriter . writeStartElement ( QStringLiteral ( " body " ) ) ;
xmlWriter . writeAttribute ( QStringLiteral ( " version " ) , QStringLiteral ( " 1.0 " ) ) ;
QSqlQuery query ;
query . prepare ( QStringLiteral ( " SELECT url, name FROM Feeds; " ) ) ;
Database : : instance ( ) . execute ( query ) ;
while ( query . next ( ) ) {
xmlWriter . writeEmptyElement ( QStringLiteral ( " outline " ) ) ;
xmlWriter . writeAttribute ( QStringLiteral ( " xmlUrl " ) , query . value ( 0 ) . toString ( ) ) ;
xmlWriter . writeAttribute ( QStringLiteral ( " title " ) , query . value ( 1 ) . toString ( ) ) ;
}
xmlWriter . writeEndElement ( ) ;
xmlWriter . writeEndElement ( ) ;
xmlWriter . writeEndDocument ( ) ;
}
void DataManager : : loadFeed ( const QString feedurl ) const
2021-04-02 17:06:27 +02:00
{
m_feeds [ feedurl ] = new Feed ( feedurl ) ;
}
2021-04-02 22:31:34 +02:00
void DataManager : : loadEntry ( const QString id ) const
{
// First find the feed that this entry belongs to
Feed * feed = nullptr ;
QHashIterator < QString , QStringList > i ( m_entrymap ) ;
while ( i . hasNext ( ) ) {
i . next ( ) ;
if ( i . value ( ) . contains ( id ) )
feed = getFeed ( i . key ( ) ) ;
}
2021-05-01 20:59:08 +02:00
if ( ! feed ) {
2021-04-02 22:31:34 +02:00
qDebug ( ) < < " Failed to find feed belonging to entry " < < id ;
return ;
}
m_entries [ id ] = new Entry ( feed , id ) ;
}
bool DataManager : : feedExists ( const QString & url )
{
return m_feeds . contains ( url ) ;
}
2021-04-03 19:29:40 +02:00
void DataManager : : updateQueueListnrs ( ) const
{
QSqlQuery query ;
for ( int i = 0 ; i < m_queuemap . count ( ) ; i + + ) {
query . prepare ( QStringLiteral ( " UPDATE Queue SET listnr=:i WHERE id=:id; " ) ) ;
query . bindValue ( QStringLiteral ( " :i " ) , i ) ;
query . bindValue ( QStringLiteral ( " :id " ) , m_queuemap [ i ] ) ;
Database : : instance ( ) . execute ( query ) ;
}
}