Add an autosave timer.
Original patch by Marc Britten <marc.britten@gmail.com>.
This commit is contained in:
parent
22d43d5b83
commit
71b7ad7f99
|
@ -85,6 +85,7 @@ int64_t SolveSpace::GetMilliseconds(void) {
|
|||
@interface DeferredHandler : NSObject
|
||||
+ (void) runLater:(id)dummy;
|
||||
+ (void) runCallback;
|
||||
+ (void) doAutosave;
|
||||
@end
|
||||
|
||||
@implementation DeferredHandler
|
||||
|
@ -95,18 +96,29 @@ int64_t SolveSpace::GetMilliseconds(void) {
|
|||
SolveSpace::SS.GW.TimerCallback();
|
||||
SolveSpace::SS.TW.TimerCallback();
|
||||
}
|
||||
+ (void) doAutosave {
|
||||
SolveSpace::SS.Autosave();
|
||||
}
|
||||
@end
|
||||
|
||||
void SolveSpace::SetTimerFor(int milliseconds) {
|
||||
static void Schedule(SEL selector, double interval) {
|
||||
NSMethodSignature *signature = [[DeferredHandler class]
|
||||
methodSignatureForSelector:@selector(runCallback)];
|
||||
methodSignatureForSelector:selector];
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
|
||||
[invocation setSelector:@selector(runCallback)];
|
||||
[invocation setSelector:selector];
|
||||
[invocation setTarget:[DeferredHandler class]];
|
||||
[NSTimer scheduledTimerWithTimeInterval:(milliseconds / 1000.0)
|
||||
[NSTimer scheduledTimerWithTimeInterval:interval
|
||||
invocation:invocation repeats:NO];
|
||||
}
|
||||
|
||||
void SolveSpace::SetTimerFor(int milliseconds) {
|
||||
Schedule(@selector(runCallback), milliseconds / 1000.0);
|
||||
}
|
||||
|
||||
void SolveSpace::SetAutosaveTimerFor(int minutes) {
|
||||
Schedule(@selector(doAutosave), minutes * 60.0);
|
||||
}
|
||||
|
||||
void SolveSpace::ScheduleLater() {
|
||||
[[NSRunLoop currentRunLoop]
|
||||
performSelector:@selector(runLater:)
|
||||
|
@ -798,6 +810,23 @@ int SolveSpace::SaveFileYesNoCancel(void) {
|
|||
abort(); /* unreachable */
|
||||
}
|
||||
|
||||
int SolveSpace::LoadAutosaveYesNo(void) {
|
||||
NSAlert *alert = [[NSAlert alloc] init];
|
||||
[alert setMessageText:
|
||||
@"An autosave file is availible for this project."];
|
||||
[alert setInformativeText:
|
||||
@"Do you want to load the autosave file instead?"];
|
||||
[alert addButtonWithTitle:@"Load"];
|
||||
[alert addButtonWithTitle:@"Don't Load"];
|
||||
switch([alert runModal]) {
|
||||
case NSAlertFirstButtonReturn:
|
||||
return SAVE_YES;
|
||||
case NSAlertSecondButtonReturn:
|
||||
return SAVE_NO;
|
||||
}
|
||||
abort(); /* unreachable */
|
||||
}
|
||||
|
||||
/* Text window */
|
||||
|
||||
@interface TextWindowView : GLViewWithEditor
|
||||
|
|
|
@ -167,6 +167,14 @@ void TextWindow::ScreenChangeGCodeParameter(int link, uint32_t v) {
|
|||
SS.TW.ShowEditControl(row, 14, buf);
|
||||
}
|
||||
|
||||
void TextWindow::ScreenChangeAutosaveInterval(int link, uint32_t v) {
|
||||
char str[1024];
|
||||
sprintf(str, "%d", SS.autosaveInterval);
|
||||
|
||||
SS.TW.ShowEditControl(111, 3, str);
|
||||
SS.TW.edit.meaning = EDIT_AUTOSAVE_INTERVAL;
|
||||
}
|
||||
|
||||
void TextWindow::ShowConfiguration(void) {
|
||||
int i;
|
||||
Printf(true, "%Ft user color (r, g, b)");
|
||||
|
@ -294,6 +302,11 @@ void TextWindow::ShowConfiguration(void) {
|
|||
&ScreenChangeCheckClosedContour,
|
||||
SS.checkClosedContour ? CHECK_TRUE : CHECK_FALSE);
|
||||
|
||||
Printf(false, "");
|
||||
Printf(false, "%Ft autosave interval (in minutes)%E");
|
||||
Printf(false, "%Ba %d %Fl%Ll%f[change]%E",
|
||||
SS.autosaveInterval, &ScreenChangeAutosaveInterval);
|
||||
|
||||
Printf(false, "");
|
||||
Printf(false, " %Ftgl vendor %E%s", glGetString(GL_VENDOR));
|
||||
Printf(false, " %Ft renderer %E%s", glGetString(GL_RENDERER));
|
||||
|
@ -425,6 +438,19 @@ bool TextWindow::EditControlDoneForConfiguration(const char *s) {
|
|||
if(e) SS.gCode.plungeFeed = (float)SS.ExprToMm(e);
|
||||
break;
|
||||
}
|
||||
case EDIT_AUTOSAVE_INTERVAL: {
|
||||
int interval;
|
||||
if(sscanf(s, "%d", &interval)==1) {
|
||||
if(interval >= 1) {
|
||||
SS.autosaveInterval = interval;
|
||||
SetAutosaveTimerFor(interval);
|
||||
} else {
|
||||
Error("Bad value: autosave interval should be positive");
|
||||
}
|
||||
} else {
|
||||
Error("Bad format: specify interval in integral minutes");
|
||||
}
|
||||
}
|
||||
|
||||
default: return false;
|
||||
}
|
||||
|
|
|
@ -224,7 +224,7 @@ static void CnfThawWindowPos(Gtk::Window *win, const char *key) {
|
|||
win->resize(w, h);
|
||||
}
|
||||
|
||||
/* Timer */
|
||||
/* Timers */
|
||||
|
||||
int64_t GetMilliseconds(void) {
|
||||
struct timespec ts;
|
||||
|
@ -242,6 +242,15 @@ void SetTimerFor(int milliseconds) {
|
|||
Glib::signal_timeout().connect(&TimerCallback, milliseconds);
|
||||
}
|
||||
|
||||
static bool AutosaveTimerCallback() {
|
||||
SS.Autosave();
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetAutosaveTimerFor(int minutes) {
|
||||
Glib::signal_timeout().connect(&AutosaveTimerCallback, minutes * 60 * 1000);
|
||||
}
|
||||
|
||||
static bool LaterCallback() {
|
||||
SS.DoLater();
|
||||
return false;
|
||||
|
@ -1186,7 +1195,7 @@ int SaveFileYesNoCancel(void) {
|
|||
Gtk::BUTTONS_NONE, /*is_modal*/ true);
|
||||
dialog.set_title("SolveSpace - Modified File");
|
||||
dialog.add_button("_Save", Gtk::RESPONSE_YES);
|
||||
dialog.add_button("Do_n't save", Gtk::RESPONSE_NO);
|
||||
dialog.add_button("Do_n't Save", Gtk::RESPONSE_NO);
|
||||
dialog.add_button("_Cancel", Gtk::RESPONSE_CANCEL);
|
||||
|
||||
switch(dialog.run()) {
|
||||
|
@ -1202,6 +1211,26 @@ int SaveFileYesNoCancel(void) {
|
|||
}
|
||||
}
|
||||
|
||||
int LoadAutosaveYesNo(void) {
|
||||
Glib::ustring message =
|
||||
"An autosave file is availible for this project.\n"
|
||||
"Do you want to load the autosave file instead?";
|
||||
Gtk::MessageDialog dialog(*GW, message, /*use_markup*/ true, Gtk::MESSAGE_QUESTION,
|
||||
Gtk::BUTTONS_NONE, /*is_modal*/ true);
|
||||
dialog.set_title("SolveSpace - Autosave Available");
|
||||
dialog.add_button("_Load autosave", Gtk::RESPONSE_YES);
|
||||
dialog.add_button("Do_n't Load", Gtk::RESPONSE_NO);
|
||||
|
||||
switch(dialog.run()) {
|
||||
case Gtk::RESPONSE_YES:
|
||||
return SAVE_YES;
|
||||
|
||||
case Gtk::RESPONSE_NO:
|
||||
default:
|
||||
return SAVE_NO;
|
||||
}
|
||||
}
|
||||
|
||||
/* Text window */
|
||||
|
||||
class TextWidget : public GlWidget {
|
||||
|
|
|
@ -91,24 +91,49 @@ void SolveSpaceUI::Init() {
|
|||
CnfThawString(RecentFile[i], MAX_PATH, name);
|
||||
}
|
||||
RefreshRecentMenus();
|
||||
// Autosave timer
|
||||
autosaveInterval = CnfThawInt(5, "AutosaveInterval");
|
||||
|
||||
// The default styles (colors, line widths, etc.) are also stored in the
|
||||
// configuration file, but we will automatically load those as we need
|
||||
// them.
|
||||
|
||||
SetAutosaveTimerFor(autosaveInterval);
|
||||
|
||||
NewFile();
|
||||
AfterNewFile();
|
||||
}
|
||||
|
||||
bool SolveSpaceUI::LoadAutosaveFor(const char *filename) {
|
||||
char autosaveFile[MAX_PATH];
|
||||
strcpy(autosaveFile, filename);
|
||||
strcat(autosaveFile, AUTOSAVE_SUFFIX);
|
||||
|
||||
FILE *f = fopen(autosaveFile, "r");
|
||||
if(!f)
|
||||
return false;
|
||||
fclose(f);
|
||||
|
||||
if(LoadAutosaveYesNo() == SAVE_YES) {
|
||||
unsaved = true;
|
||||
return LoadFromFile(autosaveFile);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SolveSpaceUI::OpenFile(const char *filename) {
|
||||
bool success = LoadFromFile(filename);
|
||||
bool autosaveLoaded = LoadAutosaveFor(filename);
|
||||
bool success = autosaveLoaded || LoadFromFile(filename);
|
||||
if(success) {
|
||||
RemoveAutosave();
|
||||
AddToRecentList(filename);
|
||||
strcpy(saveFile, filename);
|
||||
} else {
|
||||
NewFile();
|
||||
}
|
||||
AfterNewFile();
|
||||
unsaved = autosaveLoaded;
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -183,10 +208,15 @@ void SolveSpaceUI::Exit(void) {
|
|||
CnfFreezeFloat(gCode.plungeFeed, "GCode_PlungeFeed");
|
||||
// Show toolbar in the graphics window
|
||||
CnfFreezeBool(showToolbar, "ShowToolbar");
|
||||
// Autosave timer
|
||||
CnfFreezeInt(autosaveInterval, "AutosaveInterval");
|
||||
|
||||
// And the default styles, colors and line widths and such.
|
||||
Style::FreezeDefaultStyles();
|
||||
|
||||
// Exiting cleanly.
|
||||
RemoveAutosave();
|
||||
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
|
@ -345,6 +375,7 @@ bool SolveSpaceUI::GetFilenameAndSave(bool saveAs) {
|
|||
|
||||
if(SaveToFile(saveFile)) {
|
||||
AddToRecentList(saveFile);
|
||||
RemoveAutosave();
|
||||
unsaved = false;
|
||||
return true;
|
||||
} else {
|
||||
|
@ -354,6 +385,28 @@ bool SolveSpaceUI::GetFilenameAndSave(bool saveAs) {
|
|||
}
|
||||
}
|
||||
|
||||
bool SolveSpaceUI::Autosave()
|
||||
{
|
||||
SetAutosaveTimerFor(autosaveInterval);
|
||||
|
||||
if (strlen(saveFile) != 0 && unsaved) {
|
||||
char autosaveFile[MAX_PATH];
|
||||
strcpy(autosaveFile, saveFile);
|
||||
strcat(autosaveFile, AUTOSAVE_SUFFIX);
|
||||
return SaveToFile(autosaveFile);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SolveSpaceUI::RemoveAutosave()
|
||||
{
|
||||
char autosaveFile[MAX_PATH];
|
||||
strcpy(autosaveFile, saveFile);
|
||||
strcat(autosaveFile, AUTOSAVE_SUFFIX);
|
||||
remove(autosaveFile);
|
||||
}
|
||||
|
||||
bool SolveSpaceUI::OkayToStartNewFile(void) {
|
||||
if(!unsaved) return true;
|
||||
|
||||
|
@ -393,14 +446,7 @@ void SolveSpaceUI::MenuFile(int id) {
|
|||
char newFile[MAX_PATH];
|
||||
strcpy(newFile, RecentFile[id-RECENT_OPEN]);
|
||||
RemoveFromRecentList(newFile);
|
||||
if(SS.LoadFromFile(newFile)) {
|
||||
strcpy(SS.saveFile, newFile);
|
||||
AddToRecentList(newFile);
|
||||
} else {
|
||||
strcpy(SS.saveFile, "");
|
||||
SS.NewFile();
|
||||
}
|
||||
SS.AfterNewFile();
|
||||
SS.OpenFile(newFile);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -418,14 +464,7 @@ void SolveSpaceUI::MenuFile(int id) {
|
|||
|
||||
char newFile[MAX_PATH] = "";
|
||||
if(GetOpenFile(newFile, SLVS_EXT, SLVS_PATTERN)) {
|
||||
if(SS.LoadFromFile(newFile)) {
|
||||
strcpy(SS.saveFile, newFile);
|
||||
AddToRecentList(newFile);
|
||||
} else {
|
||||
strcpy(SS.saveFile, "");
|
||||
SS.NewFile();
|
||||
}
|
||||
SS.AfterNewFile();
|
||||
SS.OpenFile(newFile);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -133,6 +133,9 @@ void RefreshRecentMenus(void);
|
|||
#define SAVE_NO (-1)
|
||||
#define SAVE_CANCEL (0)
|
||||
int SaveFileYesNoCancel(void);
|
||||
int LoadAutosaveYesNo(void);
|
||||
|
||||
#define AUTOSAVE_SUFFIX "~"
|
||||
|
||||
#if defined(HAVE_GTK)
|
||||
// Selection pattern format to be parsed by GTK3 glue code:
|
||||
|
@ -242,6 +245,7 @@ void SetCurrentFilename(const char *filename);
|
|||
void SetMousePointerToHand(bool yes);
|
||||
void DoMessageBox(const char *str, int rows, int cols, bool error);
|
||||
void SetTimerFor(int milliseconds);
|
||||
void SetAutosaveTimerFor(int minutes);
|
||||
void ScheduleLater();
|
||||
void ExitNow(void);
|
||||
|
||||
|
@ -768,6 +772,7 @@ public:
|
|||
Unit viewUnits;
|
||||
int afterDecimalMm;
|
||||
int afterDecimalInch;
|
||||
int autosaveInterval; // in minutes
|
||||
|
||||
char *MmToString(double v);
|
||||
double ExprToMm(Expr *e);
|
||||
|
@ -818,6 +823,8 @@ public:
|
|||
Style s;
|
||||
} sv;
|
||||
static void MenuFile(int id);
|
||||
bool Autosave();
|
||||
void RemoveAutosave();
|
||||
bool GetFilenameAndSave(bool saveAs);
|
||||
bool OkayToStartNewFile(void);
|
||||
hGroup CreateDefaultDrawingGroup(void);
|
||||
|
@ -825,6 +832,7 @@ public:
|
|||
void ClearExisting(void);
|
||||
void NewFile(void);
|
||||
bool SaveToFile(const char *filename);
|
||||
bool LoadAutosaveFor(const char *filename);
|
||||
bool LoadFromFile(const char *filename);
|
||||
bool LoadEntitiesFromFile(const char *filename, EntityList *le,
|
||||
SMesh *m, SShell *sh);
|
||||
|
|
2
src/ui.h
2
src/ui.h
|
@ -155,6 +155,7 @@ public:
|
|||
EDIT_G_CODE_PASSES = 121,
|
||||
EDIT_G_CODE_FEED = 122,
|
||||
EDIT_G_CODE_PLUNGE_FEED = 123,
|
||||
EDIT_AUTOSAVE_INTERVAL = 124,
|
||||
// For TTF text
|
||||
EDIT_TTF_TEXT = 300,
|
||||
// For the step dimension screen
|
||||
|
@ -297,6 +298,7 @@ public:
|
|||
static void ScreenChangeExportScale(int link, uint32_t v);
|
||||
static void ScreenChangeExportOffset(int link, uint32_t v);
|
||||
static void ScreenChangeGCodeParameter(int link, uint32_t v);
|
||||
static void ScreenChangeAutosaveInterval(int link, uint32_t v);
|
||||
static void ScreenChangeStyleName(int link, uint32_t v);
|
||||
static void ScreenChangeStyleWidthOrTextHeight(int link, uint32_t v);
|
||||
static void ScreenChangeStyleTextAngle(int link, uint32_t v);
|
||||
|
|
|
@ -248,6 +248,17 @@ void SolveSpace::ScheduleLater()
|
|||
{
|
||||
}
|
||||
|
||||
static void CALLBACK AutosaveCallback(HWND hwnd, UINT msg, UINT_PTR id, DWORD time)
|
||||
{
|
||||
KillTimer(GraphicsWnd, 1);
|
||||
SS.Autosave();
|
||||
}
|
||||
|
||||
void SolveSpace::SetAutosaveTimerFor(int minutes)
|
||||
{
|
||||
SetTimer(GraphicsWnd, 2, minutes * 60 * 1000, AutosaveCallback);
|
||||
}
|
||||
|
||||
static void GetWindowSize(HWND hwnd, int *w, int *h)
|
||||
{
|
||||
RECT r;
|
||||
|
@ -880,6 +891,7 @@ bool SolveSpace::GetOpenFile(char *file, const char *defExtension, const char *s
|
|||
|
||||
return r ? true : false;
|
||||
}
|
||||
|
||||
bool SolveSpace::GetSaveFile(char *file, const char *defExtension, const char *selPattern)
|
||||
{
|
||||
OPENFILENAME ofn;
|
||||
|
@ -905,6 +917,7 @@ bool SolveSpace::GetSaveFile(char *file, const char *defExtension, const char *s
|
|||
|
||||
return r ? true : false;
|
||||
}
|
||||
|
||||
int SolveSpace::SaveFileYesNoCancel(void)
|
||||
{
|
||||
EnableWindow(GraphicsWnd, false);
|
||||
|
@ -929,6 +942,28 @@ int SolveSpace::SaveFileYesNoCancel(void)
|
|||
return SAVE_CANCEL;
|
||||
}
|
||||
|
||||
int SolveSpace::LoadAutosaveYesNo(void)
|
||||
{
|
||||
EnableWindow(GraphicsWnd, false);
|
||||
EnableWindow(TextWnd, false);
|
||||
|
||||
int r = MessageBox(GraphicsWnd,
|
||||
"An autosave file is availible for this project.\r\n\r\n"
|
||||
"Do you want to load the autosave file instead?", "SolveSpace",
|
||||
MB_YESNO | MB_ICONWARNING);
|
||||
|
||||
EnableWindow(TextWnd, true);
|
||||
EnableWindow(GraphicsWnd, true);
|
||||
SetForegroundWindow(GraphicsWnd);
|
||||
|
||||
switch (r) {
|
||||
case IDYES: return SAVE_YES;
|
||||
case IDNO: return SAVE_NO;
|
||||
}
|
||||
|
||||
oops();
|
||||
}
|
||||
|
||||
void SolveSpace::LoadAllFontFiles(void)
|
||||
{
|
||||
WIN32_FIND_DATA wfd;
|
||||
|
|
Loading…
Reference in New Issue
Block a user