When exporting files, initially fill in the basename of the sketch.
This is a common and convenient behavior; the basename is pre-selected, so exporting multiple views requires just one keystroke to put the cursor after the basename.single-window
parent
e681ba3218
commit
802d092b13
|
@ -769,7 +769,6 @@ bool SolveSpace::GetSaveFile(std::string *file, const std::string &defExtension,
|
|||
[panel setAccessoryView:[controller view]];
|
||||
|
||||
NSMutableArray *extensions = [[NSMutableArray alloc] init];
|
||||
[controller setExtensions:extensions];
|
||||
|
||||
NSPopUpButton *button = [controller button];
|
||||
[button removeAllItems];
|
||||
|
@ -787,6 +786,8 @@ bool SolveSpace::GetSaveFile(std::string *file, const std::string &defExtension,
|
|||
[button addItemWithTitle:[NSString stringWithUTF8String:title.c_str()]];
|
||||
[extensions addObject:[NSString stringWithUTF8String:ssFilter->patterns[0]]];
|
||||
}
|
||||
[panel setAllowedFileTypes:extensions];
|
||||
[controller setExtensions:extensions];
|
||||
|
||||
int extensionIndex = 0;
|
||||
if(defExtension != "") {
|
||||
|
@ -796,10 +797,19 @@ bool SolveSpace::GetSaveFile(std::string *file, const std::string &defExtension,
|
|||
extensionIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
[button selectItemAtIndex:extensionIndex];
|
||||
[panel setNameFieldStringValue:[@"untitled"
|
||||
stringByAppendingPathExtension:[extensions objectAtIndex:extensionIndex]]];
|
||||
|
||||
if(file->empty()) {
|
||||
[panel setNameFieldStringValue:[@"untitled"
|
||||
stringByAppendingPathExtension:[extensions objectAtIndex:extensionIndex]]];
|
||||
} else {
|
||||
[panel setDirectoryURL:
|
||||
[NSURL fileURLWithPath:[NSString stringWithUTF8String:Dirname(*file).c_str()]
|
||||
isDirectory:NO]];
|
||||
[panel setNameFieldStringValue:
|
||||
[[NSString stringWithUTF8String:Basename(*file, /*stripExtension=*/true).c_str()]
|
||||
stringByAppendingPathExtension:[extensions objectAtIndex:extensionIndex]]];
|
||||
}
|
||||
|
||||
if([panel runModal] == NSFileHandlingPanelOKButton) {
|
||||
*file = [[NSFileManager defaultManager]
|
||||
|
|
|
@ -1113,14 +1113,6 @@ bool GetOpenFile(std::string *filename, const std::string &activeOrEmpty,
|
|||
}
|
||||
}
|
||||
|
||||
/* Glib::path_get_basename got /removed/ in 3.0?! Come on */
|
||||
static std::string Basename(std::string filename) {
|
||||
int slash = filename.rfind('/');
|
||||
if(slash >= 0)
|
||||
return filename.substr(slash + 1, filename.length());
|
||||
return "";
|
||||
}
|
||||
|
||||
static void ChooserFilterChanged(Gtk::FileChooserDialog *chooser)
|
||||
{
|
||||
/* Extract the pattern from the filter. GtkFileFilter doesn't provide
|
||||
|
@ -1150,7 +1142,7 @@ static void ChooserFilterChanged(Gtk::FileChooserDialog *chooser)
|
|||
}
|
||||
}
|
||||
|
||||
bool GetSaveFile(std::string *filename, const std::string &activeOrEmpty,
|
||||
bool GetSaveFile(std::string *filename, const std::string &defExtension,
|
||||
const FileFilter filters[]) {
|
||||
Gtk::FileChooserDialog chooser(*GW, "SolveSpace - Save File",
|
||||
Gtk::FILE_CHOOSER_ACTION_SAVE);
|
||||
|
@ -1158,10 +1150,16 @@ bool GetSaveFile(std::string *filename, const std::string &activeOrEmpty,
|
|||
chooser.add_button("_Cancel", Gtk::RESPONSE_CANCEL);
|
||||
chooser.add_button("_Save", Gtk::RESPONSE_OK);
|
||||
|
||||
std::string active = ConvertFilters(activeOrEmpty, filters, &chooser);
|
||||
std::string activeExtension = ConvertFilters(defExtension, filters, &chooser);
|
||||
|
||||
chooser.set_current_folder(CnfThawString("", "FileChooserPath"));
|
||||
chooser.set_current_name(std::string("untitled.") + active);
|
||||
if(filename->empty()) {
|
||||
chooser.set_current_folder(CnfThawString("", "FileChooserPath"));
|
||||
chooser.set_current_name("untitled." + activeExtension);
|
||||
} else {
|
||||
chooser.set_current_folder(Dirname(*filename));
|
||||
chooser.set_current_name(Basename(*filename, /*stripExtension=*/true) +
|
||||
"." + activeExtension);
|
||||
}
|
||||
|
||||
/* Gtk's dialog doesn't change the extension when you change the filter,
|
||||
and makes it extremely hard to do so. Gtk is garbage. */
|
||||
|
|
|
@ -996,16 +996,28 @@ static std::string ConvertFilters(const FileFilter ssFilters[]) {
|
|||
|
||||
static bool OpenSaveFile(bool isOpen, std::string *filename, const std::string &defExtension,
|
||||
const FileFilter filters[]) {
|
||||
std::string activeExtension = defExtension;
|
||||
if(activeExtension == "") {
|
||||
activeExtension = filters[0].patterns[0];
|
||||
}
|
||||
|
||||
std::wstring initialFilenameW;
|
||||
if(filename->empty()) {
|
||||
initialFilenameW = Widen("untitled");
|
||||
} else {
|
||||
initialFilenameW = Widen(Dirname(*filename) + PATH_SEP +
|
||||
Basename(*filename, /*stripExtension=*/true));
|
||||
}
|
||||
std::wstring selPatternW = Widen(ConvertFilters(filters));
|
||||
std::wstring defExtensionW = Widen(defExtension);
|
||||
|
||||
// UNC paths may be as long as 32767 characters.
|
||||
// Unfortunately, the Get*FileName API does not provide any way to use it
|
||||
// except with a preallocated buffer of fixed size, so we use something
|
||||
// reasonably large.
|
||||
const int len = 32768;
|
||||
wchar_t filenameC[len] = {};
|
||||
wcsncpy(filenameC, Widen(*filename).c_str(), len - 1);
|
||||
|
||||
std::wstring selPatternW = Widen(ConvertFilters(filters));
|
||||
std::wstring defExtensionW = Widen(defExtension);
|
||||
wcsncpy(filenameC, initialFilenameW.c_str(), len - 1);
|
||||
|
||||
OPENFILENAME ofn = {};
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
|
|
|
@ -417,16 +417,6 @@ void SolveSpaceUI::UpdateWindowTitle() {
|
|||
SetCurrentFilename(saveFile);
|
||||
}
|
||||
|
||||
static std::string Extension(const std::string &filename) {
|
||||
int dot = filename.rfind('.');
|
||||
if(dot >= 0) {
|
||||
std::string ext = filename.substr(dot + 1, filename.length());
|
||||
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
|
||||
return ext;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void SolveSpaceUI::MenuFile(Command id) {
|
||||
if((uint32_t)id >= (uint32_t)Command::RECENT_OPEN &&
|
||||
(uint32_t)id < ((uint32_t)Command::RECENT_OPEN+MAX_RECENT)) {
|
||||
|
@ -465,14 +455,14 @@ void SolveSpaceUI::MenuFile(Command id) {
|
|||
break;
|
||||
|
||||
case Command::EXPORT_PNG: {
|
||||
std::string exportFile;
|
||||
std::string exportFile = SS.saveFile;
|
||||
if(!GetSaveFile(&exportFile, "", PngFileFilter)) break;
|
||||
SS.ExportAsPngTo(exportFile);
|
||||
break;
|
||||
}
|
||||
|
||||
case Command::EXPORT_VIEW: {
|
||||
std::string exportFile;
|
||||
std::string exportFile = SS.saveFile;
|
||||
if(!GetSaveFile(&exportFile, CnfThawString("", "ViewExportFormat"),
|
||||
VectorFileFilter)) break;
|
||||
CnfFreezeString(Extension(exportFile), "ViewExportFormat");
|
||||
|
@ -494,7 +484,7 @@ void SolveSpaceUI::MenuFile(Command id) {
|
|||
}
|
||||
|
||||
case Command::EXPORT_WIREFRAME: {
|
||||
std::string exportFile;
|
||||
std::string exportFile = SS.saveFile;
|
||||
if(!GetSaveFile(&exportFile, CnfThawString("", "WireframeExportFormat"),
|
||||
Vector3dFileFilter)) break;
|
||||
CnfFreezeString(Extension(exportFile), "WireframeExportFormat");
|
||||
|
@ -504,7 +494,7 @@ void SolveSpaceUI::MenuFile(Command id) {
|
|||
}
|
||||
|
||||
case Command::EXPORT_SECTION: {
|
||||
std::string exportFile;
|
||||
std::string exportFile = SS.saveFile;
|
||||
if(!GetSaveFile(&exportFile, CnfThawString("", "SectionExportFormat"),
|
||||
VectorFileFilter)) break;
|
||||
CnfFreezeString(Extension(exportFile), "SectionExportFormat");
|
||||
|
@ -514,7 +504,7 @@ void SolveSpaceUI::MenuFile(Command id) {
|
|||
}
|
||||
|
||||
case Command::EXPORT_MESH: {
|
||||
std::string exportFile;
|
||||
std::string exportFile = SS.saveFile;
|
||||
if(!GetSaveFile(&exportFile, CnfThawString("", "MeshExportFormat"),
|
||||
MeshFileFilter)) break;
|
||||
CnfFreezeString(Extension(exportFile), "MeshExportFormat");
|
||||
|
@ -524,7 +514,7 @@ void SolveSpaceUI::MenuFile(Command id) {
|
|||
}
|
||||
|
||||
case Command::EXPORT_SURFACES: {
|
||||
std::string exportFile;
|
||||
std::string exportFile = SS.saveFile;
|
||||
if(!GetSaveFile(&exportFile, CnfThawString("", "SurfacesExportFormat"),
|
||||
SurfaceFileFilter)) break;
|
||||
CnfFreezeString(Extension(exportFile), "SurfacesExportFormat");
|
||||
|
@ -759,7 +749,7 @@ void SolveSpaceUI::MenuAnalyze(Command id) {
|
|||
break;
|
||||
|
||||
case Command::STOP_TRACING: {
|
||||
std::string exportFile;
|
||||
std::string exportFile = SS.saveFile;
|
||||
if(GetSaveFile(&exportFile, "", CsvFileFilter)) {
|
||||
FILE *f = ssfopen(exportFile, "wb");
|
||||
if(f) {
|
||||
|
|
|
@ -367,6 +367,9 @@ void MakeMatrix(double *mat, double a11, double a12, double a13, double a14,
|
|||
double a41, double a42, double a43, double a44);
|
||||
std::string MakeAcceleratorLabel(int accel);
|
||||
bool FilenameHasExtension(const std::string &str, const char *ext);
|
||||
std::string Extension(const std::string &filename);
|
||||
std::string Basename(std::string filename, bool stripExtension = false);
|
||||
std::string Dirname(std::string filename);
|
||||
bool ReadFile(const std::string &filename, std::string *data);
|
||||
bool WriteFile(const std::string &filename, const std::string &data);
|
||||
void Message(const char *str, ...);
|
||||
|
|
36
src/util.cpp
36
src/util.cpp
|
@ -62,6 +62,42 @@ bool SolveSpace::FilenameHasExtension(const std::string &str, const char *ext)
|
|||
return true;
|
||||
}
|
||||
|
||||
std::string SolveSpace::Extension(const std::string &filename) {
|
||||
int dot = filename.rfind('.');
|
||||
if(dot >= 0) {
|
||||
std::string ext = filename.substr(dot + 1, filename.length());
|
||||
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
|
||||
return ext;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string SolveSpace::Basename(std::string filename, bool stripExtension) {
|
||||
int slash = filename.rfind(PATH_SEP);
|
||||
if(slash >= 0) {
|
||||
filename = filename.substr(slash + 1, filename.length());
|
||||
}
|
||||
|
||||
if(stripExtension) {
|
||||
int dot = filename.rfind('.');
|
||||
if(dot >= 0) {
|
||||
filename = filename.substr(0, dot);
|
||||
}
|
||||
}
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
std::string SolveSpace::Dirname(std::string filename) {
|
||||
int slash = filename.rfind(PATH_SEP);
|
||||
if(slash >= 0) {
|
||||
return filename.substr(0, slash);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
bool SolveSpace::ReadFile(const std::string &filename, std::string *data)
|
||||
{
|
||||
FILE *f = ssfopen(filename.c_str(), "rb");
|
||||
|
|
Loading…
Reference in New Issue