diff --git a/3rdparty/qsqlite/CMakeLists.txt b/3rdparty/qsqlite/CMakeLists.txt index 465930f45..22fc8795a 100644 --- a/3rdparty/qsqlite/CMakeLists.txt +++ b/3rdparty/qsqlite/CMakeLists.txt @@ -5,6 +5,7 @@ set(SQLITE-SOURCES sqlite3.c qsql_sqlite.cpp smain.cpp + clementinesqlcachedresult.cpp ) # Header files that have Q_OBJECT in diff --git a/3rdparty/qsqlite/clementinesqlcachedresult.cpp b/3rdparty/qsqlite/clementinesqlcachedresult.cpp new file mode 100644 index 000000000..adca3ffec --- /dev/null +++ b/3rdparty/qsqlite/clementinesqlcachedresult.cpp @@ -0,0 +1,313 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtSql module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "clementinesqlcachedresult.h" + +#include +#include +#include + +/* + ClementineSqlCachedResult is a convenience class for databases that only allow + forward only fetching. It will cache all the results so we can iterate + backwards over the results again. + + All you need to do is to inherit from ClementineSqlCachedResult and reimplement + gotoNext(). gotoNext() will have a reference to the internal cache and + will give you an index where you can start filling in your data. Special + case: If the user actually wants a forward-only query, idx will be -1 + to indicate that we are not interested in the actual values. +*/ + +static const uint initial_cache_size = 128; + +class ClementineSqlCachedResultPrivate +{ +public: + ClementineSqlCachedResultPrivate(); + bool canSeek(int i) const; + inline int cacheCount() const; + void init(int count, bool fo); + void cleanup(); + int nextIndex(); + void revertLast(); + + ClementineSqlCachedResult::ValueCache cache; + int rowCacheEnd; + int colCount; + bool forwardOnly; + bool atEnd; +}; + +ClementineSqlCachedResultPrivate::ClementineSqlCachedResultPrivate(): + rowCacheEnd(0), colCount(0), forwardOnly(false), atEnd(false) +{ +} + +void ClementineSqlCachedResultPrivate::cleanup() +{ + cache.clear(); + forwardOnly = false; + atEnd = false; + colCount = 0; + rowCacheEnd = 0; +} + +void ClementineSqlCachedResultPrivate::init(int count, bool fo) +{ + Q_ASSERT(count); + cleanup(); + forwardOnly = fo; + colCount = count; + if (fo) { + cache.resize(count); + rowCacheEnd = count; + } else { + cache.resize(initial_cache_size * count); + } +} + +int ClementineSqlCachedResultPrivate::nextIndex() +{ + if (forwardOnly) + return 0; + int newIdx = rowCacheEnd; + if (newIdx + colCount > cache.size()) + cache.resize(qMin(cache.size() * 2, cache.size() + 10000)); + rowCacheEnd += colCount; + + return newIdx; +} + +bool ClementineSqlCachedResultPrivate::canSeek(int i) const +{ + if (forwardOnly || i < 0) + return false; + return rowCacheEnd >= (i + 1) * colCount; +} + +void ClementineSqlCachedResultPrivate::revertLast() +{ + if (forwardOnly) + return; + rowCacheEnd -= colCount; +} + +inline int ClementineSqlCachedResultPrivate::cacheCount() const +{ + Q_ASSERT(!forwardOnly); + Q_ASSERT(colCount); + return rowCacheEnd / colCount; +} + +////////////// + +ClementineSqlCachedResult::ClementineSqlCachedResult(const QSqlDriver * db): QSqlResult (db) +{ + d = new ClementineSqlCachedResultPrivate(); +} + +ClementineSqlCachedResult::~ClementineSqlCachedResult() +{ + delete d; +} + +void ClementineSqlCachedResult::init(int colCount) +{ + d->init(colCount, isForwardOnly()); +} + +bool ClementineSqlCachedResult::fetch(int i) +{ + if ((!isActive()) || (i < 0)) + return false; + if (at() == i) + return true; + if (d->forwardOnly) { + // speed hack - do not copy values if not needed + if (at() > i || at() == QSql::AfterLastRow) + return false; + while(at() < i - 1) { + if (!gotoNext(d->cache, -1)) + return false; + setAt(at() + 1); + } + if (!gotoNext(d->cache, 0)) + return false; + setAt(at() + 1); + return true; + } + if (d->canSeek(i)) { + setAt(i); + return true; + } + if (d->rowCacheEnd > 0) + setAt(d->cacheCount()); + while (at() < i + 1) { + if (!cacheNext()) { + if (d->canSeek(i)) + break; + return false; + } + } + setAt(i); + + return true; +} + +bool ClementineSqlCachedResult::fetchNext() +{ + if (d->canSeek(at() + 1)) { + setAt(at() + 1); + return true; + } + return cacheNext(); +} + +bool ClementineSqlCachedResult::fetchPrevious() +{ + return fetch(at() - 1); +} + +bool ClementineSqlCachedResult::fetchFirst() +{ + if (d->forwardOnly && at() != QSql::BeforeFirstRow) { + return false; + } + if (d->canSeek(0)) { + setAt(0); + return true; + } + return cacheNext(); +} + +bool ClementineSqlCachedResult::fetchLast() +{ + if (d->atEnd) { + if (d->forwardOnly) + return false; + else + return fetch(d->cacheCount() - 1); + } + + int i = at(); + while (fetchNext()) + ++i; /* brute force */ + if (d->forwardOnly && at() == QSql::AfterLastRow) { + setAt(i); + return true; + } else { + return fetch(i); + } +} + +QVariant ClementineSqlCachedResult::data(int i) +{ + int idx = d->forwardOnly ? i : at() * d->colCount + i; + if (i >= d->colCount || i < 0 || at() < 0 || idx >= d->rowCacheEnd) + return QVariant(); + + return d->cache.at(idx); +} + +bool ClementineSqlCachedResult::isNull(int i) +{ + int idx = d->forwardOnly ? i : at() * d->colCount + i; + if (i > d->colCount || i < 0 || at() < 0 || idx >= d->rowCacheEnd) + return true; + + return d->cache.at(idx).isNull(); +} + +void ClementineSqlCachedResult::cleanup() +{ + setAt(QSql::BeforeFirstRow); + setActive(false); + d->cleanup(); +} + +void ClementineSqlCachedResult::clearValues() +{ + setAt(QSql::BeforeFirstRow); + d->rowCacheEnd = 0; + d->atEnd = false; +} + +bool ClementineSqlCachedResult::cacheNext() +{ + if (d->atEnd) + return false; + + if(isForwardOnly()) { + d->cache.clear(); + d->cache.resize(d->colCount); + } + + if (!gotoNext(d->cache, d->nextIndex())) { + d->revertLast(); + d->atEnd = true; + return false; + } + setAt(at() + 1); + return true; +} + +int ClementineSqlCachedResult::colCount() const +{ + return d->colCount; +} + +ClementineSqlCachedResult::ValueCache &ClementineSqlCachedResult::cache() +{ + return d->cache; +} + +void ClementineSqlCachedResult::virtual_hook(int id, void *data) +{ + switch (id) { + case QSqlResult::DetachFromResultSet: + case QSqlResult::SetNumericalPrecision: + cleanup(); + break; + default: + QSqlResult::virtual_hook(id, data); + } +} diff --git a/3rdparty/qsqlite/clementinesqlcachedresult.h b/3rdparty/qsqlite/clementinesqlcachedresult.h new file mode 100644 index 000000000..1951789da --- /dev/null +++ b/3rdparty/qsqlite/clementinesqlcachedresult.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtSql module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CLEMENTINECACHEDRESULT_P_H +#define CLEMENTINECACHEDRESULT_P_H + +#include + +class QVariant; +template class QVector; + +class ClementineSqlCachedResultPrivate; + +class ClementineSqlCachedResult: public QSqlResult +{ +public: + virtual ~ClementineSqlCachedResult(); + + typedef QVector ValueCache; + +protected: + ClementineSqlCachedResult(const QSqlDriver * db); + + void init(int colCount); + void cleanup(); + void clearValues(); + + virtual bool gotoNext(ValueCache &values, int index) = 0; + + QVariant data(int i); + bool isNull(int i); + bool fetch(int i); + bool fetchNext(); + bool fetchPrevious(); + bool fetchFirst(); + bool fetchLast(); + + int colCount() const; + ValueCache &cache(); + + void virtual_hook(int id, void *data); +private: + bool cacheNext(); + ClementineSqlCachedResultPrivate *d; +}; + +#endif // CLEMENTINESQLCACHEDRESULT_P_H diff --git a/3rdparty/qsqlite/qsql_sqlite.cpp b/3rdparty/qsqlite/qsql_sqlite.cpp index eb5702447..c7caae1b1 100644 --- a/3rdparty/qsqlite/qsql_sqlite.cpp +++ b/3rdparty/qsqlite/qsql_sqlite.cpp @@ -112,7 +112,7 @@ class QSQLiteResultPrivate public: QSQLiteResultPrivate(QSQLiteResult *res); void cleanup(); - bool fetchNext(QSqlCachedResult::ValueCache &values, int idx, bool initialFetch); + bool fetchNext(ClementineSqlCachedResult::ValueCache &values, int idx, bool initialFetch); // initializes the recordInfo and the cache void initColumns(bool emptyResultset); void finalize(); @@ -180,7 +180,7 @@ void QSQLiteResultPrivate::initColumns(bool emptyResultset) } } -bool QSQLiteResultPrivate::fetchNext(QSqlCachedResult::ValueCache &values, int idx, bool initialFetch) +bool QSQLiteResultPrivate::fetchNext(ClementineSqlCachedResult::ValueCache &values, int idx, bool initialFetch) { int res; int i; @@ -281,7 +281,7 @@ bool QSQLiteResultPrivate::fetchNext(QSqlCachedResult::ValueCache &values, int i } QSQLiteResult::QSQLiteResult(const QSQLiteDriver* db) - : QSqlCachedResult(db) + : ClementineSqlCachedResult(db) { d = new QSQLiteResultPrivate(this); d->access = db->d->access; @@ -301,7 +301,7 @@ void QSQLiteResult::virtual_hook(int id, void *data) sqlite3_reset(d->stmt); break; default: - QSqlCachedResult::virtual_hook(id, data); + ClementineSqlCachedResult::virtual_hook(id, data); } } @@ -417,7 +417,7 @@ bool QSQLiteResult::exec() return true; } -bool QSQLiteResult::gotoNext(QSqlCachedResult::ValueCache& row, int idx) +bool QSQLiteResult::gotoNext(ClementineSqlCachedResult::ValueCache& row, int idx) { return d->fetchNext(row, idx, false); } diff --git a/3rdparty/qsqlite/qsql_sqlite.h b/3rdparty/qsqlite/qsql_sqlite.h index 8a05fbe34..f949aefe8 100644 --- a/3rdparty/qsqlite/qsql_sqlite.h +++ b/3rdparty/qsqlite/qsql_sqlite.h @@ -42,9 +42,9 @@ #ifndef QSQL_SQLITE_H #define QSQL_SQLITE_H -#include -#include -#include +#include +#include +#include "clementinesqlcachedresult.h" struct sqlite3; @@ -61,7 +61,7 @@ class QSQLiteDriverPrivate; class QSQLiteResultPrivate; class QSQLiteDriver; -class QSQLiteResult : public QSqlCachedResult +class QSQLiteResult : public ClementineSqlCachedResult { friend class QSQLiteDriver; friend class QSQLiteResultPrivate; @@ -71,7 +71,7 @@ public: QVariant handle() const; protected: - bool gotoNext(QSqlCachedResult::ValueCache& row, int idx); + bool gotoNext(ClementineSqlCachedResult::ValueCache& row, int idx); bool reset(const QString &query); bool prepare(const QString &query); bool exec(); diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c2273acc..0048c2a39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,15 +94,18 @@ find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext) # Subdirectories add_subdirectory(3rdparty/qtsingleapplication) -add_subdirectory(3rdparty/qxt) add_subdirectory(src) +if (NOT APPLE) + add_subdirectory(3rdparty/qxt) +endif (NOT APPLE) add_subdirectory(tests) -if (WIN32) +if (WIN32 OR APPLE) + message("Building static qsqlite plugin") add_definitions(-DQT_STATICPLUGIN) add_subdirectory(3rdparty/qsqlite) -endif(WIN32) +endif(WIN32 OR APPLE) # Uninstall support configure_file( diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5484302ed..23d96e33f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -304,7 +304,6 @@ add_library(clementine_lib ) target_link_libraries(clementine_lib qtsingleapplication - qxt lastfm ${GOBJECT_LIBRARIES} ${GLIB_LIBRARIES} @@ -321,14 +320,16 @@ if (APPLE) /System/Library/Frameworks/AppKit.framework ) include_directories(${GROWL}/Headers) +else (APPLE) + target_link_libraries(clementine_lib qxt) endif (APPLE) -add_dependencies(clementine_lib qtsingleapplication qxt) +add_dependencies(clementine_lib qtsingleapplication) # Link against the qsqlite plugin on windows -if(WIN32) +if(WIN32 OR APPLE) set(3RDPARTY_SQLITE_LIBRARY qsqlite) target_link_libraries(clementine_lib qsqlite) -endif(WIN32) +endif(WIN32 OR APPLE) add_executable(clementine MACOSX_BUNDLE diff --git a/src/librarybackend.cpp b/src/librarybackend.cpp index 75c524dd0..ea394ee74 100644 --- a/src/librarybackend.cpp +++ b/src/librarybackend.cpp @@ -55,8 +55,8 @@ void LibraryBackend::StaticInit() { } sStaticInitDone = true; -#ifdef Q_OS_WIN32 - // We statically link libqsqlite.dll on windows so these symbols are already +#ifndef Q_WS_X11 + // We statically link libqsqlite.dll on windows and mac so these symbols are already // available _sqlite3_create_function = sqlite3_create_function; _sqlite3_value_type = sqlite3_value_type; @@ -65,7 +65,8 @@ void LibraryBackend::StaticInit() { _sqlite3_result_int64 = sqlite3_result_int64; _sqlite3_user_data = sqlite3_user_data; sLoadedSqliteSymbols = true; -#else // Q_OS_WIN32 + return; +#else // Q_WS_X11 QString plugin_path = QLibraryInfo::location(QLibraryInfo::PluginsPath) + "/sqldrivers/libqsqlite"; diff --git a/src/librarywatcher.cpp b/src/librarywatcher.cpp index 0609be8df..ab28a664a 100644 --- a/src/librarywatcher.cpp +++ b/src/librarywatcher.cpp @@ -279,13 +279,6 @@ void LibraryWatcher::ScanSubdirectory( } void LibraryWatcher::AddWatch(QFileSystemWatcher* w, const QString& path) { -#ifdef Q_OS_DARWIN - if (++total_watches_ > kMaxWatches) { - qWarning() << "Trying to watch more files than we can manage"; - return; - } -#endif - if (!QFile::exists(path)) return; diff --git a/src/main.cpp b/src/main.cpp index c1c756027..35cb88167 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -45,8 +45,8 @@ #include "mac_startup.h" -// Load sqlite plugin on windows -#ifdef WIN32 +// Load sqlite plugin on windows and mac. +#ifndef Q_WS_X11 # include Q_IMPORT_PLUGIN(qsqlite) #endif diff --git a/tests/main.cpp b/tests/main.cpp index c607fe03e..b54097828 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -21,7 +21,7 @@ #include "resources_env.h" #include "metatypes_env.h" -#ifdef WIN32 +#ifndef Q_WS_X11 # include Q_IMPORT_PLUGIN(qsqlite) #endif