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
whitequark 2016-11-17 12:21:41 +00:00
parent e681ba3218
commit 802d092b13
6 changed files with 86 additions and 37 deletions

View File

@ -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]

View File

@ -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. */

View File

@ -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);

View File

@ -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) {

View File

@ -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, ...);

View File

@ -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");