Skip to content

Commit

Permalink
Refactor: Added libgui, separated TextApp and GuiApp
Browse files Browse the repository at this point in the history
libgui extends libdeng2 with GUI-related code. libdeng2 itself no longer
depends on QtGui, only QtCore and QtNetwork.
  • Loading branch information
skyjake committed Feb 6, 2013
1 parent 45ec092 commit f49dc58
Show file tree
Hide file tree
Showing 28 changed files with 533 additions and 136 deletions.
12 changes: 6 additions & 6 deletions doomsday/dep_deng2.pri
@@ -1,10 +1,11 @@
include(dep_deng2_cwrapper.pri)

# libdeng2's C++ API requires the following Qt modules.
QT += core network gui
QT += core network

# Optional modules:
deng_qtopengl: QT += opengl
deng_qtgui: QT += gui

win32 {
# Install the required Qt DLLs into the products dir.
Expand All @@ -13,10 +14,9 @@ win32 {
else: qtver = "4"
qtlibs.files += \
$$[QT_INSTALL_BINS]/QtCore$${qtver}.dll \
$$[QT_INSTALL_BINS]/QtNetwork$${qtver}.dll \
$$[QT_INSTALL_BINS]/QtGui$${qtver}.dll
deng_qtopengl: qtlibs.files += \
$$[QT_INSTALL_BINS]/QtOpenGL$${qtver}.dll
$$[QT_INSTALL_BINS]/QtNetwork$${qtver}.dll
deng_qtgui: qtlibs.files += $$[QT_INSTALL_BINS]/QtGui$${qtver}.dll
deng_qtopengl: qtlibs.files += $$[QT_INSTALL_BINS]/QtOpenGL$${qtver}.dll
qtlibs.path = $$DENG_LIB_DIR

qtplugins.files = $$[QT_INSTALL_PLUGINS]/imageformats/qjpeg4.dll
Expand All @@ -28,7 +28,7 @@ macx {
fixInstallName($$1, libdeng2.2.dylib, ..)
fixInstallName($$1, QtCore.framework/Versions/4/QtCore, ..)
fixInstallName($$1, QtNetwork.framework/Versions/4/QtNetwork, ..)
fixInstallName($$1, QtGui.framework/Versions/4/QtGui, ..)
deng_qtgui: fixInstallName($$1, QtGui.framework/Versions/4/QtGui, ..)
deng_qtopengl: fixInstallName($$1, QtOpenGL.framework/Versions/4/QtOpenGL, ..)
}
defineTest(linkToBundledLibdeng2) {
Expand Down
22 changes: 22 additions & 0 deletions doomsday/dep_gui.pri
@@ -0,0 +1,22 @@
# Build configuration for using the libdeng_gui library.
INCLUDEPATH += $$PWD/libgui/include

# Use the appropriate library path.
!useLibDir($$OUT_PWD/../libgui) {
!useLibDir($$OUT_PWD/../../libgui) {
!useLibDir($$OUT_PWD/../../../libgui) {
useLibDir($$OUT_PWD/../../builddir/libgui)
}
}
}

LIBS += -ldeng_gui

macx {
defineTest(linkBinaryToBundledLibdengGui) {
fixInstallName($${1}, libdeng_gui.0.dylib, ..)
}
defineTest(linkToBundledLibdengGui) {
linkBinaryToBundledLibdengGui($${1}.bundle/$$1)
}
}
1 change: 1 addition & 0 deletions doomsday/doomsday.pro
Expand Up @@ -6,6 +6,7 @@ CONFIG += ordered
SUBDIRS = \
build \
libdeng2 \
libgui \
libdeng1 \
libshell \
client \
Expand Down
2 changes: 1 addition & 1 deletion doomsday/libdeng1/src/concurrency.cpp
Expand Up @@ -24,7 +24,7 @@
#include "de/concurrency.h"
#include "de/garbage.h"
#include <QMutex>
#include <QApplication>
#include <QCoreApplication>
#include <QDebug>
#include <de/Time>
#include <de/Log>
Expand Down
1 change: 1 addition & 0 deletions doomsday/libdeng2/include/de/TextApp
@@ -0,0 +1 @@
#include "core/textapp.h"
3 changes: 1 addition & 2 deletions doomsday/libdeng2/include/de/c_wrapper.h
Expand Up @@ -66,7 +66,7 @@ typedef enum legacycore_loglevel_e {
DE2_LOG_CRITICAL
} legacycore_loglevel_t;

DENG2_PUBLIC LegacyCore *LegacyCore_New(void *dengApp);
DENG2_PUBLIC LegacyCore *LegacyCore_New();
DENG2_PUBLIC void LegacyCore_Delete(LegacyCore *lc);
DENG2_PUBLIC LegacyCore *LegacyCore_Instance();
DENG2_PUBLIC void LegacyCore_SetLoopRate(int freqHz);
Expand All @@ -82,7 +82,6 @@ DENG2_PUBLIC int LegacyCore_SetLogFile(char const *filePath);
DENG2_PUBLIC char const *LegacyCore_LogFile();
DENG2_PUBLIC void LegacyCore_PrintLogFragment(char const *text);
DENG2_PUBLIC void LegacyCore_PrintfLogFragmentAtLevel(legacycore_loglevel_t level, char const *format, ...);
DENG2_PUBLIC void LegacyCore_SetTerminateFunc(void (*func)(char const *));
DENG2_PUBLIC void LegacyCore_FatalError(char const *msg);

/*
Expand Down
77 changes: 49 additions & 28 deletions doomsday/libdeng2/include/de/core/app.h
Expand Up @@ -29,34 +29,30 @@
#include "../Module"
#include "../Config"
#include "../UnixInfo"
#include <QApplication>

/**
* Macro for conveniently accessing the de::App singleton instance.
*/
#define DENG2_APP (static_cast<de::App *>(qApp))
#define DENG2_APP (&de::App::app())

namespace de {

class Archive;

/**
* Application whose event loop is protected against uncaught exceptions.
* Catches the exception and shuts down the app cleanly.
* Represents the application and its subsystems. This is the common
* denominator (and abstract base class) for GUI and non-GUI apps. de::App is
* not usable on its own; instead you must use one of the derived variants.
* @ingroup core
*
* @see GuiApp, TextApp
*/
class DENG2_PUBLIC App : public QApplication
class DENG2_PUBLIC App
{
Q_OBJECT

public:
/// The object or resource that was being looked for was not found. @ingroup errors
DENG2_ERROR(NotFoundError);

enum GUIMode {
GUIDisabled = 0,
GUIEnabled = 1
};

enum SubsystemInitFlag {
DefaultSubsystems = 0x0,
DisablePlugins = 0x1
Expand All @@ -67,18 +63,20 @@ class DENG2_PUBLIC App : public QApplication
/**
* Construct an App instance. The application will not be fully usable
* until initSubsystems() has been called -- you should call
* initSubsystems() as soon as possible after construction. Never throws
* an exception.
* initSubsystems() as soon as possible after construction. Never throws an
* exception.
*
* @param argc Argument count. Note that App holds the reference.
* @param argv Arguments.
* @param guiMode GUI can be enabled (client) or disabled (server).
* @param appFilePath Path of the application binary.
* @param args Arguments.
*/
App(int &argc, char **argv, GUIMode guiMode);
App(NativePath const &appFilePath, QStringList args);

~App();

bool notify(QObject *receiver, QEvent *event);
/**
* Sets a callback to be called when an uncaught exception occurs.
*/
void setTerminateFunc(void (*func)(char const *msg));

/**
* Finishes App construction by initializing all the application's
Expand Down Expand Up @@ -200,19 +198,42 @@ class DENG2_PUBLIC App : public QApplication
static Record &importModule(String const &name, String const &fromPath = "");

/**
* Emits the displayModeChanged() signal.
* Starts the application's main loop.
*
* @todo In the future when de::App (or a sub-object owned by it) is
* responsible for display modes, this should be handled internally and
* not via this public interface where anybody can call it.
* @return Return code after the loop exits.
*/
void notifyDisplayModeChanged();
virtual int execLoop() = 0;

signals:
void uncaughtException(QString message);
/**
* Stops the application's main loop.
*
* @param code Return code from the loop.
*/
virtual void stopLoop(int code) = 0;

/// Emitted when the display mode has changed.
void displayModeChanged();
/**
* Requests engine shutdown by calling the specified termination callback
* (see setTerminateFunc()). Called when an exception is caught at the
* de::App level, at which point there is no way to gracefully handle it
* and the application has to be shut down.
*
* This should not be called directly. From C++ code, one should throw an
* exception in unrecoverable error situations. From C code, one should
* call the LegacyCore_FatalError() function.
*
* @param message Error message to be shown to the user.
*/
void handleUncaughtException(String message);

protected:
/**
* Returns the native path of the directory where the application can store
* user-specific data. This is usually not the same as the user's native
* home folder.
*
* @return Application data path.
*/
virtual NativePath appDataPath() const = 0;

private:
struct Instance;
Expand Down
4 changes: 3 additions & 1 deletion doomsday/libdeng2/include/de/core/log.h
Expand Up @@ -325,7 +325,9 @@ class DENG2_PUBLIC LogEntry : public Lockable, public ISerializable

/**
* Copy constructor.
* @param other Log entry.
*
* @param other Log entry.
* @param extraFlags Additional flags to apply to the new entry.
*/
LogEntry(LogEntry const &other, Flags extraFlags = 0);

Expand Down
64 changes: 64 additions & 0 deletions doomsday/libdeng2/include/de/core/textapp.h
@@ -0,0 +1,64 @@
/** @file textapp.h Application with text-based/console interface.
*
* @authors Copyright © 2013 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program 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 2 of the License, or (at your
* option) any later version. This program 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 this program; if not, see:
* http://www.gnu.org/licenses</small>
*/

#ifndef LIBDENG2_TEXTAPP_H
#define LIBDENG2_TEXTAPP_H

#include <QCoreApplication>
#include <de/App>

/**
* Macro for conveniently accessing the de::TextApp singleton instance.
*/
#define DENG2_TEXT_APP (static_cast<de::TextApp *>(qApp))

namespace de {

/**
* Application with a text-based/console UI.
*
* The event loop is protected against uncaught exceptions. Catches the
* exception and shuts down the app cleanly.
*
* @ingroup core
*/
class DENG2_PUBLIC TextApp : public QCoreApplication, public App
{
Q_OBJECT

public:
TextApp(int &argc, char **argv);

~TextApp();

bool notify(QObject *receiver, QEvent *event);

int execLoop();
void stopLoop(int code);

protected:
NativePath appDataPath() const;

private:
struct Instance;
Instance *d;
};

} // namespace de

#endif // LIBDENG2_TEXTAPP_H
26 changes: 3 additions & 23 deletions doomsday/libdeng2/include/de/legacy/legacycore.h
Expand Up @@ -21,7 +21,6 @@
#define LIBDENG2_LEGACYCORE_H

#include "../libdeng2.h"
#include "../App"
#include "../Log"

namespace de {
Expand All @@ -33,6 +32,8 @@ class LegacyNetwork;
* libdeng2 functionality. The legacy engine needs to construct one of these
* via the deng2 C API and make sure it gets destroyed at shutdown. The C API
* can be used to access functionality in LegacyCore.
*
* @todo Move the Loop into its own class and get rid of this one.
*/
class DENG2_PUBLIC LegacyCore : public QObject
{
Expand All @@ -41,10 +42,8 @@ class DENG2_PUBLIC LegacyCore : public QObject
public:
/**
* Initializes the legacy core.
*
* @param dengApp Application instance.
*/
LegacyCore(App *dengApp);
LegacyCore();

~LegacyCore();

Expand Down Expand Up @@ -133,11 +132,6 @@ class DENG2_PUBLIC LegacyCore : public QObject
*/
void printLogFragment(char const *text, LogEntry::Level level = LogEntry::MESSAGE);

/**
* Sets a callback to be called when an uncaught exception occurs.
*/
void setTerminateFunc(void (*func)(char const *msg));

/**
* Returns the LegacyCore singleton instance.
*/
Expand All @@ -151,20 +145,6 @@ class DENG2_PUBLIC LegacyCore : public QObject
public slots:
void callback();

/**
* Requests engine shutdown by calling the specified termination callback
* (see setTerminateFunc()). Called when an exception is caught at the
* de::App level, at which point there is no way to gracefully handle it
* and the application has to be shut down.
*
* This should not be called directly. From C++ code, one should throw an
* exception in unrecoverable error situations. From C code, one should
* call the LegacyCore_FatalError() function.
*
* @param message Error message to be shown to the user.
*/
void handleUncaughtException(QString message);

private:
// Private instance data.
struct Instance;
Expand Down
1 change: 0 additions & 1 deletion doomsday/libdeng2/include/de/net/beacon.h
Expand Up @@ -67,7 +67,6 @@ class DENG2_PUBLIC Beacon : public QObject
/**
* Looks for any beacons on all accessible networks.
*
* @param port UDP port to discover on.
* @param timeOut Maximum time to spend discovering. If the timeout
* is zero or negative, discovery will not end.
* @param interval Interval between query broadcasts.
Expand Down

0 comments on commit f49dc58

Please sign in to comment.