Open mpogue2 opened 1 year ago
Might be able to run CSDS Online in a Reference pane, and import directly from there. Or, could do COPY there, switch to SD tab and PASTE. Something simple might be good enough for August.
Note sure I like the USED idea, where sequences get moved to a different folder. Might just want to mark them "used at this particular dance", which is what CSDS does.
MILESTONE 1: To get started on this doesn't require much work, since some amount of basic infrastructure is needed first (and gives us a minimally-usable product):
I think this might be enough to be a very usable (though minimal) tool for calling C1. 80% of what is needed in a sequence designer (like CSDS), but with 10% of the work.
Hmmmmm:
Good YouTube video: https://www.youtube.com/watch?v=0dpPa6f6-YA
Stuff that CSDS has:
Current SD menu:
We already have in the File menu:
We can add:
Current SD tab:
We already have a way to turn off Formation Thumbnails, to hide the Options/? Completion/Additional panes, and to highlight individual calls in a sequence (although right now we can highlight more than one at a time, which we would turn off):
We could add a new tab in the Options/?/Additional area called "Names", where we could type in names for each dancer, in a grid format:
Boy Girl
1 [Mark] [Jane]
2 [Tony] [Laurie]
3 [Todd] [Cheryl]
4 [Jim] [Gloria]
Perhaps with a [Default] button to go back to default (numbers, etc.).
SD > [X] Show SD Output menu option would allow us to turn off the SD output tab entirely.
And, we can bring in the Frames idea in a similar way (perhaps to the LEFT of the Current Sequence window, or ABOVE/BELOW both the Current Sequence and Grid panes: View > SD > Frames
Then, a SET VIEW menu option for SD makes sense: SD > Set View > Design | Playback (mutually exclusive options)
Where Playback View:
and Design View:
Still can individually turn those on and off as desired. The PLAYBACK MODE is really not a "Playback Mode" then, it just sets up a particular set of View options, all of which are still in the SD menu.
That gives us a unified single tab for designing sequences AND playing them back (dynamically selecting them) at a dance. It's pretty simple, a natural extension of what we have now, and although it doesn't have all the fancy stuff that CSDS has, I think it's a usable feature...
Change SD > Numbers > Normal | Invisible to SD > Labels > None | [X] Numbers (note reordering) and then to SD > Labels > None | [X] Numbers | Names
We have room for max of 3 characters on dancer icon labels right now. Looks like this:
I had to make the font a little smaller even for numbers, because I can't figure out how to change the font size for dancer label font on-the-fly (@danlyke, do you know how?).
7dd8e627f244bd615c22b1e3868f03b2085d03ed implements this:
This is what Taminations does. They use more characters, and because their dancer frames (squares, circles) are not black, the black labels are actually readable. We might want to do this, too, at some point.
On the other hand, while Taminations names are more readable MOST of the time, Taminations output can also get VERY crowded, because the names are too wide:
By comparison, my initial cut at this looks like this:
I do like the way Taminations colors each call by level:
and I like the Undo and Reset buttons at the bottom, too. I can live without the Copy and Paste buttons. I'd like to have a Redo button.
d79026e7440c7a9fdabdf9c732e6d43eaaf5b441 adds support for naming dancers in SD.
New Names tab in SD lower right pane allows for setting 3-character names for each dancer. Tab order is set, so you can double-click on a name, type in a new name, and hit TAB to go to the next one in order CCW around the square.
8341c164fe42fd82743fb836018b29cdacad5dc9 adds support for UI configuration. This config can be overridden manually via the usual menus. Note: these are not modes, they are just shortcuts for setting multiple view options all at once.
Sequence Designer:
Dance Arranger:
TODO: Sequence Designer: allows multiple selections in the call list (no items selected at load time, double click on item to load) Dance Arranger: allows only single item selection in the call list (item 0 selected at load time, double click OR up/down arrow to load)
TODO: Load Sequence from File... Can I make the size of the Options/?/Additional/Names smaller at startup time? Stick an HTML Redirector (or just a link?) page into Reference for CSDS Online Stick an HTML Redirector (or just a link?) page into Reference for Taminations Online Allow SEQUENCE PASTE into SquareDesk/SD (failing that, in Import From Clipboard button) -- both CSDS Online and Taminations (offline/online) allow for SEQUENCE COPY with newlines as delimiters). This will allow us to use SD or CSDS Online or Taminations (offline/online) for sequence design (from within SquareDesk, too....)
Current UX after selecting "Sequence Designer":
Current UX after selecting "Dance Arranger":
f912e1111a582b030b5f633f7bd1d6203243ed50 does this:
TODO:
Feature implemented by 4f1652ddbb6e5a1e47d956d39b4bee506d885a1a:
In the Names tab, the background colors of the lineEdit fields should match the colors of the 4 couples.
This will make it easier when 3 characters is ambiguous, e.g. David E vs David Q both are "Dav".
Looks kinda nice, I think:
TODO: Consider whether items in the Current Sequence window should be highlighted differently, e.g. with a line between cells, rather than highlighting the whole cell. Or, could be an arrow or something.
TODO: Change status from "Kybd: Plus" to "SD: Plus" or "Level: Plus" or even "SD Level: Plus". There is no Voice input anymore, so distinguishing between "Kybd" and "Voice" input levels is no longer relevant.
Done: 08065a5004ac0a0514ffe9aaf7674806cbc53e6a
TODO: In Dance Arranger mode, consider also hiding the SD Input line and the three tabs: Options/?/Additional. None of these are needed here, if we are just playing back an existing already-done sequence. Can always switch back to Designer mode with a single hotkey, if editing is needed.
Done: 826487103de7c83ec90f9e7508bc5b8d80b752a8
Current UX (Dance Arranger mode):
TODO: In Dance Arranger mode, consider a status line for the current sequence ID, similar to CSDS (although I don't know what our Sequence ID should look like yet), perhaps above the Current Sequence tab. Or, consider getting rid of the Current Sequence title, and move the Current Sequence list up one level in the hierarchy. "Current Sequence" doesn't add much useful info. I suppose that the title of the tab ("Current Sequence") could be repurposed for this, too, although that feels a bit weird.
NOTE: Added the current level to the "Current Sequence" tab name. We'll see if it feels OK, after trying this a while.
DONE: Consider changing Cmd-C (Copy Sequence) and modal Context Menu item ([X] Copy as HTML) to two separate shortcuts: Cmd-C (Copy as Plain Text) and Cmd-Shift-C (Copy as HTML).
DONE: Consider adding to the Current Sequence Context Menu, which already has Copy there. Add "Paste Sequence". Note that QtClipboard says that it can handle both plain text and HTML text, but SquareDesk's Copy As HTML is actually not recognized as HTML.
Taminations and CSDS Online are both Plain Text. Only SquareDesk has the Copy as HTML option. Also,change "Copy" to "Copy Sequence" at the same time, so that we end up with both "Copy Sequence" (Cmd-C) and "Paste Sequence" (Cmd-V).
Reorder Copy Sequence as HTML to be right below Copy Sequence.
Implementation is in: b645aaa040eab7875d39fa696da6f254493035f3
Context menu now looks like this:
TODO: Some context menu items in Current Sequence context menu should be greyed out under some conditions, e.g. Copy Sequence, Copy Sequence to HTML, Paste Sequence (if clipboard is empty), Undo, Redo (if nothing on the redo stack), Go Back To Here (if no current selection).
We can now copy sequences from either CSDS Online or from Taminations, and we can paste them successfully into SquareDesk's SD (into the Current Sequence pane, using Right Click > Paste Sequence).
Copy Sequence (Cmd-C) also works from within Squaredesk/SD, when focus is either in the SD Input field, OR in the Current Sequence pane.
TODO:
Commit: 672367dca44e6c5271cb299f2a5de3664e9441ed
TODO BUG: Whenever switching switching levels, the new level is stuck with a "HEADS Square Thru 4" as the first item in the Current Sequence. This is wrong. But, it's coming from SDThread::finishAndShutdownSD(), which intentionally sticks this in, before it sends a "quit" to the SD thread. If I comment out the Heads start and square thru 4, then if I change levels and quit SquareDesk, it crashes for some reason. So, this stuff is needed, I just don't know why. (FIXED)
I'm not sure how to stop the new Current Sequence from picking this up either. It seems to be scanning the SD thread output, and it sees the "Heads Square Thru 4" from the OLD level, and it sticks it into the Current Sequence, thinking it's the NEW level. Maybe I can somehow clear out this buffer, when a finishAndShutdownSD() is done? But, where IS that buffer?? (FIXED)
BUG: Changing levels continues to tack more level strings onto the output file name in SD, for example: "/Users/mpogue/Library/CloudStorage/Box-Box/__squareDanceMusic_Box/sd/sequence.Plus.A1.C1.A1"
Fixed by: b6946183b88ee9f2275ae78fee4720fb8238c812
This commit fixes several bugs when changing levels:
c18e17b9bc58d4dcf41a6f910d65caea6132ba71 does the following:
NOTE: I might regret doing this different from Taminations, e.g. in the use case where we are switching from SD to Music tab and back again. Perhaps it should retain the selection? Gotta try it for a while and see how it feels, and notice if anything is surprising....
TODO NEXT: We now have single click selection of items in the Current Sequence pane, which causes them to be rendered correctly. Next we need to flow through the UP/DOWN arrows from the event handler to the Current Sequence pane, IFF the SD tab is active. (DONE)
Implemented by 69accdd5d0ae1f72cb4f79dccc1715111814b2d8 .
TODO (maybe): should the selection in the Current Sequence pane persist when changing tabs from SD to Music and back again? It probably should...
The selection is currently retained when moving from Music to SD/Dance Arranger mode. The selection is NOT retained when moving from Music to SD/Sequence Designer mode.
TODO: As the user moves up and down in the Current Sequence one using UP/DOWN arrows, the Resolution field probably should be blank, except when the selection is on the last call in the Current Sequence. We're not currently remembering the resolution at every step of the sequence (which I suppose could be a different way of doing this).
Bug: Context menu in Current Sequence pane has keyboard shortcuts (I added them), but they don't all actually work. Cmd-C works, but Cmd-Shift-C and Cmd-V do not.
TODO: After Paste Sequence from Clipboard or Load Sequence from File, set selection to:
The difficulty here is that we can submit stuff to SD, but it's asynchronous, so we don't really know for sure when the paste/load operation is complete.
As of c23cc4f3999f66581f279f76b8e65c1ea2f3c3ec:
Commit: 54b5ee5225131cc3485fce089173aa78aad2c226 When Load Sequence is done, it now squares the set first, and then send the calls through the translator before they go to SD.
Paste Sequence, too: fa0a06607aa55aa01a55e0f839b56ca571510773
BUG: I am seeing occasional crashes in rendering. Could be related to this? I'm not sure what causes this.
2023-01-12 18:04:45.552 SquareDesk[61438:9366295] +[CATransaction synchronize] called within transaction
Crash also spit this out on the Application Output pane:
QPainter::begin: Paint device returned engine == 0, type: 3
I think the [CATransaction...] happens when I do Load Sequence OR Save Sequence As. Basically, as soon as the dialog box is visible. The crash seems to happen when I switch from SquareDesk to Safari. Yep, verified that.
Here's the dump:
Process: SquareDesk [61909]
Path: /Users/USER/*/SquareDesk.app/Contents/MacOS/SquareDesk
Identifier: com.zenstarstudio.SquareDesk
Version: 0.9.6 (0.9.6.1)
Code Type: ARM-64 (Native)
Parent Process: qtcreator_processlauncher [31946]
User ID: 501
Date/Time: 2023-01-12 18:15:22.0452 -0800
OS Version: macOS 13.1 (22C65)
Report Version: 12
Anonymous UUID: 4921A9E7-C3B3-A1E0-1FFD-EFBC5516BA2E
Sleep/Wake UUID: 94CD22CE-6E6D-4A71-8B12-12570D3DE0D3
Time Awake Since Boot: 640000 seconds
Time Since Wake: 6849 seconds
System Integrity Protection: enabled
Crashed Thread: 0 CrBrowserMain Dispatch queue: com.apple.main-thread
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000018
Exception Codes: 0x0000000000000001, 0x0000000000000018
Termination Reason: Namespace SIGNAL, Code 11 Segmentation fault: 11
Terminating Process: exc handler [61909]
VM Region Info: 0x18 is not in any region. Bytes before following region: 105553518919656
REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL
UNUSED SPACE AT START
--->
MALLOC_NANO (reserved) 600018000000-600020000000 [128.0M] rw-/rwx SM=NUL ...(unallocated)
Kernel Triage:
VM - pmap_enter retried due to resource shortage
VM - pmap_enter retried due to resource shortage
VM - pmap_enter retried due to resource shortage
VM - pmap_enter retried due to resource shortage
VM - pmap_enter retried due to resource shortage
Thread 0 Crashed:: CrBrowserMain Dispatch queue: com.apple.main-thread
0 QtGui 0x1039a1ef0 QScopedPointer<QPaintEnginePrivate, QScopedPointerDeleter<QPaintEnginePrivate> >::get() const + 0 (qscopedpointer.h:111) [inlined]
1 QtGui 0x1039a1ef0 decltype(fp.get()) qGetPtrHelper<QScopedPointer<QPaintEnginePrivate, QScopedPointerDeleter<QPaintEnginePrivate> > >(QScopedPointer<QPaintEnginePrivate, QScopedPointerDeleter<QPaintEnginePrivate> >&) + 0 (qglobal.h:1245) [inlined]
2 QtGui 0x1039a1ef0 QPaintEngine::d_func() + 0 (qpaintengine.h:52) [inlined]
3 QtGui 0x1039a1ef0 QPaintEnginePrivate::get(QPaintEngine*) + 0 (qpaintengine_p.h:103) [inlined]
4 QtGui 0x1039a1ef0 QMacCGContext::QMacCGContext(QPainter*) + 44 (qcoregraphics.mm:412)
5 QtGui 0x1039a1eec QMacCGContext::QMacCGContext(QPainter*) + 40 (qcoregraphics.mm:409)
6 libqmacstyle.dylib 0x10916b0f4 QMacStylePrivate::drawNSViewInRect(NSView*, QRectF const&, QPainter*, void (CGContext*, CGRect const&) block_pointer) const + 56 (qmacstyle_mac.mm:2003)
7 libqmacstyle.dylib 0x109172a90 QMacStyle::drawControl(QStyle::ControlElement, QStyleOption const*, QPainter*, QWidget const*) const + 12960 (qmacstyle_mac.mm:4012)
8 QtWidgets 0x104062e9c QCommonStyle::drawControl(QStyle::ControlElement, QStyleOption const*, QPainter*, QWidget const*) const + 2136 (qcommonstyle.cpp:1777)
9 libqmacstyle.dylib 0x109170128 QMacStyle::drawControl(QStyle::ControlElement, QStyleOption const*, QPainter*, QWidget const*) const + 2360 (qmacstyle_mac.mm:4621)
10 QtWidgets 0x1041c8098 QStylePainter::drawControl(QStyle::ControlElement, QStyleOption const&) + 28 (qstylepainter.h:51) [inlined]
11 QtWidgets 0x1041c8098 QTabBar::paintEvent(QPaintEvent*) + 1564 (qtabbar.cpp:1883)
12 QtWidgets 0x10404563c QWidget::event(QEvent*) + 132
13 QtWidgets 0x1041c790c QTabBar::event(QEvent*) + 736 (qtabbar.cpp:1771)
14 QtWidgets 0x103ffbce4 QApplicationPrivate::notify_helper(QObject*, QEvent*) + 272 (qapplication.cpp:3315)
15 QtWidgets 0x103ffd890 QApplication::notify(QObject*, QEvent*) + 3396
16 QtCore 0x104b02f64 QCoreApplication::notifyInternal2(QObject*, QEvent*) + 208 (qcoreapplication.cpp:1026)
17 QtWidgets 0x1040387ac QWidgetPrivate::sendPaintEvent(QRegion const&) + 28 (qwidget.cpp:5637) [inlined]
18 QtWidgets 0x1040387ac QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 3336 (qwidget.cpp:5587)
19 QtWidgets 0x10403ff10 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 864 (qwidget.cpp:5766)
20 QtWidgets 0x1040388ac QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 3592 (qwidget.cpp:5628)
21 QtWidgets 0x10403ff10 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 864 (qwidget.cpp:5766)
22 QtWidgets 0x10403fe00 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 592 (qwidget.cpp:5752)
23 QtWidgets 0x10403fe00 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 592 (qwidget.cpp:5752)
24 QtWidgets 0x1040388ac QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 3592 (qwidget.cpp:5628)
25 QtWidgets 0x10403ff10 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 864 (qwidget.cpp:5766)
26 QtWidgets 0x10403fe00 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 592 (qwidget.cpp:5752)
27 QtWidgets 0x10403fe00 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 592 (qwidget.cpp:5752)
28 QtWidgets 0x1040388ac QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 3592 (qwidget.cpp:5628)
29 QtWidgets 0x10403ff10 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 864 (qwidget.cpp:5766)
30 QtWidgets 0x1040388ac QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 3592 (qwidget.cpp:5628)
31 QtWidgets 0x10403ff10 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 864 (qwidget.cpp:5766)
32 QtWidgets 0x1040388ac QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 3592 (qwidget.cpp:5628)
33 QtWidgets 0x10403ff10 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 864 (qwidget.cpp:5766)
34 QtWidgets 0x10403fe00 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 592 (qwidget.cpp:5752)
35 QtWidgets 0x1040388ac QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 3592 (qwidget.cpp:5628)
36 QtWidgets 0x10403ff10 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 864 (qwidget.cpp:5766)
37 QtWidgets 0x1040388ac QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 3592 (qwidget.cpp:5628)
38 QtWidgets 0x10403ff10 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 864 (qwidget.cpp:5766)
39 QtWidgets 0x10403fe00 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 592 (qwidget.cpp:5752)
40 QtWidgets 0x10403fe00 QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 592 (qwidget.cpp:5752)
41 QtWidgets 0x1040388ac QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) + 3592 (qwidget.cpp:5628)
42 QtWidgets 0x104056450 QWidgetRepaintManager::paintAndFlush() + 3636 (qwidgetrepaintmanager.cpp:895)
43 QtWidgets 0x1040567f4 QWidgetRepaintManager::sync() + 252 (qwidgetrepaintmanager.cpp:655)
44 QtWidgets 0x104045ad8 QWidget::event(QEvent*) + 1312 (qwidget.cpp:9150)
45 QtWidgets 0x104160494 QMainWindow::event(QEvent*) + 248 (qmainwindow.cpp:1303)
46 QtWidgets 0x103ffbce4 QApplicationPrivate::notify_helper(QObject*, QEvent*) + 272 (qapplication.cpp:3315)
47 QtWidgets 0x103ffd890 QApplication::notify(QObject*, QEvent*) + 3396
48 QtCore 0x104b02f64 QCoreApplication::notifyInternal2(QObject*, QEvent*) + 208 (qcoreapplication.cpp:1026)
49 QtCore 0x104b04034 QCoreApplication::sendEvent(QObject*, QEvent*) + 16 (qcoreapplication.cpp:1442) [inlined]
50 QtCore 0x104b04034 QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) + 816 (qcoreapplication.cpp:1804)
51 libqcocoa.dylib 0x1074ef5a0 QCocoaEventDispatcherPrivate::processPostedEvents() + 312 (qcocoaeventdispatcher.mm:866)
52 libqcocoa.dylib 0x1074efc30 QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void*) + 48 (qcocoaeventdispatcher.mm:889)
53 CoreFoundation 0x1ab44ca18 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
54 CoreFoundation 0x1ab44c9ac __CFRunLoopDoSource0 + 176
55 CoreFoundation 0x1ab44c71c __CFRunLoopDoSources0 + 244
56 CoreFoundation 0x1ab44b320 __CFRunLoopRun + 836
57 CoreFoundation 0x1ab44a888 CFRunLoopRunSpecific + 612
58 HIToolbox 0x1b4b1ffa0 RunCurrentEventLoopInMode + 292
59 HIToolbox 0x1b4b1fc30 ReceiveNextEventCommon + 236
60 HIToolbox 0x1b4b1fb2c _BlockUntilNextEventMatchingListInModeWithFilter + 72
61 AppKit 0x1ae6cc424 _DPSNextEvent + 632
62 AppKit 0x1ae6cb5b4 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 728
63 AppKit 0x1ae6bf9e4 -[NSApplication run] + 464
64 libqcocoa.dylib 0x1074eeb18 QCocoaEventDispatcher::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 1800 (qcocoaeventdispatcher.mm:394)
65 QtCore 0x104b0bfcc QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 36 (qeventloop.cpp:100) [inlined]
66 QtCore 0x104b0bfcc QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) + 536 (qeventloop.cpp:182)
67 QtCore 0x104b03618 QCoreApplication::exec() + 128 (qcoreapplication.cpp:1347)
68 SquareDesk 0x102d8b404 main + 1176
69 dyld 0x1ab043e50 start + 2544
Commit: 673a85a912b693773943411d4bf26226529496ac
This allows the Chromium browser that we use for Reference pages to access non-local pages, like Taminations and CSDS Online websites.
To Include CSDS Online and Taminations Online into Reference pages, do this:
<head>
<meta http-equiv="refresh" content="5; URL=https://www.tamtwirlers.org/taminations/#?main=SEQUENCER&formation=Squared%20Set&helplink=info/sequencer" />
</head>
<body>
<p>If you are not redirected in five seconds, <a href="https://www.tamtwirlers.org/taminations/#?main=SEQUENCER&formation=Squared%20Set&helplink=info/sequencer">click here</a>.</p>
</body>
OR for CSDS Online, do this:
<head>
<meta http-equiv="refresh" content="5; URL=https://www.ceder.net/ws/" />
</head>
<body>
<p>If you are not redirected in five seconds, <a href="https://www.ceder.net/ws/">click here</a>.</p>
</body>
NOTE: The CSDS "Text to Clipboard" works fine inside a Reference page, and the resulting calls can be pasted into SquareDesk's internal SD. HOWEVER, the late version of Taminations "Copy" button, which SAYS that it copied calls to the clipboard, actually doesn't do anything to the Clipboard. Very old versions of Taminations Standalone use Cmd-C to do the copy, and that copy DOES work. My guess is that Taminations changed the way it sticks stuff into the Clipboard, and the old way worked, and the new way does not.
Accordion widgets for the Frames at the left:
This is super interesting too, and the Auto-Hide is kinda what I'm thinking about for Frames:
Commit: 23d3f7d65ee1140a4c65018a5f75d75e514a6343
A few more UX changes, to add in frames. I went with the simplest approach of just adding a vertical box layout for the Frames, and hiding it when not in use. I also took the SD output (which is used mostly for debugging) out of the tab view, and promoted the Current Sequence pane up one level.
Current Sequence designer look (intentionally very much like the current look):
Switching over to the Dance Arranger view, there are now three prototype frames present (they can be hidden via menu option). The main "Current Sequence" window becomes the "Current Frame" when in Dance Arranger mode. (This look is intentionally more like CSDS and SquareDesk had a baby.)
The content of the frames is static right now, but the look and feel is kinda working now. The flow is left-to-right from Frame List on the left to Current Frame in the middle to picture on the right (when in Arranger mode). Hitting a F-key will swap in that frame to the Current Frame position, at the current call. F11/F12 will change sequences within a frame.
Commit: 0438c613d9ac79df570db3ee3c4856d8510faaa8
Trying out zebra striping for the Current Sequence pane. Not sure if I like it or not. I've seen articles that recommend highlighting every 3 (instead of 2).
With zebra striping:
Commit: 3715798c464359b5f208ae7d14776a891b5cccc9 This makes it possible to read the SDOutput info without horizontally scrolling all the time.
Also allows us to look at the SDOutput and Current Sequence panes at the same time, and to disappear the SDOutput pane when we don't want to see it anymore.
Example UX when SDOutput is enabled (it defaults to off now):
Static Square to Resolve (SS) Ceder format example (from the Basic list):
@
#PROOFREAD#
#EASY#
#REC=10511#
#SEQTYPE=5#
#AUTHOR=Vic Ceder#
Heads 1/2 Square Thru,
Touch 1/4,
Split Circulate,
Boys Run,
Reverse Flutter Wheel,
Square Thru 4,
Trade By,
L.A
@
#PROOFREAD#
#EASY#
Record types in files ({level}.choreodb_to_csds.in) are just these:
Calls (except the last one) end in commas. There can be commas mid-line. Extra spaces can happen. Comments are (in parentheses), which can appear mid-line.
Vic's SQL schema (from https://www.ceder.net/faqdb/?section=10):
My sequence database is currently defined as:
CREATE TABLE ChoreoDb
(CheckedByVdc int,
LevelValidated int, // 0 = false, 1 = true
SeqTypeInd int,
Text blob,
SubmittedBy int, // Index into 'callerdb' where 0 = anonymous
LevelInd int,
Comments blob,
HandleList varchar(255), // stored with a comma on both ends (e.g., ",9,122,2124,")
DifficultyInd int,
ModDateTime datetime,
CreateDateTime datetime,
RecordId int AUTO_INCREMENT PRIMARY KEY)
Where
CheckedByVdc indicates that the record has been proofread. (i.e., I have verified that the sequence works).
LevelValidated indicates that I have verified the level of the sequence.
SeqTypeInd indicates the type of the sequence. (e.g., Zero-Line to Resolve, etc.)
Text is the sequence text.
SubmittedBy indicates who submitted the sequence to the database.
LevelInd is the level of the sequence.
Comments is additional text associated with the sequence.
HandleList is a list of parse handles used by CSDS, so I can do database searches for calls and concepts without using text.
DifficultyInd indicates the difficulty of the sequence.
ModDateTime indicates the date and time that the sequence was last modified.
CreateDateTime indicates the date and time that the sequence was added to the database.
RecordId is a number that uniquely identifes the sequence within the database.
Our database runs under MySQL, a freeware database product. The SQL statements given above should work (perhaps with minor tweaking) in almost any database.
My initial cut at a minimal on-disk format will be to use the Ceder format for files, each of which can contain many sequences. The file structure is this:
musicDir/sd:
I haven't yet decided whether to slurp this into a table in sqlite. It would be more convenient for searches, but then I have to have some import strategy (SD > import from CSDS, perhaps?), rather than having the import happen automatically at startup (there are only 4484 sequences total right now, in those 3 categories). And, I'll have to write a lot more code just to get something minimal up and running....I'm feeling the pressure now to get something completely up and running for August 2023. There's still much to do before I can write sequences in SD, save them on disk to a frame, and read them back for playback.
I'm tempted to just read in all the files at app startup, into an in-memory structure (I have plenty of memory, and the total of all of these files is only about 2.3Mb). I can just as easily do simple text searches by scanning thru the in-memory structure. Might take a little longer to fetch, but then again searching is not a P1 feature.
TODO:
Editorial comment: I think there's a general heuristic that I'm following here, that I like more and more as I do more of it: Rather than having strict modes like many apps do (e.g. in our case, "designer vs playback mode"), allow many individual panes to be hide/unhideable, so that custom views of many types can be made, BUT also have a small number of custom "sets of views" (in this case, exactly 2).
This might be even better with the Advanced Docking System referenced above, but for a simple minimal app without a whole embedded docking system, this heuristic seems to work surprisingly well (at least it nicely matches my mental model :-)....
Commit: f3a3645d3f64ca42055bb6c42655fb36abeacd1c
Initial load code. If files do not exist (which is the case for everybody except me), there will be placeholder calls used, as per level. Filenames that we look for are hard-code right now, in
So, if no files are found, you'll get fake data. If you want to use real data, put it here:
musicDir
sd
ceder
SStoSS
<level> = {basic, ms, plus, a1, a2, c1}
local
SStoSS
<level>, as above
Files used (and the sequences inside those files) are hard-coded right now.
File format:
This is temporary, but it's useful for testing for now. Eventually, all of the sequence files will be found automatically, and assigned to Function keys (F1 - F10). If these files are not present, very simple dummy data will be used, just to see how it looks. The Current Sequence window will be live, even with this dummy data, though.
Oh yeah, the label_SD_Resolve is back when in Dance Arranger mode, because SD can't handle Allemande Left or RLG at all, so this label tells you what the final resolve call is, just like it does in Sequence Designer mode.
Current UX (Sequence Designer):
Current UX (Dance Arranger):
Commit 3a06cf7f9b1b9849eea846f36ce9c2e424e0546e makes the function keys work.
Function keys F1-F10 will now load the corresponding frame into the central Current Sequence window, will load the last used sequence, and will highlight the first call (Dance Arranger mode).
Fake data (just 1 sequence) will be used, if a required file (see L1279 in mainwindow.cpp) is not found in the musicDir/sd directory. F11/F12 can be used to load sequences backwards/forwards within a frame.
Only F2/F3/F6/F7 are available right now (there will be another mechanism to select WHICH frames are viewed in the sidebar and central views.
NOTE: Due to a weird bug, the Options tab cannot be hidden, because if it is hidden when I switch from SDesk to another window, the whole SDesk app crashes deep in the bowels of Qt framework code.
BUG: In that last picture, I think that the first item in the Current Sequence pane should be highlighted.
FEATURE?: Should I allow double-clicking in the sidebar frames? Should I have a context menu there for something?
I need a sequence playback thing of SOME kind, since I'm calling C1 for the first time in August. I've evaluated CSDS, CSDS Online, Callerama, Taminations, and SD. I won't repeat all of that analysis here, but my conclusion is that the best approach is probably hybrid: "Design: use CSDS Online or Taminations or SquareDesk's internal SD; Playback (while calling a C1 dance): use SquareDesk's SD".
I do like the "resolver" in CSDS Online (https://www.ceder.net/ws/) a LOT. But, the UI is very weak for designing (especially if you make a typo mistake), and it's really unusable for playback (during a dance). CSDS seems really good for playback, but it's Windows X86 only (and it's $200).
I think it's possible to make a minimally usable Design/Playback tab, using SD. This ticket describes some thoughts about what I think I need for August C1 calling:
Design in CSDS Online, Convert CSDS sequences to SD, use SD sequences or converted CSDS sequences: PROS: Nice resolution in CSDS Online Can still design in SquareDesk/SD SquareDesk has better music support CONS: have to write code:
UPDATE
Here's what's implemented from the above list, as of 2023/03/12: