1 /*
2   This file is part of Lokalize
3 
4   SPDX-FileCopyrightText: 2007-2014 Nick Shaforostoff <shafff@ukr.net>
5   SPDX-FileCopyrightText: 2018-2019 Simon Depiets <sdepiets@gmail.com>
6 
7   SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
8 */
9 
10 #ifndef JOBS_H
11 #define JOBS_H
12 
13 #include "pos.h"
14 #include "tmentry.h"
15 
16 #include <QThreadPool>
17 #include <QRunnable>
18 
19 #include <QString>
20 #include <QMutex>
21 #include <QSqlDatabase>
22 class QSqlQuery;
23 
24 /**
25  * Translation Memory classes. see initDb() function for the database scheme
26  */
27 namespace TM
28 {
29 
30 #define TM_DATABASE_EXTENSION ".db"
31 #define REMOTETM_DATABASE_EXTENSION ".remotedb"
32 enum DbType {Local, Remote, Undefined}; //is needed only on opening
33 
34 #define TM_AREA 8111
35 
36 
37 QThreadPool* threadPool();
38 
39 
40 #define CLOSEDB 10001
41 #define OPENDB  10000
42 #define TMTABSELECT  100
43 #define UPDATE  80
44 #define REMOVE  70
45 #define REMOVEFILE  69
46 #define INSERT  60
47 #define SELECT  50
48 #define BATCHSELECTFINISHED  49
49 #define IMPORT 30
50 #define EXPORT 25
51 #define REMOVEMISSINGFILES    11
52 #define SCAN    10
53 #define SCANFINISHED 9
54 
55 struct TMConfig {
56     QString markup;
57     QString accel;
58     QString sourceLangCode;
59     QString targetLangCode;
60 };
61 
62 void cancelAllJobs(); //HACK because threadweaver's dequeue is not workin'
63 
64 //called on startup
65 class OpenDBJob: public QObject, public QRunnable
66 {
67     Q_OBJECT
68 public:
69     struct ConnectionParams {
70         QString driver, host, db, user, passwd;
isFilledConnectionParams71         bool isFilled()
72         {
73             return !host.isEmpty() && !db.isEmpty() && !user.isEmpty();
74         }
75     };
76 
77     explicit OpenDBJob(const QString& dbName, DbType type = TM::Local, bool reconnect = false, const ConnectionParams& connParams = ConnectionParams());
78     ~OpenDBJob() override = default;
79 
priority()80     int priority() const
81     {
82         return OPENDB;
83     }
84 
85     struct DBStat {
86         int pairsCount, uniqueSourcesCount, uniqueTranslationsCount;
DBStatDBStat87         DBStat(): pairsCount(0), uniqueSourcesCount(0), uniqueTranslationsCount(0) {}
88     };
89 
90 protected:
91     void run() override;
92 
93 Q_SIGNALS:
94     void done(OpenDBJob*);
95 
96 public:
97     QString m_dbName;
98     DbType m_type;
99     //statistics
100     DBStat m_stat;
101 
102     //for the new DB creation
103     TMConfig m_tmConfig;
104     bool m_setParams;
105 
106     bool m_connectionSuccessful;
107     bool m_reconnect;
108     ConnectionParams m_connParams;
109 };
110 
111 //called on startup
112 class CloseDBJob: public QObject, public QRunnable
113 {
114     Q_OBJECT
115 public:
116     explicit CloseDBJob(const QString& dbName);
117     ~CloseDBJob();
118 
priority()119     int priority() const
120     {
121         return CLOSEDB;
122     }
dbName()123     QString dbName()
124     {
125         return m_dbName;
126     }
127 
128 Q_SIGNALS:
129     void done(CloseDBJob*);
130 
131 protected:
132     void run() override;
133 
134     QString m_dbName;
135     //statistics?
136 };
137 
138 
139 
140 
141 class SelectJob: public QObject, public QRunnable
142 {
143     Q_OBJECT
144 public:
145     SelectJob(const CatalogString& source,
146               const QString& ctxt,
147               const QString& file,
148               const DocPosition&,//for back tracking
149               const QString& dbName);
150     ~SelectJob();
151 
priority()152     int priority() const
153     {
154         return SELECT;
155     }
156 
157 Q_SIGNALS:
158     void done(SelectJob*);
159 
160 protected:
161     void run() override;
162     //void aboutToBeDequeued(ThreadWeaver::WeaverInterface*); KDE5PORT
163 
164 private:
165     //returns true if seen translation with >85%
166     bool doSelect(QSqlDatabase&,
167                   QStringList& words,
168                   bool isShort);
169 
170 public:
171     CatalogString m_source;
172 private:
173     QString m_ctxt;
174     QString m_file;
175     bool m_dequeued;
176 
177 public:
178     DocPosition m_pos;
179     QList<TMEntry> m_entries;
180 
181     QString m_dbName;
182 };
183 
184 enum {Enqueue = 1};
185 SelectJob* initSelectJob(Catalog*, DocPosition pos, QString db = QString(), int opt = Enqueue);
186 
187 
188 class RemoveMissingFilesJob: public QObject, public QRunnable
189 {
190     Q_OBJECT
191 public:
192     explicit RemoveMissingFilesJob(const QString& dbName);
193     ~RemoveMissingFilesJob();
priority()194     int priority() const
195     {
196         return REMOVEMISSINGFILES;
197     }
198 
199 protected:
200     void run() override;
201 
202     QString m_dbName;
203 
204 Q_SIGNALS:
205     void done();
206 };
207 
208 class RemoveFileJob: public QObject, public QRunnable
209 {
210     Q_OBJECT
211 public:
212     explicit RemoveFileJob(const QString& filePath, const QString& dbName, QObject *parent = nullptr);
213     ~RemoveFileJob();
priority()214     int priority() const
215     {
216         return REMOVEFILE;
217     }
218 
219 protected:
220     void run() override;
221 
222     QString m_filePath;
223     QString m_dbName;
224     QObject m_parent;
225 
226 Q_SIGNALS:
227     void done();
228 };
229 
230 
231 class RemoveJob: public QObject, public QRunnable
232 {
233     Q_OBJECT
234 public:
235     explicit RemoveJob(const TMEntry& entry);
236     ~RemoveJob();
priority()237     int priority() const
238     {
239         return REMOVE;
240     }
241 
242 protected:
243     void run() override;
244 
245     TMEntry m_entry;
246 
247 Q_SIGNALS:
248     void done();
249 };
250 
251 
252 /**
253  * used to eliminate a lot of duplicate entries
254  *
255  * it is supposed to run on entry switch/file close in Editor
256 **/
257 //TODO a mechanism to get rid of dead dups (use strigi?).
258 //also, display usage of different translations and suggest user
259 //to use only one of them (listview, checkboxes)
260 class UpdateJob: public QRunnable
261 {
262 public:
263     explicit UpdateJob(const QString& filePath,
264                        const QString& ctxt,
265                        const CatalogString& en,
266                        const CatalogString& newTarget,
267                        int form,
268                        bool approved,
269                        //const DocPosition&,//for back tracking
270                        const QString& dbName);
271 
~UpdateJob()272     ~UpdateJob() {}
273 
priority()274     int priority() const
275     {
276         return UPDATE;
277     }
278 
279 protected:
280     void run() override;
281 
282 private:
283     QString m_filePath;
284     QString m_ctxt;
285     CatalogString m_english;
286     CatalogString m_newTarget;
287     int m_form;
288     bool m_approved;
289     QString m_dbName;
290 };
291 
292 //scan one file
293 class ScanJob: public QRunnable
294 {
295 public:
296     explicit ScanJob(const QString& filePath, const QString& dbName);
297     ~ScanJob() override = default;
298 
priority()299     int priority() const
300     {
301         return SCAN;
302     }
303 
304 protected:
305     void run() override;
306 public:
307     QString m_filePath;
308 
309     //statistics
310     ushort m_time;
311     ushort m_added;
312     ushort m_newVersions;//e1.english==e2.english, e1.target!=e2.target
313 
314     int m_size;
315 
316     QString m_dbName;
317 };
318 
319 class ScanJobFeedingBack: public QObject, public ScanJob
320 {
321     Q_OBJECT
322 public:
ScanJobFeedingBack(const QString & filePath,const QString & dbName)323     explicit ScanJobFeedingBack(const QString& filePath,
324                                 const QString& dbName)
325         : QObject(), ScanJob(filePath, dbName)
326     {
327         setAutoDelete(false);
328     }
329 
330 protected:
run()331     void run() override
332     {
333         ScanJob::run();
334         Q_EMIT done(this);
335     }
336 
337 Q_SIGNALS:
338     void done(ScanJobFeedingBack*);
339 };
340 
341 //helper
342 class BatchSelectFinishedJob: public QObject, public QRunnable
343 {
344     Q_OBJECT
345 public:
BatchSelectFinishedJob(QWidget * view)346     explicit BatchSelectFinishedJob(QWidget* view)
347         : QObject(), QRunnable()
348         , m_view(view)
349     {}
350     ~BatchSelectFinishedJob() override = default;
351 
priority()352     int priority() const
353     {
354         return BATCHSELECTFINISHED;
355     }
356 
357 Q_SIGNALS:
358     void done();
359 
360 protected:
run()361     void run() override
362     {
363         Q_EMIT done();
364     }
365 public:
366     QWidget* m_view;
367 };
368 #if 0
369 we use index stored in db now...
370 
371 
372 
373 //create index --called on startup
374 class IndexWordsJob: public QRunnable
375 {
376     Q_OBJECT
377 public:
378     IndexWordsJob(QObject* parent = nullptr);
379     ~IndexWordsJob();
380 
381     int priority() const
382     {
383         return 100;
384     }
385 
386 protected:
387     void run();
388 public:
389     TMWordHash m_tmWordHash;
390 
391     //statistics?
392 };
393 #endif
394 
395 
396 
397 
398 
399 
400 class ImportTmxJob: public QRunnable
401 {
402 public:
403     explicit ImportTmxJob(const QString& url,
404                           const QString& dbName);
405     ~ImportTmxJob();
406 
priority()407     int priority() const
408     {
409         return IMPORT;
410     }
411 
412 protected:
413     void run() override;
414 public:
415     QString m_filename;
416 
417     //statistics
418     ushort m_time;
419 
420     QString m_dbName;
421 };
422 
423 // #if 0
424 
425 class ExportTmxJob: public QRunnable
426 {
427 public:
428     explicit ExportTmxJob(const QString& url,
429                           const QString& dbName);
430     ~ExportTmxJob();
431 
priority()432     int priority() const
433     {
434         return IMPORT;
435     }
436 
437 protected:
438     void run() override;
439 public:
440     QString m_filename;
441 
442     //statistics
443     ushort m_time;
444 
445     QString m_dbName;
446 };
447 
448 // #endif
449 
450 class ExecQueryJob: public QObject, public QRunnable
451 {
452     Q_OBJECT
453 public:
454     explicit ExecQueryJob(const QString& queryString, const QString& dbName, QMutex *dbOperation);
455     ~ExecQueryJob();
456 
priority()457     int priority() const
458     {
459         return TMTABSELECT;
460     }
461 
462 
463     QSqlQuery* query;
464 
465 Q_SIGNALS:
466     void done(ExecQueryJob*);
467 
468 protected:
469     void run() override;
470 
471     QString m_dbName;
472     QString m_query;
473     QMutex* m_dbOperationMutex;
474     //statistics?
475 };
476 
477 }
478 
479 
480 #endif
481 
482