//#include #include #include #include #include #include #include #include #include "mainwindow.h" #include "zcconfig.h" #include "zcacceptpenevents.h" #include "zcpatientsandcases.h" #include "zcpatient.h" #include "zctabletsupport.h" #include "zcrepertory.h" #include "zcrepfilterresult.h" #include "zcmateriamedica.h" #include "zcsymrem.h" #include "zcdir.h" #include "zcfile.h" #include "zcdocxreport.h" #include "zcsecurity.h" #include "zcsysinfo.h" #include "zcaesfile.h" #include "signverify.h" #include "zclicensemanager.h" #include "zcdownloadrepdlg.h" #include "zcregisterdlg.h" #include "zcstyle.h" #include "zcjsonget.h" #include "zcxlsxreport.h" #include "version.h" #include "zcmmdb.h" #include "zcprogress.h" #include "zcprogressdlg.h" #include "zclogontozc4.h" #include "zclanguages.h" #include "zcopuspreconnect.h" #include "zcatexit.h" #include "zcdialog.h" #include "zcdebug.h" #include "sqlfilesystem.h" #include "zcdebug.h" #ifdef Q_OS_WIN32 #include #endif #define USE_WEBVIEW #ifdef USE_WEBVIEW #include #else #include #endif #include "pdffillin.h" #include "pdffieldposdlg.h" //#define CONVERT_MM static bool save_log = false; static void saveLog(void) { zcDir dir = zcPrefs::applicationDataDir(); int i; zcFile d(dir, "zc4_9.log"); d.remove(); for(i = 9; i >= 1; i--) { zcFile f(dir, QString("zc4_%1.log").arg(i)); zcFile g(dir, QString("zc4_%1.log").arg(i - 1)); f.rename(f.absolutePath()); } zcFile orig(dir, "zc4.log"); zcFile save(dir, "zc4_0.log"); orig.rename(save.absolutePath()); } static FILE *out = nullptr; static void closeOut(void) { if (out != stderr) { fclose(out); out = stderr; } } static void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { if (out == nullptr) { zcDir dir = zcPrefs::applicationDataDir(); zcFile f(dir, "zc4.log"); dir.mkpath(); #ifdef Q_OS_WIN32 out = _fsopen(f.fileName().toUtf8(), "wt", _SH_DENYNO); #else out = fopen(f.fileName().toUtf8(), "wt"); #endif if (out == nullptr) { out = stderr; } zcAtExit::atexitLast("myMessageOutput - closeOut", closeOut); } QByteArray localMsg = msg.toLocal8Bit(); switch (type) { case QtDebugMsg: fprintf(out, "Debug: %s (%s:%u)\n", localMsg.constData(), context.file, context.line); break; case QtInfoMsg: fprintf(out, "Info: %s (%s:%u)\n", localMsg.constData(), context.file, context.line); break; case QtWarningMsg: fprintf(out, "Warning: %s (%s:%u)\n", localMsg.constData(), context.file, context.line); break; case QtCriticalMsg: fprintf(out, "Critical: %s (%s:%u)\n", localMsg.constData(), context.file, context.line); if (!save_log) { save_log = true; zcAtExit::atexit("myMessageOutput - saveLog", saveLog); } break; case QtFatalMsg: fprintf(out, "Fatal: %s (%s:%u)\n", localMsg.constData(), context.file, context.line); if (!save_log) { save_log = true; zcAtExit::atexit("myMessageOutput - saveLog", saveLog); } break; //abort(); } fseek(out, 0, SEEK_END); } #ifdef CONVERT_MM static void convertMM(); #endif #include "zcaesfile.h" int main(int argc, char *argv[]) { // Initializations before the construction of QApplication // This setting is not for OS X. #ifdef Q_OS_WIN QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #if QT_VERSION_MAJOR == 5 && QT_VERSION_MINOR >= 14 QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); #endif #else #ifdef Q_OS_LINUX // X11 QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif #endif // Used for QQuickWidget, etc. --> QML Code for QtWebEngine QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); QApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton); // Construct the application QApplication *zc4_app = new QApplication(argc, argv); // Right after the construction of the application initialize the QtWebView #ifdef USE_WEBVIEW QtWebView::initialize(); #else QtWebEngine::initialize(); #endif // Debugging info to other log file qInstallMessageHandler(myMessageOutput); // Create other stuff zcAtExit *zc4_at_exit = new zcAtExit(zc4_app); unused(zc4_at_exit); // Meta typing qRegisterMetaType< QList >( "QList" ); // Library path QCoreApplication::addLibraryPath(zcPrefs::extraPluginDir().absolutePath()); // Log program paths LINE_DEBUG << "Qt version:" << QLibraryInfo::version().toString(); LINE_DEBUG << "Application Dir Path:" << QCoreApplication::applicationDirPath(); LINE_DEBUG << "Application File Path:" << QCoreApplication::applicationFilePath(); LINE_DEBUG << "LibraryInfo:"; LINE_DEBUG << "prefix:" << QLibraryInfo::location(QLibraryInfo::PrefixPath); LINE_DEBUG << "plugins:" << QLibraryInfo::location(QLibraryInfo::PluginsPath); LINE_DEBUG << "libraries:" << QLibraryInfo::location(QLibraryInfo::LibrariesPath); LINE_DEBUG << "translations:" << QLibraryInfo::location(QLibraryInfo::TranslationsPath); LINE_DEBUG << "binaries:" << QLibraryInfo::location(QLibraryInfo::BinariesPath); LINE_DEBUG << "arch-independent qt-data:" << QLibraryInfo::location(QLibraryInfo::DataPath); LINE_DEBUG << "arch-dependent qt-data:" << QLibraryInfo::location(QLibraryInfo::ArchDataPath); // Styling and organization information zc4_app->setStyle(new zcStyle()); zc4_app->setOrganizationDomain("homeopathie-nederland.nl"); zc4_app->setOrganizationName("Hans Dijkema"); zc4_app->setApplicationName("ZC4"); zc4_app->setApplicationVersion(QString(ZC4_VERSION_SUBVERSION)); // Determine locale zcLanguages::setApplication(zc4_app); zcLanguages::loadTranslations(); // Check if we have already started zcDir oldDocDir = zcPrefs::applicationDataDir(); { zcDir docDir = zcPrefs::applicationDataDir(); zcFile zc4StartedFile(docDir, "zc4.lck"); if (zc4StartedFile.exists()) { int result = QMessageBox::question(nullptr, QObject::tr("ZC4 %1 is al gestart").arg(ZC4_VERSION_SUBVERSION), QObject::tr("ZC4 Lijkt al gestart te zijn.

" "Dit kan meerdere oorzaken hebben:" "
    " "
  • De vorige keer is ZC4 gecrashed.
    U kunt gewoon doorgaan.
  • " "
  • U opent ZC4 voor de tweede keer.
    U dient af te sluiten.
  • " "
  • U heeft uw bestanden op een gedeeld medium, zoals Dropbox of Google Drive.
    " "U dient af te sluiten, tenzij u zeker weet dat ZC4 niet elders draait.
  • " "
" "Uw bestandslocatie is:" "
    %1
" "Kies om door te gaan of niet." ).arg(docDir.absolutePath()) ); if (result == QMessageBox::No) { exit(0); } else { zc4StartedFile.remove(); } } zc4StartedFile.open(QFile::WriteOnly); zc4StartedFile.write(ZC4_VERSION); zc4StartedFile.close(); } #ifdef Q_OS_WIN32 #else #ifdef fSECURITY { zcSecurity s; s.checkIntegrity(); } #endif #endif zcStartupSplash *splash = new zcStartupSplash(); splash->show(); zcProgress *progress = splash->progress(); QScreen *splash_screen = zc4_app->screenAt(splash->pos()); zcDialog::setApplicationScreen(splash_screen); zcTabletSupport *ts = new zcTabletSupport(zc4_app); unused(ts); bool _stop_program = false; QString expiryDate; { // Remove zc4-setup-latest.* zcDir d = zcPrefs::applicationRepDataDir(); zcFile exe(d, "zc4-setup-latest.exe"); zcFile dmg(d, "zc4-setup-latest.dmg"); if (exe.exists()) { exe.remove(); } if (dmg.exists()) { dmg.remove(); } } // Checking license / activation { bool _activation = false; bool _check_email_confirmation = false; QString _message; QString _submessage; progress->start(); progress->info(QObject::tr("Locale licentie controleren...")); progress->percentage(0.0); zcLicenseManager mgr; mgr.checkLocalLicense(); int license_state; if (mgr.licenseValid(license_state, _message, _submessage)) { qDebug() << __FUNCTION__ << __LINE__ << license_state << _message << _activation << _check_email_confirmation; // Als de lokale licentie in orde is, proberen we de server licentie // nog te checken. mgr.backupLicense(); mgr.recheckServerLicense(); if (mgr.networkProblem()) { qDebug() << __FUNCTION__ << __LINE__ << license_state << _message << _activation << _check_email_confirmation; mgr.restoreLicense(); // Geen probleem, want we hadden al een valide licentie. } else { qDebug() << __FUNCTION__ << __LINE__ << license_state << _message << _activation << _check_email_confirmation; if (!mgr.licenseValid(license_state, _message, _submessage)) { _activation = true; } } qDebug() << __FUNCTION__ << __LINE__ << license_state << _message << _activation << _check_email_confirmation; } else { qDebug() << __FUNCTION__ << __LINE__ << license_state << _message << _activation << _check_email_confirmation; // Geen valide licentie. We proberen die van de server op te halen. progress->info(QObject::tr("Licentie ophalen van de licentie server...")); progress->percentage(1.0); mgr.requestServerLicense(); if (mgr.networkProblem()) { _message = QObject::tr("Netwerk probleem - activeer ZC4"); _submessage = mgr.lastMessage(); _activation = true; } else { _activation = !mgr.licenseValid(license_state, _message, _submessage); } } qDebug() << __FUNCTION__ << __LINE__ << license_state << _message << _activation << _check_email_confirmation; // Cleaning up resources { int ZC4_REP_NO_CLEANUP = 20171103; { int zc4_rep_no_cleanup = zcPrefs::get("zc4_rep_no_cleanup", ZC4_REP_NO_CLEANUP - 1); if (zc4_rep_no_cleanup != ZC4_REP_NO_CLEANUP) { { // cleanup old repertories etc. zcDir dir(zcPrefs::applicationRepDataDir()); QStringList f; f << "cr_*.mta" << "cr_*.rep" << "cr_*.src"; f << "murphy_*.mta" << "murphy_*.rep" << "murphy_*.src"; dir.setNameFilters(f); dir.setFilter(QDir::Files); for(QString file : dir.entryList()) { dir.remove(file); } } { // cleanup old MM books zcDir dir(zcPrefs::applicationMMDataDir()); zcDir books(dir, "books"); zcFile dbfile(dir, "mm.db"); zcMMDb db(dbfile); books.setNameFilters(QStringList() << "*.book"); books.setFilter(QDir::Files); for(QString file : books.entryList()) { QString fn = file.toLower(); if (fn.startsWith("boericke_phatak")) { zcFile f(books, file); if (f.open(QFile::ReadOnly)) { QJsonDocument doc(QJsonDocument::fromJson(f.readAll())); f.close(); QJsonObject obj = doc.object(); int id = obj["id"].toInt(); db.clearBook(id); f.remove(); } } } } } } auto old_release = [&](zcLicenseManager::Resource res) { QString kind = res.kind2string(); QString type = res.type(); QString lang = res.language(); QString release = res.release(); QString current_release = zcPrefs::get("downloads." + kind + "." + type + "." + lang, QString("--NONE--")); return (current_release != release); // || (zc4_rep_no_cleanup != ZC4_REP_NO_CLEANUP); }; auto remove_repertory = [&](zcLicenseManager::Resource res) { zcDir dir(zcPrefs::applicationRepDataDir()); QString filename = res.type() + "_" + res.language() + "_" + res.release() + "."; dir.setNameFilters(QStringList() << filename + "mta" << filename + "rep" << filename + "src"); dir.setFilter(QDir::Files); for(QString file : dir.entryList()) { dir.remove(file); } }; auto remove_mm_book = [&](zcLicenseManager::Resource res) { zcDir dir(zcPrefs::applicationMMDataDir()); zcDir books(dir, "books"); zcFile dbfile(dir, "mm.db"); zcMMDb db(dbfile); books.setNameFilters(QStringList() << "*.book"); books.setFilter(QDir::Files); QString filename = res.type() + "_" + res.language() + "_"; for(QString file : books.entryList()) { QString fn = file.toLower(); if (fn.startsWith(filename)) { zcFile f(books, file); if (f.open(QFile::ReadOnly)) { QJsonDocument doc(QJsonDocument::fromJson(f.readAll())); f.close(); QJsonObject obj = doc.object(); int id = obj["id"].toInt(); db.clearBook(id); f.remove(); } } } }; auto remove_mm_images = [&](zcLicenseManager::Resource res) { unused(res); zcDir dir(zcPrefs::applicationImagesDir()); dir.setNameFilters(QStringList() << "*.img" << "*.jpg"); dir.setFilter(QDir::Files); for(QString file : dir.entryList()) { zcFile f(dir, file); f.remove(); } }; auto remove_wiki = [&](zcLicenseManager::Resource res) { unused(res); zcDir dir(zcPrefs::applicationWikiDataDir()); for(QString file : dir.entryList()) { zcFile f(dir, file); f.remove(); } }; auto remove_resource = [&](zcLicenseManager::Resource res) { if (res.kind() == zcLicenseManager::KIND_REPERTORY) { remove_repertory(res); } else if (res.kind() == zcLicenseManager::KIND_MM) { remove_mm_book(res); } else if (res.kind() == zcLicenseManager::KIND_IMAGES) { remove_mm_images(res); } else if (res.kind() == zcLicenseManager::KIND_WIKI) { remove_wiki(res); } else if (res.kind() == zcLicenseManager::KIND_MODULE) { // do nothing } else if (res.kind() == zcLicenseManager::KIND_PRG) { // do nothing } else { qCritical() << __FUNCTION__ << __LINE__ << "Unknown Resource:" << res; } }; auto remove_all_resources = [&]() { zcDir dir(zcPrefs::applicationRepDataDir()); foreach(QString file, dir.entryList()) { if (file == "." || file == "..") { // do nothing } else { zcFile f(dir, file); zcDir d(dir, file); if (d.isDir()) { d.removeRecursively(); } else { f.remove(); } } } }; QList available = mgr.availableResources(); foreach(zcLicenseManager::Resource res, available) { if (!mgr.hasResource(res)) { remove_resource(res); } else if (old_release(res)) { remove_resource(res); } } if (_activation || _check_email_confirmation) { remove_all_resources(); } zcPrefs::set("zc4_rep_no_cleanup", ZC4_REP_NO_CLEANUP); } qDebug() << __FUNCTION__ << __LINE__ << _activation << _check_email_confirmation; if (_activation || _check_email_confirmation) { splash->hide(); zcRegisterDlg dlg(mgr); dlg.setMessage(_message); dlg.setSubMessage(_submessage); if (dlg.exec() == QDialog::Rejected) { _stop_program = true; } } if (!_stop_program){ auto need_download = [&](zcLicenseManager::Resource res) { bool rep = (res.kind() == zcLicenseManager::KIND_REPERTORY); bool mm = (res.kind() == zcLicenseManager::KIND_MM); bool img = (res.kind() == zcLicenseManager::KIND_IMAGES); bool wiki = (res.kind() == zcLicenseManager::KIND_WIKI); bool module = (res.kind() == zcLicenseManager::KIND_MODULE); zcDir dir; if (rep) { dir = zcPrefs::applicationRepDataDir(); } if (mm) { dir = zcPrefs::applicationMMDataDir(); } if (img) { dir = zcPrefs::applicationImagesDir(); } if (wiki) { dir = zcPrefs::applicationWikiDataDir(); } QString kind = res.kind2string(); QString type = res.type(); QString lang = res.language(); QString release = res.release(); if (rep) { QString rep_name = type + "_" + lang + "_" + release; zcFile rep_file(dir, rep_name + ".rep"); return !rep_file.exists(); } else if (mm) { QString mm_name = type + "_" + lang + "_" + release; zcFile mm_file(dir, mm_name + ".db"); zcFile mm_book(dir, mm_name + ".book"); zcDir books(dir, "books"); books.mkpath(); zcFile to_book(books, mm_name + ".book"); return !to_book.exists(); } else if (img) { QString img_name = type + "_" + lang + "_" + release; zcFile img_file(dir, img_name + ".img"); return !img_file.exists(); } else if (wiki) { QString rep_name = type + "_" + lang + "_" + release; zcFile rep_file(dir, rep_name + ".wiki"); return !rep_file.exists(); } else if (module) { return false; // Do nothing } else { LINE_CRITICAL << "Unknown resource" << res.kind() << kind << type << lang << release; return false; } }; auto download = [&](zcLicenseManager::Resource res) { bool rep = (res.kind() == zcLicenseManager::KIND_REPERTORY); bool mm = (res.kind() == zcLicenseManager::KIND_MM); bool img = (res.kind() == zcLicenseManager::KIND_IMAGES); bool wiki = (res.kind()) == zcLicenseManager::KIND_WIKI; zcDir dir; if (rep) { dir = zcPrefs::applicationRepDataDir(); } if (mm) { dir = zcPrefs::applicationMMDataDir(); } if (img) { dir = zcPrefs::applicationImagesDir(); } if (wiki) { dir = zcPrefs::applicationWikiDataDir(); } QString kind = res.kind2string(); QString type = res.type(); QString lang = res.language(); QString release = res.release(); if (rep) { QString rep_name = type + "_" + lang + "_" + release; zcFile rep_file(dir, rep_name + ".rep"); if (!rep_file.exists()) { // Start download. splash->hide(); zcDownloadRepDlg dlg(type, lang, mgr.licenseId()); if (dlg.download()) { zcPrefs::set("downloads." + kind + "." + type + "." + lang , release); if (rep) { QString rep_shortname = type; QString rep_version = release; QString rep_language = lang; zcPrefs::set("default-repertorium", rep_shortname); zcPrefs::set("default-rep-version", rep_version); zcPrefs::set("default-rep-language", rep_language); } } else { if (rep) { zcPrefs::set("default-repertorium", QString("kent")); zcPrefs::set("default-rep-version", QString("homned2016")); zcPrefs::set("default-rep-language", QString("en")); } } splash->show(); } } else if (mm) { QString mm_name = type + "_" + lang + "_" + release; zcFile mm_file(dir, mm_name + ".db"); zcFile mm_book(dir, mm_name + ".book"); zcDir books(dir, "books"); books.mkpath(); zcFile to_book(books, mm_name + ".book"); if (!to_book.exists()) { splash->hide(); zcDownloadRepDlg dlg(type, lang, mgr.licenseId()); if (dlg.download(QObject::tr("Materia Medica Downloaden"), mm_name)) { if (mm_file.exists() && mm_book.exists()) { zcProgress prgrs; zcProgressDlg prgDlg(&prgrs, QObject::tr("Verwerken %1").arg(mm_name), QObject::tr("%1 Materia Medica wordt verwerkt").arg(mm_name) ); prgrs.start(); prgrs.info("Inlezen MM..."); auto prg = [&](int perc) { prgrs.percentage(perc); }; zcMMDb from_db(mm_file); zcMMDb to_db; to_db.forceUserDb(true); to_db.copyCryptedFrom(from_db, prg); mm_book.copy(to_book.fileName()); prgrs.finish(); zcPrefs::set("downloads." + kind + "." + type + "." + lang, release); } mm_file.remove(); mm_book.remove(); } splash->show(); } } else if (img) { QString rep_name = type + "_" + lang + "_" + release; zcFile rep_file(dir, rep_name + ".img"); if (!rep_file.exists()) { // Start download. splash->hide(); zcDownloadRepDlg dlg(type, lang, mgr.licenseId()); dlg.setDir(dir); if (dlg.download(QObject::tr("Afbeeldingen downloaden"), QObject::tr("Materia Medica Afbeeldingen"))) { zcPrefs::set("downloads." + kind + "." + type + "." + lang , release); zcFile idx_file(dir, "images.idx"); rep_file.copy(idx_file.fileName()); } splash->show(); } } else if (wiki) { QString rep_name = type + "_" + lang + "_" + release; zcFile rep_file(dir, rep_name + ".wiki"); if (!rep_file.exists()) { // Start download. splash->hide(); zcDownloadRepDlg dlg(type, lang, mgr.licenseId()); dlg.setDir(dir); if (dlg.download(QObject::tr("Extra boeken downloaden"), QObject::tr("Extra materiaal"))) { zcPrefs::set("downloads." + kind + "." + type + "." + lang , release); zcFile idx_file(dir, "index.wiki"); idx_file.copy(rep_file.fileName()); //rep_file.copy(idx_file.fileName()); } splash->show(); } } }; // Possibly download a repertory { QList available = mgr.availableResources(); int nr_of_downloads = 0; foreach(zcLicenseManager::Resource res, available) { if (mgr.hasResource(res)) { if (need_download(res)) { nr_of_downloads += 1; } } } if (nr_of_downloads > 0) { QString msg; if (nr_of_downloads == 1) { msg = QObject::tr("Er is 1 item beschikbaar voor download.

" "Wilt u deze nu downloaden en installeren?"); } else { msg = QObject::tr("Er zijn %1 items beschikbaar voor download.

" "Wilt u deze nu downloaden en installeren?").arg(nr_of_downloads); } splash->hide(); if (QMessageBox::question(nullptr, QObject::tr("ZC4 - Downloads Beschikbaar"), msg) == QMessageBox::Yes) { foreach(zcLicenseManager::Resource res, available) { if (mgr.hasResource(res)) { download(res); } } } splash->show(); } } } if (mgr.licenseExpires()) { expiryDate = QString(QObject::tr("License valid until %1")).arg(mgr.expiryInfo()); } } int retval; // Login first if (!_stop_program) { splash->hide(); zcLogonToZC4 dlg; if (dlg.exec() == QDialog::Rejected) { _stop_program = true; } splash->show(); } if (!_stop_program) { // Display main window splash->show(); MainWindow *w = new MainWindow(splash, expiryDate); LINE_DEBUG << "Main Window created - WA_DeleteOnClose = " << w->testAttribute(Qt::WA_DeleteOnClose); QPoint p(zcPrefs::get("zc4_main_window_pos", QPoint(-1, -1))); if (p.x() != -1) { QSize s(zcPrefs::get("zc4_main_window_size", QSize(-1, -1))); if (s.width() > 0) { QRect r = splash_screen->availableGeometry(); QRect wr(p, s); if (r.contains(wr)) { w->move(p); w->resize(s); } } } bool maximized = zcPrefs::get("zc4_main_window_maximized", false); if (maximized) { w->setWindowState(Qt::WindowMaximized); } zcOpusPreConnect::tryConnectOpus(); w->show(); retval = zc4_app->exec(); w->deleteLater(); } else { progress->info(QObject::tr("Exiting ZC4")); progress->finish(); retval = 0; } splash->deleteLater(); // Cleanup lock file { zcFile zc4StartedFile(oldDocDir, "zc4.lck"); QString filename = zc4StartedFile.fileName(); if (zc4StartedFile.exists()) { zc4StartedFile.remove(); } { // And if we moved our directory, we need to remove it again zcDir docDir(zcPrefs::applicationDataDir()); zcFile zc4StartedFile(docDir, "zc4.lck"); if (zc4StartedFile.exists()) { zc4StartedFile.remove(); } } } delete zc4_app; return retval; } #ifdef CONVERT_MM #include "zcsmallremedyinfo.h" void convertMM() { // Conversion for sources of MM. { zcDir dir = zcPrefs::materiaMedicaDevelDir(); zcDir sources = zcDir(dir, "sources"); zcMateriaMedica mm; zcSmallRemedyInfo info(dir); zcFile reminfo_nl(sources, "reminfo_nl.json"); info.json2db(&mm, reminfo_nl); } exit(0); } #endif