mirror of
https://github.com/UberGames/GtkRadiant.git
synced 2024-11-29 07:02:26 +00:00
This is a big big GTK file dialog change in Rambetter-temp-fixes branch.
Thank you to Markus Fischer who provided some example code on how to use the "new" method of GTK file dialogs. I then did a lot of research into how to shape his code into exactly what I wanted. This is an incomplete change in that I have not cleaned up the code such as removing unused local variables and unused functions yet. However, I wanted to commit this now because it really works beautifully (the GTK file dialog that is). - In CFileType, m_pstrGTKMasks now contains string like "quake3 maps (*.map)" instead of like "quake3 maps <*.map>". Nobody else is using this code except in gtkmisc.cpp so it's a safe change. - Removing all FILEDLG_DBG blocks in gtkmisc.cpp. It really clutters up the code and since it's completely overhauled, it's OK to remove. - Instead of the "old" way of gtk_file_selection_new(), now using gtk_file_chooser_dialog_new() instead. Thx to Markus Fischer for examples. - Actually adding GTK file dialog filters. It works really nice! :-) - Now using the same file extension logic on Windows file dialogs and GTK file dialogs. - Improved file extension logic. "No file extension specified in file to be saved. Attempt to save anyways?" Tested on Win7 and Linux. More related changes on the way. THIS SHOULD BE MERGED INTO TRUNK. git-svn-id: svn://svn.icculus.org/gtkradiant/GtkRadiant/branches/Rambetter-temp-fixes@355 8a3a26a2-13c4-0310-b231-cf6edde360e5
This commit is contained in:
parent
2c799718d7
commit
b292b8db59
1 changed files with 68 additions and 147 deletions
|
@ -1025,8 +1025,6 @@ int WINAPI gtk_MessageBox (void *parent, const char* lpText, const char* lpCapti
|
||||||
|
|
||||||
// fenris #3078 WHENHELLISFROZENOVER
|
// fenris #3078 WHENHELLISFROZENOVER
|
||||||
|
|
||||||
//#define FILEDLG_DBG
|
|
||||||
|
|
||||||
static void file_sel_callback (GtkWidget *widget, gpointer data)
|
static void file_sel_callback (GtkWidget *widget, gpointer data)
|
||||||
{
|
{
|
||||||
GtkWidget *parent;
|
GtkWidget *parent;
|
||||||
|
@ -1040,11 +1038,6 @@ static void file_sel_callback (GtkWidget *widget, gpointer data)
|
||||||
if (GPOINTER_TO_INT (data) == IDOK)
|
if (GPOINTER_TO_INT (data) == IDOK)
|
||||||
*success = true;
|
*success = true;
|
||||||
|
|
||||||
#ifdef FILEDLG_DBG
|
|
||||||
else
|
|
||||||
Sys_Printf("file_sel_callback != IDOK\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*loop = 0;
|
*loop = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1197,10 +1190,10 @@ private:
|
||||||
for(r = m_pTypes[i].m_name.c_str(); *r!='\0'; r++, w++)
|
for(r = m_pTypes[i].m_name.c_str(); *r!='\0'; r++, w++)
|
||||||
*w = *r;
|
*w = *r;
|
||||||
*w++ = ' ';
|
*w++ = ' ';
|
||||||
*w++ = '<';
|
*w++ = '(';
|
||||||
for(r = m_pTypes[i].m_pattern.c_str(); *r!='\0'; r++, w++)
|
for(r = m_pTypes[i].m_pattern.c_str(); *r!='\0'; r++, w++)
|
||||||
*w = *r;
|
*w = *r;
|
||||||
*w++ = '>';
|
*w++ = ')';
|
||||||
*w++ = '\0';
|
*w++ = '\0';
|
||||||
}
|
}
|
||||||
m_pstrGTKMasks[m_nTypes] = NULL;
|
m_pstrGTKMasks[m_nTypes] = NULL;
|
||||||
|
@ -1253,31 +1246,15 @@ const char* file_dialog (void *parent, gboolean open, const char* title, const c
|
||||||
char *new_path = NULL;
|
char *new_path = NULL;
|
||||||
|
|
||||||
const char* r;
|
const char* r;
|
||||||
char* w;
|
char *v, *w;
|
||||||
filetype_t type;
|
filetype_t type;
|
||||||
CFileType typelist;
|
CFileType typelist;
|
||||||
if(pattern != NULL)
|
if(pattern != NULL)
|
||||||
GetFileTypeRegistry()->getTypeList(pattern, &typelist);
|
GetFileTypeRegistry()->getTypeList(pattern, &typelist);
|
||||||
|
|
||||||
#ifdef FILEDLG_DBG
|
|
||||||
Sys_Printf("file_dialog: open = %d title = %s path = %s\n", open, title, path);
|
|
||||||
if (pattern)
|
|
||||||
{
|
|
||||||
Sys_Printf("Patterns:\n");
|
|
||||||
char** p = typelist.m_pstrGTKMasks;
|
|
||||||
while(*p!=NULL)
|
|
||||||
Sys_Printf("%s\n", *p++);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Sys_Printf("no patterns\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (g_PrefsDlg.m_bNativeGUI)
|
if (g_PrefsDlg.m_bNativeGUI)
|
||||||
{
|
{
|
||||||
#ifdef FILEDLG_DBG
|
|
||||||
Sys_Printf("Doing win32 file dialog...");
|
|
||||||
#endif
|
|
||||||
// do that the native way
|
// do that the native way
|
||||||
|
|
||||||
if (in_file_dialog) return NULL; // Avoid recursive entry.
|
if (in_file_dialog) return NULL; // Avoid recursive entry.
|
||||||
|
@ -1354,9 +1331,6 @@ const char* file_dialog (void *parent, gboolean open, const char* title, const c
|
||||||
if(pattern != NULL)
|
if(pattern != NULL)
|
||||||
type = typelist.GetTypeForIndex(ofn.nFilterIndex - 1);
|
type = typelist.GetTypeForIndex(ofn.nFilterIndex - 1);
|
||||||
|
|
||||||
#ifdef FILEDLG_DBG
|
|
||||||
Sys_Printf("Done.\n");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1366,9 +1340,6 @@ const char* file_dialog (void *parent, gboolean open, const char* title, const c
|
||||||
if (title == NULL)
|
if (title == NULL)
|
||||||
title = open ? _("Open File") : _("Save File");
|
title = open ? _("Open File") : _("Save File");
|
||||||
|
|
||||||
#ifdef FILEDLG_DBG
|
|
||||||
Sys_Printf("Doing Gtk file dialog:\nBuilding new_path..");
|
|
||||||
#endif
|
|
||||||
// we expect an actual path below, if the path is NULL we might crash
|
// we expect an actual path below, if the path is NULL we might crash
|
||||||
if (!path || path[0] == '\0')
|
if (!path || path[0] == '\0')
|
||||||
{
|
{
|
||||||
|
@ -1390,101 +1361,51 @@ const char* file_dialog (void *parent, gboolean open, const char* title, const c
|
||||||
// terminate string
|
// terminate string
|
||||||
*w = '\0';
|
*w = '\0';
|
||||||
|
|
||||||
#ifdef FILEDLG_DBG
|
file_sel = gtk_file_chooser_dialog_new(title,
|
||||||
Sys_Printf("Done.\n");
|
GTK_WINDOW(parent),
|
||||||
Sys_Printf("Calling gtk_file_selection_new with title: %s...", title);
|
open ? GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||||
#endif
|
GTK_STOCK_CANCEL,
|
||||||
file_sel = gtk_file_selection_new (title);
|
GTK_RESPONSE_CANCEL,
|
||||||
#ifdef FILEDLG_DBG
|
open ? GTK_STOCK_OPEN : GTK_STOCK_SAVE,
|
||||||
Sys_Printf("Done.\n");
|
GTK_RESPONSE_ACCEPT,
|
||||||
Sys_Printf("Set the masks...");
|
NULL);
|
||||||
#endif
|
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_sel), new_path);
|
||||||
|
|
||||||
#if 0 //!\todo Add masks to GtkFileSelection in gtk-2.0
|
|
||||||
// set the masks
|
|
||||||
if (pattern)
|
|
||||||
{
|
|
||||||
gtk_file_selection_clear_masks (GTK_FILE_SELECTION (file_sel));
|
|
||||||
gtk_file_selection_set_masks (GTK_FILE_SELECTION (file_sel), const_cast<const char**>(typelist.m_pstrGTKMasks));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef FILEDLG_DBG
|
|
||||||
Sys_Printf("Done.\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button), "clicked",
|
|
||||||
GTK_SIGNAL_FUNC (file_sel_callback), GINT_TO_POINTER (IDOK));
|
|
||||||
gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->cancel_button), "clicked",
|
|
||||||
GTK_SIGNAL_FUNC (file_sel_callback), GINT_TO_POINTER (IDCANCEL));
|
|
||||||
gtk_signal_connect (GTK_OBJECT (file_sel), "delete_event",
|
|
||||||
GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
|
|
||||||
gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (file_sel));
|
|
||||||
|
|
||||||
if (parent != NULL)
|
|
||||||
gtk_window_set_transient_for (GTK_WINDOW (file_sel), GTK_WINDOW (parent));
|
|
||||||
|
|
||||||
#ifdef FILEDLG_DBG
|
|
||||||
Sys_Printf("set_data...");
|
|
||||||
#endif
|
|
||||||
bool success = false;
|
|
||||||
g_object_set_data (G_OBJECT (file_sel), "loop", &loop);
|
|
||||||
g_object_set_data (G_OBJECT (file_sel), "success", &success);
|
|
||||||
#ifdef FILEDLG_DBG
|
|
||||||
Sys_Printf("Done.\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!open)
|
|
||||||
{
|
|
||||||
#ifdef FILEDLG_DBG
|
|
||||||
Sys_Printf("set_data \"overwrite\" ...");
|
|
||||||
#endif
|
|
||||||
g_object_set_data (G_OBJECT (file_sel), "overwrite", GINT_TO_POINTER (1));
|
|
||||||
#ifdef FILEDLG_DBG
|
|
||||||
Sys_Printf("Done.\n");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new_path != NULL)
|
|
||||||
{
|
|
||||||
#ifdef FILEDLG_DBG
|
|
||||||
Sys_Printf("gtk_file_selection_set_filename... %p (%s)", file_sel, new_path);
|
|
||||||
#endif
|
|
||||||
gtk_file_selection_set_filename (GTK_FILE_SELECTION (file_sel), new_path);
|
|
||||||
delete[] new_path;
|
delete[] new_path;
|
||||||
#ifdef FILEDLG_DBG
|
|
||||||
Sys_Printf("Done.\n");
|
// Setting the file chooser dialog to modal and centering it on the parent is done automatically.
|
||||||
#endif
|
|
||||||
|
if (pattern != NULL) {
|
||||||
|
for (int i = 0; i < typelist.GetNumTypes(); i++) {
|
||||||
|
GtkFileFilter *filter = gtk_file_filter_new();
|
||||||
|
type = typelist.GetTypeForIndex(i);
|
||||||
|
// We can use type.name here, or m_pstrGTKMasks[i], which includes the actual pattern.
|
||||||
|
gtk_file_filter_set_name(filter, typelist.m_pstrGTKMasks[i]);
|
||||||
|
gtk_file_filter_add_pattern(filter, type.pattern);
|
||||||
|
// "Note that the chooser takes ownership of the filter, so
|
||||||
|
// you have to ref and sink it if you want to keep a reference."
|
||||||
|
// So I guess we won't need to garbage collect this.
|
||||||
|
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_sel), filter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_grab_add (file_sel);
|
if (gtk_dialog_run(GTK_DIALOG(file_sel)) == GTK_RESPONSE_ACCEPT) {
|
||||||
#ifdef FILEDLG_DBG
|
strcpy(szFile, gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_sel)));
|
||||||
Sys_Printf("gtk_widget_show... %p", file_sel);
|
}
|
||||||
#endif
|
else {
|
||||||
gtk_widget_show (file_sel);
|
szFile[0] = '\0';
|
||||||
#ifdef FILEDLG_DBG
|
|
||||||
Sys_Printf("Done.\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef FILEDLG_DBG
|
|
||||||
Sys_Printf("gtk_main_iteration...");
|
|
||||||
#endif
|
|
||||||
while (loop)
|
|
||||||
gtk_main_iteration ();
|
|
||||||
if(success)
|
|
||||||
{
|
|
||||||
#if 0 //!\todo Add masks to GtkFileSelection in gtk2
|
|
||||||
if(pattern!=NULL)
|
|
||||||
type = typelist.GetTypeForGTKMask(GTK_FILE_SELECTION (file_sel)->mask);
|
|
||||||
#endif
|
|
||||||
strcpy(szFile, gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_sel)));
|
|
||||||
}
|
}
|
||||||
#ifdef FILEDLG_DBG
|
|
||||||
Sys_Printf("Done.\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gtk_grab_remove (file_sel);
|
if (pattern != NULL) {
|
||||||
|
GtkFileFilter *filter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(file_sel));
|
||||||
|
if (filter == NULL) {
|
||||||
|
type = filetype_t();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
type = typelist.GetTypeForGTKMask(gtk_file_filter_get_name(filter));
|
||||||
|
}
|
||||||
|
}
|
||||||
gtk_widget_destroy(file_sel);
|
gtk_widget_destroy(file_sel);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1497,24 +1418,31 @@ const char* file_dialog (void *parent, gboolean open, const char* title, const c
|
||||||
if(*w=='\\')
|
if(*w=='\\')
|
||||||
*w = '/';
|
*w = '/';
|
||||||
|
|
||||||
#if defined(WIN32)
|
|
||||||
if (g_PrefsDlg.m_bNativeGUI)
|
|
||||||
{
|
|
||||||
/* \todo SPoG - file_dialog should return filetype information separately.. not force file extension.. */
|
/* \todo SPoG - file_dialog should return filetype information separately.. not force file extension.. */
|
||||||
if(!open && pattern != NULL)
|
if(!open && pattern != NULL) {
|
||||||
{
|
v = strrchr(szFile, '/');
|
||||||
// last ext separator
|
|
||||||
w = strrchr(szFile, '.');
|
w = strrchr(szFile, '.');
|
||||||
if (w == NULL) { // No extension.
|
if ((v && w && w < v) || // Last '.' is before the file.
|
||||||
|
w == NULL) { // Extension missing.
|
||||||
|
if (type.pattern[0]) {
|
||||||
w = szFile + strlen(szFile);
|
w = szFile + strlen(szFile);
|
||||||
strcpy(w, type.pattern + 1); // Add extension of selected filter type.
|
strcpy(w, type.pattern + 1); // Add extension of selected filter type.
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// type will be empty if for example there were no filters for pattern,
|
||||||
|
// or if some other UI inconsistencies happen.
|
||||||
|
if (gtk_MessageBox(parent, "No file extension specified in file to be saved.\nAttempt to save anyways?",
|
||||||
|
"GtkRadiant", MB_YESNO) == IDNO) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else { // An extension was explicitly in the filename.
|
else { // An extension was explicitly in the filename.
|
||||||
int knownExtension = 0;
|
bool knownExtension = false;
|
||||||
for (int i = typelist.GetNumTypes() - 1; i >= 0; i--) {
|
for (int i = typelist.GetNumTypes() - 1; i >= 0; i--) {
|
||||||
type = typelist.GetTypeForIndex(i);
|
type = typelist.GetTypeForIndex(i);
|
||||||
if (strcmp(w, type.pattern + 1) == 0) {
|
if (type.pattern[0] && strcmp(w, type.pattern + 1) == 0) {
|
||||||
knownExtension = 1;
|
knownExtension = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1526,8 +1454,6 @@ const char* file_dialog (void *parent, gboolean open, const char* title, const c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// prompt to overwrite existing files
|
// prompt to overwrite existing files
|
||||||
if (!open)
|
if (!open)
|
||||||
|
@ -1535,11 +1461,6 @@ const char* file_dialog (void *parent, gboolean open, const char* title, const c
|
||||||
if (gtk_MessageBox (parent, "File already exists.\nOverwrite?", "GtkRadiant", MB_YESNO) == IDNO)
|
if (gtk_MessageBox (parent, "File already exists.\nOverwrite?", "GtkRadiant", MB_YESNO) == IDNO)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
#ifdef FILEDLG_DBG
|
|
||||||
// ... let's use a static filename
|
|
||||||
Sys_Printf("filename: %p\n", szFile);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return szFile;
|
return szFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue