Added Settings, Debugging classes and some enhancements to the code.

This commit is contained in:
Martin Rotter 2013-06-13 09:47:42 +02:00
parent f8add5125e
commit 0f91a7302b
11 changed files with 282 additions and 10 deletions

View File

@ -48,8 +48,8 @@ message(STATUS "[${APP_LOW_NAME}] Revision number obtained: " ${APP_REVISION} ".
# Configure internal C++ defines.
configure_file (
${PROJECT_SOURCE_DIR}/src/defs.h.in
${CMAKE_CURRENT_BINARY_DIR}/src/defs.h
${PROJECT_SOURCE_DIR}/src/core/defs.h.in
${CMAKE_CURRENT_BINARY_DIR}/src/core/defs.h
)
# Configure executable "properties" for Windows.
@ -152,6 +152,11 @@ set(APP_SOURCES
# GUI sources.
src/gui/formmain.cpp
src/gui/systemtrayicon.cpp
# CORE sources.
src/core/debugging.cpp
src/core/settings.cpp
# Basic application sources.
src/main.cpp
@ -168,6 +173,9 @@ set(APP_HEADERS
# GUI headers.
src/gui/formmain.h
src/gui/systemtrayicon.cpp
# CORE headers.
)
# Add form files.

46
src/core/debugging.cpp Normal file
View File

@ -0,0 +1,46 @@
#include <QApplication>
#include <QDir>
#include "core/defs.h"
#include "core/debugging.h"
#include <cstdio>
#ifndef QT_NO_DEBUG_OUTPUT
#define DEBUG_OUTPUT_WORKER(type_string, file, line, message) \
fprintf(stderr, "[%s] %s (%s:%d): %s\n", \
APP_LOW_NAME, \
type_string, \
file, \
line, \
qPrintable(message));
#endif
void Debugging::debugHandler(QtMsgType type,
const QMessageLogContext &placement,
const QString &message) {
#ifndef QT_NO_DEBUG_OUTPUT
const char *file = qPrintable(QString(placement.file).section(QDir::separator(), -1));
switch (type) {
case QtDebugMsg:
DEBUG_OUTPUT_WORKER("INFO", file, placement.line, message);
break;
case QtWarningMsg:
DEBUG_OUTPUT_WORKER("WARNING", file, placement.line, message);
break;
case QtCriticalMsg:
DEBUG_OUTPUT_WORKER("CRITICAL", file, placement.line, message);
break;
case QtFatalMsg:
DEBUG_OUTPUT_WORKER("FATAL", file, placement.line, message);
qApp->exit(EXIT_FAILURE);
default:
break;
}
#else
Q_UNUSED(type);
Q_UNUSED(placement);
Q_UNUSED(message);
#endif
}

17
src/core/debugging.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef DEBUGGING_H
#define DEBUGGING_H
#include <QtGlobal>
class Debugging {
public:
// Specifies format of output console messages.
// Macros:
// QT_NO_DEBUG_OUTPUT - disables debug outputs completely!!!
static void debugHandler(QtMsgType type,
const QMessageLogContext &placement,
const QString &message);
};
#endif // DEBUGGING_H

View File

@ -14,9 +14,8 @@
#define APP_CFG_PATH "data/config/config.ini"
#define APP_CFG_GUI "gui"
#define APP_CFG_GEN "main"
#define APP_CFG_CALC "calculator"
#define APP_CFG_LANG "language"
#define APP_CFG_GEN "general"
#define APP_CFG_LANG "localization"
#define APP_DB_PATH "data/storage/database.db"
#define APP_PREFIX "@CMAKE_INSTALL_PREFIX@"
@ -29,15 +28,18 @@
#define APP_LANG_PATH APP_PREFIX + QString("/share/qonverter/l10n")
#define APP_SKIN_PATH APP_PREFIX + QString("/share/qonverter/skins")
#define APP_INFO_PATH APP_PREFIX + QString("/share/qonverter/information")
#define APP_THEME_PATH APP_PREFIX + QString("/share/qonverter/themes")
#elif defined(Q_OS_MAC)
#define APP_LANG_PATH QApplication::applicationDirPath() + "/../Resources/l10n"
#define APP_SKIN_PATH QApplication::applicationDirPath() + "/../Resources/skins"
#define APP_PLUGIN_PATH QApplication::applicationDirPath() + "/../Resources/plugins"
#define APP_INFO_PATH QApplication::applicationDirPath() + "/../Resources/information"
#define APP_THEME_PATH QApplication::applicationDirPath() + "/../Resources/themes"
#elif defined(Q_OS_WIN) || defined(Q_OS_OS2)
#define APP_LANG_PATH QApplication::applicationDirPath() + QString("/l10n")
#define APP_SKIN_PATH QApplication::applicationDirPath() + QString("/skins")
#define APP_INFO_PATH QApplication::applicationDirPath()
#define APP_THEME_PATH QApplication::applicationDirPath() + QString("/themes")
#endif
#endif // DEFS_H

84
src/core/settings.cpp Normal file
View File

@ -0,0 +1,84 @@
/*
This file is part of Qonverter.
Qonverter is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Qonverter is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Qonverter. If not, see <http://www.gnu.org/licenses/>.
Copyright 2012 - 2013 Martin Rotter
*/
#include <QApplication>
#include <QDebug>
#include <QDir>
#include <QPointer>
#include "core/settings.h"
#include "core/defs.h"
QPointer<QSettings> Settings::s_instance;
QSettings::Status Settings::checkSettings() {
qDebug("Syncing settings.");
s_instance->sync();
return s_instance->status();
}
QVariant Settings::value(const QString &section,
const QString &key,
const QVariant &default_value) {
if (s_instance.isNull()) {
setupSettings();
}
return s_instance->value(QString("%1/%2").arg(section, key), default_value);
}
void Settings::setValue(const QString &section,
const QString &key,
const QVariant &value) {
if (s_instance.isNull()) {
setupSettings();
}
s_instance->setValue(QString("%1/%2").arg(section, key), value);
}
void Settings::deleteSettings() {
checkSettings();
qDebug("Deleting global settings.");
delete s_instance.data();
}
QSettings::Status Settings::setupSettings() {
// If settings file exists in executable file working directory,
// then use it (portable settings).
// Otherwise use settings file stored in homePath();
QString home_path = QDir::homePath() + QDir::separator() +
APP_LOW_H_NAME + QDir::separator() +
APP_CFG_PATH;
QString app_path = qApp->applicationDirPath() + QDir::separator() +
APP_CFG_PATH;
if (QFile(app_path).exists()) {
s_instance = new QSettings(app_path, QSettings::IniFormat);
qDebug("Initializing settings in %s.",
qPrintable(QDir::toNativeSeparators(app_path)));
}
else {
s_instance = new QSettings(home_path, QSettings::IniFormat);
qDebug("Initializing settings in %s.",
qPrintable(QDir::toNativeSeparators(home_path)));
}
return checkSettings();
}

34
src/core/settings.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef SETTINGS_H
#define SETTINGS_H
#include <QSettings>
class Settings {
private:
// We use QPointer instead of QScopedPointer
// because of late s_instance usage in QApplication::aboutToQuit() listeners.
static QPointer<QSettings> s_instance;
public:
// Getter/setter for settings values.
static QVariant value(const QString &section,
const QString &key,
const QVariant &default_value = QVariant());
static void setValue(const QString &section,
const QString &key,
const QVariant &value);
// It's better to cleanup settings manually via this function.
static void deleteSettings();
// Synchronises settings.
static QSettings::Status checkSettings();
protected:
// Creates settings file in correct location.
static QSettings::Status setupSettings();
};
#endif // SETTINGS_H

View File

@ -1,8 +1,12 @@
#include "formmain.h"
#include "gui/formmain.h"
#include "core/settings.h"
#include "qtsingleapplication/qtsingleapplication.h"
FormMain::FormMain(QWidget *parent) : QMainWindow(parent), m_ui(new Ui::FormMain) {
m_ui->setupUi(this);
createConnections();
}
FormMain::~FormMain() {
@ -11,4 +15,14 @@ FormMain::~FormMain() {
void FormMain::processExecutionMessage(const QString &message) {
// TODO: Implement proper reaction when application is launched more than once.
qDebug("Received '%s' execution message from another application instance.",
qPrintable(message));
}
void FormMain::cleanupResources() {
Settings::deleteSettings();
}
void FormMain::createConnections() {
connect(qApp, &QCoreApplication::aboutToQuit, this, &FormMain::cleanupResources);
}

View File

@ -13,8 +13,14 @@ class FormMain : public QMainWindow {
explicit FormMain(QWidget *parent = 0);
~FormMain();
protected:
void createConnections();
public slots:
void processExecutionMessage(const QString &message);
protected slots:
void cleanupResources();
private:
Ui::FormMain *m_ui;

View File

@ -0,0 +1,5 @@
#include "systemtrayicon.h"
SystemTrayIcon::SystemTrayIcon(QObject *parent) : QSystemTrayIcon(parent) {
}

18
src/gui/systemtrayicon.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef SYSTEMTRAYICON_H
#define SYSTEMTRAYICON_H
#include <QSystemTrayIcon>
class SystemTrayIcon : public QSystemTrayIcon
{
Q_OBJECT
public:
explicit SystemTrayIcon(QObject *parent = 0);
signals:
public slots:
};
#endif // SYSTEMTRAYICON_H

View File

@ -1,10 +1,14 @@
#include <QMainWindow>
// Needed for setting ini file format on Mac OS.
#ifdef Q_OS_MAC
#include <QSettings>
#endif
#include "core/defs.h"
#include "core/debugging.h"
#include "core/settings.h"
#include "gui/formmain.h"
#include "qtsingleapplication/qtsingleapplication.h"
#include "defs.h"
int main(int argc, char *argv[]) {
//: Name of language, e.g. English.
@ -19,23 +23,57 @@ int main(int argc, char *argv[]) {
//: Email of translator - optional.
QObject::tr("LANG_EMAIL");
// Ensure that ini format is used as application settings storage on Mac OS.
#ifdef Q_OS_MAC
QSettings::setDefaultFormat(QSettings::IniFormat);
#endif
// Setup debug output system.
qInstallMessageHandler(Debugging::debugHandler);
// TODO: Finish implementation of QtSingleApplication into RSS Guard.
// This primarily concerns slot in FormMain which reacts when application is launched
// repeatedly. See 'trivial' example from QtSingleApplication source code for more
// information.
QtSingleApplication application(argc, argv);
qDebug("Instantiated QtSingleApplication class.");
// Check if another instance is running.
if (application.sendMessage(APP_IS_RUNNING)) {
qDebug("Another instance of the application is already running. Notifying it.");
return EXIT_SUCCESS;
}
// Add 3rd party plugin directory to application PATH variable.
// This is useful for styles, encoders, ...
// This is probably not needed on Windows or Linux, not sure about Mac OS X.
#if defined(Q_OS_MAC)
QApplication::addLibraryPath(APP_PLUGIN_PATH);
#endif
// These settings needs to be set before any QSettings object.
QtSingleApplication::setApplicationName(APP_NAME);
QtSingleApplication::setApplicationVersion(APP_VERSION);
QtSingleApplication::setOrganizationName(APP_AUTHORS);
QtSingleApplication::setOrganizationDomain(APP_URL);
QtSingleApplication::setWindowIcon(QIcon(":/graphics/qonverter.png"));
// Instantiate main application window.
FormMain window;
window.show();
application.setActivationWindow(&window, true);
if (Settings::value(APP_CFG_GEN, "first_start", true).toBool()) {
// TODO: Open initial "Welcome" dialog here.
Settings::setValue(APP_CFG_GEN, "first_start", false);
}
// Setup single-instance behavior.
application.setActivationWindow(&window, true);
QObject::connect(&application, &QtSingleApplication::messageReceived,
&window, &FormMain::processExecutionMessage);
// Enter global event loop.
return QtSingleApplication::exec();
}