diff --git a/src/nokde-stubs/prefs.cpp b/src/nokde-stubs/prefs.cpp
--- a/src/nokde-stubs/prefs.cpp
+++ b/src/nokde-stubs/prefs.cpp
@@ -58,6 +58,7 @@
, mPrefetchTM(false)
, mAutoaddTM(true)
, mScanToTMOnOpen(false)
+ , mDeleteFromTMOnMissing(false)
, mWordCompletionLength(3)
, mSuggCount(10)
diff --git a/src/nokde-stubs/prefs_lokalize.h b/src/nokde-stubs/prefs_lokalize.h
--- a/src/nokde-stubs/prefs_lokalize.h
+++ b/src/nokde-stubs/prefs_lokalize.h
@@ -141,6 +141,12 @@
return self()->mScanToTMOnOpen;
}
+ static
+ bool deleteFromTMOnMissing()
+ {
+ return self()->mDeleteFromTMOnMissing;
+ }
+
protected:
Settings();
friend class SettingsHelper;
@@ -170,6 +176,7 @@
bool mPrefetchTM;
bool mAutoaddTM;
bool mScanToTMOnOpen;
+ bool mDeleteFromTMOnMissing;
int mWordCompletionLength;
int mSuggCount;
diff --git a/src/prefs/lokalize.kcfg b/src/prefs/lokalize.kcfg
--- a/src/prefs/lokalize.kcfg
+++ b/src/prefs/lokalize.kcfg
@@ -114,5 +114,11 @@
false
+
+ false
+
+
+ false
+
diff --git a/src/prefs/prefs_tm.ui b/src/prefs/prefs_tm.ui
--- a/src/prefs/prefs_tm.ui
+++ b/src/prefs/prefs_tm.ui
@@ -84,6 +84,13 @@
+ -
+
+
+ Delete missing files from translation memory on Rescan or when clicking a missing entry
+
+
+
diff --git a/src/tm/jobs.h b/src/tm/jobs.h
--- a/src/tm/jobs.h
+++ b/src/tm/jobs.h
@@ -54,15 +54,18 @@
#define TMTABSELECT 100
#define UPDATE 80
#define REMOVE 70
+#define REMOVEFILE 69
#define INSERT 60
#define SELECT 50
#define BATCHSELECTFINISHED 49
#define IMPORT 30
#define EXPORT 25
+#define REMOVEMISSINGFILES 11
#define SCAN 10
#define SCANFINISHED 9
+
struct TMConfig
{
QString markup;
@@ -87,7 +90,7 @@
explicit OpenDBJob(const QString& dbName, DbType type=TM::Local, bool reconnect=false, const ConnectionParams& connParams=ConnectionParams());
~OpenDBJob();
- int priority()const{return OPENDB;}
+ int priority() const {return OPENDB;}
struct DBStat
{
@@ -124,7 +127,7 @@
explicit CloseDBJob(const QString& dbName);
~CloseDBJob();
- int priority()const{return CLOSEDB;}
+ int priority() const {return CLOSEDB;}
QString dbName(){return m_dbName;}
signals:
@@ -151,7 +154,7 @@
const QString& dbName);
~SelectJob();
- int priority()const{return SELECT;}
+ int priority() const {return SELECT;}
signals:
void done(SelectJob*);
@@ -184,14 +187,50 @@
SelectJob* initSelectJob(Catalog*, DocPosition pos, QString db=QString(), int opt=Enqueue);
+class RemoveMissingFilesJob: public QObject, public QRunnable
+{
+ Q_OBJECT
+public:
+ explicit RemoveMissingFilesJob(const QString& dbName);
+ ~RemoveMissingFilesJob();
+ int priority() const {return REMOVEMISSINGFILES;}
+
+protected:
+ void run();
+
+ QString m_dbName;
+
+signals:
+ void done();
+};
+
+class RemoveFileJob: public QObject, public QRunnable
+{
+ Q_OBJECT
+public:
+ explicit RemoveFileJob(const QString& filePath, const QString& dbName, QObject *parent = nullptr);
+ ~RemoveFileJob();
+ int priority() const {return REMOVEFILE;}
+
+protected:
+ void run();
+
+ QString m_filePath;
+ QString m_dbName;
+ QObject m_parent;
+
+signals:
+ void done();
+};
+
class RemoveJob: public QObject, public QRunnable
{
Q_OBJECT
public:
explicit RemoveJob(const TMEntry& entry);
~RemoveJob();
- int priority()const{return REMOVE;}
+ int priority() const {return REMOVE;}
protected:
void run();
@@ -225,7 +264,7 @@
~UpdateJob(){}
- int priority()const{return UPDATE;}
+ int priority() const {return UPDATE;}
protected:
void run ();
@@ -247,7 +286,7 @@
explicit ScanJob(const QString& filePath, const QString& dbName);
~ScanJob();
- int priority()const{return SCAN;}
+ int priority() const {return SCAN;}
protected:
void run ();
@@ -293,7 +332,7 @@
{}
~BatchSelectFinishedJob(){};
- int priority()const{return BATCHSELECTFINISHED;}
+ int priority() const {return BATCHSELECTFINISHED;}
signals:
void done();
@@ -316,7 +355,7 @@
IndexWordsJob(QObject* parent=0);
~IndexWordsJob();
- int priority()const{return 100;}
+ int priority() const {return 100;}
protected:
void run ();
@@ -339,7 +378,7 @@
const QString& dbName);
~ImportTmxJob();
- int priority()const{return IMPORT;}
+ int priority() const {return IMPORT;}
protected:
void run ();
@@ -361,7 +400,7 @@
const QString& dbName);
~ExportTmxJob();
- int priority()const{return IMPORT;}
+ int priority() const {return IMPORT;}
protected:
void run ();
@@ -383,7 +422,7 @@
explicit ExecQueryJob(const QString& queryString, const QString& dbName);
~ExecQueryJob();
- int priority()const{return TMTABSELECT;}
+ int priority() const {return TMTABSELECT;}
QSqlQuery* query;
diff --git a/src/tm/jobs.cpp b/src/tm/jobs.cpp
--- a/src/tm/jobs.cpp
+++ b/src/tm/jobs.cpp
@@ -111,8 +111,6 @@
}
-
-
static qlonglong getFileId(const QString& path,
QSqlDatabase& db)
{
@@ -371,6 +369,60 @@
return query1.exec(QStringLiteral("DELETE FROM main WHERE id=")+QString::number(mainId));
}
+
+static bool doRemoveFile(const QString& filePath, QSqlDatabase& db)
+{
+ qlonglong fileId=getFileId(filePath,db);
+ QSqlQuery query1(db);
+
+ if (Q_UNLIKELY(!query1.exec(U("SELECT id FROM files WHERE "
+ "id=")+QString::number(fileId))))
+ return false;
+
+ if (!query1.next())
+ return false;
+
+ query1.clear();
+
+ query1.exec(QStringLiteral("DELETE source_strings FROM source_strings, main WHERE source_strings.id = main.source AND main.file =")+QString::number(fileId));
+ query1.exec(QStringLiteral("DELETE target_strings FROM target_strings, main WHERE target_strings.id = main.target AND main.file =")+QString::number(fileId));
+ query1.exec(QStringLiteral("DELETE FROM main WHERE file = ")+QString::number(fileId));
+ return query1.exec(QStringLiteral("DELETE FROM files WHERE id=")+QString::number(fileId));
+}
+
+
+static int doRemoveMissingFiles(QSqlDatabase& db, const QString& dbName, QObject *job)
+{
+ int deletedFiles = 0;
+ QSqlQuery query1(db);
+
+ if (Q_UNLIKELY(!query1.exec(U("SELECT files.path FROM files"))))
+ return false;
+
+ if (!query1.next())
+ return false;
+
+ do
+ {
+ QString filePath=query1.value(0).toString();
+ if (!QFile::exists(filePath)&&Project::instance()->isLoaded())
+ { //check if we are opening template
+ QString newPath=filePath;
+ newPath.replace(Project::instance()->poDir(),Project::instance()->potDir());
+ if (!QFile::exists(newPath) && !QFile::exists(newPath+='t'))
+ {
+ qCWarning(LOKALIZE_LOG)<<"Removing file "<start(job_removefile, REMOVEFILE);
+ deletedFiles++;
+ }
+ }
+ }
+ while (query1.next());
+
+ return deletedFiles;
+}
+
static QString escape(QString str)
{
return str.replace(QLatin1Char('\''),QStringLiteral("''"));
@@ -1633,6 +1685,61 @@
m_time=a.elapsed();
}
+RemoveMissingFilesJob::RemoveMissingFilesJob(const QString& dbName)
+ : QObject(), QRunnable()
+ , m_dbName(dbName)
+{
+ qCDebug(LOKALIZE_LOG)<<"removingmissingfiles"<
#include
#include
+#include
#include
#include
#include
#include
#include
#include
#include
-#include
-
#ifndef NOKDE
#include
#include
#include
+#include
+#include
#endif
#if defined(Q_OS_WIN) && defined(QStringLiteral)
@@ -546,6 +548,11 @@
void TMTab::updateTM()
{
scanRecursive(QStringList(Project::instance()->poDir()),Project::instance()->projectID());
+ if (Settings::deleteFromTMOnMissing())
+ {
+ RemoveMissingFilesJob* job=new RemoveMissingFilesJob(Project::instance()->projectID());
+ TM::threadPool()->start(job, REMOVEMISSINGFILES);
+ }
}
void TMTab::performQuery()
@@ -635,6 +642,24 @@
void TMTab::openFile()
{
QModelIndex item=ui_queryOptions->treeView->currentIndex();
+ if (Settings::deleteFromTMOnMissing())
+ {//Check if the file exists and delete it if it doesn't
+ QString filePath=item.sibling(item.row(),TMDBModel::Filepath).data(Qt::UserRole).toString();
+ if (!QFile::exists(filePath)&&Project::instance()->isLoaded())
+ { //check if we are opening template
+ QString newPath=filePath;
+ newPath.replace(Project::instance()->poDir(),Project::instance()->potDir());
+ if (!QFile::exists(newPath) && !QFile::exists(newPath+='t'))
+ {
+ //File doesn't exist
+ RemoveFileJob* job=new RemoveFileJob(filePath,ui_queryOptions->dbName->currentText());
+
+ TM::threadPool()->start(job, REMOVEFILE);
+ KMessageBox::information(this, i18nc("@info","The file %1 doesn't exist, it has been removed from the Translation Memory.",filePath));
+ return performQuery();//We relaunch the query
+ }
+ }
+ }
emit fileOpenRequested(item.sibling(item.row(),TMDBModel::Filepath).data(Qt::UserRole).toString(),
item.sibling(item.row(),TMDBModel::Source).data().toString(),
item.sibling(item.row(),TMDBModel::Context).data().toString());
diff --git a/src/tm/tmview.cpp b/src/tm/tmview.cpp
--- a/src/tm/tmview.cpp
+++ b/src/tm/tmview.cpp
@@ -43,6 +43,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -589,11 +590,36 @@
return;
const TMEntry& e=m_entries.at(block);
- enum {Remove, Open};
+ enum {Remove, RemoveFile, Open};
QMenu popup;
popup.addAction(i18nc("@action:inmenu", "Remove this entry"))->setData(Remove);
if (e.file!= m_catalog->url() && QFile::exists(e.file))
popup.addAction(i18nc("@action:inmenu", "Open file containing this entry"))->setData(Open);
+ else
+ {
+ if (Settings::deleteFromTMOnMissing())
+ {//Automatic deletion
+ QString filePath=e.file;
+ if (!QFile::exists(filePath)&&Project::instance()->isLoaded())
+ {//check if we are opening template
+ QString newPath=filePath;
+ newPath.replace(Project::instance()->poDir(),Project::instance()->potDir());
+ if (!QFile::exists(newPath) && !QFile::exists(newPath+='t'))
+ {
+ //File doesn't exist
+ RemoveFileJob* job=new RemoveFileJob(e.file,e.dbName);
+ connect(job,SIGNAL(done()),this,SLOT(slotNewEntryDisplayed()));
+ TM::threadPool()->start(job, REMOVEFILE);
+ KMessageBox::information(this, i18nc("@info","The file %1 doesn't exist, it has been removed from the Translation Memory.",e.file));
+ return;
+ }
+ }
+ }
+ else if (!QFile::exists(e.file))
+ {//Still offer manual deletion if this is not the current file
+ popup.addAction(i18nc("@action:inmenu", "Remove this missing file from TM"))->setData(RemoveFile);
+ }
+ }
QAction* r=popup.exec(m_browser->mapToGlobal(pos));
if (!r)
return;
@@ -606,7 +632,28 @@
TM::threadPool()->start(job, REMOVE);
}
else if (r->data().toInt()==Open)
+ {
emit fileOpenRequested(e.file, e.source.string, e.ctxt);
+ }
+ else if ((r->data().toInt()==RemoveFile) &&
+ KMessageBox::Yes==KMessageBox::questionYesNo(this, i18n("Do you really want to remove this missing file:
%1
from translation memory %2?", e.file, e.dbName),
+ i18nc("@title:window","Translation Memory Missing File Removal")))
+ {
+ QString filePath=e.file;
+ if (!QFile::exists(filePath)&&Project::instance()->isLoaded())
+ {//check if we are opening template
+ QString newPath=filePath;
+ newPath.replace(Project::instance()->poDir(),Project::instance()->potDir());
+ if (!QFile::exists(newPath) && !QFile::exists(newPath+='t'))
+ {
+ //File doesn't exist
+ RemoveFileJob* job=new RemoveFileJob(e.file,e.dbName);
+ connect(job,SIGNAL(done()),this,SLOT(slotNewEntryDisplayed()));
+ TM::threadPool()->start(job, REMOVEFILE);
+ return;
+ }
+ }
+ }
}
/**