Tue, 21 May 2013 18:38:06 +0300
Added fatal error message box for the.. fatal stuff. Windows isn't really good at conveying error messages, converted actions into a C-style array because I've had a ton of problems with the vector approach (it gets zeroed when it shouldn't be..)
icons/bomb.png | file | annotate | diff | comparison | revisions | |
ldforge.qrc | file | annotate | diff | comparison | revisions | |
src/common.h | file | annotate | diff | comparison | revisions | |
src/configDialog.cpp | file | annotate | diff | comparison | revisions | |
src/gui.cpp | file | annotate | diff | comparison | revisions | |
src/gui.h | file | annotate | diff | comparison | revisions | |
src/main.cpp | file | annotate | diff | comparison | revisions | |
src/string.cpp | file | annotate | diff | comparison | revisions | |
src/string.h | file | annotate | diff | comparison | revisions |
--- a/ldforge.qrc Tue May 21 17:39:27 2013 +0300 +++ b/ldforge.qrc Tue May 21 18:38:06 2013 +0300 @@ -17,6 +17,7 @@ <file>./icons/autocolor.png</file> <file>./icons/axes.png</file> <file>./icons/bfc.png</file> + <file>./icons/bomb.png</file> <file>./icons/brick-new.png</file> <file>./icons/brick.png</file> <file>./icons/camera-back.png</file>
--- a/src/common.h Tue May 21 17:39:27 2013 +0300 +++ b/src/common.h Tue May 21 18:38:06 2013 +0300 @@ -97,6 +97,25 @@ #undef null #endif // null +#ifdef __GNUC__ +#define FUNCNAME __PRETTY_FUNCTION__ +#else +#define FUNCNAME __func__ +#endif // __GNUC__ + +// Replace assert with a version that shows a GUI dialog if possible +#ifdef assert +#undef assert +#endif // assert + +void assertionFailure (const char* file, const ulong line, const char* funcname, const char* expr); +void fatalError (const char* file, const ulong line, const char* funcname, str errmsg); +#define assert(N) \ + (N) ? ((void)(0)) : assertionFailure(__FILE__, __LINE__, FUNCNAME, #N) + +#define fatal(MSG) \ + fatalError (__FILE__, __LINE__, FUNCNAME, MSG) + // Null pointer static const std::nullptr_t null = nullptr;
--- a/src/configDialog.cpp Tue May 21 17:39:27 2013 +0300 +++ b/src/configDialog.cpp Tue May 21 18:38:06 2013 +0300 @@ -177,7 +177,10 @@ // Init table items ulong i = 0; - for (actionmeta& info : g_ActionMeta) { + for (actionmeta& info : g_actionMeta) { + if (info.qAct == null) + break; + QAction* const act = *info.qAct; ShortcutListItem* item = new ShortcutListItem;
--- a/src/gui.cpp Tue May 21 17:39:27 2013 +0300 +++ b/src/gui.cpp Tue May 21 18:38:06 2013 +0300 @@ -41,7 +41,8 @@ #include "widgets.h" #include "config.h" -vector<actionmeta> g_ActionMeta; +actionmeta g_actionMeta[MAX_ACTIONS]; +static ushort g_metacursor = 0; static bool g_bSelectionLocked = false; @@ -104,13 +105,16 @@ // ============================================================================= void ForgeWindow::createMenuActions () { // Create the actions based on stored meta. - for (actionmeta meta : g_ActionMeta) { - QAction*& qAct = *meta.qAct; - qAct = new QAction (getIcon (meta.sIconName), meta.sDisplayName, this); - qAct->setStatusTip (meta.sDescription); - qAct->setShortcut (*meta.conf); + for (actionmeta meta : g_actionMeta) { + if (meta.qAct == null) + break; - connect (qAct, SIGNAL (triggered ()), this, SLOT (slot_action ())); + QAction*& act = *meta.qAct; + act = new QAction (getIcon (meta.sIconName), meta.sDisplayName, this); + act->setStatusTip (meta.sDescription); + act->setShortcut (*meta.conf); + + connect (act, SIGNAL (triggered ()), this, SLOT (slot_action ())); } // Make certain actions checkable @@ -538,7 +542,10 @@ // Find the meta for the action. actionmeta* pMeta = null; - for (actionmeta meta : g_ActionMeta) { + for (actionmeta meta : g_actionMeta) { + if (meta.qAct == null) + break; + if (*meta.qAct == qAct) { pMeta = &meta; break; @@ -1046,11 +1053,15 @@ // ============================================================================= QAction* findAction (str name) { - for (actionmeta& meta : g_ActionMeta) + for (actionmeta& meta : g_actionMeta) { + if (meta.qAct == null) + break; + if (name == meta.name) return *meta.qAct; + } - fprintf (stderr, "%s: couldn't find action named `%s'!\n", __func__, name.chars ()); + fatal (fmt ("%s: couldn't find action named `%s'!\n", __func__, name.chars ())); abort (); return null; } @@ -1122,4 +1133,12 @@ void ForgeWindow::setStatusBarText (str text) { statusBar ()->showMessage (text); +} + +void ForgeWindow::addActionMeta (actionmeta& meta) { + if (g_metacursor == 0) + memset (g_actionMeta, 0, sizeof g_actionMeta); + + assert (g_metacursor < MAX_ACTIONS); + g_actionMeta[g_metacursor++] = meta; } \ No newline at end of file
--- a/src/gui.h Tue May 21 17:39:27 2013 +0300 +++ b/src/gui.h Tue May 21 18:38:06 2013 +0300 @@ -44,13 +44,14 @@ // ============================================================================= // Metadata for actions typedef struct { - QAction** const qAct; - keyseqconfig* const conf; - const char* const name, *sDisplayName, *sIconName, *sDescription; - void (*const handler) (); + QAction** qAct; + keyseqconfig* conf; + const char* name, *sDisplayName, *sIconName, *sDescription; + void (*handler) (); } actionmeta; -extern vector<actionmeta> g_ActionMeta; +#define MAX_ACTIONS 256 +extern actionmeta g_actionMeta[256]; // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -80,24 +81,6 @@ } quickColorMetaEntry; // ============================================================================= -// ActionAdder -// -// The ACTION macro expands into - among other stuff - into an instance of this. -// This class' constructor creates meta for the newly defined action and stores -// it in g_ActionMeta. It is not supposed to be used directly! -// ============================================================================= -class ActionAdder { -public: - ActionAdder (QAction** qAct, const char* sDisplayName, const char* sIconName, - const char* sDescription, keyseqconfig* conf, void (*const handler) (), - const char* name) - { - actionmeta meta = {qAct, conf, name, sDisplayName, sIconName, sDescription, handler}; - g_ActionMeta.push_back (meta); - } -}; - -// ============================================================================= // ObjectList // // Object list class for ForgeWindow @@ -146,6 +129,7 @@ m_colorMeta = quickColorMeta; } void setStatusBarText (str text); + void addActionMeta (actionmeta& meta); protected: void closeEvent (QCloseEvent* ev); @@ -201,4 +185,22 @@ // Pointer to the instance of ForgeWindow. extern ForgeWindow* g_win; +// ============================================================================= +// ActionAdder +// +// The MAKE_ACTION macro expands into - among other stuff - into an instance +// of this. This class' constructor creates meta for the newly defined action +// and stores it in g_actionMeta. Don't use this directly! +// ============================================================================= +class ActionAdder { +public: + ActionAdder (QAction** act, const char* displayName, const char* iconName, + const char* description, keyseqconfig* conf, void (*const handler) (), + const char* name) + { + actionmeta meta = {act, conf, name, displayName, iconName, description, handler}; + g_win->addActionMeta (meta); + } +}; + #endif // GUI_H \ No newline at end of file
--- a/src/main.cpp Tue May 21 17:39:27 2013 +0300 +++ b/src/main.cpp Tue May 21 18:38:06 2013 +0300 @@ -17,6 +17,8 @@ */ #include <QApplication> +#include <QMessageBox> +#include <QAbstractButton> #include "gui.h" #include "file.h" #include "bbox.h" @@ -114,4 +116,53 @@ str fullVersionString () { return fmt ("v%s%s", versionString ().chars (), versionMoniker ()); +} + +static void bombBox (str msg) { + msg.replace ("\n", "<br />"); + + QMessageBox box (null); + const QMessageBox::StandardButton btn = QMessageBox::Close; + box.setWindowTitle ("Fatal Error"); + box.setIconPixmap (getIcon ("bomb")); + box.setWindowIcon (getIcon ("ldforge")); + box.setText (msg); + box.addButton (btn); + box.button (btn)->setText ("Damn it"); + box.setDefaultButton (btn); + box.exec (); +} + +void assertionFailure (const char* file, const ulong line, const char* funcname, const char* expr) { + str errmsg = fmt ("File %s:%lu:\nFunction %s:\n\nAssertion `%s' failed", + file, line, funcname, expr); + +#if BUILD_ID == BUILD_INTERNAL + errmsg += ", aborting."; +#else + errmsg += "."; +#endif + + printf ("%s\n", errmsg.chars ()); + +#if BUILD_ID == BUILD_INTERNAL + if (g_win) + g_win->deleteLater (); + + bombBox (errmsg); + abort (); +#endif +} + +void fatalError (const char* file, const ulong line, const char* funcname, str msg) { + str errmsg = fmt ("fatal() called:\nFile: %s\nLine: %lu\nFunction: %s\n\n%s", + file, line, funcname, msg.chars ()); + + printf ("%s\n", errmsg.chars ()); + + if (g_win) + g_win->deleteLater (); + + bombBox (errmsg); + abort (); } \ No newline at end of file
--- a/src/string.cpp Tue May 21 17:39:27 2013 +0300 +++ b/src/string.cpp Tue May 21 18:38:06 2013 +0300 @@ -177,7 +177,7 @@ int String::first (const char* c, int a) const { unsigned int r = 0; unsigned int index = 0; - for (; a < len (); a++) { + for (; a < (int) len (); a++) { if (m_string[a] == c[r]) { if (r == 0) index = a;
--- a/src/string.h Tue May 21 17:39:27 2013 +0300 +++ b/src/string.h Tue May 21 18:38:06 2013 +0300 @@ -97,6 +97,7 @@ bool operator! () const { return empty (); } operator const char* () const { return chars (); } operator QString () { return chars (); } + operator const QString () const { return chars (); } private: std::string m_string;