kopia lustrzana https://github.com/jamescoxon/dl-fldigi
340 wiersze
9.1 KiB
C++
340 wiersze
9.1 KiB
C++
// ----------------------------------------------------------------------------
|
|
//
|
|
// fileselect.cxx -- file selector front end
|
|
//
|
|
// Copyright (C) 2008-2009
|
|
// Stelios Bounanos, M0GLD
|
|
// Dave Freese, 2015
|
|
//
|
|
// This file is part of fldigi.
|
|
//
|
|
// Fldigi is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Fldigi is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with fldigi. If not, see <http://www.gnu.org/licenses/>.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#include <string>
|
|
#include <cstdlib>
|
|
#include <libgen.h>
|
|
|
|
#include <FL/fl_ask.H>
|
|
#include <FL/Fl_Native_File_Chooser.H>
|
|
|
|
#include "config.h"
|
|
|
|
#include "fileselect.h"
|
|
#include "debug.h"
|
|
#include "qrunner.h"
|
|
|
|
/**
|
|
\class Fl_Native_File_Chooser
|
|
|
|
This class lets an FLTK application easily and consistently access
|
|
the operating system's native file chooser. Some operating systems
|
|
have very complex and specific file choosers that many users want
|
|
access to specifically, instead of FLTK's default file chooser(s).
|
|
|
|
In cases where there is no native file browser, FLTK's own file browser
|
|
is used instead.
|
|
|
|
To use this widget correctly, use the following include in your code:
|
|
\code
|
|
#include <FL/Fl_Native_File_Chooser.H>
|
|
\endcode
|
|
Do not include the other Fl_Native_File_Choser_XXX.H files in your code;
|
|
those are platform specific files that will be included automatically
|
|
depending on your build platform.
|
|
|
|
The following example shows how to pick a single file:
|
|
\code
|
|
// Create and post the local native file chooser
|
|
#include <FL/Fl_Native_File_Chooser.H>
|
|
[..]
|
|
Fl_Native_File_Chooser fnfc;
|
|
fnfc.title("Pick a file");
|
|
fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE);
|
|
fnfc.filter("Text\t*.txt\n"
|
|
"C Files\t*.{cxx,h,c}");
|
|
fnfc.directory("/var/tmp"); // default directory to use
|
|
// Show native chooser
|
|
switch ( fnfc.show() ) {
|
|
case -1: printf("ERROR: %s\n", fnfc.errmsg()); break; // ERROR
|
|
case 1: printf("CANCEL\n"); break; // CANCEL
|
|
default: printf("PICKED: %s\n", fnfc.filename()); break; // FILE CHOSEN
|
|
}
|
|
\endcode
|
|
|
|
<B>Platform Specific Caveats</B>
|
|
|
|
- Under X windows, it's best if you call Fl_File_Icon::load_system_icons()
|
|
at the start of main(), to enable the nicer looking file browser widgets.
|
|
Use the static public attributes of class Fl_File_Chooser to localize
|
|
the browser.
|
|
- Some operating systems support certain OS specific options; see
|
|
Fl_Native_File_Chooser::options() for a list.
|
|
|
|
\image html Fl_Native_File_Chooser.png "The Fl_Native_File_Chooser on different platforms."
|
|
\image latex Fl_Native_File_Chooser.png "The Fl_Native_File_Chooser on different platforms" width=14cm
|
|
|
|
enum Type {
|
|
BROWSE_FILE = 0, ///< browse files (lets user choose one file)
|
|
BROWSE_DIRECTORY, ///< browse directories (lets user choose one directory)
|
|
BROWSE_MULTI_FILE, ///< browse files (lets user choose multiple files)
|
|
BROWSE_MULTI_DIRECTORY, ///< browse directories (lets user choose multiple directories)
|
|
BROWSE_SAVE_FILE, ///< browse to save a file
|
|
BROWSE_SAVE_DIRECTORY ///< browse to save a directory
|
|
};
|
|
enum Option {
|
|
NO_OPTIONS = 0x0000, ///< no options enabled
|
|
SAVEAS_CONFIRM = 0x0001, ///< Show native 'Save As' overwrite confirm dialog (if supported)
|
|
NEW_FOLDER = 0x0002, ///< Show 'New Folder' icon (if supported)
|
|
PREVIEW = 0x0004 ///< enable preview mode
|
|
};
|
|
|
|
IMPORTANT NOTICE:
|
|
|
|
The filter type must be terminated with a '\n' on OS X or the application crashes with a Bus timeout
|
|
|
|
*/
|
|
|
|
using namespace std;
|
|
|
|
namespace FSEL {
|
|
|
|
void create(void) {};
|
|
void destroy(void) {};
|
|
|
|
string filename, stitle, sfilter, sdef, sdirectory;
|
|
char dirbuf[FL_PATH_MAX + 1] = "";
|
|
char msg[400];
|
|
|
|
// use this function for testing on garbage OS, aka Windows
|
|
/*
|
|
void pfile (const char *dir, const char *fname, const char *filt) {
|
|
char fn[FL_PATH_MAX+1];
|
|
#ifdef __WIN32__
|
|
fl_filename_expand(fn, sizeof(fn) -1, "$USERPROFILE/");
|
|
#else
|
|
fl_filename_expand(fn, sizeof(fn) -1, "$HOME/");
|
|
#endif
|
|
strcat(fn, "pfile.txt");
|
|
FILE *f = fopen(fn, "a");
|
|
fprintf(f,"\
|
|
dir: %s\n\
|
|
file: %s\n\
|
|
filter: %s\n", dir, fname, filt);
|
|
fclose(f);
|
|
}
|
|
*/
|
|
|
|
void dosfname(string &s)
|
|
{
|
|
for (size_t i = 0; i < s.length(); i++)
|
|
if (s[i] == '/') s[i] = '\\';
|
|
}
|
|
|
|
const char* select(const char* title, const char* filter, const char* def, int* fsel)
|
|
{
|
|
if (strlen(dirbuf) == 0) {
|
|
#ifdef __WIN32__
|
|
fl_filename_expand(dirbuf, sizeof(dirbuf) -1, "$USERPROFILE/");
|
|
#else
|
|
fl_filename_expand(dirbuf, sizeof(dirbuf) -1, "$HOME/");
|
|
#endif
|
|
}
|
|
|
|
size_t p = 0;
|
|
Fl_Native_File_Chooser native;
|
|
|
|
stitle.clear();
|
|
sfilter.clear();
|
|
sdef.clear();
|
|
sdirectory.clear();
|
|
|
|
if (title) stitle.assign(title);
|
|
if (filter) sfilter.assign(filter);
|
|
|
|
if (def) {
|
|
sdef.assign(def);
|
|
if (!sdef.empty()) {
|
|
p = sdef.length() - 1;
|
|
if ((sdef[p] == '/') || (sdef[p] == '\\')) sdef.append("fname");
|
|
}
|
|
sdirectory.assign(sdef);
|
|
p = sdirectory.rfind(fl_filename_name(sdef.c_str()));
|
|
sdirectory.erase(p);
|
|
}
|
|
if (sdirectory.empty()) {
|
|
sdirectory.assign(dirbuf);
|
|
}
|
|
if (sdef.empty()) {
|
|
sdef.assign(sdirectory);
|
|
sdef.append("temp");
|
|
}
|
|
|
|
if (!sfilter.empty()) {
|
|
if (sfilter[sfilter.length()-1] != '\n') sfilter += '\n';
|
|
native.filter(sfilter.c_str());
|
|
}
|
|
native.title(stitle.c_str());
|
|
#if __WIN32__
|
|
dosfname(sdef);
|
|
dosfname(sdirectory);
|
|
#endif
|
|
if (!sdef.empty()) native.preset_file(sdef.c_str());
|
|
if (!sdirectory.empty()) native.directory(sdirectory.c_str());
|
|
|
|
native.type(Fl_Native_File_Chooser::BROWSE_FILE);
|
|
native.options(Fl_Native_File_Chooser::PREVIEW);
|
|
|
|
// pfile(sdirectory.c_str(), sdef.c_str(), sfilter.c_str());
|
|
|
|
filename.clear();
|
|
switch ( native.show() ) {
|
|
case -1:
|
|
LOG_ERROR("ERROR: %s\n", native.errmsg()); // Error fall through
|
|
case 1:
|
|
return 0;
|
|
break;
|
|
default:
|
|
if ( native.filename() ) {
|
|
filename = native.filename();
|
|
} else {
|
|
filename = "";
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (fsel)
|
|
*fsel = native.filter_value();
|
|
|
|
return filename.c_str();
|
|
}
|
|
|
|
const char* saveas(const char* title, const char* filter, const char* def, int* fsel)
|
|
{
|
|
if (strlen(dirbuf) == 0) {
|
|
#ifdef __WIN32__
|
|
fl_filename_expand(dirbuf, sizeof(dirbuf) -1, "$USERPROFILE/");
|
|
#else
|
|
fl_filename_expand(dirbuf, sizeof(dirbuf) -1, "$HOME/");
|
|
#endif
|
|
}
|
|
|
|
size_t p = 0;
|
|
Fl_Native_File_Chooser native;
|
|
|
|
stitle.clear();
|
|
sfilter.clear();
|
|
sdef.clear();
|
|
sdirectory.clear();
|
|
|
|
if (title) stitle.assign(title);
|
|
if (filter) sfilter.assign(filter);
|
|
|
|
if (def) {
|
|
sdef.assign(def);
|
|
if (!sdef.empty()) {
|
|
p = sdef.length() - 1;
|
|
if ((sdef[p] == '/') || (sdef[p] == '\\')) sdef.append("fname");
|
|
}
|
|
sdirectory.assign(sdef);
|
|
p = sdirectory.rfind(fl_filename_name(sdef.c_str()));
|
|
sdirectory.erase(p);
|
|
}
|
|
if (sdirectory.empty()) {
|
|
sdirectory.assign(dirbuf);
|
|
}
|
|
if (sdef.empty()) {
|
|
sdef.assign(sdirectory);
|
|
sdef.append("temp");
|
|
}
|
|
|
|
if (!sfilter.empty()) {
|
|
if (sfilter[sfilter.length()-1] != '\n') sfilter += '\n';
|
|
native.filter(sfilter.c_str());
|
|
}
|
|
native.title(stitle.c_str());
|
|
#if __WIN32__
|
|
dosfname(sdef);
|
|
dosfname(sdirectory);
|
|
#endif
|
|
if (!sdef.empty()) native.preset_file(sdef.c_str());
|
|
if (!sdirectory.empty()) native.directory(sdirectory.c_str());
|
|
native.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
|
|
native.options(Fl_Native_File_Chooser::NEW_FOLDER || Fl_Native_File_Chooser::SAVEAS_CONFIRM);
|
|
|
|
// pfile(sdirectory.c_str(), sdef.c_str(), sfilter.c_str());
|
|
|
|
filename.clear();
|
|
switch ( native.show() ) {
|
|
case -1: LOG_ERROR("ERROR: %s\n", native.errmsg()); break; // ERROR
|
|
case 1: break; // CANCEL
|
|
default:
|
|
if ( native.filename() ) {
|
|
filename = native.filename();
|
|
} else {
|
|
filename = "";
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (fsel)
|
|
*fsel = native.filter_value();
|
|
|
|
return filename.c_str();
|
|
|
|
}
|
|
|
|
const char* dir_select(const char* title, const char* filter, const char* def)
|
|
{
|
|
Fl_Native_File_Chooser native;
|
|
|
|
stitle.clear();
|
|
sfilter.clear();
|
|
sdef.clear();
|
|
if (title) stitle.assign(title);
|
|
if (filter) sfilter.assign(filter);
|
|
if (def) sdef.assign(def);
|
|
if (!sfilter.empty() && sfilter[sfilter.length()-1] != '\n') sfilter += '\n';
|
|
|
|
if (!stitle.empty()) native.title(stitle.c_str());
|
|
native.type(Fl_Native_File_Chooser::BROWSE_DIRECTORY);
|
|
if (!sfilter.empty()) native.filter(sfilter.c_str());
|
|
native.options(Fl_Native_File_Chooser::NO_OPTIONS);
|
|
#if __WIN32__
|
|
dosfname(sdef);
|
|
#endif
|
|
if (!sdef.empty()) {
|
|
native.directory(sdef.c_str());
|
|
sdirectory = sdef;
|
|
} else
|
|
sdirectory.clear();
|
|
|
|
filename.clear();
|
|
switch ( native.show() ) {
|
|
case -1: LOG_ERROR("ERROR: %s\n", native.errmsg()); break; // ERROR
|
|
case 1: break; // CANCEL
|
|
default:
|
|
if ( native.filename() ) {
|
|
filename = native.filename();
|
|
} else {
|
|
filename = "";
|
|
}
|
|
break;
|
|
}
|
|
|
|
return filename.c_str();
|
|
}
|
|
|
|
} // FSEL
|