diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -79,6 +79,7 @@ project/projectmodel.cpp project/projectwidget.cpp project/projecttab.cpp + project/updatestatsjob.cpp metadata/poextractor.cpp metadata/xliffextractor.cpp diff --git a/src/project/projectmodel.h b/src/project/projectmodel.h --- a/src/project/projectmodel.h +++ b/src/project/projectmodel.h @@ -28,11 +28,10 @@ #ifndef PROJECTMODEL_H #define PROJECTMODEL_H -#include -#include #include #include -#include + +#include #include "project.h" #include "projectlocal.h" @@ -253,31 +252,4 @@ bool m_completeScan; }; - - -class UpdateStatsJob: public QObject, public QRunnable -{ - Q_OBJECT -public: - explicit UpdateStatsJob(const QList &files, QObject* owner = nullptr); - ~UpdateStatsJob() override; - int priority()const - { - return 35; //SEE jobs.h - } - - void setStatus(int status); - - QList m_files; - QList m_info; - volatile int m_status; // 0 = running; -1 = cancel; -2 = abort - -protected: - void run() override; - -signals: - void done(UpdateStatsJob*); -}; - - #endif diff --git a/src/project/projectmodel.cpp b/src/project/projectmodel.cpp --- a/src/project/projectmodel.cpp +++ b/src/project/projectmodel.cpp @@ -27,25 +27,20 @@ #include "projectmodel.h" -#include "lokalize_debug.h" - -#include "project.h" -#include "metadata/poextractor.h" -#include "metadata/xliffextractor.h" - #include #include #include #include #include #include #include -#include -#include -#include -#include -#include +#include +#include + +#include "lokalize_debug.h" +#include "project.h" +#include "updatestatsjob.h" static int nodeCounter = 0; @@ -1261,130 +1256,3 @@ metaDataStatus = Status::NoStats; metaData = FileMetaData(); } - - -//BEGIN UpdateStatsJob -//these are run in separate thread -UpdateStatsJob::UpdateStatsJob(const QList &files, QObject*) - : QRunnable() - , m_files(files) - , m_status(0) -{ - setAutoDelete(false); -} - -UpdateStatsJob::~UpdateStatsJob() -{ -} - -//#define NOMETAINFOCACHE -#ifndef NOMETAINFOCACHE -static void initDataBase(QSqlDatabase& db) -{ - QSqlQuery queryMain(db); - queryMain.exec(QStringLiteral("PRAGMA encoding = \"UTF-8\"")); - queryMain.exec(QStringLiteral( - "CREATE TABLE IF NOT EXISTS metadata (" - "filepath INTEGER PRIMARY KEY ON CONFLICT REPLACE, "// AUTOINCREMENT," - //"filepath TEXT UNIQUE ON CONFLICT REPLACE, " - "metadata BLOB, "//XLIFF markup info, see catalog/catalogstring.h catalog/xliff/* - "changedate INTEGER" - ")")); - - //queryMain.exec("CREATE INDEX IF NOT EXISTS filepath_index ON metainfo ("filepath)"); -} -#endif - -static FileMetaData cachedMetaData(const KFileItem& file) -{ - if (file.isNull() || file.isDir()) - return FileMetaData(); -#ifdef NOMETAINFOCACHE - return FileMetaData::extract(file.localPath()); -#else - QString dbName = QStringLiteral("metainfocache"); - if (!QSqlDatabase::contains(dbName)) { - QSqlDatabase db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), dbName); - db.setDatabaseName(QStandardPaths::writableLocation(QStandardPaths::DataLocation) % QLatin1Char('/') % dbName % QLatin1String(".sqlite")); - if (Q_UNLIKELY(!db.open())) - return FileMetaData::extract(file.localPath()); - initDataBase(db); - } - QSqlDatabase db = QSqlDatabase::database(dbName); - if (!db.isOpen()) - return FileMetaData::extract(file.localPath()); - - QByteArray result; - - QSqlQuery queryCache(db); - queryCache.prepare(QStringLiteral("SELECT * from metadata where filepath=?")); - queryCache.bindValue(0, qHash(file.localPath())); - queryCache.exec(); - //not using file.time(KFileItem::ModificationTime) because it gives wrong result for files that have just been saved in editor - if (queryCache.next() && QFileInfo(file.localPath()).lastModified() == queryCache.value(2).toDateTime()) { - result = queryCache.value(1).toByteArray(); - QDataStream stream(&result, QIODevice::ReadOnly); - - FileMetaData info; - stream >> info; - Q_ASSERT(info.translated == FileMetaData::extract(file.localPath()).translated); - return info; - } - - FileMetaData m = FileMetaData::extract(file.localPath()); - - QDataStream stream(&result, QIODevice::WriteOnly); - //this is synced with ProjectModel::ProjectNode::setFileStats - stream << m; - - QSqlQuery query(db); - - query.prepare(QStringLiteral("INSERT INTO metadata (filepath, metadata, changedate) " - "VALUES (?, ?, ?)")); - query.bindValue(0, qHash(file.localPath())); - query.bindValue(1, result); - query.bindValue(2, QFileInfo(file.localPath()).lastModified()); - if (Q_UNLIKELY(!query.exec())) - qCWarning(LOKALIZE_LOG) << "metainfo cache acquiring error: " << query.lastError().text(); - - return m; -#endif -} - -void UpdateStatsJob::run() -{ -#ifndef NOMETAINFOCACHE - QString dbName = QStringLiteral("metainfocache"); - bool ok = QSqlDatabase::contains(dbName); - if (ok) { - QSqlDatabase db = QSqlDatabase::database(dbName); - QSqlQuery queryBegin(QStringLiteral("BEGIN"), db); - } -#endif - m_info.reserve(m_files.count()); - for (int pos = 0; pos < m_files.count(); pos++) { - if (m_status != 0) - break; - - m_info.append(cachedMetaData(m_files.at(pos))); - } -#ifndef NOMETAINFOCACHE - if (ok) { - QSqlDatabase db = QSqlDatabase::database(dbName); - { - //braces are needed to avoid resource leak on close - QSqlQuery queryEnd(QStringLiteral("END"), db); - } - db.close(); - db.open(); - } -#endif - emit done(this); -} - -void UpdateStatsJob::setStatus(int status) -{ - m_status = status; -} -//END UpdateStatsJob - diff --git a/src/project/updatestatsjob.h b/src/project/updatestatsjob.h new file mode 100644 --- /dev/null +++ b/src/project/updatestatsjob.h @@ -0,0 +1,62 @@ +/* **************************************************************************** + This file is part of Lokalize + + Copyright (C) 2018 by Karl Ove Hufthammer + Copyright (C) 2007-2014 by Nick Shaforostoff + Copyright (C) 2009 by Viesturs Zarins + Copyright (C) 2018-2019 by Simon Depiets + Copyright (C) 2019 by Alexander Potashev + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +**************************************************************************** */ + +#ifndef LOKALIZE_UPDATESTATSJOB_H +#define LOKALIZE_UPDATESTATSJOB_H + +#include + +#include + +#include "metadata/filemetadata.h" + +class UpdateStatsJob: public QObject, public QRunnable +{ + Q_OBJECT + +public: + explicit UpdateStatsJob(const QList &files, QObject* owner = nullptr); + ~UpdateStatsJob() override; + int priority()const + { + return 35; //SEE jobs.h + } + + void setStatus(int status); + + QList m_files; + QList m_info; + volatile int m_status; // 0 = running; -1 = cancel; -2 = abort + +protected: + void run() override; + +signals: + void done(UpdateStatsJob*); +}; + +#endif //LOKALIZE_UPDATESTATSJOB_H diff --git a/src/project/updatestatsjob.cpp b/src/project/updatestatsjob.cpp new file mode 100644 --- /dev/null +++ b/src/project/updatestatsjob.cpp @@ -0,0 +1,159 @@ +/* **************************************************************************** + This file is part of Lokalize + + Copyright (C) 2018 by Karl Ove Hufthammer + Copyright (C) 2007-2015 by Nick Shaforostoff + Copyright (C) 2009 by Viesturs Zarins + Copyright (C) 2018-2019 by Simon Depiets + Copyright (C) 2019 by Alexander Potashev + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +**************************************************************************** */ + +#include "updatestatsjob.h" + +#include +#include +#include +#include +#include + +#include "lokalize_debug.h" + +//these are run in separate thread +UpdateStatsJob::UpdateStatsJob(const QList &files, QObject*) + : QRunnable() + , m_files(files) + , m_status(0) +{ + setAutoDelete(false); +} + +UpdateStatsJob::~UpdateStatsJob() +{ +} + +//#define NOMETAINFOCACHE +#ifndef NOMETAINFOCACHE +static void initDataBase(QSqlDatabase& db) +{ + QSqlQuery queryMain(db); + queryMain.exec(QStringLiteral("PRAGMA encoding = \"UTF-8\"")); + queryMain.exec(QStringLiteral( + "CREATE TABLE IF NOT EXISTS metadata (" + "filepath INTEGER PRIMARY KEY ON CONFLICT REPLACE, "// AUTOINCREMENT," + //"filepath TEXT UNIQUE ON CONFLICT REPLACE, " + "metadata BLOB, "//XLIFF markup info, see catalog/catalogstring.h catalog/xliff/* + "changedate INTEGER" + ")")); + + //queryMain.exec("CREATE INDEX IF NOT EXISTS filepath_index ON metainfo ("filepath)"); +} +#endif + +static FileMetaData cachedMetaData(const KFileItem& file) +{ + if (file.isNull() || file.isDir()) + return FileMetaData(); +#ifdef NOMETAINFOCACHE + return FileMetaData::extract(file.localPath()); +#else + QString dbName = QStringLiteral("metainfocache"); + if (!QSqlDatabase::contains(dbName)) { + QSqlDatabase db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), dbName); + db.setDatabaseName(QStandardPaths::writableLocation(QStandardPaths::DataLocation) % QLatin1Char('/') % dbName % QLatin1String(".sqlite")); + if (Q_UNLIKELY(!db.open())) + return FileMetaData::extract(file.localPath()); + initDataBase(db); + } + QSqlDatabase db = QSqlDatabase::database(dbName); + if (!db.isOpen()) + return FileMetaData::extract(file.localPath()); + + QByteArray result; + + QSqlQuery queryCache(db); + queryCache.prepare(QStringLiteral("SELECT * from metadata where filepath=?")); + queryCache.bindValue(0, qHash(file.localPath())); + queryCache.exec(); + //not using file.time(KFileItem::ModificationTime) because it gives wrong result for files that have just been saved in editor + if (queryCache.next() && QFileInfo(file.localPath()).lastModified() == queryCache.value(2).toDateTime()) { + result = queryCache.value(1).toByteArray(); + QDataStream stream(&result, QIODevice::ReadOnly); + + FileMetaData info; + stream >> info; + Q_ASSERT(info.translated == FileMetaData::extract(file.localPath()).translated); + return info; + } + + FileMetaData m = FileMetaData::extract(file.localPath()); + + QDataStream stream(&result, QIODevice::WriteOnly); + //this is synced with ProjectModel::ProjectNode::setFileStats + stream << m; + + QSqlQuery query(db); + + query.prepare(QStringLiteral("INSERT INTO metadata (filepath, metadata, changedate) " + "VALUES (?, ?, ?)")); + query.bindValue(0, qHash(file.localPath())); + query.bindValue(1, result); + query.bindValue(2, QFileInfo(file.localPath()).lastModified()); + if (Q_UNLIKELY(!query.exec())) + qCWarning(LOKALIZE_LOG) << "metainfo cache acquiring error: " << query.lastError().text(); + + return m; +#endif +} + +void UpdateStatsJob::run() +{ +#ifndef NOMETAINFOCACHE + QString dbName = QStringLiteral("metainfocache"); + bool ok = QSqlDatabase::contains(dbName); + if (ok) { + QSqlDatabase db = QSqlDatabase::database(dbName); + QSqlQuery queryBegin(QStringLiteral("BEGIN"), db); + } +#endif + m_info.reserve(m_files.count()); + for (int pos = 0; pos < m_files.count(); pos++) { + if (m_status != 0) + break; + + m_info.append(cachedMetaData(m_files.at(pos))); + } +#ifndef NOMETAINFOCACHE + if (ok) { + QSqlDatabase db = QSqlDatabase::database(dbName); + { + //braces are needed to avoid resource leak on close + QSqlQuery queryEnd(QStringLiteral("END"), db); + } + db.close(); + db.open(); + } +#endif + emit done(this); +} + +void UpdateStatsJob::setStatus(int status) +{ + m_status = status; +}