5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-03 14:29:50 +08:00

feat: adds file filtering to gtk select/save dialogs

This commit is contained in:
Florian 2020-06-16 15:19:36 +09:00 committed by Lea Anthony
parent da20bcc8d2
commit 393a4fceb2
6 changed files with 40 additions and 20 deletions

View File

@ -17,9 +17,9 @@ type Renderer interface {
NotifyEvent(eventData *messages.EventData) error NotifyEvent(eventData *messages.EventData) error
// Dialog Runtime // Dialog Runtime
SelectFile() string SelectFile(filter string) string
SelectDirectory() string SelectDirectory() string
SelectSaveFile() string SelectSaveFile(filter string) string
// Window Runtime // Window Runtime
SetColour(string) error SetColour(string) error

View File

@ -114,7 +114,7 @@ func (h *Bridge) NewBinding(methodName string) error {
// SelectFile is unsupported for Bridge but required // SelectFile is unsupported for Bridge but required
// for the Renderer interface // for the Renderer interface
func (h *Bridge) SelectFile() string { func (h *Bridge) SelectFile(filter string) string {
h.log.Warn("SelectFile() unsupported in bridge mode") h.log.Warn("SelectFile() unsupported in bridge mode")
return "" return ""
} }
@ -128,7 +128,7 @@ func (h *Bridge) SelectDirectory() string {
// SelectSaveFile is unsupported for Bridge but required // SelectSaveFile is unsupported for Bridge but required
// for the Renderer interface // for the Renderer interface
func (h *Bridge) SelectSaveFile() string { func (h *Bridge) SelectSaveFile(filter string) string {
h.log.Warn("SelectSaveFile() unsupported in bridge mode") h.log.Warn("SelectSaveFile() unsupported in bridge mode")
return "" return ""
} }

View File

@ -245,7 +245,7 @@ func (w *WebView) NewBinding(methodName string) error {
} }
// SelectFile opens a dialog that allows the user to select a file // SelectFile opens a dialog that allows the user to select a file
func (w *WebView) SelectFile() string { func (w *WebView) SelectFile(filter string) string {
var result string var result string
// We need to run this on the main thread, however Dispatch is // We need to run this on the main thread, however Dispatch is
@ -255,7 +255,7 @@ func (w *WebView) SelectFile() string {
wg.Add(1) wg.Add(1)
go func() { go func() {
w.window.Dispatch(func() { w.window.Dispatch(func() {
result = w.window.Dialog(wv.DialogTypeOpen, 0, "Select File", "") result = w.window.Dialog(wv.DialogTypeOpen, 0, "Select File", "", filter)
wg.Done() wg.Done()
}) })
}() }()
@ -273,7 +273,7 @@ func (w *WebView) SelectDirectory() string {
wg.Add(1) wg.Add(1)
go func() { go func() {
w.window.Dispatch(func() { w.window.Dispatch(func() {
result = w.window.Dialog(wv.DialogTypeOpen, wv.DialogFlagDirectory, "Select Directory", "") result = w.window.Dialog(wv.DialogTypeOpen, wv.DialogFlagDirectory, "Select Directory", "", "")
wg.Done() wg.Done()
}) })
}() }()
@ -282,7 +282,7 @@ func (w *WebView) SelectDirectory() string {
} }
// SelectSaveFile opens a dialog that allows the user to select a file to save // SelectSaveFile opens a dialog that allows the user to select a file to save
func (w *WebView) SelectSaveFile() string { func (w *WebView) SelectSaveFile(filter string) string {
var result string var result string
// We need to run this on the main thread, however Dispatch is // We need to run this on the main thread, however Dispatch is
// non-blocking so we launch this in a goroutine and wait for // non-blocking so we launch this in a goroutine and wait for
@ -291,7 +291,7 @@ func (w *WebView) SelectSaveFile() string {
wg.Add(1) wg.Add(1)
go func() { go func() {
w.window.Dispatch(func() { w.window.Dispatch(func() {
result = w.window.Dialog(wv.DialogTypeSave, 0, "Save file", "") result = w.window.Dialog(wv.DialogTypeSave, 0, "Save file", "", filter)
wg.Done() wg.Done()
}) })
}() }()

View File

@ -74,9 +74,9 @@ static inline void CgoWebViewSetColor(void *w, uint8_t r, uint8_t g, uint8_t b,
} }
static inline void CgoDialog(void *w, int dlgtype, int flags, static inline void CgoDialog(void *w, int dlgtype, int flags,
char *title, char *arg, char *res, size_t ressz) { char *title, char *arg, char *res, size_t ressz, char *filter) {
webview_dialog(w, dlgtype, flags, webview_dialog(w, dlgtype, flags,
(const char*)title, (const char*) arg, res, ressz); (const char*)title, (const char*) arg, res, ressz, filter);
} }
static inline int CgoWebViewEval(void *w, char *js) { static inline int CgoWebViewEval(void *w, char *js) {
@ -186,7 +186,7 @@ type WebView interface {
// Dialog() opens a system dialog of the given type and title. String // Dialog() opens a system dialog of the given type and title. String
// argument can be provided for certain dialogs, such as alert boxes. For // argument can be provided for certain dialogs, such as alert boxes. For
// alert boxes argument is a message inside the dialog box. // alert boxes argument is a message inside the dialog box.
Dialog(dlgType DialogType, flags int, title string, arg string) string Dialog(dlgType DialogType, flags int, title string, arg string, filter string) string
// Terminate() breaks the main UI loop. This method must be called from the main thread // Terminate() breaks the main UI loop. This method must be called from the main thread
// only. See Dispatch() for more details. // only. See Dispatch() for more details.
Terminate() Terminate()
@ -311,7 +311,7 @@ func (w *webview) SetFullscreen(fullscreen bool) {
C.CgoWebViewSetFullscreen(w.w, C.int(boolToInt(fullscreen))) C.CgoWebViewSetFullscreen(w.w, C.int(boolToInt(fullscreen)))
} }
func (w *webview) Dialog(dlgType DialogType, flags int, title string, arg string) string { func (w *webview) Dialog(dlgType DialogType, flags int, title string, arg string, filter string) string {
const maxPath = 4096 const maxPath = 4096
titlePtr := C.CString(title) titlePtr := C.CString(title)
defer C.free(unsafe.Pointer(titlePtr)) defer C.free(unsafe.Pointer(titlePtr))
@ -319,8 +319,10 @@ func (w *webview) Dialog(dlgType DialogType, flags int, title string, arg string
defer C.free(unsafe.Pointer(argPtr)) defer C.free(unsafe.Pointer(argPtr))
resultPtr := (*C.char)(C.calloc((C.size_t)(unsafe.Sizeof((*C.char)(nil))), (C.size_t)(maxPath))) resultPtr := (*C.char)(C.calloc((C.size_t)(unsafe.Sizeof((*C.char)(nil))), (C.size_t)(maxPath)))
defer C.free(unsafe.Pointer(resultPtr)) defer C.free(unsafe.Pointer(resultPtr))
filterPtr := C.CString(filter)
defer C.free(unsafe.Pointer(filterPtr))
C.CgoDialog(w.w, C.int(dlgType), C.int(flags), titlePtr, C.CgoDialog(w.w, C.int(dlgType), C.int(flags), titlePtr,
argPtr, resultPtr, C.size_t(maxPath)) argPtr, resultPtr, C.size_t(maxPath), filterPtr)
return C.GoString(resultPtr) return C.GoString(resultPtr)
} }

View File

@ -174,7 +174,7 @@ struct webview_priv
WEBVIEW_API void webview_dialog(struct webview *w, WEBVIEW_API void webview_dialog(struct webview *w,
enum webview_dialog_type dlgtype, int flags, enum webview_dialog_type dlgtype, int flags,
const char *title, const char *arg, const char *title, const char *arg,
char *result, size_t resultsz); char *result, size_t resultsz, char *filter);
WEBVIEW_API void webview_dispatch(struct webview *w, webview_dispatch_fn fn, WEBVIEW_API void webview_dispatch(struct webview *w, webview_dispatch_fn fn,
void *arg); void *arg);
WEBVIEW_API void webview_terminate(struct webview *w); WEBVIEW_API void webview_terminate(struct webview *w);
@ -418,7 +418,7 @@ struct webview_priv
WEBVIEW_API void webview_dialog(struct webview *w, WEBVIEW_API void webview_dialog(struct webview *w,
enum webview_dialog_type dlgtype, int flags, enum webview_dialog_type dlgtype, int flags,
const char *title, const char *arg, const char *title, const char *arg,
char *result, size_t resultsz) char *result, size_t resultsz, char *filter)
{ {
GtkWidget *dlg; GtkWidget *dlg;
if (result != NULL) if (result != NULL)
@ -438,6 +438,16 @@ struct webview_priv
"_Cancel", GTK_RESPONSE_CANCEL, "_Cancel", GTK_RESPONSE_CANCEL,
(dlgtype == WEBVIEW_DIALOG_TYPE_OPEN ? "_Open" : "_Save"), (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN ? "_Open" : "_Save"),
GTK_RESPONSE_ACCEPT, NULL); GTK_RESPONSE_ACCEPT, NULL);
if (filter[0] != '\0') {
GtkFileFilter *file_filter = gtk_file_filter_new();
gchar **filters = g_strsplit(filter, ",", -1);
gint i;
for(i = 0; filters && filters[i]; i++) {
gtk_file_filter_add_pattern(file_filter, filters[i]);
}
gtk_file_filter_set_name(file_filter, filter);
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dlg), file_filter);
}
gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dlg), FALSE); gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dlg), FALSE);
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dlg), FALSE); gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dlg), FALSE);
gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(dlg), TRUE); gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(dlg), TRUE);

View File

@ -15,8 +15,12 @@ func NewDialog(renderer interfaces.Renderer) *Dialog {
} }
// SelectFile prompts the user to select a file // SelectFile prompts the user to select a file
func (r *Dialog) SelectFile() string { func (r *Dialog) SelectFile(params ...string) string {
return r.renderer.SelectFile() filter := ""
if len(params) > 0 {
filter = params[0]
}
return r.renderer.SelectFile(filter)
} }
// SelectDirectory prompts the user to select a directory // SelectDirectory prompts the user to select a directory
@ -25,6 +29,10 @@ func (r *Dialog) SelectDirectory() string {
} }
// SelectSaveFile prompts the user to select a file for saving // SelectSaveFile prompts the user to select a file for saving
func (r *Dialog) SelectSaveFile() string { func (r *Dialog) SelectSaveFile(params ...string) string {
return r.renderer.SelectSaveFile() filter := ""
if len(params) > 0 {
filter = params[0]
}
return r.renderer.SelectSaveFile(filter)
} }