Ask the user to locate imported files if they cannot be loaded.
parent
54d8957bfe
commit
28a6e04f33
|
@ -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 */
|
||||||
|
|
39
src/file.cpp
39
src/file.cpp
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
DialogChoice SolveSpace::LoadAutosaveYesNo(void)
|
||||||
return SAVE_CANCEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int 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)
|
||||||
|
|
Loading…
Reference in New Issue