Converted ForgeWindow to Designer UI(!)

Mon, 15 Jul 2013 19:30:16 +0300

author
Santeri Piippo <crimsondusk64@gmail.com>
date
Mon, 15 Jul 2013 19:30:16 +0300
changeset 382
c1642530ea35
parent 381
241f65769a57
child 383
10e60ae9ed58

Converted ForgeWindow to Designer UI(!)

changelog.txt file | annotate | diff | comparison | revisions
src/actions.h file | annotate | diff | comparison | revisions
src/common.h file | annotate | diff | comparison | revisions
src/configDialog.cpp file | annotate | diff | comparison | revisions
src/configDialog.h file | annotate | diff | comparison | revisions
src/extprogs.cpp file | annotate | diff | comparison | revisions
src/gldraw.cpp file | annotate | diff | comparison | revisions
src/gui.cpp file | annotate | diff | comparison | revisions
src/gui.h file | annotate | diff | comparison | revisions
src/gui_actions.cpp file | annotate | diff | comparison | revisions
src/gui_editactions.cpp file | annotate | diff | comparison | revisions
src/history.cpp file | annotate | diff | comparison | revisions
src/misc.cpp file | annotate | diff | comparison | revisions
src/misc.h file | annotate | diff | comparison | revisions
src/ui/ldforge.ui file | annotate | diff | comparison | revisions
--- a/changelog.txt	Mon Jul 15 14:43:29 2013 +0300
+++ b/changelog.txt	Mon Jul 15 19:30:16 2013 +0300
@@ -1,5 +1,10 @@
 =================================================
-== Changes since version 1.0
+== Changes in version 0.2.999-internal
+=================================================
+- Color icon border now reflects the color's edge color.
+
+=================================================
+== Changes in version 0.2-alpha
 =================================================
 
 - Completely rewrote history (undo/redo) code, making it a LOT stabler in the process.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/actions.h	Mon Jul 15 19:30:16 2013 +0300
@@ -0,0 +1,84 @@
+act (New)
+act (Open)
+act (Save)
+act (SaveAs)
+act (InsertFrom)
+act (ExportTo)
+act (Settings)
+act (SetLDrawPath)
+act (ScanPrimitives)
+act (Exit)
+act (ResetView)
+act (Axes)
+act (Wireframe)
+act (BFCView)
+act (SetOverlay)
+act (ClearOverlay)
+act (Screenshot)
+act (InsertRaw)
+act (NewSubfile)
+act (NewLine)
+act (NewTriangle)
+act (NewQuad)
+act (NewCLine)
+act (NewComment)
+act (NewBFC)
+act (NewVertex)
+act (Undo)
+act (Redo)
+act (Cut)
+act (Copy)
+act (Paste)
+act (Delete)
+act (SelectAll)
+act (SelectByColor)
+act (SelectByType)
+act (ModeDraw)
+act (ModeSelect)
+act (SetDrawDepth)
+act (SetColor)
+act (Autocolor)
+act (Uncolorize)
+act (Inline)
+act (InlineDeep)
+act (Invert)
+act (MakePrimitive)
+act (SplitQuads)
+act (EditRaw)
+act (Borders)
+act (CornerVerts)
+act (RoundCoordinates)
+act (Visibility)
+act (ReplaceCoords)
+act (Flip)
+act (Demote)
+act (Ytruder)
+act (Rectifier)
+act (Intersector)
+act (Isecalc)
+act (Coverer)
+act (Edger2)
+act (Help)
+act (About)
+act (AboutQt)
+act (GridCoarse)
+act (GridMedium)
+act (GridFine)
+act (Edit)
+act (MoveUp)
+act (MoveDown)
+act (MoveXNeg)
+act (MoveXPos)
+act (MoveYNeg)
+act (MoveYPos)
+act (MoveZNeg)
+act (MoveZPos)
+act (RotateXNeg)
+act (RotateXPos)
+act (RotateYNeg)
+act (RotateYPos)
+act (RotateZNeg)
+act (RotateZPos)
+act (RotationPoint)
+
+#undef act
\ No newline at end of file
--- a/src/common.h	Mon Jul 15 14:43:29 2013 +0300
+++ b/src/common.h	Mon Jul 15 19:30:16 2013 +0300
@@ -40,17 +40,17 @@
 #define VERSION_PATCH 999
 #define BUILD_ID BUILD_INTERNAL
 
-// =============================================
-#if (BUILD_ID != BUILD_INTERNAL)
-#define RELEASE
-#endif // BUILD_ID
-
 #define BUILD_INTERNAL 0
 #define BUILD_ALPHA    1
 #define BUILD_BETA     2
 #define BUILD_RC       3
 #define BUILD_RELEASE  4
 
+// =============================================
+#if (BUILD_ID != BUILD_INTERNAL)
+#define RELEASE
+#endif // BUILD_ID
+
 #ifndef RELEASE
 # define devf(...) doDevf (__func__, __VA_ARGS__);
 #else
--- a/src/configDialog.cpp	Mon Jul 15 14:43:29 2013 +0300
+++ b/src/configDialog.cpp	Mon Jul 15 19:30:16 2013 +0300
@@ -47,6 +47,9 @@
 extern_cfg (bool, edit_schemanticinline);
 extern_cfg (bool, gl_blackedges);
 
+#define act(N) extern_cfg (keyseq, key_##N);
+#include "actions.h"
+
 #define INIT_CHECKBOX(BOX, CFG) \
 	BOX->setCheckState (CFG ? Qt::Checked : Qt::Unchecked);
 
@@ -106,33 +109,33 @@
 // =============================================================================
 void ConfigDialog::initShortcutsTab () {
 	ulong i = 0;
-	for( actionmeta& info : g_actionMeta ) {
-		if( info.qAct == null )
-			break;
-		
-		QAction* const act = *info.qAct;
-		
-		ShortcutListItem* item = new ShortcutListItem;
-		setShortcutText( item, info );
-		item->setIcon( act->icon() );
-		item->setActionInfo( &info );
-		
-		// If the action doesn't have a valid icon, use an empty one
-		// so that the list is kept aligned.
-		if( act->icon().isNull() )
-			item->setIcon( getIcon( "empty" ));
-		
-		ui->shortcutsList->insertItem( i++, item );
-	}
+	
+#define act(N) addShortcut (key_##N, ACTION(N), i);
+#include "actions.h"
 	
 	ui->shortcutsList->setSortingEnabled( true );
 	ui->shortcutsList->sortItems();
-
+	
 	connect( ui->shortcut_set, SIGNAL( clicked() ), this, SLOT( slot_setShortcut() ));
 	connect( ui->shortcut_reset, SIGNAL( clicked() ), this, SLOT( slot_resetShortcut() ));
 	connect( ui->shortcut_clear, SIGNAL( clicked() ), this, SLOT( slot_clearShortcut() ));
 }
 
+void ConfigDialog::addShortcut (keyseqconfig& cfg, QAction* act, ulong& i) {
+	ShortcutListItem* item = new ShortcutListItem;
+	setShortcutText (item);
+	item->setIcon (act->icon());
+	item->setKeyConfig (&cfg);
+	item->setAction (act);
+	
+	// If the action doesn't have a valid icon, use an empty one
+	// so that the list is kept aligned.
+	if (act->icon().isNull())
+		item->setIcon (getIcon ("empty"));
+	
+	ui->shortcutsList->insertItem (i++, item);
+}
+
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
@@ -504,8 +507,8 @@
 	
 	ShortcutListItem* item = sel[0];
 	
-	if( KeySequenceDialog::staticDialog( *( item->getActionInfo() ), this ))
-		setShortcutText( item, *( item->getActionInfo() ));
+	if (KeySequenceDialog::staticDialog (item->keyConfig(), this))
+		setShortcutText (item);
 }
 
 // =============================================================================
@@ -513,50 +516,34 @@
 {
 	QList<ShortcutListItem*> sel = getShortcutSelection();
 	
-	for( ShortcutListItem * item : sel )
-	{
-		actionmeta* info = item->getActionInfo();
-		keyseqconfig* conf = info->conf;
-		
-		conf->reset();
-		( *info->qAct )->setShortcut( *conf );
-		
-		setShortcutText( item, *info );
+	for (ShortcutListItem* item : sel) {
+		item->keyConfig()->reset();
+		setShortcutText (item);
 	}
 }
 
 // =============================================================================
-void ConfigDialog::slot_clearShortcut()
-{
+void ConfigDialog::slot_clearShortcut() {
 	QList<ShortcutListItem*> sel = getShortcutSelection();
-	QKeySequence dummy;
 	
-	for( ShortcutListItem * item : sel )
-	{
-		actionmeta* info = item->getActionInfo();
-		keyseqconfig* conf = info->conf;
-		conf->value = dummy;
-		
-		( *info->qAct )->setShortcut( *conf );
-		setShortcutText( item, *info );
+	for (ShortcutListItem* item : sel) {
+		item->keyConfig()->value = QKeySequence();
+		setShortcutText (item);
 	}
 }
 
 // =============================================================================
-void ConfigDialog::slot_setExtProgPath()
-{
+void ConfigDialog::slot_setExtProgPath() {
 	const extProgInfo* info = null;
 	
-	for( const extProgInfo & it : g_extProgInfo )
-	{
-		if( it.setPathButton == sender() )
-		{
+	for (const extProgInfo& it : g_extProgInfo) {
+		if (it.setPathButton == sender()) {
 			info = &it;
 			break;
 		}
 	}
 	
-	assert( info != null );
+	assert (info != null);
 	
 	str filter;
 #ifdef _WIN32
@@ -574,13 +561,13 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-void ConfigDialog::setShortcutText( QListWidgetItem* item, actionmeta meta )
+void ConfigDialog::setShortcutText( ShortcutListItem* item )
 {
-	QAction* const act = *meta.qAct;
+	QAction* act = item->action();
 	str label = act->iconText();
-	str keybind = act->shortcut().toString();
+	str keybind = item->keyConfig()->value.toString();
 	
-	item->setText( fmt( "%1 (%2)", label, keybind ));
+	item->setText (fmt ("%1 (%2)", label, keybind));
 }
 
 // =============================================================================
@@ -641,6 +628,10 @@
 			for( int j = 0; j < 4; ++j )
 				g_GridInfo[i].confs[j]->value = dlg.getGridValue( i, j );
 		
+		// Apply key shortcuts
+#define act(N) ACTION(N)->setShortcut (key_##N);
+#include "actions.h"
+		
 		// Ext program settings
 		for( const extProgInfo & info : g_extProgInfo )
 		{
@@ -691,15 +682,13 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-bool KeySequenceDialog::staticDialog( actionmeta& meta, QWidget* parent )
-{
-	KeySequenceDialog dlg( *meta.conf, parent );
+bool KeySequenceDialog::staticDialog (keyseqconfig* cfg, QWidget* parent) {
+	KeySequenceDialog dlg (cfg->value, parent);
 	
-	if( dlg.exec() == false )
+	if (dlg.exec() == false)
 		return false;
 	
-	*meta.conf = dlg.seq;
-	( *meta.qAct )->setShortcut( *meta.conf );
+	cfg->value = dlg.seq;
 	return true;
 }
 
--- a/src/configDialog.h	Mon Jul 15 14:43:29 2013 +0300
+++ b/src/configDialog.h	Mon Jul 15 19:30:16 2013 +0300
@@ -29,22 +29,12 @@
 // =============================================================================
 class ShortcutListItem : public QListWidgetItem
 {
+	PROPERTY (keyseqconfig*, keyConfig, setKeyConfig)
+	PROPERTY (QAction*, action, setAction)
+	
 public:
 	explicit ShortcutListItem( QListWidget* view = null, int type = Type ) :
 		QListWidgetItem( view, type ) {}
-	
-	actionmeta* getActionInfo() const
-	{
-		return m_info;
-	}
-	
-	void setActionInfo( actionmeta* info )
-	{
-		m_info = info;
-	}
-	
-private:
-	actionmeta* m_info;
 };
 
 // =============================================================================
@@ -53,11 +43,11 @@
 	Q_OBJECT
 	
 public:
-	ConfigDialog( ForgeWindow* parent );
+	ConfigDialog (ForgeWindow* parent);
 	virtual ~ConfigDialog();
 	static void staticDialog();
 	const Ui_ConfigUI* getUI() const;
-	float getGridValue( int i, int j ) const;
+	float getGridValue (int i, int j) const;
 	
 	vector<quickColor> quickColorMeta;
 	QDoubleSpinBox* dsb_gridData[3][4];
@@ -73,10 +63,11 @@
 	void initQuickColorTab();
 	void initGridTab();
 	void initExtProgTab();
+	void addShortcut (keyseqconfig& cfg, QAction* act, ulong& i);
 	void setButtonBackground( QPushButton* button, str value );
 	void pickColor( strconfig& cfg, QPushButton* button );
 	void updateQuickColorList( quickColor* sel = null );
-	void setShortcutText( QListWidgetItem* qItem, actionmeta meta );
+	void setShortcutText (ShortcutListItem* item);
 	int getItemRow( QListWidgetItem* item, vector<QListWidgetItem*>& haystack );
 	str makeColorToolBarString();
 	QListWidgetItem* getSelectedQuickColor();
@@ -105,7 +96,7 @@
 
 public:
 	explicit KeySequenceDialog( QKeySequence seq, QWidget* parent = null, Qt::WindowFlags f = 0 );
-	static bool staticDialog( actionmeta& meta, QWidget* parent = null );
+	static bool staticDialog( keyseqconfig* cfg, QWidget* parent = null );
 
 	QLabel* lb_output;
 	QDialogButtonBox* bbx_buttons;
--- a/src/extprogs.cpp	Mon Jul 15 14:43:29 2013 +0300
+++ b/src/extprogs.cpp	Mon Jul 15 19:30:16 2013 +0300
@@ -573,7 +573,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (edger2, "Edger 2", "edger2", "Compute edgelines", 0) {
+DEFINE_ACTION (Edger2, 0) {
 	setlocale (LC_ALL, "C");
 	
 	if (!checkProgPath (prog_edger2, Edger2))
--- a/src/gldraw.cpp	Mon Jul 15 14:43:29 2013 +0300
+++ b/src/gldraw.cpp	Mon Jul 15 19:30:16 2013 +0300
@@ -1622,8 +1622,7 @@
 // -----------------------------------------------------------------------------
 // Read in overlays from the current file and update overlay info accordingly.
 // =============================================================================
-void GLRenderer::overlaysFromObjects()
-{
+void GLRenderer::overlaysFromObjects() {
 	for (Camera cam : g_Cameras) {
 		if (cam == Free)
 			continue;
--- a/src/gui.cpp	Mon Jul 15 14:43:29 2013 +0300
+++ b/src/gui.cpp	Mon Jul 15 19:30:16 2013 +0300
@@ -47,9 +47,7 @@
 #include "addObjectDialog.h"
 #include "messagelog.h"
 #include "config.h"
-
-actionmeta g_actionMeta[MAX_ACTIONS];
-static ushort g_metacursor = 0;
+#include "ui_ldforge.h"
 
 static bool g_bSelectionLocked = false;
 
@@ -71,255 +69,96 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-ForgeWindow::ForgeWindow () {
+ForgeWindow::ForgeWindow() {
 	g_win = this;
 	m_renderer = new GLRenderer;
 	
-	m_objList = new ObjectList;
-	m_objList->setSelectionMode (QListWidget::ExtendedSelection);
-	m_objList->setAlternatingRowColors (true);
-	connect (m_objList, SIGNAL (itemSelectionChanged ()), this, SLOT (slot_selectionChanged ()));
-	connect (m_objList, SIGNAL (itemDoubleClicked (QListWidgetItem*)), this, SLOT (slot_editObject (QListWidgetItem*)));
+	ui = new Ui_LDForgeUI;
+	ui->setupUi (this);
 	
-	m_msglog = new MessageManager;
-	m_msglog->setRenderer( R() );
-	m_renderer->setMessageLog( m_msglog );
+	// Stuff the renderer into its frame
+	QVBoxLayout* rendererLayout = new QVBoxLayout (ui->rendererFrame);
+	rendererLayout->addWidget (R());
 	
-	m_splitter = new QSplitter;
-	m_splitter->addWidget (m_renderer);
-	m_splitter->addWidget (m_objList);
-	setCentralWidget (m_splitter);
-	
-	m_colorMeta = parseQuickColorMeta ();
+	connect (ui->objectList, SIGNAL (itemSelectionChanged()), this, SLOT (slot_selectionChanged()));
+	connect (ui->objectList, SIGNAL (itemDoubleClicked (QListWidgetItem*)), this, SLOT (slot_editObject (QListWidgetItem*)));
 	
-	createMenuActions ();
-	createMenus ();
-	createToolbars ();
-	
-	slot_selectionChanged ();
-	
+	// Init message log manager
+	m_msglog = new MessageManager;
+	m_msglog->setRenderer (R());
+	m_renderer->setMessageLog (m_msglog);
+	m_colorMeta = parseQuickColorMeta();
+	slot_selectionChanged();
 	setStatusBar (new QStatusBar);
 	
+	// Init primitive loader task stuff
 	m_primLoaderBar = new QProgressBar;
 	m_primLoaderWidget = new QWidget;
 	QHBoxLayout* primLoaderLayout = new QHBoxLayout (m_primLoaderWidget);
 	primLoaderLayout->addWidget (new QLabel ("Loading primitives:"));
 	primLoaderLayout->addWidget (m_primLoaderBar);
-	statusBar ()->addPermanentWidget (m_primLoaderWidget);
-	m_primLoaderWidget->hide ();
+	statusBar()->addPermanentWidget (m_primLoaderWidget);
+	m_primLoaderWidget->hide();
 	
-	setWindowIcon (getIcon ("ldforge"));
-	updateTitle ();
-	setMinimumSize (320, 200);
-	resize (800, 600);
+	// Make certain actions checkable
+	ui->actionAxes->setChecked (gl_axes);
+	ui->actionWireframe->setChecked (gl_wireframe);
+	ui->actionBFCView->setChecked (gl_colorbfc);
+	updateGridToolBar();
+	updateEditModeActions();
+	updateRecentFilesMenu();
+	updateToolBars();
+	updateTitle();
 	
-	connect (qApp, SIGNAL (aboutToQuit ()), this, SLOT (slot_lastSecondCleanup ()));
+	setMinimumSize (300, 200);
+	
+	connect (qApp, SIGNAL (aboutToQuit()), this, SLOT (slot_lastSecondCleanup()));
+	
+	// Connect all actions
+#define act(N) \
+	connect (ui->action##N, SIGNAL (triggered()), this, SLOT (slot_action()));
+#include "actions.h"
 }
 
-// =============================================================================
-void ForgeWindow::slot_lastSecondCleanup () {
-	delete m_renderer;
+void ForgeWindow::slot_action() {
+	// Find out which action triggered this
+#define act(N) if (sender() == ui->action##N) invokeAction (ui->action##N, &actiondef_##N);
+#include "actions.h"
+}
+
+void ForgeWindow::invokeAction (QAction* act, void (*func) ()) {
+	// Open the history so we can record the edits done during this action.
+	if (act != ACTION (Undo) && act != ACTION (Redo) && act != ACTION (Open))
+		currentFile()->openHistory();
+	
+	// Invoke the function
+	(*func) ();
+	
+	// Close the history now.
+	currentFile()->closeHistory();
 }
 
 // =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-void ForgeWindow::createMenuActions () {
-	// Create the actions based on stored meta.
-	for (actionmeta meta : g_actionMeta) {
-		if (meta.qAct == null)
-			break;
-		
-		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
-	findAction ("gridCoarse")->setCheckable (true);
-	findAction ("gridMedium")->setCheckable (true);
-	findAction ("gridFine")->setCheckable (true);
-	
-	findAction ("axes")->setCheckable (true);
-	findAction ("axes")->setChecked (gl_axes);
-
-	findAction ("wireframe")->setCheckable (true);
-	findAction ("wireframe")->setChecked (gl_wireframe);
-	
-	findAction ("colorbfc")->setCheckable (true);
-	findAction ("colorbfc")->setChecked (gl_colorbfc);
-	
-	updateEditModeActions ();
-	
-	// things not implemented yet
-	findAction ("help")->setEnabled (false);
+void ForgeWindow::slot_lastSecondCleanup() {
+	delete m_renderer;
+	delete ui;
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-QMenu* g_CurrentMenu;
-
-QMenu* ForgeWindow::initMenu (const char* name) {
-	return g_CurrentMenu = menuBar ()->addMenu (tr (name));
-}
-
-void ForgeWindow::addMenuAction (const char* name) {
-	g_CurrentMenu->addAction (findAction (name));
-}
-
-
-// =============================================================================
-void ForgeWindow::createMenus () {
-	m_recentFilesMenu = new QMenu (tr ("Open &Recent"));
-	m_recentFilesMenu->setIcon (getIcon ("open-recent"));
-	updateRecentFilesMenu ();
-	
-	QMenu*& menu = g_CurrentMenu;
-	
-	// File menu
-	initMenu ("&File");
-	addMenuAction ("newFile");
-	addMenuAction ("open");
-	menu->addMenu (m_recentFilesMenu);
-	addMenuAction ("save");
-	addMenuAction ("saveAs");
-	menu->addSeparator ();
-	addMenuAction ("insertFrom");
-	addMenuAction ("exportTo");
-	menu->addSeparator ();
-	addMenuAction ("settings");
-	addMenuAction ("setLDrawPath");
-	menu->addSeparator ();
-#ifndef RELEASE
-	addMenuAction ("testpic");
-#endif
-	addMenuAction ("reloadPrimitives");
-	menu->addSeparator ();
-	addMenuAction ("exit");
-	
-	// View menu
-	initMenu ("&View");
-	addMenuAction ("resetView");
-	addMenuAction ("axes");
-	addMenuAction ("wireframe");
-	addMenuAction ("colorbfc");
-	menu->addSeparator ();
-	addMenuAction ("setOverlay");
-	addMenuAction ("clearOverlay");
-	menu->addSeparator ();
-	addMenuAction ("screencap");
-	
-	// Insert menu
-	initMenu ("&Insert");
-	addMenuAction ("insertRaw");
-	menu->addSeparator ();
-	addMenuAction ("newSubfile");
-	addMenuAction ("newLine");
-	addMenuAction ("newTriangle");
-	addMenuAction ("newQuad");
-	addMenuAction ("newCondLine");
-	addMenuAction ("newComment");
-	addMenuAction ("newBFC");
-	addMenuAction ("newVertex");
-	
-	// Edit menu
-	initMenu ("&Edit");
-	addMenuAction ("undo");
-	addMenuAction ("redo");
-	menu->addSeparator ();
-	addMenuAction ("cut");
-	addMenuAction ("copy");
-	addMenuAction ("paste");
-	addMenuAction ("del");
-	menu->addSeparator ();
-	addMenuAction ("selectAll");
-	addMenuAction ("selectByColor");
-	addMenuAction ("selectByType");
-	menu->addSeparator ();
-	addMenuAction ("modeSelect");
-	addMenuAction ("modeDraw");
-	menu->addSeparator ();
-	addMenuAction ("setDrawDepth");
-	
-	// Move menu
-	initMenu ("&Move");
-	addMenuAction ("moveUp");
-	addMenuAction ("moveDown");
-	menu->addSeparator ();
-	addMenuAction ("gridCoarse");
-	addMenuAction ("gridMedium");
-	addMenuAction ("gridFine");
-	menu->addSeparator ();
-	addMenuAction ("moveXPos");
-	addMenuAction ("moveXNeg");
-	addMenuAction ("moveYPos");
-	addMenuAction ("moveYNeg");
-	addMenuAction ("moveZPos");
-	addMenuAction ("moveZNeg");
-	menu->addSeparator ();
-	addMenuAction ("rotateXPos");
-	addMenuAction ("rotateXNeg");
-	addMenuAction ("rotateYPos");
-	addMenuAction ("rotateYNeg");
-	addMenuAction ("rotateZPos");
-	addMenuAction ("rotateZNeg");
-	addMenuAction ("rotpoint");
-	
-	initMenu ("&Tools");
-	addMenuAction ("setColor");
-	addMenuAction ("autoColor");
-	addMenuAction ("uncolorize");
-	menu->addSeparator ();
-	addMenuAction ("invert");
-	addMenuAction ("inlineContents");
-	addMenuAction ("deepInline");
-	addMenuAction ("makePrimitive");
-	menu->addSeparator ();
-	addMenuAction ("splitQuads");
-	addMenuAction ("setContents");
-	addMenuAction ("makeBorders");
-	addMenuAction ("makeCornerVerts");
-	addMenuAction ("roundCoords");
-	addMenuAction ("visibility");
-	addMenuAction ("replaceCoords");
-	addMenuAction ("flip");
-	addMenuAction ("demote");
-	
-	initMenu ("E&xternal Programs");
-	addMenuAction ("ytruder");
-	addMenuAction ("rectifier");
-	addMenuAction ("intersector");
-	addMenuAction ("isecalc");
-	addMenuAction ("coverer");
-	addMenuAction ("edger2");
-	
-	// Help menu
-	initMenu ("&Help");
-	addMenuAction ("help");
-	menu->addSeparator ();
-	addMenuAction ("about");
-	addMenuAction ("aboutQt");
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-void ForgeWindow::updateRecentFilesMenu () {
+void ForgeWindow::updateRecentFilesMenu() {
 	// First, clear any items in the recent files menu
 	for (QAction* recent : m_recentFiles)
 		delete recent;
-	m_recentFiles.clear ();
+	m_recentFiles.clear();
 	
 	vector<str> files = container_cast<QStringList, vector<str>> (io_recentfiles.value.split ("@"));
 	for (str file : c_rev<str> (files)) {
 		QAction* recent = new QAction (getIcon ("open-recent"), file, this);
 		
-		connect (recent, SIGNAL (triggered ()), this, SLOT (slot_recentFile ()));
-		m_recentFilesMenu->addAction (recent);
+		connect (recent, SIGNAL (triggered()), this, SLOT (slot_recentFile()));
+		ui->menuOpenRecent->addAction (recent);
 		m_recentFiles << recent;
 	}
 }
@@ -327,105 +166,14 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-static QToolBar* g_CurrentToolBar;
-static Qt::ToolBarArea g_ToolBarArea = Qt::TopToolBarArea;
-
-void ForgeWindow::initSingleToolBar (const char* name) {
-	QToolBar* toolbar = new QToolBar (name);
-	addToolBar (g_ToolBarArea, toolbar);
-	m_toolBars << toolbar;
-	
-	g_CurrentToolBar = toolbar;
-}
-
-// =============================================================================
-void ForgeWindow::addToolBarAction (const char* name) {
-	g_CurrentToolBar->addAction (findAction (name));
-}
-
-// =============================================================================
-void ForgeWindow::createToolbars () {
-	initSingleToolBar ("File");
-	addToolBarAction ("newFile");
-	addToolBarAction ("open");
-	addToolBarAction ("save");
-	addToolBarAction ("saveAs");
-	
-	// ==========================================
-	initSingleToolBar ("Insert");
-	addToolBarAction ("newSubfile");
-	addToolBarAction ("newLine");
-	addToolBarAction ("newTriangle");
-	addToolBarAction ("newQuad");
-	addToolBarAction ("newCondLine");
-	addToolBarAction ("newComment");
-	addToolBarAction ("newBFC");
-	addToolBarAction ("newVertex");
-	
-	// ==========================================
-	initSingleToolBar ("Edit");
-	addToolBarAction ("undo");
-	addToolBarAction ("redo");
-	addToolBarAction ("cut");
-	addToolBarAction ("copy");
-	addToolBarAction ("paste");
-	addToolBarAction ("del");
-	addToolBarBreak (Qt::TopToolBarArea);
-	
-	// ==========================================
-	initSingleToolBar ("Select");
-	addToolBarAction ("selectAll");
-	addToolBarAction ("selectByColor");
-	addToolBarAction ("selectByType");
-	
-	// ==========================================
-	initSingleToolBar ("Grids");
-	addToolBarAction ("gridCoarse");
-	addToolBarAction ("gridMedium");
-	addToolBarAction ("gridFine");
-	
-	// ==========================================
-	initSingleToolBar ("View");
-	addToolBarAction ("axes");
-	addToolBarAction ("wireframe");
-	addToolBarAction ("colorbfc");
-	
-	// ==========================================
-	// Color toolbar
-	m_colorToolBar = new QToolBar ("Quick Colors");
-	addToolBar (Qt::RightToolBarArea, m_colorToolBar);
-	
-	// ==========================================
-	initSingleToolBar ("Tools");
-	addToolBarAction ("setColor");
-	addToolBarAction ("autoColor");
-	addToolBarAction ("splitQuads");
-	addToolBarAction ("setContents");
-	addToolBarAction ("makeBorders");
-	addToolBarAction ("replaceCoords");
-	addToolBarAction ("roundCoords");
-	addToolBarAction ("visibility");
-	
-	// ==========================================
-	g_ToolBarArea = Qt::LeftToolBarArea;
-	initSingleToolBar ("Modes");
-	addToolBarAction ("modeSelect");
-	addToolBarAction ("modeDraw");
-	
-	updateToolBars ();
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-vector<quickColor> parseQuickColorMeta () {
+vector<quickColor> parseQuickColorMeta() {
 	vector<quickColor> meta;
 	
 	for (str colorname : gui_colortoolbar.value.split (":")) {
 		if (colorname == "|") {
 			meta << quickColor ({null, null, true});
 		} else {
-			LDColor* col = getColor (colorname.toLong ());
+			LDColor* col = getColor (colorname.toLong());
 			assert (col != null);
 			meta << quickColor ({col, null, false});
 		}
@@ -437,73 +185,68 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-void ForgeWindow::updateToolBars () {
-	const QSize iconsize (gui_toolbar_iconsize, gui_toolbar_iconsize);
-	
-	for (QToolBar* bar : m_toolBars)
-		bar->setIconSize (iconsize);
-	
+void ForgeWindow::updateToolBars() {
 	// Update the quick color toolbar.
 	for (QToolButton* btn : m_colorButtons)
 		delete btn;
 	
-	m_colorButtons.clear ();
+	m_colorButtons.clear();
 	
-	// Clear the toolbar to remove separators
-	m_colorToolBar->clear ();
+	// Clear the toolbar - we deleted the buttons but there's still separators
+	ui->colorToolbar->clear();
 	
 	for (quickColor& entry : m_colorMeta) {
 		if (entry.isSeparator)
-			m_colorToolBar->addSeparator ();
+			ui->colorToolbar->addSeparator();
 		else {
 			QToolButton* colorButton = new QToolButton;
 			colorButton->setIcon (makeColorIcon (entry.col, gui_toolbar_iconsize));
-			colorButton->setIconSize (iconsize);
+			colorButton->setIconSize (QSize (22, 22));
 			colorButton->setToolTip (entry.col->name);
 			
-			connect (colorButton, SIGNAL (clicked ()), this, SLOT (slot_quickColor ()));
-			m_colorToolBar->addWidget (colorButton);
+			connect (colorButton, SIGNAL (clicked()), this, SLOT (slot_quickColor()));
+			ui->colorToolbar->addWidget (colorButton);
 			m_colorButtons << colorButton;
 			
 			entry.btn = colorButton;
 		}
 	}
 	
-	updateGridToolBar ();
+	updateGridToolBar();
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-void ForgeWindow::updateGridToolBar () {
+void ForgeWindow::updateGridToolBar() {
 	// Ensure that the current grid - and only the current grid - is selected.
-	findAction ("gridCoarse")->setChecked (grid == Grid::Coarse);
-	findAction ("gridMedium")->setChecked (grid == Grid::Medium);
-	findAction ("gridFine")->setChecked (grid == Grid::Fine);
+	ui->actionGridCoarse->setChecked (grid == Grid::Coarse);
+	ui->actionGridMedium->setChecked (grid == Grid::Medium);
+	ui->actionGridFine->setChecked (grid == Grid::Fine);
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-void ForgeWindow::updateTitle () {
+void ForgeWindow::updateTitle() {
 	str title = fmt (APPNAME " %1", fullVersionString());
 	
 	// Append our current file if we have one
 	if (currentFile()) {
-		if (currentFile()->name ().length () > 0)
-			title += fmt (": %1", basename (currentFile()->name ()));
+		if (currentFile()->name().length() > 0)
+			title += fmt (": %1", basename (currentFile()->name()));
 		else
 			title += fmt (": <anonymous>");
 		
-		if (currentFile()->numObjs () > 0 &&
-			currentFile()->obj (0)->getType () == LDObject::Comment)
+		if (currentFile()->numObjs() > 0 &&
+			currentFile()->obj (0)->getType() == LDObject::Comment)
 		{
 			// Append title
 			LDCommentObject* comm = static_cast<LDCommentObject*> (currentFile()->obj (0));
 			title += fmt (": %1", comm->text);
 		}
 		
-		if (currentFile()->history ().pos () != currentFile()->savePos ())
+		if (currentFile()->history().pos() != currentFile()->savePos())
 			title += '*';
 	}
 	
@@ -513,44 +256,6 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-EXTERN_ACTION( undo );
-EXTERN_ACTION( redo );
-EXTERN_ACTION( open );
-void ForgeWindow::slot_action () {
-	// Open the history so we can record the edits done during this action.
-	if( sender() != ACTION( undo ) && sender() != ACTION( redo ) && sender() != ACTION( open ))
-		currentFile()->openHistory ();
-	
-	// Get the action that triggered this slot.
-	QAction* qAct = static_cast<QAction*> (sender ());
-	
-	// Find the meta for the action.
-	actionmeta* meta = null;
-	
-	for (actionmeta& it : g_actionMeta) {
-		if (it.qAct == null)
-			break;
-		
-		if (*it.qAct == qAct) {
-			meta = &it;
-			break;
-		}
-	}
-	
-	if (!meta) {
-		log ("Warning: unknown signal sender %p!\n", qAct);
-		return;
-	}
-	
-	// We have the meta, now call the handler.
-	(*meta->handler) ();
-	
-	currentFile()->closeHistory ();
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
 int ForgeWindow::deleteSelection()
 {
 	if( m_sel.size() == 0 )
@@ -560,9 +265,8 @@
 	int num = 0;
 	
 	// Delete the objects that were being selected
-	for( LDObject * obj : selCopy )
-	{
-		currentFile()->forgetObject( obj );
+	for (LDObject* obj : selCopy) {
+		currentFile()->forgetObject (obj);
 		++num;
 		delete obj;
 	}
@@ -574,7 +278,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-void ForgeWindow::buildObjList () {
+void ForgeWindow::buildObjList() {
 	if (!currentFile())
 		return;
 	
@@ -583,15 +287,15 @@
 	// while this is done.
 	g_bSelectionLocked = true;
 	
-	for (int i = 0; i < m_objList->count (); ++i)
-		delete m_objList->item (i);
+	for (int i = 0; i < ui->objectList->count(); ++i)
+		delete ui->objectList->item (i);
 	
-	m_objList->clear ();
+	ui->objectList->clear();
 	
-	for (LDObject* obj : currentFile()->objs ()) {
+	for (LDObject* obj : currentFile()->objs()) {
 		str descr;
 		
-		switch (obj->getType ()) {
+		switch (obj->getType()) {
 		case LDObject::Comment:
 			descr = static_cast<LDCommentObject*> (obj)->text;
 			
@@ -607,7 +311,7 @@
 		case LDObject::Triangle:
 		case LDObject::Quad:
 		case LDObject::CondLine:
-			for (short i = 0; i < obj->vertices (); ++i) {
+			for (short i = 0; i < obj->vertices(); ++i) {
 				if (i != 0)
 					descr += ", ";
 				
@@ -627,11 +331,11 @@
 			{
 				LDSubfileObject* ref = static_cast<LDSubfileObject*> (obj);
 				
-				descr = fmt ("%1 %2, (", ref->fileInfo ()->name (),
-					ref->position ().stringRep (true));
+				descr = fmt ("%1 %2, (", ref->fileInfo()->name(),
+					ref->position().stringRep (true));
 				
 				for (short i = 0; i < 9; ++i)
-					descr += fmt ("%1%2", ftoa (ref->transform ()[i]),
+					descr += fmt ("%1%2", ftoa (ref->transform()[i]),
 						(i != 8) ? " " : "");
 				
 				descr += ')';
@@ -656,7 +360,7 @@
 		}
 		
 		// Put it into brackets if it's hidden
-		if (obj->hidden ()) {
+		if (obj->hidden()) {
 			descr = fmt ("[[ %1 ]]", descr);
 		}
 		
@@ -667,64 +371,56 @@
 		if (obj->getType() == LDObject::Error) {
 			item->setBackground (QColor ("#AA0000"));
 			item->setForeground (QColor ("#FFAA00"));
-		} elif (lv_colorize && obj->isColored () &&
-			obj->color () != maincolor && obj->color () != edgecolor)
+		} elif (lv_colorize && obj->isColored() &&
+			obj->color() != maincolor && obj->color() != edgecolor)
 		{
 			// If the object isn't in the main or edge color, draw this
 			// list entry in said color.
-			LDColor* col = getColor (obj->color ());
+			LDColor* col = getColor (obj->color());
 			if (col)
 				item->setForeground (col->faceColor);
 		}
 		
 		obj->qObjListEntry = item;
-		m_objList->insertItem (m_objList->count (), item);
+		ui->objectList->insertItem (ui->objectList->count(), item);
 	}
 	
 	g_bSelectionLocked = false;
-	updateSelection ();
-	scrollToSelection ();
+	updateSelection();
+	scrollToSelection();
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-void ForgeWindow::scrollToSelection () {
+void ForgeWindow::scrollToSelection() {
 	if (m_sel.size() == 0)
 		return;
 	
-	LDObject* obj = m_sel[m_sel.size () - 1];
-	m_objList->scrollToItem (obj->qObjListEntry);
+	LDObject* obj = m_sel[m_sel.size() - 1];
+	ui->objectList->scrollToItem (obj->qObjListEntry);
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-void ForgeWindow::slot_selectionChanged () {
+void ForgeWindow::slot_selectionChanged() {
 	if (g_bSelectionLocked == true || currentFile() == null)
 		return;
 	
-	/*
-	// If the selection isn't 1 exact, disable setting contents
-	findAction ("setContents")->setEnabled (qObjList->selectedItems().size() == 1);
-	
-	// If we have no selection, disable splitting quads
-	findAction ("splitQuads")->setEnabled (qObjList->selectedItems().size() > 0);
-	*/
-	
 	// Update the shared selection array, though don't do this if this was
 	// called during GL picking, in which case the GL renderer takes care
 	// of the selection.
-	if (m_renderer->picking ())
+	if (m_renderer->picking())
 		return;
 	
 	vector<LDObject*> priorSelection = m_sel;
 	
 	// Get the objects from the object list selection
-	m_sel.clear ();	
-	const QList<QListWidgetItem*> items = m_objList->selectedItems ();
+	m_sel.clear();
+	const QList<QListWidgetItem*> items = ui->objectList->selectedItems();
 	
-	for (LDObject* obj : currentFile()->objs ())
+	for (LDObject* obj : currentFile()->objs())
 	for (QListWidgetItem* item : items) {
 		if (item == obj->qObjListEntry) {
 			m_sel << obj;
@@ -743,21 +439,21 @@
 		m_renderer->compileObject (obj);
 	}
 	
-	m_renderer->update ();
+	m_renderer->update();
 }
 
 // =============================================================================
-void ForgeWindow::slot_recentFile () {
-	QAction* qAct = static_cast<QAction*> (sender ());
-	openMainFile (qAct->text ());
+void ForgeWindow::slot_recentFile() {
+	QAction* qAct = static_cast<QAction*> (sender());
+	openMainFile (qAct->text());
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-void ForgeWindow::slot_quickColor () {
-	currentFile()->openHistory ();
-	QToolButton* button = static_cast<QToolButton*> (sender ());
+void ForgeWindow::slot_quickColor() {
+	currentFile()->openHistory();
+	QToolButton* button = static_cast<QToolButton*> (sender());
 	LDColor* col = null;
 	
 	for (quickColor entry : m_colorMeta) {
@@ -773,52 +469,52 @@
 	short newColor = col->index;
 	
 	for (LDObject* obj : m_sel) {
-		if (obj->isColored () == false)
+		if (obj->isColored() == false)
 			continue; // uncolored object
 		
 		obj->setColor (newColor);
 	}
 	
-	fullRefresh ();
-	currentFile()->closeHistory ();
+	fullRefresh();
+	currentFile()->closeHistory();
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-ulong ForgeWindow::getInsertionPoint () {
-	if (m_sel.size () > 0) {
+ulong ForgeWindow::getInsertionPoint() {
+	if (m_sel.size() > 0) {
 		// If we have a selection, put the item after it.
 		return (m_sel[m_sel.size() - 1]->getIndex (currentFile())) + 1;
 	}
 	
 	// Otherwise place the object at the end.
-	return currentFile()->numObjs ();
+	return currentFile()->numObjs();
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-void ForgeWindow::fullRefresh () {
-	buildObjList ();
-	m_renderer->hardRefresh ();
+void ForgeWindow::fullRefresh() {
+	buildObjList();
+	m_renderer->hardRefresh();
 }
 
-void ForgeWindow::refresh () {
-	buildObjList ();
-	m_renderer->update ();
+void ForgeWindow::refresh() {
+	buildObjList();
+	m_renderer->update();
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-void ForgeWindow::updateSelection () {
+void ForgeWindow::updateSelection() {
 	g_bSelectionLocked = true;
 	
-	for (LDObject* obj : currentFile()->objs ())
+	for (LDObject* obj : currentFile()->objs())
 		obj->setSelected (false);
 	
-	m_objList->clearSelection ();
+	ui->objectList->clearSelection();
 	for (LDObject* obj : m_sel) {
 		if( obj->qObjListEntry == null )
 			continue;
@@ -828,14 +524,14 @@
 	}
 	
 	g_bSelectionLocked = false;
-	slot_selectionChanged ();
+	slot_selectionChanged();
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
 bool ForgeWindow::isSelected (LDObject* obj) {
-	LDObject* needle = obj->topLevelParent ();
+	LDObject* needle = obj->topLevelParent();
 	
 	for (LDObject* hay : m_sel)
 		if (hay == needle)
@@ -844,18 +540,18 @@
 	return false;
 }
 
-short ForgeWindow::getSelectedColor () {
+short ForgeWindow::getSelectedColor() {
 	short result = -1;
 	
 	for (LDObject* obj : m_sel) {
-		if (obj->isColored () == false)
+		if (obj->isColored() == false)
 			continue; // doesn't use color
 		
-		if (result != -1 && obj->color () != result)
+		if (result != -1 && obj->color() != result)
 			return -1; // No consensus in object color
 		
 		if (result == -1)
-			result = obj->color ();
+			result = obj->color();
 	}
 	
 	return result;
@@ -864,15 +560,15 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-LDObject::Type ForgeWindow::uniformSelectedType () {
+LDObject::Type ForgeWindow::uniformSelectedType() {
 	LDObject::Type result = LDObject::Unidentified;
 	
 	for (LDObject* obj : m_sel) {
-		if (result != LDObject::Unidentified && obj->color () != result)
+		if (result != LDObject::Unidentified && obj->color() != result)
 			return LDObject::Unidentified;
 		
 		if (result == LDObject::Unidentified)
-			result = obj->getType ();
+			result = obj->getType();
 	}
 	
 	return result;
@@ -883,52 +579,51 @@
 // =============================================================================
 void ForgeWindow::closeEvent (QCloseEvent* ev) {
 	// Check whether it's safe to close all files.
-	if (!safeToCloseAll ()) {
-		ev->ignore ();
+	if (!safeToCloseAll()) {
+		ev->ignore();
 		return;
 	}
 	
 	// Save the configuration before leaving so that, for instance, grid choice
 	// is preserved across instances.
-	config::save ();
+	config::save();
 	
-	ev->accept ();
+	ev->accept();
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
 void ForgeWindow::spawnContextMenu (const QPoint pos) {
-	const bool single = (g_win->sel ().size () == 1);
-	LDObject* singleObj = (single) ? g_win->sel ()[0] : null;
+	const bool single = (g_win->sel().size() == 1);
+	LDObject* singleObj = (single) ? g_win->sel()[0] : null;
 	
 	QMenu* contextMenu = new QMenu;
 	
-	if (single && singleObj->getType () != LDObject::Empty) {
-		contextMenu->addAction (findAction ("editObject"));
-		contextMenu->addSeparator ();
+	if (single && singleObj->getType() != LDObject::Empty) {
+		contextMenu->addAction (ACTION (Edit));
+		contextMenu->addSeparator();
 	}
 	
-	contextMenu->addAction (findAction ("cut"));
-	contextMenu->addAction (findAction ("copy"));
-	contextMenu->addAction (findAction ("paste"));
-	contextMenu->addAction (findAction ("del"));
-	contextMenu->addSeparator ();
-	contextMenu->addAction (findAction ("setColor"));
+	contextMenu->addAction (ACTION (Cut));
+	contextMenu->addAction (ACTION (Copy));
+	contextMenu->addAction (ACTION (Paste));
+	contextMenu->addAction (ACTION (Delete));
+	contextMenu->addSeparator();
+	contextMenu->addAction (ACTION (SetColor));
 	
 	if (single)
-		contextMenu->addAction (findAction ("setContents"));
-	
-	contextMenu->addAction (findAction ("makeBorders"));
-	contextMenu->addAction (findAction ("setOverlay"));
-	contextMenu->addAction (findAction ("clearOverlay"));
+		contextMenu->addAction (ACTION (EditRaw));
 	
-	for (const char* mode : g_modeActionNames)
-		contextMenu->addAction (findAction (mode));
+	contextMenu->addAction (ACTION (Borders));
+	contextMenu->addAction (ACTION (SetOverlay));
+	contextMenu->addAction (ACTION (ClearOverlay));
+	contextMenu->addAction (ACTION (ModeSelect));
+	contextMenu->addAction (ACTION (ModeDraw));
 	
-	if (R ()->camera () != GL::Free) {
-		contextMenu->addSeparator ();
-		contextMenu->addAction (findAction ("setDrawDepth"));
+	if (R()->camera() != GL::Free) {
+		contextMenu->addSeparator();
+		contextMenu->addAction (ACTION (SetDrawDepth));
 	}
 	
 	contextMenu->exec (pos);
@@ -945,8 +640,8 @@
 // =============================================================================
 void ForgeWindow::deleteByColor (const short colnum) {
 	vector<LDObject*> objs;
-	for (LDObject* obj : currentFile()->objs ()) {
-		if (!obj->isColored () || obj->color () != colnum)
+	for (LDObject* obj : currentFile()->objs()) {
+		if (!obj->isColored() || obj->color() != colnum)
 			continue;
 		
 		objs << obj;
@@ -956,20 +651,10 @@
 }
 
 // =============================================================================
-void ForgeWindow::updateEditModeActions () {
-	const EditMode mode = R ()->editMode ();
-	const size_t numModeActions = (sizeof g_modeActionNames / sizeof *g_modeActionNames);
-	assert ((size_t) mode < numModeActions);
-	
-	for (size_t i = 0; i < numModeActions; ++i) {
-		QAction* act = findAction (g_modeActionNames[i]);
-		
-		act->setCheckable (true);
-		act->setChecked (i == (size_t) mode);
-		
-		if (i != Select)
-			act->setEnabled (R ()->camera () != GL::Free);
-	}
+void ForgeWindow::updateEditModeActions() {
+	const EditMode mode = R()->editMode();
+	ACTION (ModeSelect)->setChecked (mode == Select);
+	ACTION (ModeDraw)->setChecked (mode == Draw);
 }
 
 void ForgeWindow::slot_editObject (QListWidgetItem* listitem) {
@@ -981,11 +666,11 @@
 		}
 	}
 	
-	AddObjectDialog::staticDialog (obj->getType (), obj);
+	AddObjectDialog::staticDialog (obj->getType(), obj);
 }
 
 void ForgeWindow::primitiveLoaderStart (ulong max) {
-	m_primLoaderWidget->show ();
+	m_primLoaderWidget->show();
 	m_primLoaderBar->setRange (0, max);
 	m_primLoaderBar->setValue (0);
 	m_primLoaderBar->setFormat ("%p%");
@@ -995,26 +680,26 @@
 	m_primLoaderBar->setValue (prog);
 }
 
-void ForgeWindow::primitiveLoaderEnd () {
+void ForgeWindow::primitiveLoaderEnd() {
 	QTimer* hidetimer = new QTimer;
-	connect (hidetimer, SIGNAL (timeout ()), m_primLoaderWidget, SLOT (hide ()));
+	connect (hidetimer, SIGNAL (timeout()), m_primLoaderWidget, SLOT (hide()));
 	hidetimer->setSingleShot (true);
 	hidetimer->start (1500);
 	m_primLoaderBar->setFormat( tr( "Done" ));
-	log( tr( "Primitives scanned: %1 primitives listed" ), m_primLoaderBar->value() );
+	log (tr ("Primitives scanned: %1 primitives listed"), m_primLoaderBar->value());
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
 void ForgeWindow::save (LDOpenFile* f, bool saveAs) {
-	str path = f->name ();
+	str path = f->name();
 	
-	if (path.length () == 0 || saveAs) {
+	if (path.length() == 0 || saveAs) {
 		path = QFileDialog::getSaveFileName (g_win, tr ("Save As"),
-			currentFile()->name (), tr ("LDraw files (*.dat *.ldr)"));
+			currentFile()->name(), tr ("LDraw files (*.dat *.ldr)"));
 		
-		if (path.length () == 0) {
+		if (path.length() == 0) {
 			// User didn't give a file name. This happens if the user cancelled
 			// saving in the save file dialog. Abort.
 			return;
@@ -1025,20 +710,17 @@
 		f->setName (path);
 		
 		if (f == currentFile())
-			g_win->updateTitle ();
+			g_win->updateTitle();
 		
 		log ("Saved to %1.", path);
 		
 		// Add it to recent files
 		addRecentFile (path);
 	} else {
-		setlocale (LC_ALL, "C");
-		
 		str message = fmt (tr ("Failed to save to %1: %2"), path, strerror (errno));
 		
 		// Tell the user the save failed, and give the option for saving as with it.
-		QMessageBox dlg (QMessageBox::Critical, tr ("Save Failure"), message,
-						 QMessageBox::Close, g_win);
+		QMessageBox dlg (QMessageBox::Critical, tr ("Save Failure"), message, QMessageBox::Close, g_win);
 		
 		// Add a save-as button
 		QPushButton* saveAsBtn = new QPushButton (tr ("Save As"));
@@ -1047,19 +729,18 @@
 		dlg.setDefaultButton (QMessageBox::Close);
 		dlg.exec();
 		
-		if (dlg.clickedButton () == saveAsBtn)
+		if (dlg.clickedButton() == saveAsBtn)
 			save (f, true); // yay recursion!
 	}
 }
 
-void ForgeWindow::addMessage( str msg )
-{
-	m_msglog->addLine( msg );
+void ForgeWindow::addMessage (str msg) {
+	m_msglog->addLine (msg);
 }
 
 // ============================================================================
 void ObjectList::contextMenuEvent (QContextMenuEvent* ev) {
-	g_win->spawnContextMenu (ev->globalPos ());
+	g_win->spawnContextMenu (ev->globalPos());
 }
 
 // =============================================================================
@@ -1071,7 +752,7 @@
 
 // =============================================================================
 bool confirm (str msg) {
-	return confirm ("Confirm", msg);
+	return confirm (ForgeWindow::tr ("Confirm"), msg);
 }
 
 bool confirm (str title, str msg) {
@@ -1081,26 +762,11 @@
 
 // =============================================================================
 void critical (str msg) {
-	QMessageBox::critical (g_win, QObject::tr( "Error" ), msg,
+	QMessageBox::critical (g_win, ForgeWindow::tr("Error"), msg,
 		(QMessageBox::Close), QMessageBox::Close);
 }
 
 // =============================================================================
-QAction* findAction (str name) {
-	for (actionmeta& meta : g_actionMeta) {
-		if (meta.qAct == null)
-			break;
-		
-		if (name == meta.name)
-			return *meta.qAct;
-	}
-	
-	fatal (fmt ("Couldn't find action named `%2'!", name));
-	abort ();
-	return null;
-}
-
-// =============================================================================
 QIcon makeColorIcon (LDColor* colinfo, const ushort size) {
 	// Create an image object and link a painter to it.
 	QImage img (size, size, QImage::Format_ARGB32);
@@ -1110,11 +776,11 @@
 	if (colinfo->index == maincolor) {
 		// Use the user preferences for main color here
 		col = gl_maincolor.value;
-		col.setAlpha (gl_maincolor_alpha * 255.0f);
+		col.setAlphaF (gl_maincolor_alpha);
 	}
 	
 	// Paint the icon
-	paint.fillRect (QRect (0, 0, size, size), Qt::black);
+	paint.fillRect (QRect (0, 0, size, size), colinfo->edgeColor);
 	paint.drawPixmap (QRect (1, 1, size - 2, size - 2), getIcon ("checkerboard"), QRect (0, 0, 8, 8));
 	paint.fillRect (QRect (1, 1, size - 2, size - 2), col);
 	return QIcon (QPixmap::fromImage (img));
@@ -1124,17 +790,17 @@
 void makeColorSelector (QComboBox* box) {
 	std::map<short, ulong> counts;
 	
-	for (LDObject* obj : currentFile()->objs ()) {
-		if (!obj->isColored ())
+	for (LDObject* obj : currentFile()->objs()) {
+		if (!obj->isColored())
 			continue;
 		
-		if (counts.find (obj->color ()) == counts.end ())
-			counts[obj->color ()] = 1;
+		if (counts.find (obj->color()) == counts.end())
+			counts[obj->color()] = 1;
 		else
-			counts[obj->color ()]++;
+			counts[obj->color()]++;
 	}
 	
-	box->clear ();
+	box->clear();
 	ulong row = 0;
 	for (const auto& pair : counts) {
 		LDColor* col = getColor (pair.first);
@@ -1152,12 +818,12 @@
 // =============================================================================
 QDialogButtonBox* makeButtonBox (QDialog& dlg) {
 	QDialogButtonBox* bbx_buttons = new QDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
-	QWidget::connect (bbx_buttons, SIGNAL (accepted ()), &dlg, SLOT (accept ()));
-	QWidget::connect (bbx_buttons, SIGNAL (rejected ()), &dlg, SLOT (reject ()));
+	QWidget::connect (bbx_buttons, SIGNAL (accepted()), &dlg, SLOT (accept()));
+	QWidget::connect (bbx_buttons, SIGNAL (rejected()), &dlg, SLOT (reject()));
 	return bbx_buttons;
 }
 
-CheckBoxGroup* makeAxesBox () {
+CheckBoxGroup* makeAxesBox() {
 	CheckBoxGroup* cbg_axes = new CheckBoxGroup ("Axes", Qt::Horizontal);
 	cbg_axes->addCheckBox ("X", X);
 	cbg_axes->addCheckBox ("Y", Y);
@@ -1166,23 +832,21 @@
 }
 
 void ForgeWindow::setStatusBarText (str text) {
-	statusBar ()->showMessage (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;
-}
-
-void ForgeWindow::clearSelection()
-{
+void ForgeWindow::clearSelection() {
 	m_sel.clear();
 }
 
+Ui_LDForgeUI* ForgeWindow::interface() const {
+	return ui;
+}
+
+#define act(N) QAction* ForgeWindow::action##N() { return ui->action##N; }
+#include "actions.h"
+
 QImage imageFromScreencap (uchar* data, ushort w, ushort h) {
 	// GL and Qt formats have R and B swapped. Also, GL flips Y - correct it as well.
-	return QImage (data, w, h, QImage::Format_ARGB32).rgbSwapped ().mirrored ();
+	return QImage (data, w, h, QImage::Format_ARGB32).rgbSwapped().mirrored();
 }
\ No newline at end of file
--- a/src/gui.h	Mon Jul 15 14:43:29 2013 +0300
+++ b/src/gui.h	Mon Jul 15 19:30:16 2013 +0300
@@ -29,13 +29,13 @@
 class MessageManager;
 class ForgeWindow;
 class LDColor;
-class QSplitter;
 class QToolButton;
 class QDialogButtonBox;
 class GLRenderer;
 class CheckBoxGroup;
 class QComboBox;
 class QProgressBar;
+class Ui_LDForgeUI;
 
 // Stuff for dialogs
 #define IMPLEMENT_DIALOG_BUTTONS \
@@ -44,30 +44,13 @@
 	connect (bbx_buttons, SIGNAL (rejected ()), this, SLOT (reject ())); \
 
 // =============================================================================
-// Metadata for actions
-typedef struct {
-	QAction** qAct;
-	keyseqconfig* conf;
-	const char* name, *sDisplayName, *sIconName, *sDescription;
-	void (*handler) ();
-} actionmeta;
-
-#define MAX_ACTIONS 256
-extern actionmeta g_actionMeta[256];
-
-// =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-#define MAKE_ACTION(NAME, DISPLAYNAME, ICONNAME, DESCR, DEFSHORTCUT) \
-	QAction* ACTION (NAME); \
+#define DEFINE_ACTION(NAME, DEFSHORTCUT) \
 	cfg (keyseq, key_##NAME, DEFSHORTCUT); \
-	static void actionHandler_##NAME (); \
-	static ActionAdder ActionAdderInstance_##NAME (&ACTION(NAME), DISPLAYNAME, \
-		ICONNAME, DESCR, &key_##NAME, actionHandler_##NAME, #NAME); \
-	static void actionHandler_##NAME ()
+	void actiondef_##NAME ()
 
-#define EXTERN_ACTION(NAME) extern QAction* ACTION (NAME);
-#define ACTION(N) LDForgeAction_##N
+#define ACTION(N) g_win->action##N()
 
 // Convenience macros for key sequences.
 #define KEY(N) (Qt::Key_##N)
@@ -124,58 +107,55 @@
 	void deleteObjVector (vector< LDObject* > objs);
 	int deleteSelection ();
 	void deleteByColor (const short int colnum);
-	void save( LDOpenFile* f, bool saveAs );
+	void save (LDOpenFile* f, bool saveAs);
 	GLRenderer* R () { return m_renderer; }
 	vector<LDObject*>& sel () { return m_sel; }
 	void setQuickColorMeta (vector<quickColor>& quickColorMeta) {
 		m_colorMeta = quickColorMeta;
 	}
 	void setStatusBarText (str text);
-	void addActionMeta (actionmeta& meta);
-	void addMessage( str msg );
+	void addMessage (str msg);
+	Ui_LDForgeUI* interface() const;
+	
+#define act(N) QAction* action##N();
+#include "actions.h"
 	
 public slots:
 	void primitiveLoaderStart (ulong max);
 	void primitiveLoaderUpdate (ulong prog);
 	void primitiveLoaderEnd ();
 	void clearSelection();
+	void slot_action();
 	
 protected:
 	void closeEvent (QCloseEvent* ev);
 	
 private:
 	GLRenderer* m_renderer;
-	ObjectList* m_objList;
-	QMenu* m_recentFilesMenu;
-	QSplitter* m_splitter;
-	QToolBar* m_colorToolBar;
 	QProgressBar* m_primLoaderBar;
 	QWidget* m_primLoaderWidget;
-	vector<QToolBar*> m_toolBars;
 	vector<LDObject*> m_sel;
 	vector<quickColor> m_colorMeta;
 	vector<QToolButton*> m_colorButtons;
 	vector<QAction*> m_recentFiles;
 	MessageManager* m_msglog;
+	Ui_LDForgeUI* ui;
 	
-	void createMenuActions ();
-	void createMenus ();
-	void createToolbars ();
-	void initSingleToolBar (const char* name);
-	void addToolBarAction (const char* name);
+	void invokeAction (QAction* act, void (*func) ());
 	
-	QMenu* initMenu (const char* name);
-	void addMenuAction (const char* name);
 
 private slots:
 	void slot_selectionChanged ();
-	void slot_action ();
 	void slot_recentFile ();
 	void slot_quickColor ();
 	void slot_lastSecondCleanup ();
 	void slot_editObject (QListWidgetItem* listitem);
 };
 
+#define INVOKE_ACTION(N) actiondef_##N();
+#define act(N) void actiondef_##N();
+#include "actions.h"
+
 // -----------------------------------------------------------------------------
 // Pointer to the instance of ForgeWindow.
 extern ForgeWindow* g_win;
@@ -187,7 +167,6 @@
 bool confirm (str title, str msg);
 bool confirm (str msg);
 void critical (str msg);
-QAction* findAction (str name);
 QIcon makeColorIcon (LDColor* colinfo, const ushort size);
 void makeColorSelector (QComboBox* box);
 QDialogButtonBox* makeButtonBox (QDialog& dlg);
@@ -199,10 +178,9 @@
 // Takes in pairs of radio buttons and respective values and returns the value of
 // the first found radio button that was checked.
 // =============================================================================
-template<class T> T radioSwitch( const T& defval, vector<pair<QRadioButton*, T>> haystack )
-{
-	for( pair<QRadioButton*, const T&> i : haystack )
-		if( i.first->isChecked() )
+template<class T> T radioSwitch (const T& defval, vector<pair<QRadioButton*, T>> haystack) {
+	for (pair<QRadioButton*, const T&> i : haystack)
+		if (i.first->isChecked())
 			return i.second;
 	
 	return defval;
@@ -213,34 +191,13 @@
 // Takes in pairs of radio buttons and respective values and checks the first
 // found radio button to have the given value.
 // =============================================================================
-template<class T> void radioDefault( const T& expr, vector<pair<QRadioButton*, T>> haystack )
-{
-	for( pair<QRadioButton*, const T&> i : haystack )
-	{
-		if( i.second == expr )
-		{
-			i.first->setChecked( true );
+template<class T> void radioDefault (const T& expr, vector<pair<QRadioButton*, T>> haystack) {
+	for (pair<QRadioButton*, const T&> i : haystack) {
+		if (i.second == expr) {
+			i.first->setChecked (true);
 			return;
 		}
 	}
 }
 
-// =============================================================================
-// 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/gui_actions.cpp	Mon Jul 15 14:43:29 2013 +0300
+++ b/src/gui_actions.cpp	Mon Jul 15 19:30:16 2013 +0300
@@ -43,7 +43,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (newFile, "&New", "brick", "Create a new part model.", CTRL (N)) {
+DEFINE_ACTION (New, CTRL (N)) {
 	if (safeToCloseAll() == false)
 		return;
 	
@@ -84,7 +84,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (open, "&Open", "file-open", "Load a part model from a file.", CTRL (O)) {
+DEFINE_ACTION (Open, CTRL (O)) {
 	if (safeToCloseAll() == false)
 		return;
 	
@@ -100,27 +100,25 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (save, "&Save", "file-save", "Save the part model.", CTRL (S))
-{
+DEFINE_ACTION (Save, CTRL (S)) {
 	g_win->save (currentFile(), false);
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (saveAs, "Save &As", "file-save-as", "Save the part model to a specific file.", CTRL_SHIFT (S))
-{
+DEFINE_ACTION (SaveAs, CTRL_SHIFT (S)) {
 	g_win->save (currentFile(), true);
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (settings, "Settin&gs", "settings", "Edit the settings of " APPNAME ".", (0)) {
+DEFINE_ACTION (Settings, 0) {
 	ConfigDialog::staticDialog();
 }
 
-MAKE_ACTION (setLDrawPath, "Set LDraw Path", "settings", "Change the LDraw directory path.", (0)) {
+DEFINE_ACTION (SetLDrawPath, 0) {
 	LDrawPathDialog dlg (true);
 	dlg.exec();
 }
@@ -128,51 +126,50 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (exit, "&Exit", "exit", "Close " APPNAME ".", CTRL (Q)) {
+DEFINE_ACTION (Exit, CTRL (Q)) {
 	exit (0);
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (newSubfile, "New Subfile", "add-subfile", "Creates a new subfile reference.", 0) {
+DEFINE_ACTION (NewSubfile, 0) {
 	AddObjectDialog::staticDialog (LDObject::Subfile, null);
 }
 
-MAKE_ACTION (newLine, "New Line",  "add-line", "Creates a new line.", 0) {
+DEFINE_ACTION (NewLine, 0) {
 	AddObjectDialog::staticDialog (LDObject::Line, null);
 }
 
-MAKE_ACTION (newTriangle, "New Triangle", "add-triangle", "Creates a new triangle.", 0) {
+DEFINE_ACTION (NewTriangle, 0) {
 	AddObjectDialog::staticDialog (LDObject::Triangle, null);
 }
 
-MAKE_ACTION (newQuad, "New Quadrilateral", "add-quad", "Creates a new quadrilateral.", 0) {
+DEFINE_ACTION (NewQuad, 0) {
 	AddObjectDialog::staticDialog (LDObject::Quad, null);
 }
 
-MAKE_ACTION (newCondLine, "New Conditional Line", "add-condline", "Creates a new conditional line.", 0) {
+DEFINE_ACTION (NewCLine, 0) {
 	AddObjectDialog::staticDialog (LDObject::CondLine, null);
 }
 
-MAKE_ACTION (newComment, "New Comment", "add-comment", "Creates a new comment.", 0) {
+DEFINE_ACTION (NewComment, 0) {
 	AddObjectDialog::staticDialog (LDObject::Comment, null);
 }
 
-MAKE_ACTION (newBFC, "New BFC Statement", "add-bfc", "Creates a new BFC statement.", 0) {
+DEFINE_ACTION (NewBFC, 0) {
 	AddObjectDialog::staticDialog (LDObject::BFC, null);
 }
 
-MAKE_ACTION (newVertex, "New Vertex", "add-vertex", "Creates a new vertex.", 0) {
+DEFINE_ACTION (NewVertex, 0) {
 	AddObjectDialog::staticDialog (LDObject::Vertex, null);
 }
 
-MAKE_ACTION (makePrimitive, "Make a Primitive", "radial", "Generate a new circular primitive.", 0)
-{
+DEFINE_ACTION (MakePrimitive, 0) {
 	generatePrimitive();
 }
 
-MAKE_ACTION (editObject, "Edit Object", "edit-object", "Edits this object.", 0) {
+DEFINE_ACTION (Edit, 0) {
 	if (g_win->sel().size() != 1)
 		return;
 	
@@ -180,28 +177,25 @@
 	AddObjectDialog::staticDialog (obj->getType(), obj);
 }
 
-MAKE_ACTION (help, "Help", "help", "Shows the " APPNAME " help manual.", KEY (F1)) {
+DEFINE_ACTION (Help, KEY (F1)) {
 	
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (about, "About " APPNAME, "ldforge",
-	"Shows information about " APPNAME ".", (0))
-{
-	AboutDialog dlg;
-	dlg.exec();
+DEFINE_ACTION (About, 0) {
+	AboutDialog().exec();
 }
 
-MAKE_ACTION (aboutQt, "About Qt", "qt", "Shows information about Qt.", (0)) {
+DEFINE_ACTION (AboutQt, 0) {
 	QMessageBox::aboutQt (g_win);
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (selectAll, "Select All", "select-all", "Selects all objects.", CTRL (A)) {
+DEFINE_ACTION (SelectAll, CTRL (A)) {
 	g_win->sel().clear();
 	
 	for (LDObject* obj : currentFile()->objs())
@@ -211,9 +205,7 @@
 }
 
 // =============================================================================
-MAKE_ACTION (selectByColor, "Select by Color", "select-color",
-	"Select all objects by the given color.", CTRL_SHIFT (A))
-{
+DEFINE_ACTION (SelectByColor, CTRL_SHIFT (A)) {
 	short colnum = g_win->getSelectedColor();
 	
 	if (colnum == -1)
@@ -228,9 +220,7 @@
 }
 
 // =============================================================================
-MAKE_ACTION (selectByType, "Select by Type", "select-type",
-	"Select all objects by the given type.", (0))
-{
+DEFINE_ACTION (SelectByType, 0) {
 	if (g_win->sel().size() == 0)
 		return;
 	
@@ -268,17 +258,17 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (gridCoarse, "Coarse Grid", "grid-coarse", "Set the grid to Coarse", (0)) {
+DEFINE_ACTION (GridCoarse, 0) {
 	grid = Grid::Coarse;
 	g_win->updateGridToolBar();
 }
 
-MAKE_ACTION (gridMedium, "Medium Grid", "grid-medium", "Set the grid to Medium", (0)) {
+DEFINE_ACTION (GridMedium, 0) {
 	grid = Grid::Medium;
 	g_win->updateGridToolBar();
 }
 
-MAKE_ACTION (gridFine, "Fine Grid", "grid-fine", "Set the grid to Fine", (0)) {
+DEFINE_ACTION (GridFine, 0) {
 	grid = Grid::Fine;
 	g_win->updateGridToolBar();
 }
@@ -286,7 +276,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (resetView, "Reset View", "reset-view", "Reset view angles, pan and zoom", CTRL (0)) {
+DEFINE_ACTION (ResetView, CTRL (0)) {
 	g_win->R()->resetAngles();
 	g_win->R()->update();
 }
@@ -294,7 +284,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (insertFrom, "Insert from File", "file-import", "Insert LDraw data from a file.", (0)) {
+DEFINE_ACTION (InsertFrom, 0) {
 	str fname = QFileDialog::getOpenFileName();
 	ulong idx = g_win->getInsertionPoint();
 	
@@ -325,7 +315,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (exportTo, "Export To File", "file-export", "Export current selection to file", (0)) {
+DEFINE_ACTION (ExportTo, 0) {
 	if (g_win->sel().size() == 0)
 		return;
 	
@@ -350,7 +340,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (insertRaw, "Insert Raw", "insert-raw", "Type in LDraw code to insert.", (0)) {
+DEFINE_ACTION (InsertRaw, 0) {
 	ulong idx = g_win->getInsertionPoint();
 	
 	QDialog* const dlg = new QDialog;
@@ -382,8 +372,7 @@
 	g_win->scrollToSelection();
 }
 
-// =========================================================================================================================================
-MAKE_ACTION (screencap, "Screencap Part", "screencap", "Save a picture of the model", (0)) {
+DEFINE_ACTION (Screenshot, 0) {
 	setlocale (LC_ALL, "C");
 	
 	ushort w, h;
@@ -404,28 +393,28 @@
 	delete[] imgdata;
 }
 
-// =========================================================================================================================================
+// =============================================================================
 extern_cfg (bool, gl_axes);
-MAKE_ACTION (axes, "Draw Axes", "axes", "Toggles drawing of axes", (0)) {
+DEFINE_ACTION (Axes, 0) {
 	gl_axes = !gl_axes;
-	ACTION (axes)->setChecked (gl_axes);
+	ACTION (Axes)->setChecked (gl_axes);
 	g_win->R()->update();
 }
 
-// =========================================================================================================================================
-MAKE_ACTION (visibility, "Toggle Visibility", "visibility", "Toggles visibility/hiding on objects.", (0)) {
+// =============================================================================
+DEFINE_ACTION (Visibility, 0) {
 	for (LDObject* obj : g_win->sel())
 		obj->setHidden (!obj->hidden());
 	
 	g_win->fullRefresh();
 }
 
-MAKE_ACTION (wireframe, "Wireframe", "wireframe", "Toggle wireframe view", (0)) {
+DEFINE_ACTION (Wireframe, 0) {
 	gl_wireframe = !gl_wireframe;
 	g_win->R()->refresh();
 }
 
-MAKE_ACTION (setOverlay, "Set Overlay Image", "overlay", "Set an overlay image", 0)
+DEFINE_ACTION (SetOverlay,  0)
 {
 	OverlayDialog dlg;
 	
@@ -436,19 +425,19 @@
 		dlg.ofsy(), dlg.lwidth(), dlg.lheight() );
 }
 
-MAKE_ACTION (clearOverlay, "Clear Overlay Image", "overlay-clear", "Clear the overlay image.", (0)) {
+DEFINE_ACTION (ClearOverlay, 0) {
 	g_win->R()->clearOverlay();
 }
 
-MAKE_ACTION (modeSelect, "Select Mode", "mode-select", "Select objects from the camera view.", CTRL (1)) {
+DEFINE_ACTION (ModeSelect, CTRL (1)) {
 	g_win->R()->setEditMode (Select);
 }
 
-MAKE_ACTION (modeDraw, "Draw Mode", "mode-draw", "Draw objects into the camera view.", CTRL (2)) {
+DEFINE_ACTION (ModeDraw, CTRL (2)) {
 	g_win->R()->setEditMode (Draw);
 }
 
-MAKE_ACTION (setDrawDepth, "Set Depth Value", "depth-value", "Set the depth coordinate of the current camera.", (0)) {
+DEFINE_ACTION (SetDrawDepth, 0) {
 	if (g_win->R()->camera() == GL::Free)
 		return;
 	
@@ -461,11 +450,11 @@
 		g_win->R()->setDepthValue (depth);
 }
 
-#ifndef RELEASE
+#if 0
 // This is a test to draw a dummy axle. Meant to be used as a primitive gallery,
 // but I can't figure how to generate these pictures properly. Multi-threading
 // these is an immense pain.
-MAKE_ACTION (testpic, "Test picture", "", "", (0)) {
+DEFINE_ACTION (testpic, "Test picture", "", "", (0)) {
 	LDOpenFile* file = getFile ("axle.dat");
 	setlocale (LC_ALL, "C");
 	
@@ -505,13 +494,12 @@
 }
 #endif
 
-MAKE_ACTION (reloadPrimitives, "Scan Primitives", "", "", (0)) {
+DEFINE_ACTION (ScanPrimitives, 0) {
 	PrimitiveLister::start();
 }
 
-MAKE_ACTION (colorbfc, "BFC Red/Green View", "bfc-view", "", SHIFT (B))
-{
+DEFINE_ACTION (BFCView, SHIFT (B)) {
 	gl_colorbfc = !gl_colorbfc;
-	ACTION (colorbfc)->setChecked (gl_colorbfc);
+	ACTION (BFCView)->setChecked (gl_colorbfc);
 	g_win->R()->refresh();
 }
\ No newline at end of file
--- a/src/gui_editactions.cpp	Mon Jul 15 14:43:29 2013 +0300
+++ b/src/gui_editactions.cpp	Mon Jul 15 19:30:16 2013 +0300
@@ -65,7 +65,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (cut, "Cut", "cut", "Cut the current selection to clipboard.", CTRL (X)) {
+DEFINE_ACTION (Cut, CTRL (X)) {
 	int num = copyToClipboard();
 	g_win->deleteSelection();
 	log (ForgeWindow::tr ("%1 objects cut"), num);
@@ -74,7 +74,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (copy, "Copy", "copy", "Copy the current selection to clipboard.", CTRL (C)) {
+DEFINE_ACTION (Copy, CTRL (C)) {
 	int num = copyToClipboard();
 	log (ForgeWindow::tr ("%1 objects copied"), num);
 }
@@ -82,7 +82,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (paste, "Paste", "paste", "Paste clipboard contents.", CTRL (V)) {
+DEFINE_ACTION (Paste, CTRL (V)) {
 	const str clipboardText = qApp->clipboard()->text();
 	ulong idx = g_win->getInsertionPoint();
 	g_win->sel().clear();
@@ -104,7 +104,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (del, "Delete", "delete", "Delete the selection", KEY (Delete)) {
+DEFINE_ACTION (Delete, KEY (Delete)) {
 	int num = g_win->deleteSelection();
 	log (ForgeWindow::tr ("%1 objects deleted"), num);
 }
@@ -148,20 +148,18 @@
 	g_win->fullRefresh();
 }
 
-MAKE_ACTION (inlineContents, "Inline", "inline", "Inline selected subfiles.", CTRL (I)) {
+DEFINE_ACTION (Inline, CTRL (I)) {
 	doInline (false);
 }
 
-MAKE_ACTION (deepInline, "Deep Inline", "inline-deep", "Recursively inline selected subfiles "
-	"down to polygons only.", CTRL_SHIFT (I))
-{
+DEFINE_ACTION (InlineDeep, CTRL_SHIFT (I)) {
 	doInline (true);
 }
 
 // ===============================================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // ===============================================================================================
-MAKE_ACTION (splitQuads, "Split Quads", "quad-split", "Split quads into triangles.", (0)) {
+DEFINE_ACTION (SplitQuads, 0) {
 	vector<LDObject*> objs = g_win->sel();
 	int num = 0;
 	
@@ -195,7 +193,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (setContents, "Edit LDraw Code", "set-contents", "Edit the LDraw code of this object.", KEY (F9)) {
+DEFINE_ACTION (EditRaw, KEY (F9)) {
 	if (g_win->sel().size() != 1)
 		return;
 	
@@ -230,7 +228,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (setColor, "Set Color", "palette", "Set the color on given objects.", KEY (C)) {
+DEFINE_ACTION (SetColor, KEY (C)) {
 	if (g_win->sel().size() <= 0)
 		return;
 	
@@ -260,7 +258,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (makeBorders, "Make Borders", "make-borders", "Add borders around given polygons.", CTRL_SHIFT (B)) {
+DEFINE_ACTION (Borders, CTRL_SHIFT (B)) {
 	vector<LDObject*> objs = g_win->sel();
 	int num = 0;
 	
@@ -306,9 +304,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (makeCornerVerts, "Make Corner Vertices", "corner-verts",
-	"Adds vertex objects to the corners of the given polygons", (0))
-{
+DEFINE_ACTION (CornerVerts, 0) {
 	int num = 0;
 	
 	for (LDObject* obj : g_win->sel()) {
@@ -341,22 +337,22 @@
 	g_win->buildObjList();
 }
 
-MAKE_ACTION (moveUp, "Move Up", "arrow-up", "Move the current selection up.", KEY (PageUp)) {
+DEFINE_ACTION (MoveUp, KEY (PageUp)) {
 	doMoveSelection (true);
 }
 
-MAKE_ACTION (moveDown, "Move Down", "arrow-down", "Move the current selection down.", KEY (PageDown)) {
+DEFINE_ACTION (MoveDown, KEY (PageDown)) {
 	doMoveSelection (false);
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (undo, "Undo", "undo", "Undo a step.", CTRL (Z)) {
+DEFINE_ACTION (Undo, CTRL (Z)) {
 	currentFile()->undo();
 }
 
-MAKE_ACTION (redo, "Redo", "redo", "Redo a step.", CTRL_SHIFT (Z)) {
+DEFINE_ACTION (Redo, CTRL_SHIFT (Z)) {
 	currentFile()->redo();
 }
 
@@ -377,32 +373,32 @@
 	g_win->refresh();
 }
 
-MAKE_ACTION (moveXNeg, "Move -X", "move-x-neg", "Move selected objects negative on the X axis.", KEY (Left)) {
-	doMoveObjects ( { -1, 0, 0});
+DEFINE_ACTION (MoveXNeg, KEY (Left)) {
+	doMoveObjects ({ -1, 0, 0});
 }
 
-MAKE_ACTION (moveYNeg, "Move -Y", "move-y-neg", "Move selected objects negative on the Y axis.", KEY (Home)) {
-	doMoveObjects ( {0, -1, 0});
+DEFINE_ACTION (MoveYNeg, KEY (Home)) {
+	doMoveObjects ({0, -1, 0});
 }
 
-MAKE_ACTION (moveZNeg, "Move -Z", "move-z-neg", "Move selected objects negative on the Z axis.", KEY (Down)) {
-	doMoveObjects ( {0, 0, -1});
+DEFINE_ACTION (MoveZNeg, KEY (Down)) {
+	doMoveObjects ({0, 0, -1});
 }
 
-MAKE_ACTION (moveXPos, "Move +X", "move-x-pos", "Move selected objects positive on the X axis.", KEY (Right)) {
-	doMoveObjects ( {1, 0, 0});
+DEFINE_ACTION (MoveXPos, KEY (Right)) {
+	doMoveObjects ({1, 0, 0});
 }
 
-MAKE_ACTION (moveYPos, "Move +Y", "move-y-pos", "Move selected objects positive on the Y axis.", KEY (End)) {
-	doMoveObjects ( {0, 1, 0});
+DEFINE_ACTION (MoveYPos, KEY (End)) {
+	doMoveObjects ({0, 1, 0});
 }
 
-MAKE_ACTION (moveZPos, "Move +Z", "move-z-pos", "Move selected objects positive on the Z axis.", KEY (Up)) {
-	doMoveObjects ( {0, 0, 1});
+DEFINE_ACTION (MoveZPos, KEY (Up)) {
+	doMoveObjects ({0, 0, 1});
 }
 
 // =============================================================================
-MAKE_ACTION (invert, "Invert", "invert", "Reverse the winding of given objects.", CTRL_SHIFT (W)) {
+DEFINE_ACTION (Invert, CTRL_SHIFT (W)) {
 	vector<LDObject*> sel = g_win->sel();
 	
 	for (LDObject* obj : sel) {
@@ -471,38 +467,21 @@
 	g_win->refresh();
 }
 
-MAKE_ACTION (rotateXPos, "Rotate +X", "rotate-x-pos", "Rotate objects around X axis", CTRL (Right)) {
-	doRotate (1, 0, 0);
-}
-
-MAKE_ACTION (rotateYPos, "Rotate +Y", "rotate-y-pos", "Rotate objects around Y axis", CTRL (End)) {
-	doRotate (0, 1, 0);
-}
-
-MAKE_ACTION (rotateZPos, "Rotate +Z", "rotate-z-pos", "Rotate objects around Z axis", CTRL (Up)) {
-	doRotate (0, 0, 1);
-}
+DEFINE_ACTION (RotateXPos, CTRL (Right)) { doRotate (1, 0, 0); }
+DEFINE_ACTION (RotateYPos, CTRL (End))   { doRotate (0, 1, 0); }
+DEFINE_ACTION (RotateZPos, CTRL (Up))    { doRotate (0, 0, 1); }
+DEFINE_ACTION (RotateXNeg, CTRL (Left))  { doRotate (-1, 0, 0); }
+DEFINE_ACTION (RotateYNeg, CTRL (Home))  { doRotate (0, -1, 0); }
+DEFINE_ACTION (RotateZNeg, CTRL (Down))  { doRotate (0, 0, -1); }
 
-MAKE_ACTION (rotateXNeg, "Rotate -X", "rotate-x-neg", "Rotate objects around X axis", CTRL (Left)) {
-	doRotate (-1, 0, 0);
-}
-
-MAKE_ACTION (rotateYNeg, "Rotate -Y", "rotate-y-neg", "Rotate objects around Y axis", CTRL (Home)) {
-	doRotate (0, -1, 0);
-}
-
-MAKE_ACTION (rotateZNeg, "Rotate -Z", "rotate-z-neg", "Rotate objects around Z axis", CTRL (Down)) {
-	doRotate (0, 0, -1);
-}
-
-MAKE_ACTION (rotpoint, "Set Rotation Point", "rotpoint", "Configure the rotation point.", (0)) {
+DEFINE_ACTION (RotationPoint, (0)) {
 	configRotationPoint();
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (roundCoords, "Round Coordinates", "round-coords", "Round coordinates down to 3/4 decimals", (0)) {
+DEFINE_ACTION (RoundCoordinates, 0) {
 	setlocale (LC_ALL, "C");
 	int num = 0;
 	
@@ -528,7 +507,7 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (uncolorize, "Uncolorize", "uncolorize", "Reduce colors of everything selected to main and edge colors", (0)) {
+DEFINE_ACTION (Uncolorize, 0) {
 	int num = 0;
 	
 	for (LDObject* obj : g_win->sel()) {
@@ -551,28 +530,28 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-MAKE_ACTION (ytruder, "Ytruder", "ytruder", "Extrude selected lines to a given plane", (0)) {
+DEFINE_ACTION (Ytruder, 0) {
 	runYtruder();
 }
 
-MAKE_ACTION (rectifier, "Rectifier", "rectifier", "Optimizes quads into rect primitives.", (0)) {
+DEFINE_ACTION (Rectifier, 0) {
 	runRectifier();
 }
 
-MAKE_ACTION (intersector, "Intersector", "intersector", "Perform clipping between two input groups.", (0)) {
+DEFINE_ACTION (Intersector, 0) {
 	runIntersector();
 }
 
-MAKE_ACTION (coverer, "Coverer", "coverer", "Fill the space between two line shapes", (0)) {
+DEFINE_ACTION (Coverer, 0) {
 	runCoverer();
 }
 
-MAKE_ACTION (isecalc, "Isecalc", "isecalc", "Compute intersection between objects", (0)) {
+DEFINE_ACTION (Isecalc, 0) {
 	runIsecalc();
 }
 
 // =============================================================================
-MAKE_ACTION (replaceCoords, "Replace Coordinates", "replace-coords", "Find and replace coordinate values", CTRL (R)) {
+DEFINE_ACTION (ReplaceCoords, CTRL (R)) {
 	QDialog* dlg = new QDialog (g_win);
 	Ui::ReplaceCoordsUI ui;
 	ui.setupUi (dlg);
@@ -616,7 +595,7 @@
 }
 
 // ================================================================================================
-MAKE_ACTION (flip, "Flip", "flip", "Flip coordinates", CTRL_SHIFT (F)) {
+DEFINE_ACTION (Flip, CTRL_SHIFT (F)) {
 	QDialog* dlg = new QDialog;
 	Ui::FlipUI ui;
 	ui.setupUi (dlg);
@@ -644,7 +623,7 @@
 }
 
 // ================================================================================================
-MAKE_ACTION (demote, "Demote conditional lines", "demote", "Demote conditional lines down to normal lines.", (0)) {
+DEFINE_ACTION (Demote, 0) {
 	vector<LDObject*> sel = g_win->sel();
 	int num = 0;
 	
@@ -670,13 +649,13 @@
 	return false;
 }
 
-MAKE_ACTION (autoColor, "Autocolor", "autocolor", "Set the color of the given object to the first found unused color.", (0)) {
+DEFINE_ACTION (Autocolor, 0) {
 	short colnum = 0;
 	
-	while (colnum < 512 && (getColor (colnum) == null || isColorUsed (colnum)))
+	while (colnum < MAX_COLORS && (getColor (colnum) == null || isColorUsed (colnum)))
 		colnum++;
 	
-	if (colnum >= 512) {
+	if (colnum >= MAX_COLORS) {
 		//: Auto-colorer error message
 		critical (ForgeWindow::tr ("Out of unused colors! What are you doing?!"));
 		return;
--- a/src/history.cpp	Mon Jul 15 14:43:29 2013 +0300
+++ b/src/history.cpp	Mon Jul 15 19:30:16 2013 +0300
@@ -23,9 +23,6 @@
 #include "gui.h"
 #include "gldraw.h"
 
-EXTERN_ACTION (undo)
-EXTERN_ACTION (redo)
-
 bool g_fullRefresh = false;
 
 History::History() {
@@ -84,8 +81,8 @@
 }
 
 void History::updateActions() const {
-	ACTION (undo)->setEnabled (pos() != -1);
-	ACTION (redo)->setEnabled (pos() < (long) m_changesets.size() - 1);
+	ACTION (Undo)->setEnabled (pos() != -1);
+	ACTION (Redo)->setEnabled (pos() < (long) m_changesets.size() - 1);
 }
 
 void History::open() {
--- a/src/misc.cpp	Mon Jul 15 14:43:29 2013 +0300
+++ b/src/misc.cpp	Mon Jul 15 19:30:16 2013 +0300
@@ -84,9 +84,6 @@
 // =============================================================================
 // Grid stuff
 cfg (int, grid, Grid::Medium);
-EXTERN_ACTION (gridCoarse)
-EXTERN_ACTION (gridMedium)
-EXTERN_ACTION (gridFine)
 
 cfg (float, grid_coarse_x,			5.0f);
 cfg (float, grid_coarse_y,			5.0f);
@@ -106,9 +103,9 @@
 cfg (float, edit_rotpoint_z, 0.0f);
 
 const gridinfo g_GridInfo[3] = {
-	{ "Coarse",	{ &grid_coarse_x,	&grid_coarse_y,	&grid_coarse_z,	&grid_coarse_angle	}, &ACTION (gridCoarse) },
-	{ "Medium",	{ &grid_medium_x,	&grid_medium_y,		&grid_medium_z,		&grid_medium_angle	}, &ACTION (gridMedium) },
-	{ "Fine",		{ &grid_fine_x,	&grid_fine_y,		&grid_fine_z,		&grid_fine_angle	}, &ACTION (gridFine) }
+	{ "Coarse", { &grid_coarse_x, &grid_coarse_y, &grid_coarse_z, &grid_coarse_angle }},
+	{ "Medium", { &grid_medium_x, &grid_medium_y, &grid_medium_z, &grid_medium_angle }},
+	{ "Fine",   { &grid_fine_x,   &grid_fine_y,   &grid_fine_z,   &grid_fine_angle   }}
 };
 
 // =============================================================================
--- a/src/misc.h	Mon Jul 15 14:43:29 2013 +0300
+++ b/src/misc.h	Mon Jul 15 19:30:16 2013 +0300
@@ -48,7 +48,6 @@
 typedef struct {
 	const char* const name;
 	floatconfig* const confs[4];
-	QAction** const actionptr;
 } gridinfo;
 
 extern_cfg (int, grid);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ui/ldforge.ui	Mon Jul 15 19:30:16 2013 +0300
@@ -0,0 +1,1229 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>LDForgeUI</class>
+ <widget class="QMainWindow" name="LDForgeUI">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>900</width>
+    <height>600</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string/>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="../../ldforge.qrc">
+    <normaloff>:/icons/ldforge.png</normaloff>:/icons/ldforge.png</iconset>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QVBoxLayout" name="verticalLayout">
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,4,2">
+      <item>
+       <widget class="QListWidget" name="fileList">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QFrame" name="rendererFrame">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="frameShape">
+         <enum>QFrame::StyledPanel</enum>
+        </property>
+        <property name="frameShadow">
+         <enum>QFrame::Raised</enum>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QListWidget" name="objectList">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>900</width>
+     <height>23</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menuFile">
+    <property name="title">
+     <string>File</string>
+    </property>
+    <widget class="QMenu" name="menuOpenRecent">
+     <property name="title">
+      <string>Open Recent...</string>
+     </property>
+     <property name="icon">
+      <iconset resource="../../ldforge.qrc">
+       <normaloff>:/icons/open-recent.png</normaloff>:/icons/open-recent.png</iconset>
+     </property>
+    </widget>
+    <addaction name="actionNew"/>
+    <addaction name="actionOpen"/>
+    <addaction name="menuOpenRecent"/>
+    <addaction name="actionSave"/>
+    <addaction name="actionSaveAs"/>
+    <addaction name="separator"/>
+    <addaction name="actionInsertFrom"/>
+    <addaction name="actionExportTo"/>
+    <addaction name="separator"/>
+    <addaction name="actionSettings"/>
+    <addaction name="actionSetLDrawPath"/>
+    <addaction name="actionScanPrimitives"/>
+    <addaction name="separator"/>
+    <addaction name="actionExit"/>
+   </widget>
+   <widget class="QMenu" name="menuView">
+    <property name="title">
+     <string>View</string>
+    </property>
+    <addaction name="actionResetView"/>
+    <addaction name="actionAxes"/>
+    <addaction name="actionWireframe"/>
+    <addaction name="actionBFCView"/>
+    <addaction name="separator"/>
+    <addaction name="actionSetOverlay"/>
+    <addaction name="actionClearOverlay"/>
+    <addaction name="separator"/>
+    <addaction name="actionScreenshot"/>
+   </widget>
+   <widget class="QMenu" name="menuInsert">
+    <property name="title">
+     <string>Insert</string>
+    </property>
+    <addaction name="actionInsertRaw"/>
+    <addaction name="separator"/>
+    <addaction name="actionNewSubfile"/>
+    <addaction name="actionNewLine"/>
+    <addaction name="actionNewTriangle"/>
+    <addaction name="actionNewQuad"/>
+    <addaction name="actionNewCLine"/>
+    <addaction name="actionNewComment"/>
+    <addaction name="actionNewBFC"/>
+    <addaction name="actionNewVertex"/>
+   </widget>
+   <widget class="QMenu" name="menuEdit">
+    <property name="title">
+     <string>Edit</string>
+    </property>
+    <addaction name="actionUndo"/>
+    <addaction name="actionRedo"/>
+    <addaction name="separator"/>
+    <addaction name="actionEdit"/>
+    <addaction name="separator"/>
+    <addaction name="actionCut"/>
+    <addaction name="actionCopy"/>
+    <addaction name="actionPaste"/>
+    <addaction name="actionDelete"/>
+    <addaction name="separator"/>
+    <addaction name="actionSelectAll"/>
+    <addaction name="actionSelectByColor"/>
+    <addaction name="actionSelectByType"/>
+    <addaction name="separator"/>
+    <addaction name="actionModeSelect"/>
+    <addaction name="actionModeDraw"/>
+    <addaction name="separator"/>
+    <addaction name="actionSetDrawDepth"/>
+   </widget>
+   <widget class="QMenu" name="menuTools">
+    <property name="title">
+     <string>Tools</string>
+    </property>
+    <addaction name="actionSetColor"/>
+    <addaction name="actionAutocolor"/>
+    <addaction name="actionUncolorize"/>
+    <addaction name="separator"/>
+    <addaction name="actionInvert"/>
+    <addaction name="actionInline"/>
+    <addaction name="actionInlineDeep"/>
+    <addaction name="actionMakePrimitive"/>
+    <addaction name="separator"/>
+    <addaction name="actionSplitQuads"/>
+    <addaction name="actionEditRaw"/>
+    <addaction name="actionBorders"/>
+    <addaction name="actionCornerVerts"/>
+    <addaction name="actionRoundCoordinates"/>
+    <addaction name="actionVisibility"/>
+    <addaction name="actionReplaceCoords"/>
+    <addaction name="actionFlip"/>
+    <addaction name="actionDemote"/>
+   </widget>
+   <widget class="QMenu" name="menuExternal_Tools">
+    <property name="title">
+     <string>External Tools</string>
+    </property>
+    <addaction name="actionYtruder"/>
+    <addaction name="actionRectifier"/>
+    <addaction name="actionIntersector"/>
+    <addaction name="actionIsecalc"/>
+    <addaction name="actionCoverer"/>
+    <addaction name="actionEdger2"/>
+   </widget>
+   <widget class="QMenu" name="menuHelp">
+    <property name="title">
+     <string>Help</string>
+    </property>
+    <addaction name="actionHelp"/>
+    <addaction name="separator"/>
+    <addaction name="actionAbout"/>
+    <addaction name="actionAboutQt"/>
+   </widget>
+   <widget class="QMenu" name="menuMov">
+    <property name="title">
+     <string>Move</string>
+    </property>
+    <widget class="QMenu" name="menuGrids">
+     <property name="title">
+      <string>Grids</string>
+     </property>
+     <addaction name="actionGridCoarse"/>
+     <addaction name="actionGridMedium"/>
+     <addaction name="actionGridFine"/>
+    </widget>
+    <widget class="QMenu" name="menuMove_Objects">
+     <property name="title">
+      <string>Move Objects</string>
+     </property>
+     <addaction name="actionMoveXNeg"/>
+     <addaction name="actionMoveXPos"/>
+     <addaction name="actionMoveYNeg"/>
+     <addaction name="actionMoveYPos"/>
+     <addaction name="actionMoveZNeg"/>
+     <addaction name="actionMoveZPos"/>
+    </widget>
+    <widget class="QMenu" name="menuObject_List">
+     <property name="title">
+      <string>Object List</string>
+     </property>
+     <addaction name="actionMoveUp"/>
+     <addaction name="actionMoveDown"/>
+    </widget>
+    <widget class="QMenu" name="menuRotate">
+     <property name="title">
+      <string>Rotate</string>
+     </property>
+     <addaction name="actionRotateXNeg"/>
+     <addaction name="actionRotateXPos"/>
+     <addaction name="actionRotateYNeg"/>
+     <addaction name="actionRotateYPos"/>
+     <addaction name="actionRotateZNeg"/>
+     <addaction name="actionRotateZPos"/>
+    </widget>
+    <addaction name="menuGrids"/>
+    <addaction name="menuMove_Objects"/>
+    <addaction name="menuRotate"/>
+    <addaction name="menuObject_List"/>
+    <addaction name="separator"/>
+    <addaction name="actionRotationPoint"/>
+   </widget>
+   <addaction name="menuFile"/>
+   <addaction name="menuView"/>
+   <addaction name="menuInsert"/>
+   <addaction name="menuEdit"/>
+   <addaction name="menuMov"/>
+   <addaction name="menuTools"/>
+   <addaction name="menuExternal_Tools"/>
+   <addaction name="menuHelp"/>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+  <widget class="QToolBar" name="toolBar">
+   <property name="windowTitle">
+    <string>toolBar</string>
+   </property>
+   <attribute name="toolBarArea">
+    <enum>TopToolBarArea</enum>
+   </attribute>
+   <attribute name="toolBarBreak">
+    <bool>false</bool>
+   </attribute>
+   <addaction name="actionNew"/>
+   <addaction name="actionOpen"/>
+   <addaction name="actionSave"/>
+   <addaction name="actionSaveAs"/>
+  </widget>
+  <widget class="QToolBar" name="toolBar_2">
+   <property name="windowTitle">
+    <string>toolBar_2</string>
+   </property>
+   <attribute name="toolBarArea">
+    <enum>TopToolBarArea</enum>
+   </attribute>
+   <attribute name="toolBarBreak">
+    <bool>false</bool>
+   </attribute>
+   <addaction name="actionNewSubfile"/>
+   <addaction name="actionNewLine"/>
+   <addaction name="actionNewTriangle"/>
+   <addaction name="actionNewQuad"/>
+   <addaction name="actionNewCLine"/>
+   <addaction name="actionNewComment"/>
+   <addaction name="actionNewBFC"/>
+   <addaction name="actionNewVertex"/>
+  </widget>
+  <widget class="QToolBar" name="toolBar_3">
+   <property name="windowTitle">
+    <string>toolBar_3</string>
+   </property>
+   <attribute name="toolBarArea">
+    <enum>TopToolBarArea</enum>
+   </attribute>
+   <attribute name="toolBarBreak">
+    <bool>false</bool>
+   </attribute>
+   <addaction name="actionUndo"/>
+   <addaction name="actionRedo"/>
+   <addaction name="actionCut"/>
+   <addaction name="actionCopy"/>
+   <addaction name="actionPaste"/>
+   <addaction name="actionDelete"/>
+  </widget>
+  <widget class="QToolBar" name="toolBar_4">
+   <property name="windowTitle">
+    <string>toolBar_4</string>
+   </property>
+   <attribute name="toolBarArea">
+    <enum>TopToolBarArea</enum>
+   </attribute>
+   <attribute name="toolBarBreak">
+    <bool>true</bool>
+   </attribute>
+   <addaction name="actionSelectAll"/>
+   <addaction name="actionSelectByColor"/>
+   <addaction name="actionSelectByType"/>
+  </widget>
+  <widget class="QToolBar" name="toolBar_5">
+   <property name="windowTitle">
+    <string>toolBar_5</string>
+   </property>
+   <attribute name="toolBarArea">
+    <enum>TopToolBarArea</enum>
+   </attribute>
+   <attribute name="toolBarBreak">
+    <bool>false</bool>
+   </attribute>
+   <addaction name="actionGridCoarse"/>
+   <addaction name="actionGridMedium"/>
+   <addaction name="actionGridFine"/>
+  </widget>
+  <widget class="QToolBar" name="toolBar_6">
+   <property name="windowTitle">
+    <string>toolBar_6</string>
+   </property>
+   <attribute name="toolBarArea">
+    <enum>TopToolBarArea</enum>
+   </attribute>
+   <attribute name="toolBarBreak">
+    <bool>false</bool>
+   </attribute>
+   <addaction name="actionAxes"/>
+   <addaction name="actionWireframe"/>
+   <addaction name="actionBFCView"/>
+  </widget>
+  <widget class="QToolBar" name="toolBar_7">
+   <property name="windowTitle">
+    <string>toolBar_7</string>
+   </property>
+   <attribute name="toolBarArea">
+    <enum>TopToolBarArea</enum>
+   </attribute>
+   <attribute name="toolBarBreak">
+    <bool>false</bool>
+   </attribute>
+   <addaction name="actionSetColor"/>
+   <addaction name="actionAutocolor"/>
+   <addaction name="actionUncolorize"/>
+   <addaction name="actionInvert"/>
+   <addaction name="actionSplitQuads"/>
+   <addaction name="actionEditRaw"/>
+   <addaction name="actionBorders"/>
+   <addaction name="actionReplaceCoords"/>
+   <addaction name="actionRoundCoordinates"/>
+   <addaction name="actionVisibility"/>
+  </widget>
+  <widget class="QToolBar" name="toolBar_8">
+   <property name="windowTitle">
+    <string>toolBar_8</string>
+   </property>
+   <attribute name="toolBarArea">
+    <enum>LeftToolBarArea</enum>
+   </attribute>
+   <attribute name="toolBarBreak">
+    <bool>false</bool>
+   </attribute>
+   <addaction name="actionModeSelect"/>
+   <addaction name="actionModeDraw"/>
+  </widget>
+  <widget class="QToolBar" name="colorToolbar">
+   <property name="windowTitle">
+    <string>toolBar_9</string>
+   </property>
+   <attribute name="toolBarArea">
+    <enum>RightToolBarArea</enum>
+   </attribute>
+   <attribute name="toolBarBreak">
+    <bool>false</bool>
+   </attribute>
+  </widget>
+  <action name="actionNew">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/brick.png</normaloff>:/icons/brick.png</iconset>
+   </property>
+   <property name="text">
+    <string>New</string>
+   </property>
+   <property name="statusTip">
+    <string>Create a new part model.</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+N</string>
+   </property>
+  </action>
+  <action name="actionOpen">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/file-open.png</normaloff>:/icons/file-open.png</iconset>
+   </property>
+   <property name="text">
+    <string>Open</string>
+   </property>
+   <property name="statusTip">
+    <string>Load a part model from a file.</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+O</string>
+   </property>
+  </action>
+  <action name="actionSave">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/file-save.png</normaloff>:/icons/file-save.png</iconset>
+   </property>
+   <property name="text">
+    <string>Save</string>
+   </property>
+   <property name="statusTip">
+    <string>Save the part model.</string>
+   </property>
+   <property name="whatsThis">
+    <string/>
+   </property>
+  </action>
+  <action name="actionSaveAs">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/file-save-as.png</normaloff>:/icons/file-save-as.png</iconset>
+   </property>
+   <property name="text">
+    <string>Save As..</string>
+   </property>
+   <property name="whatsThis">
+    <string>Save the part model to a specific file.</string>
+   </property>
+  </action>
+  <action name="actionInsertFrom">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/file-import.png</normaloff>:/icons/file-import.png</iconset>
+   </property>
+   <property name="text">
+    <string>Insert From..</string>
+   </property>
+  </action>
+  <action name="actionExportTo">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/file-export.png</normaloff>:/icons/file-export.png</iconset>
+   </property>
+   <property name="text">
+    <string>Export To..</string>
+   </property>
+  </action>
+  <action name="actionSettings">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/settings.png</normaloff>:/icons/settings.png</iconset>
+   </property>
+   <property name="text">
+    <string>Settings</string>
+   </property>
+   <property name="statusTip">
+    <string>Edit the settings of LDForge.</string>
+   </property>
+   <property name="whatsThis">
+    <string/>
+   </property>
+  </action>
+  <action name="actionSetLDrawPath">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/settings.png</normaloff>:/icons/settings.png</iconset>
+   </property>
+   <property name="text">
+    <string>Set LDraw Path</string>
+   </property>
+   <property name="statusTip">
+    <string>Change the LDraw directory path.</string>
+   </property>
+  </action>
+  <action name="actionScanPrimitives">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/radial.png</normaloff>:/icons/radial.png</iconset>
+   </property>
+   <property name="text">
+    <string>Scan Primitives</string>
+   </property>
+   <property name="statusTip">
+    <string>Scan the primitives folder for primitive info. Use this if you add new primitives.</string>
+   </property>
+  </action>
+  <action name="actionExit">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/exit.png</normaloff>:/icons/exit.png</iconset>
+   </property>
+   <property name="text">
+    <string>Exit</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+Q</string>
+   </property>
+  </action>
+  <action name="actionResetView">
+   <property name="text">
+    <string>Reset View</string>
+   </property>
+  </action>
+  <action name="actionAxes">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="checked">
+    <bool>true</bool>
+   </property>
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/axes.png</normaloff>:/icons/axes.png</iconset>
+   </property>
+   <property name="text">
+    <string>Draw Axes</string>
+   </property>
+  </action>
+  <action name="actionWireframe">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/wireframe.png</normaloff>:/icons/wireframe.png</iconset>
+   </property>
+   <property name="text">
+    <string>Wireframe</string>
+   </property>
+  </action>
+  <action name="actionBFCView">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/bfc-view.png</normaloff>:/icons/bfc-view.png</iconset>
+   </property>
+   <property name="text">
+    <string>BFC Red/Green View</string>
+   </property>
+  </action>
+  <action name="actionSetOverlay">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/overlay.png</normaloff>:/icons/overlay.png</iconset>
+   </property>
+   <property name="text">
+    <string>Set Overlay Image</string>
+   </property>
+  </action>
+  <action name="actionClearOverlay">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/overlay-clear.png</normaloff>:/icons/overlay-clear.png</iconset>
+   </property>
+   <property name="text">
+    <string>Clear Overlay Image</string>
+   </property>
+  </action>
+  <action name="actionScreenshot">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/screencap.png</normaloff>:/icons/screencap.png</iconset>
+   </property>
+   <property name="text">
+    <string>Screenshot</string>
+   </property>
+  </action>
+  <action name="actionInsertRaw">
+   <property name="text">
+    <string>LDraw Code..</string>
+   </property>
+  </action>
+  <action name="actionNewLine">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/add-line.png</normaloff>:/icons/add-line.png</iconset>
+   </property>
+   <property name="text">
+    <string>New Line</string>
+   </property>
+  </action>
+  <action name="actionNewSubfile">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/add-subfile.png</normaloff>:/icons/add-subfile.png</iconset>
+   </property>
+   <property name="text">
+    <string>New Subfile Reference</string>
+   </property>
+  </action>
+  <action name="actionNewTriangle">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/add-triangle.png</normaloff>:/icons/add-triangle.png</iconset>
+   </property>
+   <property name="text">
+    <string>New Triangle</string>
+   </property>
+  </action>
+  <action name="actionNewQuad">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/add-quad.png</normaloff>:/icons/add-quad.png</iconset>
+   </property>
+   <property name="text">
+    <string>New Quadrilateral</string>
+   </property>
+  </action>
+  <action name="actionNewCLine">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/add-condline.png</normaloff>:/icons/add-condline.png</iconset>
+   </property>
+   <property name="text">
+    <string>New Conditional Line</string>
+   </property>
+  </action>
+  <action name="actionNewComment">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/add-comment.png</normaloff>:/icons/add-comment.png</iconset>
+   </property>
+   <property name="text">
+    <string>New Comment</string>
+   </property>
+  </action>
+  <action name="actionNewBFC">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/add-bfc.png</normaloff>:/icons/add-bfc.png</iconset>
+   </property>
+   <property name="text">
+    <string>New BFC Statement</string>
+   </property>
+  </action>
+  <action name="actionNewVertex">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/add-vertex.png</normaloff>:/icons/add-vertex.png</iconset>
+   </property>
+   <property name="text">
+    <string>New Vertex</string>
+   </property>
+  </action>
+  <action name="actionUndo">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/undo.png</normaloff>:/icons/undo.png</iconset>
+   </property>
+   <property name="text">
+    <string>Undo</string>
+   </property>
+   <property name="statusTip">
+    <string>Undo a step.</string>
+   </property>
+  </action>
+  <action name="actionRedo">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/redo.png</normaloff>:/icons/redo.png</iconset>
+   </property>
+   <property name="text">
+    <string>Redo</string>
+   </property>
+   <property name="statusTip">
+    <string>Redo a step.</string>
+   </property>
+  </action>
+  <action name="actionCut">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/cut.png</normaloff>:/icons/cut.png</iconset>
+   </property>
+   <property name="text">
+    <string>Cut</string>
+   </property>
+   <property name="statusTip">
+    <string>Cut the current selection to clipboard.</string>
+   </property>
+  </action>
+  <action name="actionCopy">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/copy.png</normaloff>:/icons/copy.png</iconset>
+   </property>
+   <property name="text">
+    <string>Copy</string>
+   </property>
+   <property name="statusTip">
+    <string>Copy the current selection to clipboard.</string>
+   </property>
+   <property name="whatsThis">
+    <string/>
+   </property>
+  </action>
+  <action name="actionPaste">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/paste.png</normaloff>:/icons/paste.png</iconset>
+   </property>
+   <property name="text">
+    <string>Paste</string>
+   </property>
+   <property name="statusTip">
+    <string>Paste clipboard contents.</string>
+   </property>
+  </action>
+  <action name="actionDelete">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/delete.png</normaloff>:/icons/delete.png</iconset>
+   </property>
+   <property name="text">
+    <string>Delete</string>
+   </property>
+   <property name="statusTip">
+    <string>Delete the selection</string>
+   </property>
+  </action>
+  <action name="actionSelectAll">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/select-all.png</normaloff>:/icons/select-all.png</iconset>
+   </property>
+   <property name="text">
+    <string>Select All</string>
+   </property>
+  </action>
+  <action name="actionSelectByColor">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/select-color.png</normaloff>:/icons/select-color.png</iconset>
+   </property>
+   <property name="text">
+    <string>Select by Color</string>
+   </property>
+  </action>
+  <action name="actionSelectByType">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/select-type.png</normaloff>:/icons/select-type.png</iconset>
+   </property>
+   <property name="text">
+    <string>Select by Type</string>
+   </property>
+  </action>
+  <action name="actionModeSelect">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="checked">
+    <bool>true</bool>
+   </property>
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/mode-select.png</normaloff>:/icons/mode-select.png</iconset>
+   </property>
+   <property name="text">
+    <string>Select Mode</string>
+   </property>
+  </action>
+  <action name="actionModeDraw">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/mode-draw.png</normaloff>:/icons/mode-draw.png</iconset>
+   </property>
+   <property name="text">
+    <string>Draw Mode</string>
+   </property>
+  </action>
+  <action name="actionSetDrawDepth">
+   <property name="text">
+    <string>Set Draw Depth</string>
+   </property>
+  </action>
+  <action name="actionSetColor">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/palette.png</normaloff>:/icons/palette.png</iconset>
+   </property>
+   <property name="text">
+    <string>Set Color</string>
+   </property>
+   <property name="statusTip">
+    <string>Set the color on given objects.</string>
+   </property>
+  </action>
+  <action name="actionAutocolor">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/autocolor.png</normaloff>:/icons/autocolor.png</iconset>
+   </property>
+   <property name="text">
+    <string>Auto-color</string>
+   </property>
+   <property name="statusTip">
+    <string>Set the color of the given object to the first found unused color.</string>
+   </property>
+  </action>
+  <action name="actionUncolorize">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/uncolorize.png</normaloff>:/icons/uncolorize.png</iconset>
+   </property>
+   <property name="text">
+    <string>Uncolorize</string>
+   </property>
+   <property name="statusTip">
+    <string>Reduce colors of everything selected to main and edge colors</string>
+   </property>
+  </action>
+  <action name="actionInline">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/inline.png</normaloff>:/icons/inline.png</iconset>
+   </property>
+   <property name="text">
+    <string>Inline</string>
+   </property>
+   <property name="statusTip">
+    <string>Inline selected subfiles.</string>
+   </property>
+  </action>
+  <action name="actionInlineDeep">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/inline-deep.png</normaloff>:/icons/inline-deep.png</iconset>
+   </property>
+   <property name="text">
+    <string>Deep Inline</string>
+   </property>
+   <property name="statusTip">
+    <string>Recursively inline selected subfiles down to polygons only.</string>
+   </property>
+  </action>
+  <action name="actionInvert">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/invert.png</normaloff>:/icons/invert.png</iconset>
+   </property>
+   <property name="text">
+    <string>Invert</string>
+   </property>
+  </action>
+  <action name="actionMakePrimitive">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/radial.png</normaloff>:/icons/radial.png</iconset>
+   </property>
+   <property name="text">
+    <string>Generate Primitive</string>
+   </property>
+  </action>
+  <action name="actionSplitQuads">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/quad-split.png</normaloff>:/icons/quad-split.png</iconset>
+   </property>
+   <property name="text">
+    <string>Split Quads</string>
+   </property>
+   <property name="statusTip">
+    <string>Split quads into triangles.</string>
+   </property>
+  </action>
+  <action name="actionEditRaw">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/set-contents.png</normaloff>:/icons/set-contents.png</iconset>
+   </property>
+   <property name="text">
+    <string>Edit LDraw Code</string>
+   </property>
+   <property name="statusTip">
+    <string>Edit the LDraw code of this object.</string>
+   </property>
+  </action>
+  <action name="actionBorders">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/make-borders.png</normaloff>:/icons/make-borders.png</iconset>
+   </property>
+   <property name="text">
+    <string>Make Borders</string>
+   </property>
+   <property name="statusTip">
+    <string>Add borders around given polygons.</string>
+   </property>
+  </action>
+  <action name="actionCornerVerts">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/corner-verts.png</normaloff>:/icons/corner-verts.png</iconset>
+   </property>
+   <property name="text">
+    <string>Make Corner Vertices</string>
+   </property>
+   <property name="statusTip">
+    <string>Adds vertex objects to the corners of the given polygons</string>
+   </property>
+  </action>
+  <action name="actionRoundCoordinates">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/round-coords.png</normaloff>:/icons/round-coords.png</iconset>
+   </property>
+   <property name="text">
+    <string>Round Coordinates</string>
+   </property>
+   <property name="statusTip">
+    <string>Round coordinates down to 3/4 decimals</string>
+   </property>
+  </action>
+  <action name="actionVisibility">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/visibility.png</normaloff>:/icons/visibility.png</iconset>
+   </property>
+   <property name="text">
+    <string>Toggle Visibility</string>
+   </property>
+   <property name="statusTip">
+    <string>Toggles visibility/hiding on objects.</string>
+   </property>
+  </action>
+  <action name="actionReplaceCoords">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/replace-coords.png</normaloff>:/icons/replace-coords.png</iconset>
+   </property>
+   <property name="text">
+    <string>Replace Coordinates</string>
+   </property>
+   <property name="statusTip">
+    <string>Find and replace coordinate values.</string>
+   </property>
+  </action>
+  <action name="actionFlip">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/flip.png</normaloff>:/icons/flip.png</iconset>
+   </property>
+   <property name="text">
+    <string>Flip</string>
+   </property>
+   <property name="statusTip">
+    <string>Flip coordinates.</string>
+   </property>
+  </action>
+  <action name="actionDemote">
+   <property name="text">
+    <string>Demote Conditional Lines</string>
+   </property>
+   <property name="statusTip">
+    <string>Demote conditional lines down to normal lines.</string>
+   </property>
+  </action>
+  <action name="actionYtruder">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/ytruder.png</normaloff>:/icons/ytruder.png</iconset>
+   </property>
+   <property name="text">
+    <string>Ytruder</string>
+   </property>
+   <property name="statusTip">
+    <string>Extrude selected lines to a given plane</string>
+   </property>
+  </action>
+  <action name="actionRectifier">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/rectifier.png</normaloff>:/icons/rectifier.png</iconset>
+   </property>
+   <property name="text">
+    <string>Rectifier</string>
+   </property>
+   <property name="statusTip">
+    <string>Optimizes quads into rect primitives.</string>
+   </property>
+  </action>
+  <action name="actionIntersector">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/intersector.png</normaloff>:/icons/intersector.png</iconset>
+   </property>
+   <property name="text">
+    <string>Intersector</string>
+   </property>
+   <property name="statusTip">
+    <string>Perform clipping between two input groups.</string>
+   </property>
+  </action>
+  <action name="actionIsecalc">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/isecalc.png</normaloff>:/icons/isecalc.png</iconset>
+   </property>
+   <property name="text">
+    <string>Isecalc</string>
+   </property>
+   <property name="statusTip">
+    <string>Compute intersection edgelines between two input groups.</string>
+   </property>
+  </action>
+  <action name="actionCoverer">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/coverer.png</normaloff>:/icons/coverer.png</iconset>
+   </property>
+   <property name="text">
+    <string>Coverer</string>
+   </property>
+   <property name="statusTip">
+    <string>Fill the space between two line shapes</string>
+   </property>
+  </action>
+  <action name="actionEdger2">
+   <property name="text">
+    <string>Edger 2</string>
+   </property>
+  </action>
+  <action name="actionHelp">
+   <property name="enabled">
+    <bool>false</bool>
+   </property>
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/help.png</normaloff>:/icons/help.png</iconset>
+   </property>
+   <property name="text">
+    <string>Help</string>
+   </property>
+  </action>
+  <action name="actionAbout">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/ldforge.png</normaloff>:/icons/ldforge.png</iconset>
+   </property>
+   <property name="text">
+    <string>About LDForge</string>
+   </property>
+  </action>
+  <action name="actionAboutQt">
+   <property name="text">
+    <string>About Qt</string>
+   </property>
+  </action>
+  <action name="actionGridCoarse">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/grid-coarse.png</normaloff>:/icons/grid-coarse.png</iconset>
+   </property>
+   <property name="text">
+    <string>Coarse Grid</string>
+   </property>
+  </action>
+  <action name="actionGridMedium">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="checked">
+    <bool>true</bool>
+   </property>
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/grid-medium.png</normaloff>:/icons/grid-medium.png</iconset>
+   </property>
+   <property name="text">
+    <string>Medium Grid</string>
+   </property>
+  </action>
+  <action name="actionGridFine">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/grid-fine.png</normaloff>:/icons/grid-fine.png</iconset>
+   </property>
+   <property name="text">
+    <string>Fine Grid</string>
+   </property>
+  </action>
+  <action name="actionEdit">
+   <property name="text">
+    <string>Edit Selected Object</string>
+   </property>
+  </action>
+  <action name="actionMoveUp">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/arrow-up.png</normaloff>:/icons/arrow-up.png</iconset>
+   </property>
+   <property name="text">
+    <string>Move Up</string>
+   </property>
+  </action>
+  <action name="actionMoveDown">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/arrow-down.png</normaloff>:/icons/arrow-down.png</iconset>
+   </property>
+   <property name="text">
+    <string>Move Down</string>
+   </property>
+  </action>
+  <action name="actionMoveXNeg">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/move-x-neg.png</normaloff>:/icons/move-x-neg.png</iconset>
+   </property>
+   <property name="text">
+    <string>Move -X</string>
+   </property>
+  </action>
+  <action name="actionMoveXPos">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/move-x-pos.png</normaloff>:/icons/move-x-pos.png</iconset>
+   </property>
+   <property name="text">
+    <string>Move +X</string>
+   </property>
+  </action>
+  <action name="actionMoveYNeg">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/move-y-neg.png</normaloff>:/icons/move-y-neg.png</iconset>
+   </property>
+   <property name="text">
+    <string>Move -Y</string>
+   </property>
+  </action>
+  <action name="actionMoveYPos">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/move-y-pos.png</normaloff>:/icons/move-y-pos.png</iconset>
+   </property>
+   <property name="text">
+    <string>Move +Y</string>
+   </property>
+  </action>
+  <action name="actionMoveZNeg">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/move-z-neg.png</normaloff>:/icons/move-z-neg.png</iconset>
+   </property>
+   <property name="text">
+    <string>Move -Z</string>
+   </property>
+  </action>
+  <action name="actionMoveZPos">
+   <property name="icon">
+    <iconset resource="../../ldforge.qrc">
+     <normaloff>:/icons/move-z-pos.png</normaloff>:/icons/move-z-pos.png</iconset>
+   </property>
+   <property name="text">
+    <string>Move +Z</string>
+   </property>
+  </action>
+  <action name="actionRotateXNeg">
+   <property name="text">
+    <string>Rotate -X</string>
+   </property>
+  </action>
+  <action name="actionRotateXPos">
+   <property name="text">
+    <string>Rotate +X</string>
+   </property>
+  </action>
+  <action name="actionRotateYNeg">
+   <property name="text">
+    <string>Rotate -Y</string>
+   </property>
+  </action>
+  <action name="actionRotateYPos">
+   <property name="text">
+    <string>Rotate +Y</string>
+   </property>
+  </action>
+  <action name="actionRotateZNeg">
+   <property name="text">
+    <string>Rotate -Z</string>
+   </property>
+  </action>
+  <action name="actionRotateZPos">
+   <property name="text">
+    <string>Rotate +Z</string>
+   </property>
+  </action>
+  <action name="actionRotationPoint">
+   <property name="text">
+    <string>Set Rotation Point</string>
+   </property>
+  </action>
+ </widget>
+ <resources>
+  <include location="../../ldforge.qrc"/>
+ </resources>
+ <connections/>
+</ui>

mercurial