xca/lib/main.cpp
2020-03-29 22:33:57 +02:00

331 lines
6.5 KiB
C++

/* vi: set sw=4 ts=4:
*
* Copyright (C) 2001 - 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
#include <signal.h>
#include <QApplication>
#include <QClipboard>
#include <QTranslator>
#include <QTextCodec>
#include <QDir>
#include <QDirIterator>
#include <QFile>
#include <QDebug>
#include <openssl/rand.h>
#include "widgets/MainWindow.h"
#include "widgets/OpenDb.h"
#include "lib/func.h"
#include "lib/db.h"
#include "lib/main.h"
#include "lib/entropy.h"
#if defined(Q_OS_WIN32)
//For the segfault handler
#include <windows.h>
#endif
QLocale XCA_application::lang = QLocale::system();
QFont XCA_application::tableFont;
QList<QLocale> XCA_application::langAvail;
void XCA_application::setMainwin(MainWindow *m)
{
mainw = m;
}
bool XCA_application::languageAvailable(QLocale l)
{
return langAvail.contains(l);
}
static QString defaultlang()
{
return getUserSettingsDir() + QDir::separator() + "defaultlang";
}
XCA_application::XCA_application(int &argc, char *argv[])
:QApplication(argc, argv)
{
qtTr = NULL;
xcaTr = NULL;
mainw = NULL;
QFile file(defaultlang());
if (file.open(QIODevice::ReadOnly)) {
lang = QLocale(QString(file.read(128)));
}
langAvail << QLocale::system();
langAvail << QString("en");
QDirIterator qmIt(getI18nDir(), QStringList() << "*.qm", QDir::Files);
while (qmIt.hasNext()) {
XcaTranslator t;
qmIt.next();
QString language = qmIt.fileInfo().baseName().mid(4, -1);
if (t.load(language, "xca", getI18nDir()))
langAvail << QLocale(language);
}
setupLanguage(lang);
#ifdef Q_OS_MAC
QStringList libp = libraryPaths();
libp.prepend(applicationDirPath() + "/../Plugins");
setLibraryPaths(libp);
#endif
tableFont = QFont("Courier", QApplication::font().pointSize()
#if defined (Q_OS_WIN32)
+1
#else
+2
#endif
);
installEventFilter(this);
}
void XCA_application::setupLanguage(QLocale l)
{
QStringList dirs;
lang = l;
if (qtTr) {
removeTranslator(qtTr);
delete qtTr;
}
qtTr = new XcaTranslator();
if (xcaTr) {
removeTranslator(xcaTr);
delete xcaTr;
}
xcaTr = new XcaTranslator();
dirs
#ifdef XCA_DEFAULT_QT_TRANSLATE
<< XCA_DEFAULT_QT_TRANSLATE
#endif
<< getI18nDir()
#ifndef WIN32
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
<< "/usr/local/share/qt5/translations/"
<< "/usr/share/qt5/translations/"
#else
<< "/usr/local/share/qt4/translations/"
<< "/usr/share/qt4/translations/"
#endif
<< "/usr/share/qt/translations/"
#endif
;
qDebug() << "Setup language: " << lang;
foreach(QString dir, dirs) {
if (qtTr->load(lang, "qt", dir)) {
break;
}
}
xcaTr->load(lang, "xca", getI18nDir());
QLocale::setDefault(l);
installTranslator(qtTr);
installTranslator(xcaTr);
if (mainw)
mainw->initResolver();
}
void XCA_application::quit()
{
if (mainw)
mainw->close();
}
void XCA_application::switchLanguage(QAction* a)
{
QLocale lang = a->data().toLocale();
setupLanguage(lang);
QFile file(defaultlang());
if (lang == QLocale::system()) {
file.remove();
return;
}
if (file.open(QIODevice::WriteOnly)) {
file.write(lang.name().toUtf8());
}
}
bool XCA_application::eventFilter(QObject *watched, QEvent *ev)
{
static int mctr;
QMouseEvent *me;
QStringList l;
XcaTreeView *treeview;
int key;
switch (ev->type()) {
case QEvent::FileOpen:
l << static_cast<QFileOpenEvent *>(ev)->file();
mainw->openURLs(l);
return true;
case QEvent::MouseMove:
case QEvent::NonClientAreaMouseMove:
if (mctr++ > 8) {
me = static_cast<QMouseEvent *>(ev);
entropy.add(me->globalX());
entropy.add(me->globalY());
mctr = 0;
}
break;
case QEvent::KeyPress:
key = static_cast<QKeyEvent *>(ev)->key();
if (key < 0x100) {
entropy.add(key);
}
break;
case QEvent::MouseButtonPress:
me = static_cast<QMouseEvent *>(ev);
treeview = watched ?
dynamic_cast<XcaTreeView*>(watched->parent()) : NULL;
if ((watched == mainw || treeview) &&
me->button() == Qt::MidButton &&
QApplication::clipboard()->supportsSelection())
{
mainw->pastePem();
return true;
}
break;
default:
break;
}
return false;
}
bool XCA_application::notify(QObject* receiver, QEvent* event)
{
try {
return QApplication::notify(receiver, event);
} catch (errorEx &err) {
mainw->Error(err);
} catch (...) {
qDebug() << QString("Event exception: ")
<< receiver << event;
abort();
}
return false;
}
XCA_application::~XCA_application()
{
}
char segv_data[1024];
#if defined(Q_OS_WIN32)
static LONG CALLBACK w32_segfault(LPEXCEPTION_POINTERS e)
{
if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
if (segv_data[0]) {
XCA_WARN(QString(segv_data));
abort();
}
return EXCEPTION_CONTINUE_EXECUTION;
} else
return EXCEPTION_CONTINUE_SEARCH;
}
#else
static void segv_handler_gui(int)
{
if (segv_data[0])
XCA_WARN(QString(segv_data));
abort();
}
#endif
#define CYAN "\x1b[0;36m"
#define LRED "\x1b[0;92m"
#define YELL "\x1b[0;33m"
#define RED "\x1b[0;31m"
#define RESET "\x1b[0m"
void myMsgOutput(QtMsgType type, const char *msg)
{
static QTime *t;
static int debug;
if (!t) {
char *d = getenv("XCA_DEBUG");
t = new QTime();
t->start();
if (d && *d)
debug = 1;
}
int el = t->elapsed();
const char *severity = "Unknown";
switch (type) {
case QtDebugMsg:
if (!debug)
return;
severity = CYAN "Debug";
break;
case QtWarningMsg: severity = LRED "Warning"; break;
case QtCriticalMsg: severity = RED "Critical"; break;
case QtFatalMsg: severity = RED "Fatal"; break;
#if QT_VERSION >= 0x050000
case QtInfoMsg: severity = CYAN "Info"; break;
#endif
default: severity = CYAN "Default"; break;
}
fprintf(stderr, YELL "% 4d.%02d %s:" RESET " %s\n",
el/1000, (el%1000)/100, severity, msg);
}
#if QT_VERSION >= 0x050000
void myMessageOutput(QtMsgType t, const QMessageLogContext &, const QString &m)
{
myMsgOutput(t, CCHAR(m));
}
#endif
int main( int argc, char *argv[] )
{
int ret = 0;
MainWindow *mw;
QDir d;
#if defined(Q_OS_WIN32)
SetUnhandledExceptionFilter(w32_segfault);
#else
signal(SIGSEGV, segv_handler_gui);
#endif
d.mkpath(getUserSettingsDir());
#if QT_VERSION < 0x050000
qInstallMsgHandler(myMsgOutput);
#else
qInstallMessageHandler(myMessageOutput);
#endif
initOIDs();
XCA_application a(argc, argv);
mw = new MainWindow(NULL);
try {
a.setMainwin(mw);
OpenDb::checkSqLite();
mw->read_cmdline(argc, argv);
if (mw->exitApp == 0) {
mw->load_history();
if (mw->open_default_db() != 2) {
mw->show();
ret = a.exec();
}
}
} catch (errorEx &ex) {
mw->Error(ex);
}
delete mw;
return ret;
}