Skip to content

Commit

Permalink
UI: Reload app info on changes.
Browse files Browse the repository at this point in the history
  • Loading branch information
tnodir committed Oct 1, 2019
1 parent 40dd6c2 commit 2d5157e
Show file tree
Hide file tree
Showing 14 changed files with 107 additions and 40 deletions.
16 changes: 16 additions & 0 deletions src/ui/3rdparty/sqlite/sqlitedb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ SqliteDb::~SqliteDb()

bool SqliteDb::open(const QString &filePath)
{
m_filePath = filePath;
return sqlite3_open16(filePath.utf16(), &m_db) == SQLITE_OK;
}

Expand Down Expand Up @@ -283,6 +284,7 @@ int SqliteDb::userVersion()
}

bool SqliteDb::migrate(const QString &sqlDir, int version,
bool recreate,
SQLITEDB_MIGRATE_FUNC migrateFunc,
void *migrateContext)
{
Expand All @@ -297,15 +299,28 @@ bool SqliteDb::migrate(const QString &sqlDir, int version,
return false;
}

// Re-create the DB
if (recreate) {
close();
if (!(QFile::remove(m_filePath) && open(m_filePath))) {
qWarning() << "SQLite: Cannot re-create the DB" << m_filePath;
return false;
}
}

// Run migration SQL scripts
QDir dir(sqlDir);
bool res = true;

beginTransaction();

for (int i = userVersion + 1; i <= version; ++i) {
const QString filePath = dir.filePath(QString::number(i) + ".sql");

QFile file(filePath);
if (!file.exists())
break;

if (!file.open(QFile::ReadOnly | QFile::Text)) {
qWarning() << "SQLite: Cannot open migration file" << filePath
<< file.errorString();
Expand All @@ -331,6 +346,7 @@ bool SqliteDb::migrate(const QString &sqlDir, int version,
}
releaseSavepoint();
}

commitTransaction();

return res;
Expand Down
2 changes: 2 additions & 0 deletions src/ui/3rdparty/sqlite/sqlitedb.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,13 @@ class SqliteDb
int userVersion();

bool migrate(const QString &sqlDir, int version,
bool recreate = false,
SQLITEDB_MIGRATE_FUNC migrateFunc = nullptr,
void *migrateContext = nullptr);

private:
sqlite3 *m_db;
QString m_filePath;
};

#endif // SQLITEDB_H
2 changes: 1 addition & 1 deletion src/ui/db/databasemanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ bool DatabaseManager::initialize()
m_sqliteDb->execute(DatabaseSql::sqlPragmas);

if (!m_sqliteDb->migrate(":/db/migrations", DATABASE_USER_VERSION,
&migrateFunc)) {
false, &migrateFunc)) {
qCritical(CLOG_DATABASE_MANAGER()) << "Migration error" << m_filePath;
return false;
}
Expand Down
1 change: 0 additions & 1 deletion src/ui/util/app/app-migrations.qrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<RCC>
<qresource prefix="/appinfocache">
<file>migrations/1.sql</file>
<file>migrations/2.sql</file>
</qresource>
</RCC>
7 changes: 7 additions & 0 deletions src/ui/util/app/appinfo.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
#include "appinfo.h"

#include "appiconprovider.h"
#include "apputil.h"

QString AppInfo::iconPath() const
{
return AppIconProvider::iconPath(iconId);
}

bool AppInfo::isFileModified(const QString &appPath) const
{
return !fileModTime.isNull()
&& fileModTime != AppUtil::getModTime(appPath);
}
5 changes: 5 additions & 0 deletions src/ui/util/app/appinfo.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef APPINFO_H
#define APPINFO_H

#include <QDateTime>
#include <QObject>

class AppInfo
Expand All @@ -15,13 +16,17 @@ class AppInfo
public:
QString iconPath() const;

bool isFileModified(const QString &appPath) const;

public:
qint64 iconId = 0;

QString fileDescription;
QString companyName;
QString productName;
QString productVersion;

QDateTime fileModTime;
};

Q_DECLARE_METATYPE(AppInfo)
Expand Down
7 changes: 7 additions & 0 deletions src/ui/util/app/appinfocache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,18 @@ AppInfoCache::AppInfoCache(QObject *parent) :
AppInfo AppInfoCache::appInfo(const QString &appPath)
{
AppInfo *appInfo = m_cache.object(appPath);
bool lookupRequired = false;

if (appInfo == nullptr) {
appInfo = new AppInfo();

m_cache.insert(appPath, appInfo, 1);
lookupRequired = true;
} else {
lookupRequired = appInfo->isFileModified(appPath);
}

if (lookupRequired) {
m_manager->lookupAppInfo(appPath);
}

Expand Down
70 changes: 38 additions & 32 deletions src/ui/util/app/appinfomanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@
Q_DECLARE_LOGGING_CATEGORY(CLOG_APPINFOCACHE)
Q_LOGGING_CATEGORY(CLOG_APPINFOCACHE, "fort.appInfoWorker")

#define DATABASE_USER_VERSION 2
#define DATABASE_USER_VERSION 3

#define APP_CACHE_MAX_COUNT 2000

namespace {

const char * const sqlSelectAppInfo =
"SELECT file_descr, company_name,"
" product_name, product_ver, icon_id"
" product_name, product_ver, icon_id,"
" file_mod_time"
" FROM app WHERE path = ?1;"
;

Expand Down Expand Up @@ -52,8 +53,9 @@ const char * const sqlUpdateIconRefCount =

const char * const sqlInsertAppInfo =
"INSERT INTO app(path, file_descr, company_name,"
" product_name, product_ver, icon_id, access_time)"
" VALUES(?1, ?2, ?3, ?4, ?5, ?6, datetime('now'));"
" product_name, product_ver, icon_id,"
" file_mod_time, access_time)"
" VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, datetime('now'));"
;

const char * const sqlSelectAppCount =
Expand All @@ -76,25 +78,6 @@ const char * const sqlDeleteApp =
"DELETE FROM app WHERE path = ?1;"
;

bool migrateFunc(SqliteDb *db, int version, void *ctx)
{
Q_UNUSED(db)

AppInfoManager *manager = static_cast<AppInfoManager *>(ctx);
bool res = true;

if (version == 2) {
// Delete "System" app
const char * const sqlSelectAppSystem =
"SELECT path, icon_id FROM app"
" WHERE path = 'System';"
;
res = manager->deleteApps(sqlSelectAppSystem);
}

return res;
}

}

AppInfoManager::AppInfoManager(QObject *parent) :
Expand Down Expand Up @@ -126,8 +109,8 @@ void AppInfoManager::setupDb()
return;
}

if (!m_sqliteDb->migrate(":/appinfocache/migrations", DATABASE_USER_VERSION,
&migrateFunc, this)) {
if (!m_sqliteDb->migrate(":/appinfocache/migrations",
DATABASE_USER_VERSION, true)) {
qCritical(CLOG_APPINFOCACHE()) << "Migration error" << filePath;
return;
}
Expand Down Expand Up @@ -186,6 +169,7 @@ bool AppInfoManager::loadInfoFromDb(const QString &appPath, AppInfo &appInfo)
appInfo.productName = list.at(2).toString();
appInfo.productVersion = list.at(3).toString();
appInfo.iconId = list.at(4).toLongLong();
appInfo.fileModTime = list.at(5).toDateTime();

// Update last access time
m_sqliteDb->executeEx(sqlUpdateAppAccessTime, vars);
Expand Down Expand Up @@ -243,6 +227,7 @@ bool AppInfoManager::saveToDb(const QString &appPath, AppInfo &appInfo,
<< appInfo.productName
<< appInfo.productVersion
<< iconId
<< appInfo.fileModTime
;

m_sqliteDb->executeEx(sqlInsertAppInfo, vars, 0, &ok);
Expand All @@ -258,26 +243,36 @@ bool AppInfoManager::saveToDb(const QString &appPath, AppInfo &appInfo,
const int excessCount = appCount - APP_CACHE_MAX_COUNT;

if (excessCount > 0) {
deleteApps(sqlSelectAppOlds, excessCount);
deleteOldApps(excessCount);
}
}

return ok;
}

bool AppInfoManager::deleteApps(const char *sql, int limitCount)
void AppInfoManager::deleteAppInfo(const QString &appPath, const AppInfo &appInfo)
{
QStringList appPaths;
QHash<qint64, int> iconIds;

bool ok = false;
appPaths.append(appPath);

m_sqliteDb->beginTransaction();
if (appInfo.iconId != 0) {
iconIds.insert(appInfo.iconId, 1);
}

deleteAppsAndIcons(appPaths, iconIds);
}

void AppInfoManager::deleteOldApps(int limitCount)
{
QStringList appPaths;
QHash<qint64, int> iconIds;

// Get old app info list
{
SqliteStmt stmt;
if (stmt.prepare(m_sqliteDb->db(), sql,
if (stmt.prepare(m_sqliteDb->db(), sqlSelectAppOlds,
SqliteStmt::PreparePersistent)) {
if (limitCount != 0) {
stmt.bindInt(1, limitCount);
Expand All @@ -291,11 +286,22 @@ bool AppInfoManager::deleteApps(const char *sql, int limitCount)
const int iconCount = iconIds.value(iconId) + 1;
iconIds.insert(iconId, iconCount);
}

ok = true;
}
}

// Delete old app infos & icons
if (!appPaths.isEmpty()) {
deleteAppsAndIcons(appPaths, iconIds);
}
}

bool AppInfoManager::deleteAppsAndIcons(const QStringList &appPaths,
const QHash<qint64, int> &iconIds)
{
bool ok = false;

m_sqliteDb->beginTransaction();

// Delete old icons
auto iconIt = iconIds.constBegin();
for (; iconIt != iconIds.constEnd(); ++iconIt) {
Expand Down
6 changes: 5 additions & 1 deletion src/ui/util/app/appinfomanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ class AppInfoManager : public WorkerManager
bool saveToDb(const QString &appPath, AppInfo &appInfo,
const QImage &appIcon);

bool deleteApps(const char *sql, int limitCount = 0);
void deleteAppInfo(const QString &appPath, const AppInfo &appInfo);
void deleteOldApps(int limitCount = 0);

signals:
void lookupFinished(const QString &appPath, const AppInfo appInfo);
Expand All @@ -43,6 +44,9 @@ public slots:
private:
void setupDb();

bool deleteAppsAndIcons(const QStringList &appPaths,
const QHash<qint64, int> &iconIds);

private:
SqliteDb *m_sqliteDb;
QMutex m_mutex;
Expand Down
16 changes: 13 additions & 3 deletions src/ui/util/app/appinfoworker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,21 @@ void AppInfoWorker::doJob(WorkerJob *workerJob)
auto job = static_cast<AppInfoJob *>(workerJob);
const QString &appPath = job->appPath();

if (!manager()->loadInfoFromDb(appPath, job->appInfo)
&& manager()->loadInfoFromFs(appPath, job->appInfo)) {
// Try to load from DB
AppInfo &appInfo = job->appInfo;
bool loadedFromDb = manager()->loadInfoFromDb(appPath, appInfo);

// Was the file modified?
if (loadedFromDb && appInfo.isFileModified(appPath)) {
loadedFromDb = false;
manager()->deleteAppInfo(appPath, appInfo);
}

// Try to load from FS
if (!loadedFromDb && manager()->loadInfoFromFs(appPath, appInfo)) {
const QImage appIcon = manager()->loadIconFromFs(appPath);

manager()->saveToDb(appPath, job->appInfo, appIcon);
manager()->saveToDb(appPath, appInfo, appIcon);
}

WorkerObject::doJob(workerJob);
Expand Down
9 changes: 9 additions & 0 deletions src/ui/util/app/apputil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ bool AppUtil::getInfo(const QString &appPath, AppInfo &appInfo)
return true;
}

// File modification time
appInfo.fileModTime = getModTime(appPath);

return extractVersionInfo(appPath, appInfo);
}

Expand All @@ -153,3 +156,9 @@ QImage AppUtil::getIcon(const QString &appPath)
return extractShellIcon(appPath)
.toImage();
}

QDateTime AppUtil::getModTime(const QString &appPath)
{
QFileInfo fi(appPath);
return fi.lastModified();
}
2 changes: 2 additions & 0 deletions src/ui/util/app/apputil.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef APPUTIL_H
#define APPUTIL_H

#include <QDateTime>
#include <QObject>
#include <QImage>

Expand All @@ -11,6 +12,7 @@ class AppUtil
public:
static bool getInfo(const QString &appPath, AppInfo &appInfo);
static QImage getIcon(const QString &appPath);
static QDateTime getModTime(const QString &appPath);
};

#endif // APPUTIL_H
3 changes: 2 additions & 1 deletion src/ui/util/app/migrations/1.sql
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
PRAGMA user_version = 1;
PRAGMA user_version = 3;

PRAGMA journal_mode = WAL;

Expand All @@ -9,6 +9,7 @@ CREATE TABLE app(
product_name TEXT,
product_ver TEXT,
icon_id INTEGER,
file_mod_time DATETIME,
access_time DATETIME
) WITHOUT ROWID;

Expand Down
1 change: 0 additions & 1 deletion src/ui/util/app/migrations/2.sql

This file was deleted.

0 comments on commit 2d5157e

Please sign in to comment.