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..)

Tue, 21 May 2013 18:38:06 +0300

author
Santeri Piippo <crimsondusk64@gmail.com>
date
Tue, 21 May 2013 18:38:06 +0300
changeset 237
ec77f6e9a19f
parent 236
b58d35dc5d52
child 238
3b35f502a6c7

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
Binary file icons/bomb.png has changed
--- 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;

mercurial