Fleshed out the history dialog further

Thu, 11 Apr 2013 01:35:30 +0300

author
Santeri Piippo <crimsondusk64@gmail.com>
date
Thu, 11 Apr 2013 01:35:30 +0300
changeset 97
52bcca21579e
parent 96
2f175b3d8211
child 98
5dcc551f260a

Fleshed out the history dialog further

common.h file | annotate | diff | comparison | revisions
gui.cpp file | annotate | diff | comparison | revisions
gui.h file | annotate | diff | comparison | revisions
gui_actions.cpp file | annotate | diff | comparison | revisions
gui_editactions.cpp file | annotate | diff | comparison | revisions
history.cpp file | annotate | diff | comparison | revisions
history.h file | annotate | diff | comparison | revisions
zz_addObjectDialog.cpp file | annotate | diff | comparison | revisions
zz_historyDialog.cpp file | annotate | diff | comparison | revisions
zz_historyDialog.h file | annotate | diff | comparison | revisions
--- a/common.h	Wed Apr 10 19:26:14 2013 +0300
+++ b/common.h	Thu Apr 11 01:35:30 2013 +0300
@@ -28,6 +28,9 @@
 #define VERSION_MINOR 1
 #define VERSION_MINOR_STR "1"
 
+// ============---
+// #define RELEASE
+
 #define VERSION_STRING VERSION_MAJOR_STR "." VERSION_MINOR_STR
 
 #define CONFIG_WITH_QT
@@ -37,7 +40,7 @@
 #include <assert.h>
 #include <vector>
 #include <stdint.h>
-#include "stdarg.h"
+#include <stdarg.h>
 #include "str.h"
 #include "config.h"
 #include "types.h"
@@ -74,6 +77,7 @@
 // Plural expression
 #define PLURAL(n) ((n != 1) ? "s" : "")
 
+// -----------------------------------------------------------------------------
 // Shortcut for formatting
 #define PERFORM_FORMAT(in, out) \
 	va_list v; \
@@ -81,12 +85,12 @@
 	char* out = vdynformat (in, v, 256); \
 	va_end (v);
 
+// -----------------------------------------------------------------------------
 // Shortcuts for stuffing vertices into printf-formatting.
 #define FMT_VERTEX "(%.3f, %.3f, %.3f)"
 #define FVERTEX(V) V.x, V.y, V.z
 
-typedef unsigned char byte;
-
+// -----------------------------------------------------------------------------
 template<class T> inline T clamp (T a, T min, T max) {
 	return (a > max) ? max : (a < min) ? min : a;
 }
@@ -105,6 +109,7 @@
 
 static const double pi = 3.14159265358979323846f;
 
+// -----------------------------------------------------------------------------
 // main.cpp
 enum logtype_e {
 	LOG_Normal,
@@ -112,15 +117,17 @@
 	LOG_Info,
 	LOG_Warning,
 	LOG_Error,
+	LOG_Dev,
 };
 
+void logf (const char* fmt, ...) FORMAT_PRINTF (1, 2);
+void logf (logtype_e eType, const char* fmt, ...) FORMAT_PRINTF (2, 3);
+
+// -----------------------------------------------------------------------------
 // Vertex at (0, 0, 0)
 extern const vertex g_Origin;
 extern bool g_bApplicationReady;
 
-void logf (const char* fmt, ...) FORMAT_PRINTF (1, 2);
-void logf (logtype_e eType, const char* fmt, ...) FORMAT_PRINTF (2, 3);
-
 // -----------------------------------------------------------------------------
 // Pointer to the OpenFile which is currently being edited by the user.
 extern OpenFile* g_CurrentFile;
@@ -137,10 +144,8 @@
 // Pointer to the main application.
 extern QApplication* g_qMainApp;
 
-#ifndef unix
 typedef unsigned int uint;
 typedef unsigned long ulong;
-#endif // unix
 
 // Typedef out the _t suffices :)
 typedef int8_t int8;
--- a/gui.cpp	Wed Apr 10 19:26:14 2013 +0300
+++ b/gui.cpp	Thu Apr 11 01:35:30 2013 +0300
@@ -60,6 +60,10 @@
 EXTERN_ACTION (redo)
 EXTERN_ACTION (showHistory)
 
+#ifndef RELEASE
+EXTERN_ACTION (addTestQuad)
+#endif // RELEASE
+
 vector<actionmeta> g_ActionMeta;
 
 cfg (bool, lv_colorize, true);
@@ -74,7 +78,8 @@
 	qObjList = new QTreeWidget;
 	qObjList->setHeaderHidden (true);
 	qObjList->setMaximumWidth (256);
-	qObjList->setSelectionMode (QTreeWidget::MultiSelection);
+	qObjList->setSelectionMode (QTreeWidget::ExtendedSelection);
+	qObjList->setAlternatingRowColors (true);
 	connect (qObjList, SIGNAL (itemSelectionChanged ()), this, SLOT (slot_selectionChanged ()));
 	
 	qMessageLog = new QTextEdit;
@@ -178,10 +183,16 @@
 	ADD_MENU_ITEM (Edit, setContents)		// Set Contents
 	ADD_MENU_ITEM (Edit, makeBorders)		// Make Borders
 	
-	// Control menuBar
+	// Control menu
 	qControlMenu = menuBar ()->addMenu (tr ("&Control"));
 	ADD_MENU_ITEM (Control, showHistory)	// Show History
 	
+#ifndef RELEASE
+	// Debug menu
+	qDebugMenu = menuBar ()->addMenu (tr ("&Debug"));
+	ADD_MENU_ITEM (Debug, addTestQuad)		// Add Test Quad
+#endif // RELEASE
+	
 	// Help menu
 	qHelpMenu = menuBar ()->addMenu (tr ("&Help"));
 	ADD_MENU_ITEM (Help, help)				// Help
--- a/gui.h	Wed Apr 10 19:26:14 2013 +0300
+++ b/gui.h	Thu Apr 11 01:35:30 2013 +0300
@@ -100,6 +100,12 @@
 	QTreeWidget* qObjList;
 	QTextEdit* qMessageLog;
 	QMenu* qFileMenu, *qEditMenu, *qInsertMenu, *qHelpMenu, *qControlMenu;
+	
+#ifndef RELEASE
+	QMenu* qDebugMenu;
+	QToolBar* qDebugToolBar;
+#endif // RELEASE
+	
 	std::vector<QToolBar*> qaToolBars;
 	
 	str zMessageLogHTML;
--- a/gui_actions.cpp	Wed Apr 10 19:26:14 2013 +0300
+++ b/gui_actions.cpp	Thu Apr 11 01:35:30 2013 +0300
@@ -23,6 +23,7 @@
 #include "zz_newPartDialog.h"
 #include "zz_configDialog.h"
 #include "zz_addObjectDialog.h"
+#include "history.h"
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@@ -137,4 +138,23 @@
 
 ACTION (aboutQt, "About Qt", "qt", "Shows information about Qt.", CTRL_SHIFT (F1)) {
 	QMessageBox::aboutQt (g_ForgeWindow);
-}
\ No newline at end of file
+}
+
+// =============================================================================
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// =============================================================================
+// Debug things
+#ifndef RELEASE
+ACTION (addTestQuad, "Add Test Quad", "add-quad", "Adds a test quad.", CTRL_SHIFT (Q)) {
+	LDQuad* pQuad = new LDQuad;
+	pQuad->dColor = rand () % 16;
+	pQuad->vaCoords[0] = { 1.0f, 0.0f,  1.0f};
+	pQuad->vaCoords[1] = {-1.0f, 0.0f,  1.0f};
+	pQuad->vaCoords[2] = {-1.0f, 0.0f, -1.0f};
+	pQuad->vaCoords[3] = { 1.0f, 0.0f, -1.0f};
+	
+	g_CurrentFile->addObject (pQuad);
+	History::addEntry (new AddHistory ({(ulong)pQuad->getIndex (g_CurrentFile)}, {pQuad->clone ()}));
+	g_ForgeWindow->refresh ();
+}
+#endif // RELEASE
\ No newline at end of file
--- a/gui_editactions.cpp	Wed Apr 10 19:26:14 2013 +0300
+++ b/gui_editactions.cpp	Thu Apr 11 01:35:30 2013 +0300
@@ -62,7 +62,7 @@
 		return;
 	
 	g_ForgeWindow->deleteSelection (&ulaIndices, &copies);
-	History::addEntry (new DeleteHistory (ulaIndices, copies));
+	History::addEntry (new DelHistory (ulaIndices, copies, DelHistory::Cut));
 }
 
 // =============================================================================
@@ -86,7 +86,7 @@
 		paCopies.push_back (obj->clone ());
 	}
 	
-	History::addEntry (new AdditionHistory (ulaIndices, paCopies));
+	History::addEntry (new AddHistory (ulaIndices, paCopies, AddHistory::Paste));
 	g_ForgeWindow->refresh ();
 }
 
@@ -100,7 +100,7 @@
 	g_ForgeWindow->deleteSelection (&ulaIndices, &copies);
 	
 	if (copies.size ())
-		History::addEntry (new DeleteHistory (ulaIndices, copies));
+		History::addEntry (new DelHistory (ulaIndices, copies));
 }
 
 // =============================================================================
@@ -295,7 +295,7 @@
 		}
 	}
 	
-	History::addEntry (new AdditionHistory (ulaIndices, paObjs));
+	History::addEntry (new AddHistory (ulaIndices, paObjs));
 	g_ForgeWindow->refresh ();
 }
 
--- a/history.cpp	Wed Apr 10 19:26:14 2013 +0300
+++ b/history.cpp	Thu Apr 11 01:35:30 2013 +0300
@@ -80,12 +80,17 @@
 		ACTION_NAME (undo)->setEnabled (lPos > -1);
 		ACTION_NAME (redo)->setEnabled (lPos < (long) entries.size () - 1);
 	}
+	
+	// =========================================================================
+	long pos () {
+		return lPos;
+	}
 }
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-void DeleteHistory::undo () {
+void DelHistory::undo () {
 	for (ulong i = 0; i < cache.size(); ++i) {
 		ulong idx = cache.size() - i - 1;
 		LDObject* obj = cache[idx]->clone ();
@@ -96,7 +101,7 @@
 }
 
 // =============================================================================
-void DeleteHistory::redo () {
+void DelHistory::redo () {
 	for (ulong i = 0; i < cache.size(); ++i) {
 		LDObject* obj = g_CurrentFile->objects[indices[i]];
 		
@@ -108,7 +113,7 @@
 }
 
 // =============================================================================
-DeleteHistory::~DeleteHistory () {
+DelHistory::~DelHistory () {
 	for (LDObject* obj : cache)
 		delete obj;
 }
@@ -183,12 +188,12 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-AdditionHistory::~AdditionHistory () {
+AddHistory::~AddHistory () {
 	for (LDObject* pObj : paObjs)
 		delete pObj;
 }
 
-void AdditionHistory::undo () {
+void AddHistory::undo () {
 	for (ulong i = 0; i < paObjs.size(); ++i) {
 		ulong idx = ulaIndices[ulaIndices.size() - i - 1];
 		LDObject* obj = g_CurrentFile->objects[idx];
@@ -200,7 +205,7 @@
 	g_ForgeWindow->refresh ();
 }
 
-void AdditionHistory::redo () {
+void AddHistory::redo () {
 	for (ulong i = 0; i < paObjs.size(); ++i) {
 		ulong idx = ulaIndices[i];
 		LDObject* obj = paObjs[i]->clone ();
@@ -225,7 +230,6 @@
 		// added after it. Thus, we remove the second one here and replace
 		// the first with a copy of the quad.
 		ulong idx = ulaIndices[i];
-		printf ("%lu (%lu)\n", i, idx);
 		
 		LDTriangle* tri1 = static_cast<LDTriangle*> (g_CurrentFile->objects[idx]),
 			*tri2 = static_cast<LDTriangle*> (g_CurrentFile->objects[idx + 1]);
@@ -243,8 +247,6 @@
 	for (long i = paQuads.size() - 1; i >= 0; --i) {
 		ulong idx = ulaIndices[i];
 		
-		printf ("redo: %ld (%lu)\n", i, idx);
-		
 		LDQuad* pQuad = static_cast<LDQuad*> (g_CurrentFile->objects[idx]);
 		std::vector<LDTriangle*> paTriangles = pQuad->splitToTriangles ();
 		
--- a/history.h	Wed Apr 10 19:26:14 2013 +0300
+++ b/history.h	Thu Apr 11 01:35:30 2013 +0300
@@ -30,11 +30,11 @@
 
 // =============================================================================
 enum HistoryType {
-	HISTORY_Delete,
+	HISTORY_Del,
 	HISTORY_SetColor,
 	HISTORY_SetContents,
 	HISTORY_ListMove,
-	HISTORY_Addition,
+	HISTORY_Add,
 	HISTORY_QuadSplit,
 };
 
@@ -52,15 +52,21 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-class DeleteHistory : public HistoryEntry {
+class DelHistory : public HistoryEntry {
 public:
-	IMPLEMENT_HISTORY_TYPE (Delete)
+	enum Type {
+		Cut,	// were deleted with a cut operation
+		Other,	// were deleted witout specific reason
+	};
+	
+	IMPLEMENT_HISTORY_TYPE (Del)
 	
 	vector<ulong> indices;
 	vector<LDObject*> cache;
+	const Type eType;
 	
-	DeleteHistory (vector<ulong> indices, vector<LDObject*> cache) :
-		indices (indices), cache (cache) {}
+	DelHistory (vector<ulong> indices, vector<LDObject*> cache, const Type eType = Other) :
+		indices (indices), cache (cache), eType (eType) {}
 };
 
 // =============================================================================
@@ -110,15 +116,22 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-class AdditionHistory : public HistoryEntry {
+class AddHistory : public HistoryEntry {
 public:
-	IMPLEMENT_HISTORY_TYPE (Addition)
+	enum Type {
+		Other,	// was "just added"
+		Paste,	// was added through a paste operation
+	};
+	
+	IMPLEMENT_HISTORY_TYPE (Add)
 	
 	std::vector<ulong> ulaIndices;
 	std::vector<LDObject*> paObjs;
+	const Type eType;
 	
-	AdditionHistory (std::vector<ulong> ulaIndices, std::vector<LDObject*> paObjs) :
-		ulaIndices (ulaIndices), paObjs (paObjs) {}
+	AddHistory (std::vector<ulong> ulaIndices, std::vector<LDObject*> paObjs,
+		const Type eType = Other) :
+		ulaIndices (ulaIndices), paObjs (paObjs), eType (eType) {}
 };
 
 // =============================================================================
@@ -146,6 +159,7 @@
 	void redo ();
 	void clear ();
 	void updateActions ();
+	long pos ();
 };
 
 #endif // HISTORY_H
\ No newline at end of file
--- a/zz_addObjectDialog.cpp	Wed Apr 10 19:26:14 2013 +0300
+++ b/zz_addObjectDialog.cpp	Thu Apr 11 01:35:30 2013 +0300
@@ -210,7 +210,7 @@
 		}
 		
 		ulong idx = g_CurrentFile->addObject (obj);
-		History::addEntry (new AdditionHistory ({idx}, {obj->clone ()}));
+		History::addEntry (new AddHistory ({idx}, {obj->clone ()}));
 		window->refresh ();
 	}
 }
\ No newline at end of file
--- a/zz_historyDialog.cpp	Wed Apr 10 19:26:14 2013 +0300
+++ b/zz_historyDialog.cpp	Thu Apr 11 01:35:30 2013 +0300
@@ -18,6 +18,7 @@
 
 #include "zz_historyDialog.h"
 #include "history.h"
+#include "colors.h"
 #include <qboxlayout.h>
 #include <qmessagebox.h>
 
@@ -34,6 +35,8 @@
 	qClearButton = new QPushButton ("Clear");
 	qButtons = new QDialogButtonBox (QDialogButtonBox::Close);
 	
+	qHistoryList->setAlternatingRowColors (true);
+	
 	qUndoButton->setIcon (getIcon ("undo"));
 	qRedoButton->setIcon (getIcon ("redo"));
 	
@@ -41,6 +44,7 @@
 	connect (qRedoButton, SIGNAL (clicked ()), this, SLOT (slot_redo ()));
 	connect (qClearButton, SIGNAL (clicked ()), this, SLOT (slot_clear ()));
 	connect (qButtons, SIGNAL (rejected ()), this, SLOT (reject ()));
+	connect (qHistoryList, SIGNAL (itemSelectionChanged ()), this, SLOT (slot_selChanged ()));
 	
 	QVBoxLayout* qButtonLayout = new QVBoxLayout;
 	qButtonLayout->setDirection (QBoxLayout::TopToBottom);
@@ -60,6 +64,7 @@
 	
 	populateList ();
 	updateButtons ();
+	updateSelection ();
 }
 
 // =============================================================================
@@ -68,14 +73,54 @@
 void HistoryDialog::populateList () {
 	qHistoryList->clear ();
 	
+	QListWidgetItem* qItem = new QListWidgetItem;
+	qItem->setText ("[[ initial state ]]");
+	qItem->setIcon (getIcon ("empty"));
+	qHistoryList->addItem (qItem);
+	
 	for (HistoryEntry* entry : History::entries) {
 		str zText;
+		QIcon qEntryIcon;
 		
 		switch (entry->type ()) {
-		case HISTORY_Addition:
+		case HISTORY_Add:
 			{
-				AdditionHistory* addentry = static_cast<AdditionHistory*> (entry);
-				zText.format ("Added %s", LDObject::objectListContents (addentry->paObjs).chars());
+				AddHistory* addentry = static_cast<AddHistory*> (entry);
+				ulong ulCount = addentry->paObjs.size ();
+				str zVerb = "Added";
+				
+				switch (addentry->eType) {
+				case AddHistory::Paste:
+					zVerb = "Pasted";
+					qEntryIcon = getIcon ("paste");
+					break;
+				
+				default:
+					{
+						// Determine a common type for these objects. If all objects are of the same
+						// type, we display its addition icon. Otherwise, we draw a subfile addition
+						// one as a default.
+						LDObjectType_e eCommonType = OBJ_Unidentified;
+						for (LDObject* obj : addentry->paObjs) {
+							if (eCommonType == OBJ_Unidentified or obj->getType() == eCommonType)
+								eCommonType = obj->getType ();
+							else {
+								eCommonType = OBJ_Unidentified;
+								break;
+							}
+						}
+						
+						// Set the icon based on the common type decided above.
+						if (eCommonType == OBJ_Unidentified)
+							qEntryIcon = getIcon ("add-subfile");
+						else
+							qEntryIcon = getIcon (str::mkfmt ("add-%s", g_saObjTypeIcons[eCommonType]));
+					}
+					break;
+				}
+				
+				zText.format ("%s %lu objects\n%s", zVerb.chars(), ulCount,
+					LDObject::objectListContents (addentry->paObjs).chars());
 			}
 			break;
 		
@@ -84,8 +129,66 @@
 				QuadSplitHistory* splitentry = static_cast<QuadSplitHistory*> (entry);
 				ulong ulCount = splitentry->paQuads.size ();
 				zText.format ("Split %lu quad%s to triangles", ulCount, PLURAL (ulCount));
-				break;
+				
+				qEntryIcon = getIcon ("quad-split");
+			}
+			break;
+		
+		case HISTORY_Del:
+			{
+				DelHistory* delentry = static_cast<DelHistory*> (entry);
+				ulong ulCount = delentry->cache.size ();
+				str zVerb = "Deleted";
+				qEntryIcon = getIcon ("delete");
+				
+				switch (delentry->eType) {
+				case DelHistory::Cut:
+					qEntryIcon = getIcon ("cut");
+					zVerb = "Cut";
+					break;
+				
+				default:
+					break;
+				}
+				
+				zText.format ("%s %lu objects:\n%s", zVerb.chars(), ulCount,
+					LDObject::objectListContents (delentry->cache).chars ());
 			}
+			break;
+		
+		case HISTORY_SetColor:
+			{
+				SetColorHistory* colentry = static_cast<SetColorHistory*> (entry);
+				ulong ulCount = colentry->ulaIndices.size ();
+				zText.format ("Set color of %lu objects to %d (%s)", ulCount,
+					colentry->dNewColor, getColor (colentry->dNewColor)->zName.chars());
+				
+				qEntryIcon = getIcon ("palette");
+			}
+			break;
+		
+		case HISTORY_ListMove:
+			{
+				ListMoveHistory* moveentry = static_cast<ListMoveHistory*> (entry);
+				ulong ulCount = moveentry->ulaIndices.size ();
+				
+				zText.format ("Moved %lu objects %s", ulCount,
+					moveentry->bUp ? "up" : "down");
+				qEntryIcon = getIcon (moveentry->bUp ? "arrow-up" : "arrow-down");
+			}
+			break;
+		
+		case HISTORY_SetContents:
+			{
+				SetContentsHistory* setentry = static_cast<SetContentsHistory*> (entry);
+				
+				zText.format ("Set contents of %s\n%s (%s)",
+					g_saObjTypeNames [setentry->oldObj->getType ()],
+					setentry->newObj->getContents ().chars (),
+					g_saObjTypeNames [setentry->newObj->getType ()]);
+				qEntryIcon = getIcon ("set-contents");
+			}
+			break;
 		
 		default:
 			zText = "???";
@@ -94,6 +197,7 @@
 		
 		QListWidgetItem* qItem = new QListWidgetItem;
 		qItem->setText (zText);
+		qItem->setIcon (qEntryIcon);
 		qHistoryList->addItem (qItem);
 	}
 }
@@ -104,12 +208,18 @@
 void HistoryDialog::slot_undo () {
 	History::undo ();
 	updateButtons ();
+	updateSelection ();
 }
 
 // =============================================================================
 void HistoryDialog::slot_redo () {
 	History::redo ();
 	updateButtons ();
+	updateSelection ();
+}
+
+void HistoryDialog::updateSelection () {
+	qHistoryList->setCurrentItem (qHistoryList->item (History::pos () + 1));
 }
 
 // =============================================================================
@@ -124,10 +234,41 @@
 	
 	History::clear ();
 	populateList ();
+	updateButtons ();
 }
 
 // =============================================================================
 void HistoryDialog::updateButtons () {
 	qUndoButton->setEnabled (ACTION_NAME (undo)->isEnabled ());
 	qRedoButton->setEnabled (ACTION_NAME (redo)->isEnabled ());
+}
+
+// =============================================================================
+void HistoryDialog::slot_selChanged () {
+	if (qHistoryList->selectedItems ().size () != 1)
+		return;
+	
+	QListWidgetItem* qItem = qHistoryList->selectedItems ()[0];
+	
+	// Find the index of the edit
+	long idx = -1;
+	QListWidgetItem* it;
+	while ((it = qHistoryList->item (++idx)) != nullptr)
+		if (it == qItem)
+			break;
+	
+	idx--; // qHistoryList is 0-based, History is -1-based.
+	
+	if (idx == History::pos ())
+		return;
+	
+	// Seek to the selected edit by repeadetly undoing or redoing.
+	while (History::pos () != idx) {
+		if (History::pos () > idx)
+			History::undo ();
+		else
+			History::redo ();
+	}
+	
+	updateButtons ();
 }
\ No newline at end of file
--- a/zz_historyDialog.h	Wed Apr 10 19:26:14 2013 +0300
+++ b/zz_historyDialog.h	Thu Apr 11 01:35:30 2013 +0300
@@ -38,11 +38,13 @@
 	
 private:
 	void updateButtons ();
+	void updateSelection ();
 	
 private slots:
 	void slot_undo ();
 	void slot_redo ();
 	void slot_clear ();
+	void slot_selChanged ();
 };
 
 #endif // ZZ_HISTORYDIALOG_H
\ No newline at end of file

mercurial