diff --git a/plugins/devtoolsplugin/devtoolsplugin.cpp b/plugins/devtoolsplugin/devtoolsplugin.cpp new file mode 100644 index 0000000..3174313 --- /dev/null +++ b/plugins/devtoolsplugin/devtoolsplugin.cpp @@ -0,0 +1,62 @@ +#include "devtoolsplugin.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "mainwindow.h" + +#include "logmodel.h" +#include "logdialog.h" + +std::shared_ptr model; +QtMessageHandler previousHandler; + +void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message) +{ + previousHandler(type, context, message); + + if(!model) + model = std::make_shared(); + model->log(type, context.file, context.line, context.function, context.category, message); +} + +void registerMessageHandler() +{ + previousHandler = qInstallMessageHandler(myMessageHandler); +} + +Q_COREAPP_STARTUP_FUNCTION(registerMessageHandler) + +DevToolsPlugin::DevToolsPlugin(QObject *parent) : + ZeiterfassungPlugin(parent) +{ + qDebug() << "called"; + + static auto dir = QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(QStringLiteral("translations")); + + if(m_translator.load(QLocale(), QStringLiteral("devtoolsplugin"), QStringLiteral("_"), dir)) + { + if(!QCoreApplication::installTranslator(&m_translator)) + { + qWarning() << "could not install translation devtoolsplugin"; + } + } + else + { + qWarning() << "could not load translation devtoolsplugin"; + } +} + +void DevToolsPlugin::attachTo(MainWindow &mainWindow) +{ + auto dialog = new LogDialog(&mainWindow); + dialog->setModel(model.get()); + mainWindow.menuTools()->addAction(QIcon(QStringLiteral(":/zeiterfassung/plugins/devtoolsplugin/images/dev-tools.png")), + tr("Show log"), dialog, &QDialog::open); +} diff --git a/plugins/devtoolsplugin/devtoolsplugin.h b/plugins/devtoolsplugin/devtoolsplugin.h new file mode 100644 index 0000000..f02e084 --- /dev/null +++ b/plugins/devtoolsplugin/devtoolsplugin.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +#include "zeiterfassungplugin.h" + +class Q_DECL_EXPORT DevToolsPlugin : public ZeiterfassungPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "dbsoftware.zeiterfassung.plugin/1.0" FILE "devtoolsplugin.json") + Q_INTERFACES(ZeiterfassungPlugin) + +public: + explicit DevToolsPlugin(QObject *parent = Q_NULLPTR); + + // ZeiterfassungPlugin interface + void attachTo(MainWindow &mainWindow) Q_DECL_OVERRIDE; + +private: + QTranslator m_translator; +}; diff --git a/plugins/devtoolsplugin/devtoolsplugin.json b/plugins/devtoolsplugin/devtoolsplugin.json new file mode 100644 index 0000000..e69de29 diff --git a/plugins/devtoolsplugin/devtoolsplugin.pro b/plugins/devtoolsplugin/devtoolsplugin.pro new file mode 100644 index 0000000..424bf9e --- /dev/null +++ b/plugins/devtoolsplugin/devtoolsplugin.pro @@ -0,0 +1,40 @@ +QT += core network gui widgets + +TARGET = devtoolsplugin +TEMPLATE = lib + +CONFIG += shared c++14 + +DESTDIR = $${OUT_PWD}/../../bin/plugins/zeiterfassung + +LIBS += -L$$OUT_PWD/../../lib -lzeiterfassungcorelib -lzeiterfassungguilib + +INCLUDEPATH += $$PWD/../../zeiterfassungcorelib $$PWD/../../zeiterfassungguilib +DEPENDPATH += $$PWD/../../zeiterfassungcorelib $$PWD/../../zeiterfassungguilib + +DEFINES += QT_DEPRECATED_WARNINGS QT_DISABLE_DEPRECATED_BEFORE=0x060000 QT_MESSAGELOGCONTEXT + +HEADERS += devtoolsplugin.h \ + logmodel.h \ + logdialog.h + +SOURCES += devtoolsplugin.cpp \ + logmodel.cpp \ + logdialog.cpp + +FORMS += \ + logdialog.ui + +RESOURCES += devtoolsplugin_resources.qrc + +TRANSLATIONS += translations/devtoolsplugin_en.ts \ + translations/devtoolsplugin_de.ts + +OTHER_FILES += devtoolsplugin.json + +include(../../lrelease.pri) + +COMPILED_TRANSLATIONS += $${OUT_PWD}/translations/devtoolsplugin_en.qm \ + $${OUT_PWD}/translations/devtoolsplugin_de.qm + +include(../copy_translations.pri) diff --git a/plugins/devtoolsplugin/devtoolsplugin_resources.qrc b/plugins/devtoolsplugin/devtoolsplugin_resources.qrc new file mode 100644 index 0000000..5c8bd5c --- /dev/null +++ b/plugins/devtoolsplugin/devtoolsplugin_resources.qrc @@ -0,0 +1,5 @@ + + + images/dev-tools.png + + diff --git a/plugins/devtoolsplugin/images/dev-tools.png b/plugins/devtoolsplugin/images/dev-tools.png new file mode 100644 index 0000000..a12dbb0 Binary files /dev/null and b/plugins/devtoolsplugin/images/dev-tools.png differ diff --git a/plugins/devtoolsplugin/logdialog.cpp b/plugins/devtoolsplugin/logdialog.cpp new file mode 100644 index 0000000..8605398 --- /dev/null +++ b/plugins/devtoolsplugin/logdialog.cpp @@ -0,0 +1,19 @@ +#include "logdialog.h" +#include "ui_logdialog.h" + +LogDialog::LogDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::LogDialog) +{ + ui->setupUi(this); +} + +LogDialog::~LogDialog() +{ + delete ui; +} + +void LogDialog::setModel(QAbstractItemModel *model) +{ + ui->treeView->setModel(model); +} diff --git a/plugins/devtoolsplugin/logdialog.h b/plugins/devtoolsplugin/logdialog.h new file mode 100644 index 0000000..52ae161 --- /dev/null +++ b/plugins/devtoolsplugin/logdialog.h @@ -0,0 +1,24 @@ +#ifndef LOGDIALOG_H +#define LOGDIALOG_H + +#include + +class QAbstractItemModel; + +namespace Ui { class LogDialog; } + +class LogDialog : public QDialog +{ + Q_OBJECT + +public: + explicit LogDialog(QWidget *parent = 0); + ~LogDialog(); + + void setModel(QAbstractItemModel *model); + +private: + Ui::LogDialog *ui; +}; + +#endif // LOGDIALOG_H diff --git a/plugins/devtoolsplugin/logdialog.ui b/plugins/devtoolsplugin/logdialog.ui new file mode 100644 index 0000000..583dbcc --- /dev/null +++ b/plugins/devtoolsplugin/logdialog.ui @@ -0,0 +1,67 @@ + + + LogDialog + + + + 0 + 0 + 694 + 300 + + + + Log + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + buttonBox + accepted() + LogDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + LogDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/plugins/devtoolsplugin/logmodel.cpp b/plugins/devtoolsplugin/logmodel.cpp new file mode 100644 index 0000000..ad71ceb --- /dev/null +++ b/plugins/devtoolsplugin/logmodel.cpp @@ -0,0 +1,80 @@ +#include "logmodel.h" + +LogModel::LogModel(QObject *parent) : + QAbstractListModel(parent) +{ +} + +void LogModel::log(QtMsgType type, const char *fileName, int lineNumber, const char *functionName, const char *categoryName, const QString &message) +{ + beginInsertRows(QModelIndex(), m_entries.count(), m_entries.count()); + m_entries.append(Entry { QDateTime::currentDateTime(), type, fileName, lineNumber, functionName, categoryName, message }); + endInsertRows(); +} + +int LogModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + return m_entries.count(); +} + +int LogModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + return 4; +} + +QVariant LogModel::data(const QModelIndex &index, int role) const +{ + Q_ASSERT(index.row() < m_entries.count()); + const auto &entry = m_entries.at(index.row()); + + switch(role) + { + case Qt::DisplayRole: + case Qt::EditRole: + switch(index.column()) + { + case 0: + { + switch(entry.type) + { + case QtDebugMsg: return tr("Debug"); + case QtWarningMsg: return tr("Warning"); + case QtCriticalMsg: return tr("Critical"); + case QtFatalMsg: return tr("Fatal"); + case QtInfoMsg: return tr("Info"); + } + } + case 1: return entry.dateTime.toString(QStringLiteral("dd.MM.yyyy HH:mm:ss.zzz")); + case 2: return entry.functionName; + case 3: return entry.message; + } + } + + return QVariant(); +} + +QVariant LogModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + switch(orientation) + { + case Qt::Horizontal: + switch(role) + { + case Qt::DisplayRole: + case Qt::EditRole: + switch(section) + { + case 0: return tr("Type"); + case 1: return tr("Timestamp"); + case 2: return tr("Function"); + case 3: return tr("Message"); + } + } + default: + qt_noop(); + } + + return QVariant(); +} diff --git a/plugins/devtoolsplugin/logmodel.h b/plugins/devtoolsplugin/logmodel.h new file mode 100644 index 0000000..75d9eb5 --- /dev/null +++ b/plugins/devtoolsplugin/logmodel.h @@ -0,0 +1,39 @@ +#ifndef LOGMODEL_H +#define LOGMODEL_H + +#include +#include +#include +#include + +class LogModel : public QAbstractListModel +{ + Q_OBJECT + +public: + explicit LogModel(QObject *parent = Q_NULLPTR); + + void log(QtMsgType type, const char *fileName, int lineNumber, const char *functionName, const char *categoryName, const QString &message); + + // QAbstractItemModel interface + int rowCount(const QModelIndex &parent) const Q_DECL_OVERRIDE; + int columnCount(const QModelIndex &parent) const Q_DECL_OVERRIDE; + QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE; + QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE; + +private: + struct Entry + { + QDateTime dateTime; + QtMsgType type; + const char *fileName; + int lineNumber; + const char *functionName; + const char *categoryName; + QString message; + }; + + QList m_entries; +}; + +#endif // LOGMODEL_H diff --git a/plugins/devtoolsplugin/translations/devtoolsplugin_de.ts b/plugins/devtoolsplugin/translations/devtoolsplugin_de.ts new file mode 100644 index 0000000..f0cf20a --- /dev/null +++ b/plugins/devtoolsplugin/translations/devtoolsplugin_de.ts @@ -0,0 +1,57 @@ + + + + + DevToolsPlugin + + Show log + Log anzeigen + + + + LogDialog + + Log + Log + + + + LogModel + + Type + Typ + + + Timestamp + Zeitpunkt + + + Function + Funktion + + + Message + Nachricht + + + Debug + Debug + + + Warning + Warnung + + + Critical + Kritisch + + + Fatal + Fatal + + + Info + Info + + + diff --git a/plugins/devtoolsplugin/translations/devtoolsplugin_en.ts b/plugins/devtoolsplugin/translations/devtoolsplugin_en.ts new file mode 100644 index 0000000..93ffe55 --- /dev/null +++ b/plugins/devtoolsplugin/translations/devtoolsplugin_en.ts @@ -0,0 +1,57 @@ + + + + + DevToolsPlugin + + Show log + + + + + LogDialog + + Log + + + + + LogModel + + Type + + + + Timestamp + + + + Function + + + + Message + + + + Debug + + + + Warning + + + + Critical + + + + Fatal + + + + Info + + + + diff --git a/plugins/plugins.pro b/plugins/plugins.pro index f8c26c3..dab007d 100644 --- a/plugins/plugins.pro +++ b/plugins/plugins.pro @@ -1,6 +1,7 @@ TEMPLATE = subdirs SUBDIRS += advancedviewplugin \ + devtoolsplugin \ lunchmealplugin \ presenceplugin \ reportsplugin \ diff --git a/zeiterfassung/main.cpp b/zeiterfassung/main.cpp index 4b6c39a..2d5eb51 100755 --- a/zeiterfassung/main.cpp +++ b/zeiterfassung/main.cpp @@ -1,3 +1,5 @@ +#include + #include #include #include @@ -32,7 +34,7 @@ struct { QTranslator zeiterfassungguilibTranslator; } translators; -QVector plugins; +QVector > pluginLoaders; bool loadAndInstallTranslator(QTranslator &translator, const QString &filename) { @@ -270,44 +272,25 @@ bool loadPlugins(QSplashScreen &splashScreen) ).absoluteFilePath(QStringLiteral("zeiterfassung")) ); - for(const auto &fileInfo : dir.entryInfoList(QDir::Files)) + for(const auto &fileInfo : dir.entryInfoList(QDir::Files | QDir::NoSymLinks)) { - if(fileInfo.isSymLink()) - { - qWarning() << "skipping" << fileInfo.fileName() << "because symlink"; - continue; // to skip unix so symlinks - } - if(!QLibrary::isLibrary(fileInfo.filePath())) { qWarning() << "skipping" << fileInfo.fileName() << "because no QLibrary"; continue; // to skip windows junk files } - qDebug() << "loading" << fileInfo.fileName(); - - QPluginLoader loader(fileInfo.filePath()); - if(!loader.load()) + auto pluginLoader = std::make_shared(fileInfo.filePath()); + if(!pluginLoader->load()) { QMessageBox::warning(&splashScreen, QCoreApplication::translate("main", "Could not load plugin %0!"), QCoreApplication::translate("main", "Could not load plugin %0!").arg(fileInfo.fileName()) % - "\n\n" % loader.errorString()); + "\n\n" % pluginLoader->errorString()); ok = false; continue; } - auto plugin = qobject_cast(loader.instance()); - - if(!plugin) - { - QMessageBox::warning(&splashScreen, QCoreApplication::translate("main", "Plugin not valid %0!"), - QCoreApplication::translate("main", "Plugin not valid %0!").arg(fileInfo.fileName()) % - "\n\n" % loader.errorString()); - ok = false; - continue; - } - - plugins.append(plugin); + pluginLoaders.append(pluginLoader); } return ok; @@ -370,8 +353,13 @@ int main(int argc, char *argv[]) MainWindow mainWindow(settings, erfassung, userInfo, stripFactory); splashScreen.finish(&mainWindow); - for(auto plugin : plugins) - plugin->attachTo(mainWindow); + for(auto &pluginLoader : pluginLoaders) + if(auto plugin = qobject_cast(pluginLoader->instance())) + plugin->attachTo(mainWindow); + else + QMessageBox::warning(&splashScreen, QCoreApplication::translate("main", "Plugin not valid %0!"), + QCoreApplication::translate("main", "Plugin not valid %0!").arg(pluginLoader->fileName()) % + "\n\n" % pluginLoader->errorString()); mainWindow.show();