Thu, 11 Apr 2013 01:35:30 +0300
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