Ask the user to locate imported files if they cannot be loaded.

pull/4/head
whitequark 2016-01-11 12:18:18 +00:00
parent 54d8957bfe
commit 28a6e04f33
6 changed files with 165 additions and 45 deletions

View File

@ -791,7 +791,7 @@ bool SolveSpace::GetSaveFile(std::string &file, const std::string &defExtension,
} }
} }
int SolveSpace::SaveFileYesNoCancel(void) { SolveSpace::DialogChoice SolveSpace::SaveFileYesNoCancel(void) {
NSAlert *alert = [[NSAlert alloc] init]; NSAlert *alert = [[NSAlert alloc] init];
if(!std::string(SolveSpace::SS.saveFile).empty()) { if(!std::string(SolveSpace::SS.saveFile).empty()) {
[alert setMessageText: [alert setMessageText:
@ -809,16 +809,16 @@ int SolveSpace::SaveFileYesNoCancel(void) {
[alert addButtonWithTitle:@"Don't Save"]; [alert addButtonWithTitle:@"Don't Save"];
switch([alert runModal]) { switch([alert runModal]) {
case NSAlertFirstButtonReturn: case NSAlertFirstButtonReturn:
return SAVE_YES; return DIALOG_YES;
case NSAlertSecondButtonReturn: case NSAlertSecondButtonReturn:
return SAVE_CANCEL; default:
return DIALOG_CANCEL;
case NSAlertThirdButtonReturn: case NSAlertThirdButtonReturn:
return SAVE_NO; return DIALOG_NO;
} }
abort(); /* unreachable */
} }
int SolveSpace::LoadAutosaveYesNo(void) { SolveSpace::DialogChoice SolveSpace::LoadAutosaveYesNo(void) {
NSAlert *alert = [[NSAlert alloc] init]; NSAlert *alert = [[NSAlert alloc] init];
[alert setMessageText: [alert setMessageText:
@"An autosave file is availible for this project."]; @"An autosave file is availible for this project."];
@ -828,11 +828,37 @@ int SolveSpace::LoadAutosaveYesNo(void) {
[alert addButtonWithTitle:@"Don't Load"]; [alert addButtonWithTitle:@"Don't Load"];
switch([alert runModal]) { switch([alert runModal]) {
case NSAlertFirstButtonReturn: case NSAlertFirstButtonReturn:
return SAVE_YES; return DIALOG_YES;
case NSAlertSecondButtonReturn: case NSAlertSecondButtonReturn:
return SAVE_NO; default:
return DIALOG_NO;
}
}
SolveSpace::DialogChoice SolveSpace::LocateImportedFileYesNoCancel(
const std::string &filename, bool canCancel) {
NSAlert *alert = [[NSAlert alloc] init];
[alert setMessageText:[NSString stringWithUTF8String:
("The imported file " + filename + " is not present.").c_str()]];
[alert setInformativeText:
@"Do you want to locate it manually?\n"
"If you select \"No\", any geometry that depends on "
"the missing file will be removed."];
[alert addButtonWithTitle:@"Yes"];
if(canCancel)
[alert addButtonWithTitle:@"Cancel"];
[alert addButtonWithTitle:@"No"];
switch([alert runModal]) {
case NSAlertFirstButtonReturn:
return DIALOG_YES;
case NSAlertSecondButtonReturn:
default:
if(canCancel)
return DIALOG_CANCEL;
/* fallthrough */
case NSAlertThirdButtonReturn:
return DIALOG_NO;
} }
abort(); /* unreachable */
} }
/* Text window */ /* Text window */

View File

@ -765,8 +765,9 @@ static std::string PathSepUNIXToPlatform(const std::string &filename)
#endif #endif
} }
void SolveSpaceUI::ReloadAllImported(void) bool SolveSpaceUI::ReloadAllImported(bool canCancel)
{ {
std::map<std::string, std::string> importMap;
allConsistent = false; allConsistent = false;
int i; int i;
@ -785,6 +786,12 @@ void SolveSpaceUI::ReloadAllImported(void)
g->impMesh.Clear(); g->impMesh.Clear();
g->impShell.Clear(); g->impShell.Clear();
if(importMap.count(g->impFile)) {
std::string newPath = importMap[g->impFile];
if(!newPath.empty())
g->impFile = newPath;
}
FILE *test = ssfopen(g->impFile, "rb"); FILE *test = ssfopen(g->impFile, "rb");
if(test) { if(test) {
fclose(test); // okay, exists fclose(test); // okay, exists
@ -803,6 +810,7 @@ void SolveSpaceUI::ReloadAllImported(void)
} }
} }
try_load_file:
if(LoadEntitiesFromFile(g->impFile, &(g->impEntity), &(g->impMesh), &(g->impShell))) if(LoadEntitiesFromFile(g->impFile, &(g->impEntity), &(g->impMesh), &(g->impShell)))
{ {
if(!SS.saveFile.empty()) { if(!SS.saveFile.empty()) {
@ -816,9 +824,34 @@ void SolveSpaceUI::ReloadAllImported(void)
// is always nonempty when we are actually writing anything. // is always nonempty when we are actually writing anything.
g->impFileRel = g->impFile; g->impFileRel = g->impFile;
} }
} else if(!importMap.count(g->impFile)) {
switch(LocateImportedFileYesNoCancel(g->impFileRel, canCancel)) {
case DIALOG_YES: {
std::string oldImpFile = g->impFile;
if(!GetOpenFile(g->impFile, "", SLVS_PATTERN)) {
if(canCancel)
return false;
break;
} else { } else {
Error("Failed to load imported file '%s'", g->impFile.c_str()); importMap[oldImpFile] = g->impFile;
goto try_load_file;
} }
} }
case DIALOG_NO:
importMap[g->impFile] = "";
/* Geometry will be pruned by GenerateAll(). */
break;
case DIALOG_CANCEL:
return false;
}
} else {
// User was already asked to and refused to locate a missing
// imported file.
}
}
return true;
} }

View File

@ -1165,7 +1165,7 @@ bool GetSaveFile(std::string &file, const std::string &activeOrEmpty,
} }
} }
int SaveFileYesNoCancel(void) { DialogChoice SaveFileYesNoCancel(void) {
Glib::ustring message = Glib::ustring message =
"The file has changed since it was last saved.\n" "The file has changed since it was last saved.\n"
"Do you want to save the changes?"; "Do you want to save the changes?";
@ -1178,18 +1178,18 @@ int SaveFileYesNoCancel(void) {
switch(dialog.run()) { switch(dialog.run()) {
case Gtk::RESPONSE_YES: case Gtk::RESPONSE_YES:
return SAVE_YES; return DIALOG_YES;
case Gtk::RESPONSE_NO: case Gtk::RESPONSE_NO:
return SAVE_NO; return DIALOG_NO;
case Gtk::RESPONSE_CANCEL: case Gtk::RESPONSE_CANCEL:
default: default:
return SAVE_CANCEL; return DIALOG_CANCEL;
} }
} }
int LoadAutosaveYesNo(void) { DialogChoice LoadAutosaveYesNo(void) {
Glib::ustring message = Glib::ustring message =
"An autosave file is availible for this project.\n" "An autosave file is availible for this project.\n"
"Do you want to load the autosave file instead?"; "Do you want to load the autosave file instead?";
@ -1201,11 +1201,39 @@ int LoadAutosaveYesNo(void) {
switch(dialog.run()) { switch(dialog.run()) {
case Gtk::RESPONSE_YES: case Gtk::RESPONSE_YES:
return SAVE_YES; return DIALOG_YES;
case Gtk::RESPONSE_NO: case Gtk::RESPONSE_NO:
default: default:
return SAVE_NO; return DIALOG_NO;
}
}
DialogChoice LocateImportedFileYesNoCancel(const std::string &filename,
bool canCancel) {
Glib::ustring message =
"The imported file " + filename + " is not present.\n"
"Do you want to locate it manually?\n"
"If you select \"No\", any geometry that depends on "
"the missing file will be removed.";
Gtk::MessageDialog dialog(*GW, message, /*use_markup*/ true, Gtk::MESSAGE_QUESTION,
Gtk::BUTTONS_NONE, /*is_modal*/ true);
dialog.set_title("SolveSpace - Missing File");
dialog.add_button("_Yes", Gtk::RESPONSE_YES);
dialog.add_button("_No", Gtk::RESPONSE_NO);
if(canCancel)
dialog.add_button("_Cancel", Gtk::RESPONSE_CANCEL);
switch(dialog.run()) {
case Gtk::RESPONSE_YES:
return DIALOG_YES;
case Gtk::RESPONSE_NO:
return DIALOG_NO;
case Gtk::RESPONSE_CANCEL:
default:
return DIALOG_CANCEL;
} }
} }

View File

@ -110,7 +110,7 @@ bool SolveSpaceUI::LoadAutosaveFor(const std::string &filename) {
return false; return false;
fclose(f); fclose(f);
if(LoadAutosaveYesNo() == SAVE_YES) { if(LoadAutosaveYesNo() == DIALOG_YES) {
unsaved = true; unsaved = true;
return LoadFromFile(autosaveFile); return LoadFromFile(autosaveFile);
} }
@ -120,12 +120,15 @@ bool SolveSpaceUI::LoadAutosaveFor(const std::string &filename) {
bool SolveSpaceUI::OpenFile(const std::string &filename) { bool SolveSpaceUI::OpenFile(const std::string &filename) {
bool autosaveLoaded = LoadAutosaveFor(filename); bool autosaveLoaded = LoadAutosaveFor(filename);
bool success = autosaveLoaded || LoadFromFile(filename); bool fileLoaded = autosaveLoaded || LoadFromFile(filename);
if(fileLoaded)
saveFile = filename;
bool success = fileLoaded && ReloadAllImported(/*canCancel=*/true);
if(success) { if(success) {
RemoveAutosave(); RemoveAutosave();
AddToRecentList(filename); AddToRecentList(filename);
saveFile = filename;
} else { } else {
saveFile = "";
NewFile(); NewFile();
} }
AfterNewFile(); AfterNewFile();
@ -291,7 +294,6 @@ void SolveSpaceUI::AfterNewFile(void) {
SS.GW.projRight = Vector::From(1, 0, 0); SS.GW.projRight = Vector::From(1, 0, 0);
SS.GW.projUp = Vector::From(0, 1, 0); SS.GW.projUp = Vector::From(0, 1, 0);
ReloadAllImported();
GenerateAll(-1, -1); GenerateAll(-1, -1);
TW.Init(); TW.Init();
@ -386,13 +388,13 @@ bool SolveSpaceUI::OkayToStartNewFile(void) {
if(!unsaved) return true; if(!unsaved) return true;
switch(SaveFileYesNoCancel()) { switch(SaveFileYesNoCancel()) {
case SAVE_YES: case DIALOG_YES:
return GetFilenameAndSave(false); return GetFilenameAndSave(false);
case SAVE_NO: case DIALOG_NO:
return true; return true;
case SAVE_CANCEL: case DIALOG_CANCEL:
return false; return false;
default: oops(); break; default: oops(); break;
@ -415,7 +417,6 @@ void SolveSpaceUI::MenuFile(int id) {
if(!SS.OkayToStartNewFile()) return; if(!SS.OkayToStartNewFile()) return;
std::string newFile = RecentFile[id - RECENT_OPEN]; std::string newFile = RecentFile[id - RECENT_OPEN];
RemoveFromRecentList(newFile);
SS.OpenFile(newFile); SS.OpenFile(newFile);
return; return;
} }

View File

@ -19,6 +19,7 @@
#include <algorithm> #include <algorithm>
#include <string> #include <string>
#include <vector> #include <vector>
#include <map>
#ifdef HAVE_STDINT_H #ifdef HAVE_STDINT_H
# include <stdint.h> # include <stdint.h>
#endif #endif
@ -146,11 +147,11 @@ void ssremove(const std::string &filename);
extern std::string RecentFile[MAX_RECENT]; extern std::string RecentFile[MAX_RECENT];
void RefreshRecentMenus(void); void RefreshRecentMenus(void);
#define SAVE_YES (1) enum DialogChoice { DIALOG_YES = 1, DIALOG_NO = -1, DIALOG_CANCEL = 0 };
#define SAVE_NO (-1) DialogChoice SaveFileYesNoCancel(void);
#define SAVE_CANCEL (0) DialogChoice LoadAutosaveYesNo(void);
int SaveFileYesNoCancel(void); DialogChoice LocateImportedFileYesNoCancel(const std::string &filename,
int LoadAutosaveYesNo(void); bool canCancel);
#define AUTOSAVE_SUFFIX "~" #define AUTOSAVE_SUFFIX "~"
@ -851,7 +852,7 @@ public:
bool LoadFromFile(const std::string &filename); bool LoadFromFile(const std::string &filename);
bool LoadEntitiesFromFile(const std::string &filename, EntityList *le, bool LoadEntitiesFromFile(const std::string &filename, EntityList *le,
SMesh *m, SShell *sh); SMesh *m, SShell *sh);
void ReloadAllImported(void); bool ReloadAllImported(bool canCancel=false);
// And the various export options // And the various export options
void ExportAsPngTo(const std::string &filename); void ExportAsPngTo(const std::string &filename);
void ExportMeshTo(const std::string &filename); void ExportMeshTo(const std::string &filename);

View File

@ -1024,13 +1024,13 @@ bool SolveSpace::GetSaveFile(std::string &filename,
return OpenSaveFile(false, filename, defExtension, selPattern); return OpenSaveFile(false, filename, defExtension, selPattern);
} }
int SolveSpace::SaveFileYesNoCancel(void) DialogChoice SolveSpace::SaveFileYesNoCancel(void)
{ {
EnableWindow(GraphicsWnd, false); EnableWindow(GraphicsWnd, false);
EnableWindow(TextWnd, false); EnableWindow(TextWnd, false);
int r = MessageBoxW(GraphicsWnd, int r = MessageBoxW(GraphicsWnd,
L"The program has changed since it was last saved.\r\n\r\n" L"The file has changed since it was last saved.\n\n"
L"Do you want to save the changes?", L"SolveSpace", L"Do you want to save the changes?", L"SolveSpace",
MB_YESNOCANCEL | MB_ICONWARNING); MB_YESNOCANCEL | MB_ICONWARNING);
@ -1039,22 +1039,23 @@ int SolveSpace::SaveFileYesNoCancel(void)
SetForegroundWindow(GraphicsWnd); SetForegroundWindow(GraphicsWnd);
switch(r) { switch(r) {
case IDYES: return SAVE_YES; case IDYES:
case IDNO: return SAVE_NO; return DIALOG_YES;
case IDCANCEL: return SAVE_CANCEL; case IDNO:
return DIALOG_NO;
case IDCANCEL:
default:
return DIALOG_CANCEL;
} }
oops();
return SAVE_CANCEL;
} }
int SolveSpace::LoadAutosaveYesNo(void) DialogChoice SolveSpace::LoadAutosaveYesNo(void)
{ {
EnableWindow(GraphicsWnd, false); EnableWindow(GraphicsWnd, false);
EnableWindow(TextWnd, false); EnableWindow(TextWnd, false);
int r = MessageBoxW(GraphicsWnd, int r = MessageBoxW(GraphicsWnd,
L"An autosave file is availible for this project.\r\n\r\n" L"An autosave file is availible for this project.\n\n"
L"Do you want to load the autosave file instead?", L"SolveSpace", L"Do you want to load the autosave file instead?", L"SolveSpace",
MB_YESNO | MB_ICONWARNING); MB_YESNO | MB_ICONWARNING);
@ -1063,11 +1064,41 @@ int SolveSpace::LoadAutosaveYesNo(void)
SetForegroundWindow(GraphicsWnd); SetForegroundWindow(GraphicsWnd);
switch (r) { switch (r) {
case IDYES: return SAVE_YES; case IDYES:
case IDNO: return SAVE_NO; return DIALOG_YES;
case IDNO:
default:
return DIALOG_NO;
} }
}
oops(); DialogChoice SolveSpace::LocateImportedFileYesNoCancel(const std::string &filename,
bool canCancel) {
EnableWindow(GraphicsWnd, false);
EnableWindow(TextWnd, false);
std::string message =
"The imported file " + filename + " is not present.\n\n"
"Do you want to locate it manually?\n\n"
"If you select \"No\", any geometry that depends on "
"the missing file will be removed.";
int r = MessageBoxW(GraphicsWnd, Widen(message).c_str(), L"SolveSpace",
(canCancel ? MB_YESNOCANCEL : MB_YESNO) | MB_ICONWARNING);
EnableWindow(TextWnd, true);
EnableWindow(GraphicsWnd, true);
SetForegroundWindow(GraphicsWnd);
switch(r) {
case IDYES:
return DIALOG_YES;
case IDNO:
return DIALOG_NO;
case IDCANCEL:
default:
return DIALOG_CANCEL;
}
} }
void SolveSpace::LoadAllFontFiles(void) void SolveSpace::LoadAllFontFiles(void)