The MinGW.org Installation Manager Tool
Revision | 39d47c8ed1fbe042072a3ba1e37d8681a4d4c4fd (tree) |
---|---|
Time | 2013-07-30 18:22:31 |
Author | Keith Marshall <keithmarshall@user...> |
Commiter | Keith Marshall |
Avoid discarding pending changes when catalogue is updated.
@@ -1,3 +1,23 @@ | ||
1 | +2013-07-30 Keith Marshall <keithmarshall@users.sourceforge.net> | |
2 | + | |
3 | + Avoid discarding pending changes when catalogue is updated. | |
4 | + | |
5 | + * src/guimain.h (IDD_CONFIRMATION): New manifest constant; define it. | |
6 | + (AppWindowMaker::ConfirmActionDialogue): New static method; declare it. | |
7 | + (AppWindowMaker::ConfirmActionRequest): New method; declare it. | |
8 | + | |
9 | + * src/guimain.rc (IDD_CONFIRMATION): Implement new dialogue template. | |
10 | + | |
11 | + * src/guiexec.cpp (pkgConfirmAction, pkgConfirmActionClient): New | |
12 | + static variables; they are used as pseudo-arguments, together with... | |
13 | + (DIALOGUE_DISPATCH, DIALOGUE_RESPONSE, DIALOGUE_CHKSTATE): ...these | |
14 | + new macros; define them; they facilitate the implementation of... | |
15 | + (AppWindowMaker::ConfirmActionDialogue): ...this; implement it. | |
16 | + (AppWindowMaker::ConfirmActionRequest): Implement it; use it... | |
17 | + (AppWindowMaker::OnCommand) [IDM_REPO_UPDATE]: ...here, and... | |
18 | + | |
19 | + * src/pkgdata.cpp (AppWindowMaker::OnClose): ...here. | |
20 | + | |
1 | 21 | 2013-07-26 Keith Marshall <keithmarshall@users.sourceforge.net> |
2 | 22 | |
3 | 23 | Make a minor GUI layout adjustment. |
@@ -34,6 +34,7 @@ | ||
34 | 34 | |
35 | 35 | #include <unistd.h> |
36 | 36 | #include <wtkexcept.h> |
37 | +#include <wtkalign.h> | |
37 | 38 | |
38 | 39 | /* The DMH sub-system provides the following function, but it does not |
39 | 40 | * declare the prototype; (this is to obviate any automatic requirement |
@@ -567,6 +568,145 @@ int AppWindowMaker::Invoked( void ) | ||
567 | 568 | return WTK::MainWindowMaker::Invoked(); |
568 | 569 | } |
569 | 570 | |
571 | +/* The following static entities are provided to facilitate the | |
572 | + * implementation of the "discard changes" confirmation dialogue. | |
573 | + */ | |
574 | +static const char *pkgConfirmAction = NULL; | |
575 | +static AppWindowMaker *pkgConfirmActionClient = NULL; | |
576 | + | |
577 | +static void dlgReplaceText( HWND dlg, ... ) | |
578 | +{ | |
579 | + /* Local helper routine, used by AppWindowMaker::ConfirmActionDialogue(), | |
580 | + * to substitute the designated action description into the format strings, | |
581 | + * as specified within the dialogue box template. | |
582 | + * | |
583 | + * First step is to copy the format specification from the dialogue item. | |
584 | + */ | |
585 | + int len = 1 + SendMessage( dlg, WM_GETTEXTLENGTH, 0, 0 ); | |
586 | + char fmt[len]; SendMessage( dlg, WM_GETTEXT, len, (LPARAM)(fmt) ); | |
587 | + | |
588 | + /* Having established the format, we allocate a sufficient buffer, in | |
589 | + * which we prepare the formatted text... | |
590 | + */ | |
591 | + va_list argv; va_start( argv, dlg ); | |
592 | + char text[1 + vsnprintf( NULL, 0, fmt, argv )]; | |
593 | + vsnprintf( text, sizeof( text ), fmt, argv ); | |
594 | + va_end( argv ); | |
595 | + | |
596 | + /* ...which we then copy back to the active dialogue item. | |
597 | + */ | |
598 | + SendMessage( dlg, WM_SETTEXT, 0, (LPARAM)(text) ); | |
599 | +} | |
600 | + | |
601 | +int CALLBACK AppWindowMaker::ConfirmActionDialogue | |
602 | +( HWND dlg, unsigned int msg, WPARAM wparam, LPARAM lparam ) | |
603 | +#define DIALOGUE_CHKSTATE pkgConfirmActionClient->EnumerateActions | |
604 | +#define DIALOGUE_DISPATCH pkgConfirmActionClient->DispatchDialogueThread | |
605 | +#define DIALOGUE_RESPONSE pkgConfirmActionClient->DialogueResponse | |
606 | +{ | |
607 | + /* Call back handler for the messages generated by the "discard changes" | |
608 | + * confirmation dialogue. | |
609 | + */ | |
610 | + switch( msg ) | |
611 | + { case WM_INITDIALOG: | |
612 | + /* When the confirmation dialogue is invoked, we centre it within | |
613 | + * its owner window, and replace the format specification strings | |
614 | + * from its text controls with their formatted equivalents. | |
615 | + */ | |
616 | + WTK::AlignWindow( dlg, WTK_ALIGN_CENTRED ); | |
617 | + dlgReplaceText( GetDlgItem( dlg, IDD_PROGRESS_MSG ), pkgConfirmAction ); | |
618 | + dlgReplaceText( GetDlgItem( dlg, IDD_PROGRESS_TXT ), pkgConfirmAction, | |
619 | + pkgConfirmAction | |
620 | + ); | |
621 | + return TRUE; | |
622 | + | |
623 | + case WM_COMMAND: | |
624 | + /* Process the messages from the dialogue's three command buttons: | |
625 | + */ | |
626 | + switch( msg = LOWORD( wparam ) ) | |
627 | + { | |
628 | + case IDIGNORE: | |
629 | + /* Sent when the user selects the "Discard Changes" option, | |
630 | + * we return "IDOK" to confirm that the action should be | |
631 | + * progressed, ignoring any uncommitted changes. | |
632 | + */ | |
633 | + EndDialog( dlg, IDOK ); | |
634 | + return TRUE; | |
635 | + | |
636 | + case IDOK: | |
637 | + /* Sent when the user selects the "Review Changes" option; we | |
638 | + * shelve the active dialogue, and delegate the decision as to | |
639 | + * whether to proceed to the "Apply Changes" dialogue. | |
640 | + */ | |
641 | + ShowWindow( dlg, SW_HIDE ); | |
642 | + switch( DIALOGUE_RESPONSE( IDD_APPLY_APPROVE, pkgApplyApproved ) ) | |
643 | + { | |
644 | + case ID_DEFER: | |
645 | + /* Handle a "Defer" request from the "Apply Changes" | |
646 | + * dialogue as equivalent to our own "Cancel Request" | |
647 | + * option. | |
648 | + */ | |
649 | + msg = IDCANCEL; | |
650 | + break; | |
651 | + | |
652 | + case ID_APPLY: | |
653 | + /* When "Apply" confirmation is forthcoming, we proceed to | |
654 | + * download any required packages, and invoke the scheduled | |
655 | + * remove, upgrade, or install actions. | |
656 | + */ | |
657 | + DIALOGUE_DISPATCH( IDD_APPLY_DOWNLOAD, pkgInvokeDownload ); | |
658 | + DIALOGUE_DISPATCH( IDD_APPLY_EXECUTE, pkgApplyChanges ); | |
659 | + | |
660 | + /* Ensure that all "Apply" actions completed successfully... | |
661 | + */ | |
662 | + if( DIALOGUE_CHKSTATE( ACTION_UNSUCCESSFUL ) > 0 ) | |
663 | + /* | |
664 | + * ...otherwise, cancel the ensuing action, so that the | |
665 | + * user may have an opportunity to remedy the problem. | |
666 | + */ | |
667 | + msg = IDCANCEL; | |
668 | + } | |
669 | + /* Regardless of the outcome from the "Review Changes" activity, | |
670 | + * simply fall through to terminate the dialogue appropriately. | |
671 | + */ | |
672 | + case IDCANCEL: | |
673 | + /* Sent when the user selects the "Cancel Request" option; we | |
674 | + * simply allow the message ID to propagate back to the caller, | |
675 | + * as the response code. | |
676 | + */ | |
677 | + EndDialog( dlg, msg ); | |
678 | + return TRUE; | |
679 | + } | |
680 | + } | |
681 | + /* We don't handle any other message; if any is received, mark it as | |
682 | + * "unhandled", and pass it on to the default dialogue handler. | |
683 | + */ | |
684 | + return FALSE; | |
685 | +} | |
686 | + | |
687 | +bool AppWindowMaker::ConfirmActionRequest( const char *desc ) | |
688 | +{ | |
689 | + /* Helper to confirm user's intent to proceed, when a request | |
690 | + * to update the catalogue, or to quit, would result in pending | |
691 | + * installation actions being discarded. | |
692 | + * | |
693 | + * We begin by saving reference data to be passed to the static | |
694 | + * dialogue handler method... | |
695 | + */ | |
696 | + pkgConfirmAction = desc; | |
697 | + pkgConfirmActionClient = this; | |
698 | + | |
699 | + /* ...prior to checking for pending actions, and invoking the | |
700 | + * dialogue procedure when appropriate, or simply allowing the | |
701 | + * action to proceed, otherwise. | |
702 | + */ | |
703 | + return (pkgData->Schedule()->EnumeratePendingActions() > 0) | |
704 | + ? DialogBox( AppInstance, MAKEINTRESOURCE( IDD_CONFIRMATION ), | |
705 | + AppWindow, ConfirmActionDialogue | |
706 | + ) == IDOK | |
707 | + : true; | |
708 | +} | |
709 | + | |
570 | 710 | long AppWindowMaker::OnCommand( WPARAM cmd ) |
571 | 711 | #define ACTION_PRESERVE_FAILED (ACTION_DOWNLOAD_FAILED | ACTION_APPLY_FAILED) |
572 | 712 | { |
@@ -623,8 +763,15 @@ long AppWindowMaker::OnCommand( WPARAM cmd ) | ||
623 | 763 | * dialogue, from which a background thread is invoked to download |
624 | 764 | * fresh copies of the package catalogue files from the remote |
625 | 765 | * repository, and consolidate them into the local catalogue. |
766 | + * | |
767 | + * Note that this activity will cause any pending installation | |
768 | + * actions to be discarded; seek confirmation of user's intent | |
769 | + * to proceed, when this situation prevails. | |
626 | 770 | */ |
627 | - DispatchDialogueThread( IDD_REPO_UPDATE, pkgInvokeUpdate ); | |
771 | + if( ConfirmActionRequest( "update the catalogue" ) ) | |
772 | + { DispatchDialogueThread( IDD_REPO_UPDATE, pkgInvokeUpdate ); | |
773 | + UpdatePackageMenuBindings(); | |
774 | + } | |
628 | 775 | break; |
629 | 776 | |
630 | 777 | case IDM_REPO_MARK_UPGRADES: |
@@ -97,6 +97,7 @@ | ||
97 | 97 | #define IDD_PROGRESS_MAX 616 |
98 | 98 | #define IDD_PROGRESS_PCT 617 |
99 | 99 | #define IDD_PROGRESS_TXT 618 |
100 | +#define IDD_CONFIRMATION 619 | |
100 | 101 | |
101 | 102 | #define IDD_APPLY_APPROVE 630 |
102 | 103 | #define IDD_APPLY_DOWNLOAD 631 |
@@ -218,6 +219,8 @@ class AppWindowMaker: public WTK::MainWindowMaker | ||
218 | 219 | HWND PackageListView; |
219 | 220 | void InitPackageListView( void ); |
220 | 221 | void UpdatePackageMenuBindings( void ); |
222 | + bool ConfirmActionRequest( const char * ); | |
223 | + static int CALLBACK ConfirmActionDialogue( HWND, unsigned, WPARAM, LPARAM ); | |
221 | 224 | void Schedule( unsigned long, const char * = NULL, const char * = NULL ); |
222 | 225 | inline void MarkSchedule( pkgActionItem * ); |
223 | 226 | void SelectPackageAction( unsigned ); |
@@ -175,6 +175,27 @@ BEGIN | ||
175 | 175 | LTEXT "", IDD_PROGRESS_MSG, 7, 6, 256, 12 |
176 | 176 | END |
177 | 177 | |
178 | +IDD_CONFIRMATION DIALOG DISCARDABLE 10, 20, 270, 115 | |
179 | +CAPTION "Action Requires Confirmation" | |
180 | +STYLE DS_MODALFRAME | DS_SETFONT | WS_POPUP | WS_CAPTION | WS_DLGFRAME | |
181 | +FONT 10, "Verdana" | |
182 | +BEGIN | |
183 | + ICON IDI_WARNING, IDI_WARNING, 15, 16, 0, 0 | |
184 | + LTEXT "You have marked packages for installation, upgrade, or " \ | |
185 | + "removal, but you have not yet committed these changes; " \ | |
186 | + "if you %s without committing these changes, they will " \ | |
187 | + "be discarded, and you may need to reschedule them.", \ | |
188 | + IDD_PROGRESS_MSG, 42, 10, 219, 35 | |
189 | + LTEXT "You are advised to review your marked changes, before you " \ | |
190 | + "%s; (you may select the ""Review Changes"" option button " \ | |
191 | + "below), or alternatively, you may simply discard the changes, " \ | |
192 | + "unseen, or you may cancel this request to %s.", \ | |
193 | + IDD_PROGRESS_TXT, 9, 50, 260, 35 | |
194 | + DEFPUSHBUTTON "Review Changes", IDOK, 10, 91, 76, 13, WS_GROUP | WS_TABSTOP | |
195 | + PUSHBUTTON "Discard Changes", IDIGNORE, 97, 91, 76, 13, WS_TABSTOP | |
196 | + PUSHBUTTON "Cancel Request", IDCANCEL, 184, 91, 76, 13, WS_TABSTOP | |
197 | +END | |
198 | + | |
178 | 199 | /* Template for dialogue requesting user confirmation of intent |
179 | 200 | * to proceed with scheduled change actions. |
180 | 201 | */ |
@@ -1483,15 +1483,7 @@ long AppWindowMaker::OnClose() | ||
1483 | 1483 | * option for the termination request, so that the user |
1484 | 1484 | * has an opportunity to complete such actions. |
1485 | 1485 | */ |
1486 | - if( (pkgData->Schedule()->EnumeratePendingActions() > 0) | |
1487 | - && (MessageBox( AppWindow, | |
1488 | - "You have marked changes which have not been applied;\n" | |
1489 | - "these will be lost, if you quit without applying them.\n\n" | |
1490 | - "Are you sure you want to discard these marked changes?", | |
1491 | - "Discard Marked Changes?", MB_YESNO | MB_ICONWARNING | |
1492 | - ) == IDNO) | |
1493 | - ) return 0; | |
1494 | - return -1; | |
1486 | + return ConfirmActionRequest( "quit" ) ? -1 : 0; | |
1495 | 1487 | } |
1496 | 1488 | |
1497 | 1489 | /* $RCSfile$: end of file */ |