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