From: Enar Väikene Date: Wed, 19 Oct 2011 12:58:22 +0000 (+0300) Subject: Merge branch 'master' of ssh://server/var/gitpub/evaf X-Git-Url: https://vaikene.ee/gitweb/highlight.css?a=commitdiff_plain;h=0957525838e501a4609a15b8d7a765da43362025;hp=39a073ff1e5397e9be1a8f16d2aa48d0ace01112;p=evaf Merge branch 'master' of ssh://server/var/gitpub/evaf --- diff --git a/CMakeLists.txt b/CMakeLists.txt index f7baf28..ddff8df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ endif(COMMAND cmake_policy) set(CMAKE_MODULE_PATH ${eVaf_SOURCE_DIR}/mk/cmake) # Find Qt4 -find_package(Qt4 REQUIRED) +find_package(Qt4 4.6 REQUIRED) # Default to the Debug build type if none is specified IF(NOT CMAKE_BUILD_TYPE) diff --git a/src/apps/PswGen/GUI/CMakeLists.txt b/src/apps/PswGen/GUI/CMakeLists.txt index 060625b..329cd17 100644 --- a/src/apps/PswGen/GUI/CMakeLists.txt +++ b/src/apps/PswGen/GUI/CMakeLists.txt @@ -8,7 +8,7 @@ include(${QT_USE_FILE}) include_directories(${eVaf_INCLUDE}) # Required eVaf libraries -set(eVaf_LIBRARIES CommonLib PluginsLib SdiWindow) +set(eVaf_LIBRARIES CommonLib PluginsLib) # Source files set(SRCS diff --git a/src/apps/PswGen/GUI/gui.h b/src/apps/PswGen/GUI/gui.h index 9102945..d3c89d4 100644 --- a/src/apps/PswGen/GUI/gui.h +++ b/src/apps/PswGen/GUI/gui.h @@ -43,6 +43,7 @@ namespace GUI { class Module : public Plugins::iPlugin { Q_OBJECT + Q_INTERFACES(eVaf::Plugins::iPlugin) public: diff --git a/src/apps/PswGen/Generator/module.h b/src/apps/PswGen/Generator/module.h index 927adc6..90affff 100644 --- a/src/apps/PswGen/Generator/module.h +++ b/src/apps/PswGen/Generator/module.h @@ -44,6 +44,7 @@ namespace Internal { class Module : public Plugins::iPlugin { Q_OBJECT + Q_INTERFACES(eVaf::Plugins::iPlugin) public: diff --git a/src/apps/PswGen/Storage/module.h b/src/apps/PswGen/Storage/module.h index ae784e9..95b935f 100644 --- a/src/apps/PswGen/Storage/module.h +++ b/src/apps/PswGen/Storage/module.h @@ -48,6 +48,7 @@ namespace Internal { class Module : public Plugins::iPlugin { Q_OBJECT + Q_INTERFACES(eVaf::Plugins::iPlugin) public: diff --git a/src/libs/Common/eventqueue.cpp b/src/libs/Common/eventqueue.cpp index bbf30ed..33e73c0 100644 --- a/src/libs/Common/eventqueue.cpp +++ b/src/libs/Common/eventqueue.cpp @@ -67,20 +67,20 @@ bool EventQueue::event(QEvent * e) } // Send the event to all the subscribers - QHash > >::const_iterator subscribersIt = mSubscribers.constFind(id); + QHash > >::const_iterator subscribersIt = mSubscribers.constFind(id); if (subscribersIt != mSubscribers.constEnd()) { - QList > subscribers = *subscribersIt; + QVector > subscribers = *subscribersIt; int sz = subscribers.size(); for (int i = 0; i < sz; ++i) { // Get the subscriber object and make sure that it is still alive - QPointer obj = subscribers.at(i); + QWeakPointer obj = subscribers.at(i); if (obj.isNull()) { continue; } // Notify the subscriber - bool rval = QCoreApplication::sendEvent(obj, e); + bool rval = QCoreApplication::sendEvent(obj.data(), e); if (rval) { // The event was consumed and should be sent to any other subscribers @@ -146,7 +146,15 @@ void EventQueue::unsubscribeEvent(uint id, QObject * obj) if (mEvents.constFind(id) == mEvents.constEnd()) return; - mSubscribers[id].removeAll(obj); + // Remove from the list of subscribers + QVector >::iterator it = mSubscribers[id].begin(); + QVector >::iterator e = mSubscribers[id].end(); + while (it != e) { + if (!it->isNull() && it->data() == obj) + it = mSubscribers[id].erase(it); + else + ++it; + } } void EventQueue::broadcastEvent(Event * event) diff --git a/src/libs/Common/eventqueue.h b/src/libs/Common/eventqueue.h index 92bcb06..b029376 100644 --- a/src/libs/Common/eventqueue.h +++ b/src/libs/Common/eventqueue.h @@ -25,8 +25,8 @@ #include #include #include -#include -#include +#include +#include namespace eVaf { @@ -75,7 +75,7 @@ private: // Members QHash mEvents; /// List of subscribers - QHash > > mSubscribers; + QHash > > mSubscribers; }; diff --git a/src/libs/Common/ilogger.h b/src/libs/Common/ilogger.h index 7c91585..71dbd14 100644 --- a/src/libs/Common/ilogger.h +++ b/src/libs/Common/ilogger.h @@ -62,7 +62,8 @@ public: Error, ///< Unexpected issues in the software that could be solved automatically. Warning, ///< Expected issues in the software that will be solved automatically. Info, ///< General information output by the application or modules. - Debug ///< Information for debugging purposes. + Debug, ///< Information for debugging purposes. + Count ///< Number of severity levels }; /// Interface constructor @@ -240,7 +241,7 @@ signals: * your receiver to this signal if you want to add your own message handling. For example, * use this signal to show messages in a log window etc. */ - void loggerEvent(eVaf::Common::iLogger::Severity severity, QString const & text, QString const & source, QString const & where); + void loggerEvent(Common::iLogger::Severity severity, QString const & text, QString const & source, QString const & where); }; diff --git a/src/libs/Common/logger.cpp b/src/libs/Common/logger.cpp index c7a50dd..01d5687 100644 --- a/src/libs/Common/logger.cpp +++ b/src/libs/Common/logger.cpp @@ -160,7 +160,7 @@ Logger::Logger() Logger::~Logger() { // Disconnect any potential receivers from this object - disconnect(this, SIGNAL(loggerEvent(eVaf::Common::iLogger::Severity,QString,QString,QString)), 0, 0); + disconnect(this, SIGNAL(loggerEvent(Common::iLogger::Severity,QString,QString,QString)), 0, 0); // Destroy the worker thread if (mWorker) { diff --git a/src/libs/Common/registry.cpp b/src/libs/Common/registry.cpp index d93e469..661d2c7 100644 --- a/src/libs/Common/registry.cpp +++ b/src/libs/Common/registry.cpp @@ -54,13 +54,13 @@ Registry::~Registry() bool Registry::registerInterface(QString const & name, QObject * obj) { - mInterfaces.insert(name, QPointer(obj)); + mInterfaces.insert(name, QWeakPointer(obj)); return true; } QObject * Registry::queryInterface(QString const & name) const { - QHash >::const_iterator it = mInterfaces.constFind(name); - return it != mInterfaces.constEnd() ? *it : 0; + QHash >::const_iterator it = mInterfaces.constFind(name); + return it != mInterfaces.constEnd() ? (*it).data() : 0; } diff --git a/src/libs/Common/registry.h b/src/libs/Common/registry.h index 1046c48..9c05c50 100644 --- a/src/libs/Common/registry.h +++ b/src/libs/Common/registry.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include namespace eVaf { @@ -35,7 +35,7 @@ namespace Internal { * iRegistry interface implementation. * * This class implements the global registry for interfaces. Interfaces are stored in a QHash container - * and quarded with QPointer. + * and quarded with QWeakPointer. */ class Registry : public iRegistry { @@ -59,7 +59,7 @@ public: private: /// All the registered interfaces - QHash > mInterfaces; + QHash > mInterfaces; }; diff --git a/src/libs/Common/version.h b/src/libs/Common/version.h index 7584798..b99636f 100644 --- a/src/libs/Common/version.h +++ b/src/libs/Common/version.h @@ -25,12 +25,12 @@ /** * Module/library version number in the form major,minor,release,build */ -#define VER_FILE_VERSION 0,1,1,3 +#define VER_FILE_VERSION 0,1,2,5 /** * Module/library version number in the string format (shall end with \0) */ -#define VER_FILE_VERSION_STR "0.1.1.3\0" +#define VER_FILE_VERSION_STR "0.1.2.5\0" /** * Module/library name (shall end with \0) diff --git a/src/libs/Plugins/iplugin.h b/src/libs/Plugins/iplugin.h index 4b8b198..f83bbbc 100644 --- a/src/libs/Plugins/iplugin.h +++ b/src/libs/Plugins/iplugin.h @@ -91,4 +91,6 @@ public: } // namespace eVaf::Plugins } // namespace eVaf +Q_DECLARE_INTERFACE(eVaf::Plugins::iPlugin, "eVaf.Plugins.iPlugin/1.0") + #endif // iplugin.h diff --git a/src/libs/Plugins/ipluginfactory.h b/src/libs/Plugins/ipluginfactory.h index 59f64ca..ea3e9cb 100644 --- a/src/libs/Plugins/ipluginfactory.h +++ b/src/libs/Plugins/ipluginfactory.h @@ -70,4 +70,6 @@ public: } // namespace eVaf::Plugins } // namespace eVaf +Q_DECLARE_INTERFACE(eVaf::Plugins::iPluginFactory, "eVaf.Plugins.iPluginFactory/1.0") + #endif // ipluginfactory.h diff --git a/src/libs/Plugins/version.h b/src/libs/Plugins/version.h index 219a10a..cbf8f0f 100644 --- a/src/libs/Plugins/version.h +++ b/src/libs/Plugins/version.h @@ -25,12 +25,12 @@ /** * Module/library version number in the form major,minor,release,build */ -#define VER_FILE_VERSION 0,1,2,4 +#define VER_FILE_VERSION 0,1,3,5 /** * Module/library version number in the string format (shall end with \0) */ -#define VER_FILE_VERSION_STR "0.1.2.4\0" +#define VER_FILE_VERSION_STR "0.1.3.5\0" /** * Module/library name (shall end with \0) diff --git a/src/main/CLI/main.cpp b/src/main/CLI/main.cpp index 51d5f51..4e8fe7e 100644 --- a/src/main/CLI/main.cpp +++ b/src/main/CLI/main.cpp @@ -178,7 +178,7 @@ bool Application::processCommandLine(int argc, char ** argv) case Common::iLogger::Info: consoleSeverityLevel = Common::iLogger::Debug; break; - case Common::iLogger::Debug: + default: break; } } diff --git a/src/main/CLI/version.h b/src/main/CLI/version.h index 5d43974..25d61e2 100644 --- a/src/main/CLI/version.h +++ b/src/main/CLI/version.h @@ -25,12 +25,12 @@ /** * Module/library version number in the form major,minor,release,build */ -#define VER_FILE_VERSION 0,1,1,1 +#define VER_FILE_VERSION 0,1,1,2 /** * Module/library version number in the string format (shall end with \0) */ -#define VER_FILE_VERSION_STR "0.1.1.1\0" +#define VER_FILE_VERSION_STR "0.1.1.2\0" /** * Module/library name (shall end with \0) diff --git a/src/main/GUI/main.cpp b/src/main/GUI/main.cpp index 30f1500..c30e7ad 100644 --- a/src/main/GUI/main.cpp +++ b/src/main/GUI/main.cpp @@ -234,7 +234,7 @@ bool Application::processCommandLine(int argc, char ** argv) case Common::iLogger::Info: Internal::ConsoleSeverityLevel = Common::iLogger::Debug; break; - case Common::iLogger::Debug: + default: break; } } diff --git a/src/main/GUI/version.h b/src/main/GUI/version.h index 2a6c047..b593649 100644 --- a/src/main/GUI/version.h +++ b/src/main/GUI/version.h @@ -25,12 +25,12 @@ /** * Module/library version number in the form major,minor,release,build */ -#define VER_FILE_VERSION 0,1,1,3 +#define VER_FILE_VERSION 0,1,1,4 /** * Module/library version number in the string format (shall end with \0) */ -#define VER_FILE_VERSION_STR "0.1.1.3\0" +#define VER_FILE_VERSION_STR "0.1.1.4\0" /** * Module/library name (shall end with \0) diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index 7c1d85c..133d289 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(SdiWindow) +add_subdirectory(LogView) add_subdirectory(Test) diff --git a/src/plugins/LogView/CMakeLists.txt b/src/plugins/LogView/CMakeLists.txt new file mode 100644 index 0000000..557cacc --- /dev/null +++ b/src/plugins/LogView/CMakeLists.txt @@ -0,0 +1,39 @@ +# Name of the target +set(TARGET LogView) + +# Qt modules +include(${QT_USE_FILE}) + +# Needed for exporting/importing symbols +add_definitions(-DLOGVIEW_LIBRARY) + +# Include files +include_directories(${eVaf_INCLUDE}) + +# Required eVaf libraries +set(eVaf_LIBRARIES CommonLib PluginsLib) + +# Source files +set(SRCS + factory.cpp + logview.cpp +) + +# Header files for the meta-object compiler +set(MOC_HDRS + factory.h + logview.h +) + +# Version info resource file for Windows builds +if(WIN32) + set(SRCS ${SRCS} version.rc) +endif(WIN32) + +qt4_wrap_cpp(MOC_SRCS ${MOC_HDRS}) + +add_library(${TARGET} SHARED ${SRCS} ${MOC_SRCS}) + +target_link_libraries(${TARGET} ${QT_LIBRARIES} ${eVaf_LIBRARIES}) + +install(TARGETS ${TARGET} DESTINATION bin) diff --git a/src/plugins/LogView/factory.cpp b/src/plugins/LogView/factory.cpp new file mode 100644 index 0000000..c4d5d09 --- /dev/null +++ b/src/plugins/LogView/factory.cpp @@ -0,0 +1,60 @@ +/** + * @file LogView/factory.cpp + * @brief LogView module's factory class + * @author Enar Vaikene + * + * Copyright (c) 2011 Enar Vaikene + * + * This file is part of the eVaf C++ cross-platform application development framework. + * + * This file can be used under the terms of the GNU General Public License + * version 3.0 as published by the Free Software Foundation and appearing in + * the file LICENSE included in the packaging of this file. Please review the + * the following information to ensure the GNU General Public License version + * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. + * + * Alternatively, this file may be used in accordance with the Commercial License + * Agreement provided with the Software. + */ + +#include "factory.h" +#include "logview.h" +#include "version.h" + +#include + +#include + +using namespace eVaf::LogView; + +VER_EXPORT_VERSION_INFO() +Q_EXPORT_PLUGIN2(VER_MODULE_NAME_STR, Factory) + + +//------------------------------------------------------------------- + +Factory::Factory() + : Plugins::iPluginFactory() + , mPlugin(0) +{ + setObjectName(QString("%1-Factory").arg(VER_MODULE_NAME_STR)); + + EVAF_INFO("%s created", qPrintable(objectName())); +} + +Factory::~Factory() +{ + if (mPlugin) + delete mPlugin; + + EVAF_INFO("%s destroyed", qPrintable(objectName())); +} + +QObject * Factory::create(QString const & name) +{ + Q_UNUSED(name); + + if (mPlugin == 0) + mPlugin = new Internal::Module; + return mPlugin; +} diff --git a/src/plugins/LogView/factory.h b/src/plugins/LogView/factory.h new file mode 100644 index 0000000..4d36f91 --- /dev/null +++ b/src/plugins/LogView/factory.h @@ -0,0 +1,58 @@ +/** + * @file LogView/factory.h + * @brief LogView module's factory class + * @author Enar Vaikene + * + * Copyright (c) 2011 Enar Vaikene + * + * This file is part of the eVaf C++ cross-platform application development framework. + * + * This file can be used under the terms of the GNU General Public License + * version 3.0 as published by the Free Software Foundation and appearing in + * the file LICENSE included in the packaging of this file. Please review the + * the following information to ensure the GNU General Public License version + * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. + * + * Alternatively, this file may be used in accordance with the Commercial License + * Agreement provided with the Software. + */ + +#ifndef __LOGVIEW_FACTORY_H +# define __LOGVIEW_FACTORY_H + +#include + +namespace eVaf { +namespace LogView { +namespace Internal { + class Module; +} // namespace eVaf::LogView::Internal + + +/** + * Plugin factory class for the module + */ +class Factory : public Plugins::iPluginFactory +{ + Q_OBJECT + Q_INTERFACES(eVaf::Plugins::iPluginFactory) + +public: + + Factory(); + + virtual ~Factory(); + + virtual QObject * create(QString const & name); + + +private: // Members + + Internal::Module * mPlugin; + +}; + +} // namespace eVaf::LogView +} // namespace eVaf + +#endif // factory.h diff --git a/src/plugins/LogView/liblogview.h b/src/plugins/LogView/liblogview.h new file mode 100644 index 0000000..1f88060 --- /dev/null +++ b/src/plugins/LogView/liblogview.h @@ -0,0 +1,30 @@ +/** + * @file LogView/liblogview.h + * @author Enar Vaikene + * + * Copyright (c) 2011 Enar Vaikene + * + * This file is part of the eVaf C++ cross-platform application development framework. + * + * This file can be used under the terms of the GNU General Public License + * version 3.0 as published by the Free Software Foundation and appearing in + * the file LICENSE included in the packaging of this file. Please review the + * the following information to ensure the GNU General Public License version + * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. + * + * Alternatively, this file may be used in accordance with the Commercial License + * Agreement provided with the Software. + */ + +#ifndef __LOGVIEW_LIBLOGVIEW_H +# define __LOGVIEW_LIBLOGVIEW_H + +#include + +#if defined(LOGVIEW_LIBRARY) +# define LOGVIEW_EXPORT Q_DECL_EXPORT +#else +# define LOGVIEW_EXPORT Q_DECL_IMPORT +#endif + +#endif // liblogview.h diff --git a/src/plugins/LogView/logview.cpp b/src/plugins/LogView/logview.cpp new file mode 100644 index 0000000..2eaae97 --- /dev/null +++ b/src/plugins/LogView/logview.cpp @@ -0,0 +1,391 @@ +/** + * @file LogView/logview.cpp + * @brief Implementation of the LogView module + * @author Enar Vaikene + * + * Copyright (c) 2011 Enar Vaikene + * + * This file is part of the eVaf C++ cross-platform application development framework. + * + * This file can be used under the terms of the GNU General Public License + * version 3.0 as published by the Free Software Foundation and appearing in + * the file LICENSE included in the packaging of this file. Please review the + * the following information to ensure the GNU General Public License version + * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. + * + * Alternatively, this file may be used in accordance with the Commercial License + * Agreement provided with the Software. + */ + +#include "logview.h" +#include "version.h" + +#include +#include +#include + +#include + + +using namespace eVaf; +using namespace eVaf::LogView::Internal; + + +//------------------------------------------------------------------- + +int const Model::MaxLines = 1000; + +char const * const Model::SeverityText[Common::iLogger::Count] = { + QT_TR_NOOP("[NONE] "), + QT_TR_NOOP("[FATAL] "), + QT_TR_NOOP("[ERROR] "), + QT_TR_NOOP("[WARNING]"), + QT_TR_NOOP("[INFO] "), + QT_TR_NOOP("[DEBUG] ") +}; + +Model::Model(QObject * parent) + : QAbstractListModel(parent) +{ +} + +QVariant Model::data(QModelIndex const & index, int role) const +{ + if (!index.isValid() || index.row() < 0 || index.row() >= mData.size() || index.column() != 0) + return QVariant(); + + switch (role) { + + // Return the message for the display role + case Qt::DisplayRole: { + return mData.at(index.row()).simplified; + break; + } + + // Change color for different message types + case Qt::ForegroundRole: { + Common::iLogger::Severity s = mData.at(index.row()).severity; + switch (s) { + case Common::iLogger::Info: + return QBrush(QColor(Qt::blue)); + break; + case Common::iLogger::Warning: + return QBrush(QColor(Qt::black)); + break; + case Common::iLogger::Error: + case Common::iLogger::Fatal: + return QBrush(QColor(Qt::red)); + break; + default: + return QVariant(); + } + break; + } + } // switch (role) + + return QVariant(); +} + +void Model::addMessage(Common::iLogger::Severity severity, QString const & text, QString const & where) +{ + // Add the message to the end of the queue + beginInsertRows(QModelIndex(), mData.size(), mData.size()); + mData.enqueue(Message(severity, text, where)); + endInsertRows(); + + // Remove oldest messages if the list is full + if (mData.size() > MaxLines) { + beginRemoveRows(QModelIndex(), 0, 0); + mData.dequeue(); + endRemoveRows(); + } + + emit messageAdded(index(mData.size() - 1, 0)); +} + +QString Model::details(QModelIndex const & index) const +{ + Message const & m = mData.at(index.row()); + return tr("%1 %2 %3 : %4\nOccurred in %5") + .arg(m.dt.date().toString(Qt::DefaultLocaleShortDate)) + .arg(m.dt.time().toString("HH:mm:ss.zzz")) + .arg(tr(severityText(m.severity))) + .arg(m.text) + .arg(m.where); +} + +bool Model::copyToClipboard(QModelIndex const & index) +{ + mErrorString.clear(); + + QClipboard * cb = QApplication::clipboard(); + if (cb) { + cb->setText(details(index)); + return true; + } + else { + mErrorString = tr("The global clipboard is not available"); + return false; + } +} + +bool Model::saveToFile(QString const & fileName) +{ + mErrorString.clear(); + + QFile f(fileName); + if (!f.open(QFile::WriteOnly)) { + mErrorString = tr("Failed to open the file '%1' for writing : %2").arg(fileName).arg(f.errorString()); + return false; + } + + QTextStream out(&f); + + for (int i = 0; i < mData.size(); ++i) { + Message const & m = mData.at(i); + out << tr("%1 %2 %3 : %4 (occurred in %5)\n") + .arg(m.dt.date().toString(Qt::DefaultLocaleShortDate)) + .arg(m.dt.time().toString("HH:mm:ss.zzz")) + .arg(tr(severityText(m.severity))) + .arg(m.text) + .arg(m.where) + << endl; + } + + return true; +} + +char const * const Model::severityText(Common::iLogger::Severity s) const +{ + if (s >= Common::iLogger::None && s < Common::iLogger::Count) + return SeverityText[s]; + else + return SeverityText[Common::iLogger::None]; +} + + +//------------------------------------------------------------------- + +Widget::Widget(QString const & source, QWidget * parent) + : QWidget(parent) + , mSource(source) + , mAutoScroll(true) +{ + QVBoxLayout * w = new QVBoxLayout; + setLayout(w); + + mModel = new Model(this); + connect(mModel, SIGNAL(messageAdded(QModelIndex)), this, SLOT(messageAdded(QModelIndex))); + + wList = new QListView; + wList->setModel(mModel); + wList->setUniformItemSizes(true); + connect(wList->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(currentChanged(QModelIndex,QModelIndex))); + w->addWidget(wList); + + wList->setContextMenuPolicy(Qt::ActionsContextMenu); + + QAction * a = new QAction(tr("&Copy", VER_MODULE_NAME_STR), this); + a->setStatusTip(tr("Copies the selected message to the clipboard for pasting into other applications", VER_MODULE_NAME_STR)); + connect(a, SIGNAL(triggered()), this, SLOT(copyToClipboard())); + wList->addAction(a); + + a = new QAction(tr("&Save to ...", VER_MODULE_NAME_STR), this); + a->setStatusTip(tr("Saves all the messages to a file", VER_MODULE_NAME_STR)); + connect(a, SIGNAL(triggered()), this, SLOT(saveToFile())); + wList->addAction(a); + + wDetails = new QLabel; + wDetails->setWordWrap(true); + w->addWidget(wDetails); +} + +void Widget::messageAdded(QModelIndex const & index) +{ + if (mAutoScroll) + wList->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect); +} + +void Widget::currentChanged(QModelIndex const & current, QModelIndex const & previous) +{ + Q_UNUSED(previous); + + if (!current.isValid() || current.row() < 0 || current.row() > mModel->rowCount()) { + wDetails->clear(); + return; + } + + mAutoScroll = current.row() == (mModel->rowCount() - 1); + + wDetails->setText(mModel->details(current)); +} + +void Widget::copyToClipboard() +{ + QModelIndex idx = wList->selectionModel()->currentIndex(); + if (idx.isValid()) + mModel->copyToClipboard(idx); +} + +void Widget::saveToFile() +{ + QString fileName = QFileDialog::getSaveFileName(this, + tr("Save to file", VER_MODULE_NAME_STR), + Common::iApp::instance()->dataRootDir() + QString("%1_%2.txt").arg(mSource).arg(QDate::currentDate().toString("yyyyMMdd")), + tr("Text files (*.txt);;All files (*)", VER_MODULE_NAME_STR)); + if (fileName.isEmpty()) + return; + + if (!mModel->saveToFile(fileName)) + QMessageBox::critical(this, tr("Error", VER_MODULE_NAME_STR), mModel->errorString()); +} + + +//------------------------------------------------------------------- + +Window::Window(QWidget * parent, Qt::WindowFlags flags) + : QWidget(parent, flags) +{ + setObjectName(QString("%1-Window").arg(VER_MODULE_NAME_STR)); + + setWindowTitle(tr("Messages")); + + Common::iLogger * logger = Common::iLogger::instance(); + EVAF_TEST_X(logger, "No iLogger interface"); + + mDefSource = logger->defaultSource(); + if (mDefSource.isEmpty()) + mDefSource = "Common"; + + QVBoxLayout * w = new QVBoxLayout; + w->setMargin(0); + setLayout(w); + + wTabs = new QTabWidget; + w->addWidget(wTabs); + + // Add the default source + Widget * s = new Widget(mDefSource); + mLogViews.insert(s->source(), s); + wTabs->addTab(s, s->source()); + + wStatusBar = new QStatusBar; + w->addWidget(wStatusBar); + + QAction * a = new QAction(this); + a->setShortcut(Qt::Key_Escape); + connect(a, SIGNAL(triggered()), this, SLOT(close())); + addAction(a); + + restoreSettings(); + + connect(logger, SIGNAL(loggerEvent(Common::iLogger::Severity,QString,QString,QString)), this, SLOT(loggerEvent(Common::iLogger::Severity,QString,QString,QString))); + + show(); + + EVAF_INFO("%s created", qPrintable(objectName())); +} + +Window::~Window() +{ + mLogViews.clear(); + + saveSettings(); + + EVAF_INFO("%s destroyed", qPrintable(objectName())); +} + +bool Window::event(QEvent * e) +{ + if (e->type() == QEvent::StatusTip) { + QStatusTipEvent * event = static_cast(e); + wStatusBar->showMessage(event->tip()); + return true; + } + return QWidget::event(e); +} + +void Window::saveSettings() +{ + static int ver[4] = {VER_FILE_VERSION}; + QSettings settings(VER_COMPANY_NAME_STR, Common::iApp::instance()->name()); + settings.setValue(QString("%1/version/major").arg(objectName()), ver[0]); + settings.setValue(QString("%1/version/minor").arg(objectName()), ver[1]); + settings.setValue(QString("%1/geometry").arg(objectName()), saveGeometry()); +} + +void Window::restoreSettings() +{ + static int ver[4] = {VER_FILE_VERSION}; + QSettings settings(VER_COMPANY_NAME_STR, Common::iApp::instance()->name()); + + // Ignore saved settings if the version number is not the same + // More intelligent checks can be implemented to allow upgrading from previous versions + QVariant v = settings.value(QString("%1/version/major").arg(objectName())); + if (!v.isValid() || v.toInt() != ver[0]) + return; + v = settings.value(QString("%1/version/minor").arg(objectName())); + if (!v.isValid() || v.toInt() != ver[1]) + return; + + // Restore the geometry + restoreGeometry(settings.value(QString("%1/geometry").arg(objectName())).toByteArray()); +} + +void Window::loggerEvent(Common::iLogger::Severity severity, QString const & text, QString const & source, QString const & where) +{ + // Ignore messages with >=DEBUG severity level + if (severity >= Common::iLogger::Debug) + return; + + // Find or create the log view widget for this source + Widget * w = 0; + QString s = source.isEmpty() ? mDefSource : source; + QHash::const_iterator it = mLogViews.constFind(s); + if (it == mLogViews.constEnd()) { + w = new Widget(s); + mLogViews.insert(w->source(), w); + wTabs->addTab(w, w->source()); + } + else + w = *it; + + w->addMessage(severity, text, where); +} + + +//------------------------------------------------------------------- + +Module::Module() + : Plugins::iPlugin() + , wWindow(0) +{ + setObjectName(QString("%1-Module").arg(VER_MODULE_NAME_STR)); + EVAF_INFO("%s created", qPrintable(objectName())); +} + +Module::~Module() +{ + EVAF_INFO("%s destroyed", qPrintable(objectName())); +} + +bool Module::init(QString const & args) +{ + Q_UNUSED(args); + + wWindow = new Window(); + + EVAF_INFO("%s initialized", qPrintable(objectName())); + + return true; +} + +void Module::done() +{ + if (wWindow) { + delete wWindow; + wWindow = 0; + } + + EVAF_INFO("%s finalized", qPrintable(objectName())); +} diff --git a/src/plugins/LogView/logview.h b/src/plugins/LogView/logview.h new file mode 100644 index 0000000..1bfe6a8 --- /dev/null +++ b/src/plugins/LogView/logview.h @@ -0,0 +1,238 @@ +/** + * @file LogView/logview.h + * @brief Implementation of the LogView module + * @author Enar Vaikene + * + * Copyright (c) 2011 Enar Vaikene + * + * This file is part of the eVaf C++ cross-platform application development framework. + * + * This file can be used under the terms of the GNU General Public License + * version 3.0 as published by the Free Software Foundation and appearing in + * the file LICENSE included in the packaging of this file. Please review the + * the following information to ensure the GNU General Public License version + * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. + * + * Alternatively, this file may be used in accordance with the Commercial License + * Agreement provided with the Software. + */ + +#ifndef __LOGVIEW_LOGVIEW_H +# define __LOGVIEW_LOGVIEW_H + +#include +#include + +#include +#include +#include +#include +#include +#include + +class QListView; +class QLabel; +class QTabWidget; +class QStatusBar; +class QEvent; + +namespace eVaf { + +/** + * Module for showing messages output with the eVaf::Common::iLogger interface. + * + * The LogView module implements a widget that shows all the messages output with the + * eVaf::Common::iLogger interface. + */ +namespace LogView { + +/** + * Internal implementation of the LogView module. + */ +namespace Internal { + +/** + * Data model for the log view widget + */ +class Model : public QAbstractListModel +{ + Q_OBJECT + +public: + + /// One logger message + struct Message + { + Message(Common::iLogger::Severity s, QString const & t, QString const & w) + : dt(QDateTime::currentDateTime()) + , severity(s) + , text(t) + , simplified(t.simplified()) + , where(w) + {} + + QDateTime dt; + Common::iLogger::Severity severity; + QString text; + QString simplified; + QString where; + }; + + Model(QObject * parent = 0); + + Message const & messageAt(int idx) const { return mData.at(idx); } + + virtual int rowCount(QModelIndex const & parent = QModelIndex()) const { return mData.size(); } + + virtual QVariant data(QModelIndex const & index, int role = Qt::DisplayRole) const; + + void addMessage(Common::iLogger::Severity severity, QString const & text, QString const & where); + + QString details(QModelIndex const & index) const; + + bool saveToFile(QString const & fileName); + + bool copyToClipboard(QModelIndex const & index); + + QString errorString() const { return mErrorString; } + + +signals: + + void messageAdded(QModelIndex const & index); + + +private: // Members + + /// Maximum number of lines in the queue + static int const MaxLines; + + /// Human-readable texts for message severity levels + static char const * const SeverityText[Common::iLogger::Count]; + + /// Currently shown messages + QQueue mData; + + /// Human-readable error string if the last operation failed + QString mErrorString; + + +private: // Methods + + inline char const * const severityText(Common::iLogger::Severity s) const; + +}; + +/** + * The log view widget + * + * The Widget class implements a widget that shows messages from one logger source. + */ +class Widget : public QWidget +{ + Q_OBJECT + +public: + + Widget(QString const & source, QWidget * parent = 0); + + QString const & source() const { return mSource; } + + inline void addMessage(Common::iLogger::Severity severity, QString const & text, QString const & where) + { + mModel->addMessage(severity, text, where); + } + + +private slots: + + void messageAdded(QModelIndex const & index); + + void currentChanged(QModelIndex const &, QModelIndex const &); + + void copyToClipboard(); + + void saveToFile(); + + +private: + + QString mSource; + + Model * mModel; + + bool mAutoScroll; + + QListView * wList; + QLabel * wDetails; + +}; + +/** + * The log view window + */ +class Window : public QWidget +{ + Q_OBJECT + +public: + + Window(QWidget * parent = 0, Qt::WindowFlags flags = 0); + + virtual ~Window(); + + virtual bool event(QEvent * e); + + +public slots: + + void loggerEvent(Common::iLogger::Severity severity, QString const & text, QString const & source, QString const & where); + + +private: // Methods + + void saveSettings(); + + void restoreSettings(); + + +private: // Members + + QString mDefSource; + QTabWidget * wTabs; + QHash mLogViews; + QStatusBar * wStatusBar; + +}; + +/** + * LogView module's implementation + */ +class Module : public Plugins::iPlugin +{ + Q_OBJECT + Q_INTERFACES(eVaf::Plugins::iPlugin) + +public: + + Module(); + + virtual ~Module(); + + virtual bool init(QString const & args); + + virtual void done(); + + virtual bool isReady() const { return wWindow != 0; } + +private: // Members + + Window * wWindow; + +}; + +} // namespace eVaf::LogView::Internal +} // namespace eVaf::LogView +} // namespace eVaf + +#endif // logview.h diff --git a/src/plugins/LogView/version.h b/src/plugins/LogView/version.h new file mode 100644 index 0000000..d8d3133 --- /dev/null +++ b/src/plugins/LogView/version.h @@ -0,0 +1,60 @@ +/** + * @file LogView/version.h + * @brief Version information for eVaf modules + * @author Enar Vaikene + * + * Copyright (c) 2011 Enar Vaikene + * + * This file is part of the eVaf C++ cross-platform application development framework. + * + * This file can be used under the terms of the GNU General Public License + * version 3.0 as published by the Free Software Foundation and appearing in + * the file LICENSE included in the packaging of this file. Please review the + * the following information to ensure the GNU General Public License version + * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. + * + * Alternatively, this file may be used in accordance with the Commercial License + * Agreement provided with the Software. + */ + +#ifndef __LOGVIEW_VERSION_H +#define __LOGVIEW_VERSION_H + +#include + +/** + * Module/library version number in the form major,minor,release,build + */ +#define VER_FILE_VERSION 0,1,1,2 + +/** + * Module/library version number in the string format (shall end with \0) + */ +#define VER_FILE_VERSION_STR "0.1.1.2\0" + +/** + * Module/library name (shall end with \0) + */ +#define VER_MODULE_NAME_STR "LogView\0" + +/** + * Module type (see version_rc.h for all the types) + */ +#define VER_MODULE_TYPE MT_GENERIC + +/** + * Module type in the string format (see version_rc for all the types) + */ +#define VER_MODULE_TYPE_STR MT_GENERIC + +/** + * Original file name for windows (shall end with \0) + */ +#define VER_ORIGINAL_FILE_NAME_STR "LogView.dll\0" + +/** + * Description of the module/library (shall end with \0) + */ +#define VER_FILE_DESCRIPTION_STR "Module for viewing messages output using the iLogger interface.\0" + +#endif // version.h diff --git a/src/plugins/LogView/version.rc b/src/plugins/LogView/version.rc new file mode 100644 index 0000000..99afb33 --- /dev/null +++ b/src/plugins/LogView/version.rc @@ -0,0 +1,54 @@ +/** + * @file LogView/version.rc + * @brief Windows resource file with module/library version information. + * @author Enar Vaikene + * + * Copyright (c) 2011 Enar Vaikene + * + * This file is part of the eVaf C++ cross-platform application development framework. + * + * This file can be used under the terms of the GNU General Public License + * version 3.0 as published by the Free Software Foundation and appearing in + * the file LICENSE included in the packaging of this file. Please review the + * the following information to ensure the GNU General Public License version + * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. + * + * Alternatively, this file may be used in accordance with the Commercial License + * Agreement provided with the Software. + */ + +#include "version.h" +#include +#include + + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VER_FILE_VERSION + PRODUCTVERSION VER_PRODUCT_VERSION + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "CompanyName", VER_COMPANY_NAME_STR + VALUE "FileDescription", VER_FILE_DESCRIPTION_STR + VALUE "FileVersion", VER_FILE_VERSION_STR + VALUE "LegalCopyright", VER_LEGAL_COPYRIGHT_STR + VALUE "OriginalFilename", VER_ORIGINAL_FILE_NAME_STR + VALUE "ProductName", VER_PRODUCT_NAME_STR + VALUE "ProductVersion", VER_PRODUCT_VERSION_STR + VALUE "Build Date", VER_PRODUCT_DATE_STR + VALUE "Module Name", VER_MODULE_NAME_STR + VALUE "Module Type", VER_MODULE_TYPE_STR + END + END + END diff --git a/src/plugins/SdiWindow/CMakeLists.txt b/src/plugins/SdiWindow/CMakeLists.txt index 9edf476..b1a9c79 100644 --- a/src/plugins/SdiWindow/CMakeLists.txt +++ b/src/plugins/SdiWindow/CMakeLists.txt @@ -22,7 +22,6 @@ set(SRCS # Header files for the meta-object compiler set(MOC_HDRS factory.h - isdiwindow.h sdiwindow.h ) diff --git a/src/plugins/SdiWindow/factory.h b/src/plugins/SdiWindow/factory.h index 3b7201b..5010928 100644 --- a/src/plugins/SdiWindow/factory.h +++ b/src/plugins/SdiWindow/factory.h @@ -45,6 +45,7 @@ namespace Internal { class Factory : public Plugins::iPluginFactory { Q_OBJECT + Q_INTERFACES(eVaf::Plugins::iPluginFactory) public: diff --git a/src/plugins/SdiWindow/isdiwindow.h b/src/plugins/SdiWindow/isdiwindow.h index 8cd4343..28e774d 100644 --- a/src/plugins/SdiWindow/isdiwindow.h +++ b/src/plugins/SdiWindow/isdiwindow.h @@ -22,8 +22,8 @@ #include "libsdiwindow.h" -#include #include +#include class QWidget; class QLayout; @@ -37,18 +37,8 @@ namespace SdiWindow { * The iSdiWindow interface provides access to the SDI main window. The SDI main window is * an empty window that the application can fill with widgets. */ -class SDIWINDOW_EXPORT iSdiWindow : public QObject +struct SDIWINDOW_EXPORT iSdiWindow { - Q_OBJECT - -public: - - /// Interface constructor - iSdiWindow() : QObject() {} - - /// Empty virtual destructor - virtual ~iSdiWindow() {} - /** * Returns the iSdiWindow interface instance * @return The iSdiWindow interface or zero if not available @@ -80,4 +70,6 @@ public: } // namespace eVaf::SdiWindow } // namespace eVaf +Q_DECLARE_INTERFACE(eVaf::SdiWindow::iSdiWindow, "eVaf.SdiWindow.iSdiWindow/1.0") + #endif // isdiwindow.h diff --git a/src/plugins/SdiWindow/sdiwindow.cpp b/src/plugins/SdiWindow/sdiwindow.cpp index d0294d8..aba9ce2 100644 --- a/src/plugins/SdiWindow/sdiwindow.cpp +++ b/src/plugins/SdiWindow/sdiwindow.cpp @@ -54,6 +54,7 @@ using namespace eVaf::SdiWindow::Internal; MainWindow::MainWindow(QWidget * parent, Qt::WindowFlags flags) : QWidget(parent, flags) + , mReady(false) { setObjectName(QString("%1-%2").arg(VER_MODULE_NAME_STR).arg(__FUNCTION__)); @@ -67,23 +68,33 @@ MainWindow::MainWindow(QWidget * parent, Qt::WindowFlags flags) mLayout = new QVBoxLayout; setLayout(mLayout); + mSdiWindow = this; + EVAF_INFO("%s created", qPrintable(objectName())); } MainWindow::~MainWindow() { + mSdiWindow = 0; + // Save geometry saveSettings(); EVAF_INFO("%s destroyed", qPrintable(objectName())); } -bool MainWindow::init() +bool MainWindow::init(QString const & args) { + Q_UNUSED(args); + + Common::iRegistry::instance()->registerInterface("iSdiWindow", this); + setWindowTitle(Common::iApp::instance()->name()); show(); + mReady = true; + EVAF_INFO("%s initialized", qPrintable(objectName())); return true; @@ -91,12 +102,14 @@ bool MainWindow::init() void MainWindow::done() { + mReady = false; + close(); // Delete all the items added to the main window while (mItemsAdded.count() > 0) { - QPointer item = mItemsAdded.takeAt(0); - if (item) + QWeakPointer item = mItemsAdded.takeAt(0); + if (!item.isNull()) delete item.data(); } @@ -178,56 +191,6 @@ void MainWindow::setWindowSize() } -//------------------------------------------------------------------- - -SdiWindowImpl::SdiWindowImpl() - : iSdiWindow() - , mReady(false) -{ - setObjectName(QString("%1.iSdiWindow").arg(VER_MODULE_NAME_STR)); - - mSdiWindow = this; - - wWindow = new MainWindow; - - Common::iRegistry::instance()->registerInterface("iSdiWindow", this); - - EVAF_INFO("%s created", qPrintable(objectName())); -} - -SdiWindowImpl::~SdiWindowImpl() -{ - delete wWindow; - - mSdiWindow = 0; - - EVAF_INFO("%s destroyed", qPrintable(objectName())); -} - -bool SdiWindowImpl::init(const QString & args) -{ - Q_UNUSED(args); - - if (!wWindow->init()) - return false; - - mReady = true; - - EVAF_INFO("%s initialized", qPrintable(objectName())); - - return true; -} - -void SdiWindowImpl::done() -{ - mReady = false; - - wWindow->done(); - - EVAF_INFO("%s finalized", qPrintable(objectName())); -} - - //------------------------------------------------------------------- SdiWindowPlugin::SdiWindowPlugin() @@ -235,7 +198,7 @@ SdiWindowPlugin::SdiWindowPlugin() { setObjectName(VER_MODULE_NAME_STR); - mWindow = new SdiWindowImpl; + mWindow = new MainWindow; EVAF_INFO("%s created", qPrintable(objectName())); } diff --git a/src/plugins/SdiWindow/sdiwindow.h b/src/plugins/SdiWindow/sdiwindow.h index 31b311d..f0cfe6f 100644 --- a/src/plugins/SdiWindow/sdiwindow.h +++ b/src/plugins/SdiWindow/sdiwindow.h @@ -28,7 +28,7 @@ #include #include #include -#include +#include class QVBoxLayout; @@ -37,11 +37,12 @@ namespace SdiWindow { namespace Internal { /** - * Main window widget + * Main window widget implementing the iSdiWindow interface */ -class MainWindow : public QWidget +class MainWindow : public QWidget, public iSdiWindow { Q_OBJECT + Q_INTERFACES(eVaf::SdiWindow::iSdiWindow) public: @@ -49,13 +50,15 @@ public: virtual ~MainWindow(); - bool init(); + virtual bool init(QString const & args); - void done(); + virtual void done(); + + virtual bool isReady() { return mReady; } - void addWidget(QWidget * widget); + virtual void addWidget(QWidget * widget); - void addLayout(QLayout * layout); + virtual void addLayout(QLayout * layout); private: // Methods @@ -69,45 +72,15 @@ private: // Methods private: // Members + /// Ready flag + bool mReady; + /// The layout of the window QVBoxLayout * mLayout; /// Widgets and layouts added to the main window - QList > mItemsAdded; - -}; - -/** - * iSdiWindow interface implementation - */ -class SdiWindowImpl : public iSdiWindow -{ - Q_OBJECT - -public: - - SdiWindowImpl(); - - virtual ~SdiWindowImpl(); - - bool init(const QString & args); - - void done(); - - bool isReady() const { return mReady; } - - virtual void addWidget(QWidget * widget) { wWindow->addWidget(widget); } - - virtual void addLayout(QLayout * layout) { wWindow->addLayout(layout); } - - -private: // Members - - /// Ready flag - bool mReady; + QList > mItemsAdded; - /// The main window widget - MainWindow * wWindow; }; /** @@ -116,6 +89,7 @@ private: // Members class SdiWindowPlugin : public Plugins::iPlugin { Q_OBJECT + Q_INTERFACES(eVaf::Plugins::iPlugin) public: @@ -133,7 +107,7 @@ public: private: /// iSdiWindow interface implementation - SdiWindowImpl * mWindow; + MainWindow * mWindow; }; } // namespace eVaf::SdiWindow::Internal diff --git a/src/plugins/SdiWindow/version.h b/src/plugins/SdiWindow/version.h index 44023e6..9671900 100644 --- a/src/plugins/SdiWindow/version.h +++ b/src/plugins/SdiWindow/version.h @@ -25,12 +25,12 @@ /** * Module/library version number in the form major,minor,release,build */ -#define VER_FILE_VERSION 0,2,2,3 +#define VER_FILE_VERSION 0,2,4,5 /** * Module/library version number in the string format (shall end with \0) */ -#define VER_FILE_VERSION_STR "0.2.2.3\0" +#define VER_FILE_VERSION_STR "0.2.4.5\0" /** * Module/library name (shall end with \0) diff --git a/src/plugins/Test/factory.h b/src/plugins/Test/factory.h index 2b798a2..089d869 100644 --- a/src/plugins/Test/factory.h +++ b/src/plugins/Test/factory.h @@ -43,6 +43,7 @@ namespace Internal { class Factory : public Plugins::iPluginFactory { Q_OBJECT + Q_INTERFACES(eVaf::Plugins::iPluginFactory) public: diff --git a/src/plugins/Test/test.h b/src/plugins/Test/test.h index 35630cd..0526d6e 100644 --- a/src/plugins/Test/test.h +++ b/src/plugins/Test/test.h @@ -36,6 +36,7 @@ namespace Internal { class TestPlugin : public Plugins::iPlugin { Q_OBJECT + Q_INTERFACES(eVaf::Plugins::iPlugin) public: