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.
This commit is contained in:
parent
e681ba3218
commit
802d092b13
|
@ -769,7 +769,6 @@ bool SolveSpace::GetSaveFile(std::string *file, const std::string &defExtension,
|
||||||
[panel setAccessoryView:[controller view]];
|
[panel setAccessoryView:[controller view]];
|
||||||
|
|
||||||
NSMutableArray *extensions = [[NSMutableArray alloc] init];
|
NSMutableArray *extensions = [[NSMutableArray alloc] init];
|
||||||
[controller setExtensions:extensions];
|
|
||||||
|
|
||||||
NSPopUpButton *button = [controller button];
|
NSPopUpButton *button = [controller button];
|
||||||
[button removeAllItems];
|
[button removeAllItems];
|
||||||
|
@ -787,6 +786,8 @@ bool SolveSpace::GetSaveFile(std::string *file, const std::string &defExtension,
|
||||||
[button addItemWithTitle:[NSString stringWithUTF8String:title.c_str()]];
|
[button addItemWithTitle:[NSString stringWithUTF8String:title.c_str()]];
|
||||||
[extensions addObject:[NSString stringWithUTF8String:ssFilter->patterns[0]]];
|
[extensions addObject:[NSString stringWithUTF8String:ssFilter->patterns[0]]];
|
||||||
}
|
}
|
||||||
|
[panel setAllowedFileTypes:extensions];
|
||||||
|
[controller setExtensions:extensions];
|
||||||
|
|
||||||
int extensionIndex = 0;
|
int extensionIndex = 0;
|
||||||
if(defExtension != "") {
|
if(defExtension != "") {
|
||||||
|
@ -796,10 +797,19 @@ bool SolveSpace::GetSaveFile(std::string *file, const std::string &defExtension,
|
||||||
extensionIndex = 0;
|
extensionIndex = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[button selectItemAtIndex:extensionIndex];
|
[button selectItemAtIndex:extensionIndex];
|
||||||
|
|
||||||
|
if(file->empty()) {
|
||||||
[panel setNameFieldStringValue:[@"untitled"
|
[panel setNameFieldStringValue:[@"untitled"
|
||||||
stringByAppendingPathExtension:[extensions objectAtIndex:extensionIndex]]];
|
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) {
|
if([panel runModal] == NSFileHandlingPanelOKButton) {
|
||||||
*file = [[NSFileManager defaultManager]
|
*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)
|
static void ChooserFilterChanged(Gtk::FileChooserDialog *chooser)
|
||||||
{
|
{
|
||||||
/* Extract the pattern from the filter. GtkFileFilter doesn't provide
|
/* 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[]) {
|
const FileFilter filters[]) {
|
||||||
Gtk::FileChooserDialog chooser(*GW, "SolveSpace - Save File",
|
Gtk::FileChooserDialog chooser(*GW, "SolveSpace - Save File",
|
||||||
Gtk::FILE_CHOOSER_ACTION_SAVE);
|
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("_Cancel", Gtk::RESPONSE_CANCEL);
|
||||||
chooser.add_button("_Save", Gtk::RESPONSE_OK);
|
chooser.add_button("_Save", Gtk::RESPONSE_OK);
|
||||||
|
|
||||||
std::string active = ConvertFilters(activeOrEmpty, filters, &chooser);
|
std::string activeExtension = ConvertFilters(defExtension, filters, &chooser);
|
||||||
|
|
||||||
|
if(filename->empty()) {
|
||||||
chooser.set_current_folder(CnfThawString("", "FileChooserPath"));
|
chooser.set_current_folder(CnfThawString("", "FileChooserPath"));
|
||||||
chooser.set_current_name(std::string("untitled.") + active);
|
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,
|
/* Gtk's dialog doesn't change the extension when you change the filter,
|
||||||
and makes it extremely hard to do so. Gtk is garbage. */
|
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,
|
static bool OpenSaveFile(bool isOpen, std::string *filename, const std::string &defExtension,
|
||||||
const FileFilter filters[]) {
|
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.
|
// UNC paths may be as long as 32767 characters.
|
||||||
// Unfortunately, the Get*FileName API does not provide any way to use it
|
// 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
|
// except with a preallocated buffer of fixed size, so we use something
|
||||||
// reasonably large.
|
// reasonably large.
|
||||||
const int len = 32768;
|
const int len = 32768;
|
||||||
wchar_t filenameC[len] = {};
|
wchar_t filenameC[len] = {};
|
||||||
wcsncpy(filenameC, Widen(*filename).c_str(), len - 1);
|
wcsncpy(filenameC, initialFilenameW.c_str(), len - 1);
|
||||||
|
|
||||||
std::wstring selPatternW = Widen(ConvertFilters(filters));
|
|
||||||
std::wstring defExtensionW = Widen(defExtension);
|
|
||||||
|
|
||||||
OPENFILENAME ofn = {};
|
OPENFILENAME ofn = {};
|
||||||
ofn.lStructSize = sizeof(ofn);
|
ofn.lStructSize = sizeof(ofn);
|
||||||
|
|
|
@ -417,16 +417,6 @@ void SolveSpaceUI::UpdateWindowTitle() {
|
||||||
SetCurrentFilename(saveFile);
|
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) {
|
void SolveSpaceUI::MenuFile(Command id) {
|
||||||
if((uint32_t)id >= (uint32_t)Command::RECENT_OPEN &&
|
if((uint32_t)id >= (uint32_t)Command::RECENT_OPEN &&
|
||||||
(uint32_t)id < ((uint32_t)Command::RECENT_OPEN+MAX_RECENT)) {
|
(uint32_t)id < ((uint32_t)Command::RECENT_OPEN+MAX_RECENT)) {
|
||||||
|
@ -465,14 +455,14 @@ void SolveSpaceUI::MenuFile(Command id) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Command::EXPORT_PNG: {
|
case Command::EXPORT_PNG: {
|
||||||
std::string exportFile;
|
std::string exportFile = SS.saveFile;
|
||||||
if(!GetSaveFile(&exportFile, "", PngFileFilter)) break;
|
if(!GetSaveFile(&exportFile, "", PngFileFilter)) break;
|
||||||
SS.ExportAsPngTo(exportFile);
|
SS.ExportAsPngTo(exportFile);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Command::EXPORT_VIEW: {
|
case Command::EXPORT_VIEW: {
|
||||||
std::string exportFile;
|
std::string exportFile = SS.saveFile;
|
||||||
if(!GetSaveFile(&exportFile, CnfThawString("", "ViewExportFormat"),
|
if(!GetSaveFile(&exportFile, CnfThawString("", "ViewExportFormat"),
|
||||||
VectorFileFilter)) break;
|
VectorFileFilter)) break;
|
||||||
CnfFreezeString(Extension(exportFile), "ViewExportFormat");
|
CnfFreezeString(Extension(exportFile), "ViewExportFormat");
|
||||||
|
@ -494,7 +484,7 @@ void SolveSpaceUI::MenuFile(Command id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case Command::EXPORT_WIREFRAME: {
|
case Command::EXPORT_WIREFRAME: {
|
||||||
std::string exportFile;
|
std::string exportFile = SS.saveFile;
|
||||||
if(!GetSaveFile(&exportFile, CnfThawString("", "WireframeExportFormat"),
|
if(!GetSaveFile(&exportFile, CnfThawString("", "WireframeExportFormat"),
|
||||||
Vector3dFileFilter)) break;
|
Vector3dFileFilter)) break;
|
||||||
CnfFreezeString(Extension(exportFile), "WireframeExportFormat");
|
CnfFreezeString(Extension(exportFile), "WireframeExportFormat");
|
||||||
|
@ -504,7 +494,7 @@ void SolveSpaceUI::MenuFile(Command id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case Command::EXPORT_SECTION: {
|
case Command::EXPORT_SECTION: {
|
||||||
std::string exportFile;
|
std::string exportFile = SS.saveFile;
|
||||||
if(!GetSaveFile(&exportFile, CnfThawString("", "SectionExportFormat"),
|
if(!GetSaveFile(&exportFile, CnfThawString("", "SectionExportFormat"),
|
||||||
VectorFileFilter)) break;
|
VectorFileFilter)) break;
|
||||||
CnfFreezeString(Extension(exportFile), "SectionExportFormat");
|
CnfFreezeString(Extension(exportFile), "SectionExportFormat");
|
||||||
|
@ -514,7 +504,7 @@ void SolveSpaceUI::MenuFile(Command id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case Command::EXPORT_MESH: {
|
case Command::EXPORT_MESH: {
|
||||||
std::string exportFile;
|
std::string exportFile = SS.saveFile;
|
||||||
if(!GetSaveFile(&exportFile, CnfThawString("", "MeshExportFormat"),
|
if(!GetSaveFile(&exportFile, CnfThawString("", "MeshExportFormat"),
|
||||||
MeshFileFilter)) break;
|
MeshFileFilter)) break;
|
||||||
CnfFreezeString(Extension(exportFile), "MeshExportFormat");
|
CnfFreezeString(Extension(exportFile), "MeshExportFormat");
|
||||||
|
@ -524,7 +514,7 @@ void SolveSpaceUI::MenuFile(Command id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case Command::EXPORT_SURFACES: {
|
case Command::EXPORT_SURFACES: {
|
||||||
std::string exportFile;
|
std::string exportFile = SS.saveFile;
|
||||||
if(!GetSaveFile(&exportFile, CnfThawString("", "SurfacesExportFormat"),
|
if(!GetSaveFile(&exportFile, CnfThawString("", "SurfacesExportFormat"),
|
||||||
SurfaceFileFilter)) break;
|
SurfaceFileFilter)) break;
|
||||||
CnfFreezeString(Extension(exportFile), "SurfacesExportFormat");
|
CnfFreezeString(Extension(exportFile), "SurfacesExportFormat");
|
||||||
|
@ -759,7 +749,7 @@ void SolveSpaceUI::MenuAnalyze(Command id) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Command::STOP_TRACING: {
|
case Command::STOP_TRACING: {
|
||||||
std::string exportFile;
|
std::string exportFile = SS.saveFile;
|
||||||
if(GetSaveFile(&exportFile, "", CsvFileFilter)) {
|
if(GetSaveFile(&exportFile, "", CsvFileFilter)) {
|
||||||
FILE *f = ssfopen(exportFile, "wb");
|
FILE *f = ssfopen(exportFile, "wb");
|
||||||
if(f) {
|
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);
|
double a41, double a42, double a43, double a44);
|
||||||
std::string MakeAcceleratorLabel(int accel);
|
std::string MakeAcceleratorLabel(int accel);
|
||||||
bool FilenameHasExtension(const std::string &str, const char *ext);
|
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 ReadFile(const std::string &filename, std::string *data);
|
||||||
bool WriteFile(const std::string &filename, const std::string &data);
|
bool WriteFile(const std::string &filename, const std::string &data);
|
||||||
void Message(const char *str, ...);
|
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;
|
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)
|
bool SolveSpace::ReadFile(const std::string &filename, std::string *data)
|
||||||
{
|
{
|
||||||
FILE *f = ssfopen(filename.c_str(), "rb");
|
FILE *f = ssfopen(filename.c_str(), "rb");
|
||||||
|
|
Loading…
Reference in New Issue
Block a user