From 6d48342da037cb5ecfb496357afa58d79866ee48 Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Wed, 18 Jan 2017 09:36:46 +0100 Subject: [PATCH] display summary of unsaved content on exit --- src/ce_editor.pas | 12 ++++---- src/ce_interfaces.pas | 8 ++--- src/ce_main.pas | 69 +++++++++++++++++++++++++++++++++++-------- src/ce_projgroup.pas | 19 +++++++++--- 4 files changed, 81 insertions(+), 27 deletions(-) diff --git a/src/ce_editor.pas b/src/ce_editor.pas index 7b50bb31..a2ea5d72 100644 --- a/src/ce_editor.pas +++ b/src/ce_editor.pas @@ -161,8 +161,8 @@ type function getDocument(index: Integer): TCESynMemo; function findDocument(const fname: string): TCESynMemo; procedure openDocument(const fname: string); - function closeDocument(index: Integer): boolean; - function closeDocument(doc: TCESynMemo): boolean; + function closeDocument(index: Integer;promptOnChanged: boolean = true): boolean; + function closeDocument(doc: TCESynMemo;promptOnChanged: boolean = true): boolean; public constructor create(aOwner: TComponent); override; destructor destroy; override; @@ -509,14 +509,14 @@ begin end; end; -function TCEEditorWidget.closeDocument(index: Integer): boolean; +function TCEEditorWidget.closeDocument(index: Integer; promptOnChanged: boolean = true): boolean; var doc: TCESynMemo; begin doc := getDocument(index); if doc.isNil then exit(false); - if (doc.modified or (doc.fileName = doc.tempFilename)) and + if promptOnChanged and (doc.modified or (doc.fileName = doc.tempFilename)) and (dlgFileChangeClose(doc.fileName, UnsavedFile) = mrCancel) then exit(false); showWidget; @@ -526,14 +526,14 @@ begin result := true; end; -function TCEEditorWidget.closeDocument(doc: TCESynMemo): boolean; +function TCEEditorWidget.closeDocument(doc: TCESynMemo;promptOnChanged: boolean = true): boolean; var page: TCEPage = nil; begin page := TCEPage(doc.Parent); if page.isNil then exit(false); - exit(closeDocument(page.index)); + exit(closeDocument(page.index, promptOnChanged)); end; {$ENDREGION} diff --git a/src/ce_interfaces.pas b/src/ce_interfaces.pas index 7e1d451a..1dc70626 100644 --- a/src/ce_interfaces.pas +++ b/src/ce_interfaces.pas @@ -275,9 +275,9 @@ type // opens or set the focus on the document matching aFilename. procedure openDocument(const fname: string); // closes the nth document. - function closeDocument(index: Integer): boolean; + function closeDocument(index: Integer; promptOnChanged: boolean = true): boolean; // closes a particular document. - function closeDocument(doc: TCESynMemo): boolean; + function closeDocument(doc: TCESynMemo; promptOnChanged: boolean = true): boolean; // conveniance property. property document[index: integer]: TCESynMemo read getDocument; end; @@ -306,6 +306,8 @@ type function getProjectIndex: integer; // returns the nth project. function getProject(index: Integer): ICECommonProject; + // returns true if the nth project is modified + function projectModified(index: integer): boolean; // tries to find the project named fname. function findProject(const fname: string): ICECommonProject; // selects the nth project of the group. @@ -336,8 +338,6 @@ type end; - // TODO-cOptions: widgets that expose options can use ICEOptionsEditor in their ctxt menu - (** * Single service provided by the options editor. *) diff --git a/src/ce_main.pas b/src/ce_main.pas index f2ef207f..9081e169 100644 --- a/src/ce_main.pas +++ b/src/ce_main.pas @@ -1836,6 +1836,17 @@ end; procedure TCEMainForm.FormCloseQuery(Sender: TObject; var CanClose: boolean); var i: Integer; + files: string = ''; + projs: string = ''; + group: string = #9'no'; + chang: boolean = false; + d: TCESynMemo; +const + s: string = 'The following content is modified and changes will be lost'#10#10 + + '- Modified files:'#10' %s '#10 + + '- Modified projects:'#10' %s '#10 + + '- Project group modified:'#10' %s'#10#10 + + 'Close without saving ?'; begin canClose := false; SaveLastDocsAndProj; @@ -1844,22 +1855,54 @@ begin (dlgOkCancel('A project is still being compiled, close anyway ?') <> mrOK) then exit; - if assigned(fFreeProj) then + if assigned(fFreeProj) and fFreeProj.modified then begin - if fFreeProj.modified and - (dlgFileChangeClose(fFreeProj.filename, UnsavedProj) = mrCancel) then - exit; - fFreeProj.getProject.Free; - fFreeProj := nil; + projs += #9 + fFreeProj.filename + LineEnding; + chang := true; end; - for i := fMultidoc.documentCount-1 downto 0 do - if not fMultidoc.closeDocument(i) then - exit; - if fProjectGroup.groupModified and - (dlgFileChangeClose(fProjectGroup.groupFilename, UnsavedPGrp) = mrCancel) then - exit; - canClose := true; + + for i := 0 to fMultidoc.documentCount-1 do + begin + d := fMultidoc.getDocument(i); + if d.modified then + begin + files += #9 + shortenPath(d.filename) + LineEnding; + chang := true; + end; + end; + + for i:= 0 to fProjectGroup.projectCount-1 do + begin + if not fProjectGroup.projectModified(i) then + continue; + projs += #9 + shortenPath(fProjectGroup.getProject(i).filename) + LineEnding; + chang := true; + end; + + if fProjectGroup.groupModified then + begin + group := #9'yes'; + chang := true; + end; + + if chang then + begin + if projs.isEmpty then + projs := '(no modified projects)'#10; + if files.isEmpty then + files := '(no modified files)'#10; + + if MessageDlg('Modified content', format(s, [files, projs, group]), + TMsgDlgType.mtConfirmation, [mbOk, mbCancel], '') <> mrOk then + exit; + end; + + CanClose:= true; fProjectGroup.closeGroup; + if assigned(fFreeProj) then + fFreeProj.getProject.Free; + for i:= fMultidoc.documentCount-1 downto 0 do + fMultidoc.closeDocument(i, false); end; procedure TCEMainForm.updateDocumentBasedAction(sender: TObject); diff --git a/src/ce_projgroup.pas b/src/ce_projgroup.pas index ae4f2a46..98198c21 100644 --- a/src/ce_projgroup.pas +++ b/src/ce_projgroup.pas @@ -85,7 +85,8 @@ type function getProject(ix: Integer): ICECommonProject; function findProject(const fname: string): ICECommonProject; procedure setProjectIndex(value: Integer); - function projectIsAsync(index: integer): boolean; + function projectIsAsync(ix: integer): boolean; + function projectModified(ix: integer): boolean; // function addItem(const fname: string): TProjectGroupItem; property item[ix: integer]: TProjectGroupItem read getItem; default; @@ -245,9 +246,9 @@ begin end; end; -function TProjectGroup.projectIsAsync(index: integer): boolean; +function TProjectGroup.projectIsAsync(ix: integer): boolean; begin - exit(item[index].asyncMode = amParallel); + exit(item[ix].asyncMode = amParallel); end; function TProjectGroup.addItem(const fname: string): TProjectGroupItem; @@ -284,6 +285,16 @@ begin result.setActiveConfigurationIndex(item[ix].configurationIndex); end; +function TProjectGroup.projectModified(ix: integer): boolean; +var + p: ICECommonProject; +begin + result := false; + p := item[ix].project; + if assigned(p) and (p.modified) then + result := true +end; + function TProjectGroup.findProject(const fname: string): ICECommonProject; var i: integer; @@ -407,7 +418,7 @@ var b: boolean = false; begin for i:= 0 to fItems.Count-1 do - if (getItem(i).fProj <> nil) and getItem(i).fProj.modified then + if projectModified(i) then begin b := true; break;