Applied patch 1173802: Reimplementation of GtkFileChooser wxFileDialog

by Mart Raudsepp


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@33228 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Julian Smart
2005-03-31 21:20:58 +00:00
parent 6def2b5299
commit f8bc53eb53
7 changed files with 372 additions and 397 deletions

View File

@@ -51,6 +51,8 @@ wxGTK:
- Corrected splitter sash size and look for different themes. - Corrected splitter sash size and look for different themes.
- Fixed keyboard input for dead-keys. - Fixed keyboard input for dead-keys.
- Added support for more wrapping styles (Mart Raudsepp). - Added support for more wrapping styles (Mart Raudsepp).
- GTK2.4+ wxFileDialog reimplemented to support non-modal usage better,
and fix all known bugs (Mart Raudsepp).
wxMac: wxMac:

View File

@@ -19,9 +19,9 @@ This class represents the file chooser dialog.
\wxheading{Remarks} \wxheading{Remarks}
Pops up a file selector box. In Windows, this is the common file selector Pops up a file selector box. In Windows and GTK2.4+, this is the common
dialog. In X, this is a file selector box with somewhat less functionality. file selector dialog. In X, this is a file selector box with somewhat less
The path and filename are distinct elements of a full file pathname. functionality. The path and filename are distinct elements of a full file pathname.
If path is ``", the current directory will be used. If filename is ``", If path is ``", the current directory will be used. If filename is ``",
no default filename will be supplied. The wildcard determines what files no default filename will be supplied. The wildcard determines what files
are displayed in the file selector, and file extension supplies a type are displayed in the file selector, and file extension supplies a type

View File

@@ -142,14 +142,15 @@ an excerpt from this example.
Classes: \helpref{wxFileDialog}{wxfiledialog} Classes: \helpref{wxFileDialog}{wxfiledialog}
Pops up a file selector box. In Windows, this is the common file selector Pops up a file selector box. In Windows and GTK2.4+, this is the common
dialog. In X, this is a file selector box with somewhat less functionality. file selector dialog. In X, this is a file selector box with somewhat less
The path and filename are distinct elements of a full file pathname. functionality. The path and filename are distinct elements of a full file pathname.
If path is ``", the current directory will be used. If filename is ``", If path is ``", the current directory will be used. If filename is ``",
no default filename will be supplied. The wildcard determines what files no default filename will be supplied. The wildcard determines what files
are displayed in the file selector, and file extension supplies a type are displayed in the file selector, and file extension supplies a type
extension for the required filename. Flags may be a combination of wxOPEN, extension for the required filename. Flags may be a combination of wxOPEN,
wxSAVE, wxOVERWRITE\_PROMPT, wxHIDE\_READONLY, wxFILE\_MUST\_EXIST or 0. wxSAVE, wxOVERWRITE\_PROMPT, wxHIDE\_READONLY, wxFILE\_MUST\_EXIST,
wxMULTIPLE, wxCHANGE\_DIR or 0.
Both the X and Windows versions implement a wildcard filter. Typing a Both the X and Windows versions implement a wildcard filter. Typing a
filename containing wildcards (*, ?) in the filename text item, and filename containing wildcards (*, ?) in the filename text item, and

View File

@@ -33,33 +33,33 @@ public:
const wxString& wildCard = wxFileSelectorDefaultWildcardStr, const wxString& wildCard = wxFileSelectorDefaultWildcardStr,
long style = 0, long style = 0,
const wxPoint& pos = wxDefaultPosition); const wxPoint& pos = wxDefaultPosition);
~wxFileDialog(); virtual ~wxFileDialog();
virtual wxString GetPath() const;
virtual void GetPaths(wxArrayString& paths) const; virtual void GetPaths(wxArrayString& paths) const;
virtual wxString GetDirectory() const;
virtual wxString GetFilename() const;
virtual void GetFilenames(wxArrayString& files) const; virtual void GetFilenames(wxArrayString& files) const;
virtual int GetFilterIndex() const;
virtual void SetMessage(const wxString& message); virtual void SetMessage(const wxString& message);
virtual void SetPath(const wxString& path); virtual void SetPath(const wxString& path);
virtual void SetDirectory(const wxString& dir); virtual void SetDirectory(const wxString& dir);
virtual void SetFilename(const wxString& name); virtual void SetFilename(const wxString& name);
virtual void SetWildcard(const wxString& wildCard); virtual void SetWildcard(const wxString& wildCard);
virtual void SetFilterIndex(int filterIndex); virtual void SetFilterIndex(int filterIndex);
virtual int ShowModal(); virtual int ShowModal();
virtual bool Show( bool show = true ); virtual bool Show( bool show = true );
void OnFakeOk( wxCommandEvent &event );
//private: //private:
bool m_destroyed_by_delete; bool m_destroyed_by_delete;
void UpdateFromDialog();
void UpdateDialog();
private: private:
DECLARE_DYNAMIC_CLASS(wxFileDialog) DECLARE_DYNAMIC_CLASS(wxFileDialog)
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
void OnFakeOk( wxCommandEvent &event );
}; };
#endif // __GTKFILEDLGH__ #endif // __GTKFILEDLGH__

View File

@@ -33,33 +33,33 @@ public:
const wxString& wildCard = wxFileSelectorDefaultWildcardStr, const wxString& wildCard = wxFileSelectorDefaultWildcardStr,
long style = 0, long style = 0,
const wxPoint& pos = wxDefaultPosition); const wxPoint& pos = wxDefaultPosition);
~wxFileDialog(); virtual ~wxFileDialog();
virtual wxString GetPath() const;
virtual void GetPaths(wxArrayString& paths) const; virtual void GetPaths(wxArrayString& paths) const;
virtual wxString GetDirectory() const;
virtual wxString GetFilename() const;
virtual void GetFilenames(wxArrayString& files) const; virtual void GetFilenames(wxArrayString& files) const;
virtual int GetFilterIndex() const;
virtual void SetMessage(const wxString& message); virtual void SetMessage(const wxString& message);
virtual void SetPath(const wxString& path); virtual void SetPath(const wxString& path);
virtual void SetDirectory(const wxString& dir); virtual void SetDirectory(const wxString& dir);
virtual void SetFilename(const wxString& name); virtual void SetFilename(const wxString& name);
virtual void SetWildcard(const wxString& wildCard); virtual void SetWildcard(const wxString& wildCard);
virtual void SetFilterIndex(int filterIndex); virtual void SetFilterIndex(int filterIndex);
virtual int ShowModal(); virtual int ShowModal();
virtual bool Show( bool show = true ); virtual bool Show( bool show = true );
void OnFakeOk( wxCommandEvent &event );
//private: //private:
bool m_destroyed_by_delete; bool m_destroyed_by_delete;
void UpdateFromDialog();
void UpdateDialog();
private: private:
DECLARE_DYNAMIC_CLASS(wxFileDialog) DECLARE_DYNAMIC_CLASS(wxFileDialog)
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
void OnFakeOk( wxCommandEvent &event );
}; };
#endif // __GTKFILEDLGH__ #endif // __GTKFILEDLGH__

View File

@@ -1,9 +1,9 @@
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// Name: gtk/filedlg.cpp // Name: gtk/filedlg.cpp
// Purpose: native implementation of wxFileDialog // Purpose: native implementation of wxFileDialog
// Author: Robert Roebling, Zbigniew Zagorski // Author: Robert Roebling, Zbigniew Zagorski, Mart Raudsepp
// Id: $Id$ // Id: $Id$
// Copyright: (c) 1998 Robert Roebling, 2004 Zbigniew Zagorski // Copyright: (c) 1998 Robert Roebling, 2004 Zbigniew Zagorski, 2005 Mart Raudsepp
// Licence: wxWindows licence // Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
@@ -14,20 +14,26 @@
// For compilers that support precompilation, includes "wx.h". // For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h" #include "wx/wxprec.h"
// Include setup.h to get wxUSE flags for compilers that do not support precompilation of headers
#include "wx/setup.h"
#if wxUSE_FILEDLG #if wxUSE_FILEDLG
#include "wx/filedlg.h" #include "wx/filedlg.h"
#include "wx/utils.h"
#include "wx/intl.h"
#include "wx/filename.h"
#include "wx/msgdlg.h"
#include "wx/log.h"
#include <gtk/gtk.h>
#ifdef __WXGTK24__ #ifdef __WXGTK24__
#include <gtk/gtk.h>
#include "wx/gtk/private.h" #include "wx/gtk/private.h"
#include <unistd.h> // chdir
#include "wx/intl.h"
#include "wx/filename.h" // wxFilename
#include "wx/tokenzr.h" // wxStringTokenizer
#include "wx/filefn.h" // ::wxGetCwd
#include "wx/msgdlg.h" // wxMessageDialog
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// idle system // idle system
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -43,23 +49,17 @@ extern "C" {
static void gtk_filedialog_ok_callback(GtkWidget *widget, wxFileDialog *dialog) static void gtk_filedialog_ok_callback(GtkWidget *widget, wxFileDialog *dialog)
{ {
int style = dialog->GetStyle(); int style = dialog->GetStyle();
gchar* text = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget)); gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget));
wxString filename = wxConvFileName->cMB2WX( text );
if ( filename.empty() )
{
// this is totally lame but better than silent error
wxLogWarning(_("This filename can't be used by wxWidgets because it contains invalid UTF-8 characters, please rename the file."));
return;
}
if ((style & wxSAVE) && (style & wxOVERWRITE_PROMPT)) if ((style & wxSAVE) && (style & wxOVERWRITE_PROMPT))
{ {
if (wxFileExists(filename)) if ( g_file_test(filename, G_FILE_TEST_EXISTS) )
{ {
wxString msg; wxString msg;
msg.Printf( msg.Printf(
_("File '%s' already exists, do you really want to overwrite it?"), _("File '%s' already exists, do you really want to overwrite it?"),
filename.c_str()); wxString(wxConvFileName->cMB2WX(filename)).c_str());
wxMessageDialog dlg(dialog, msg, _("Confirm"), wxMessageDialog dlg(dialog, msg, _("Confirm"),
wxYES_NO | wxICON_QUESTION); wxYES_NO | wxICON_QUESTION);
@@ -67,33 +67,17 @@ static void gtk_filedialog_ok_callback(GtkWidget *widget, wxFileDialog *dialog)
return; return;
} }
} }
else if ((style & wxOPEN) && ( style & wxFILE_MUST_EXIST))
{
if (!wxFileExists( filename ))
{
wxMessageDialog dlg(dialog,
_("Please choose an existing file."),
_("Error"), wxOK | wxICON_ERROR);
dlg.ShowModal();
return;
}
}
// change to the directory where the user went if asked // change to the directory where the user went if asked
if (style & wxCHANGE_DIR) if (style & wxCHANGE_DIR)
{ {
wxString cwd; // Use chdir to not care about filename encodings
wxSplitPath(filename, &cwd, NULL, NULL); gchar* folder = g_path_get_dirname(filename);
chdir(folder);
if (cwd != wxGetCwd()) g_free(folder);
{
wxSetWorkingDirectory(cwd);
}
} }
dialog->SetPath(filename); g_free(filename);
dialog->UpdateFromDialog();
wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK); wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK);
event.SetEventObject(dialog); event.SetEventObject(dialog);
@@ -117,7 +101,7 @@ static void gtk_filedialog_cancel_callback(GtkWidget *WXUNUSED(w),
extern "C" { extern "C" {
static void gtk_filedialog_response_callback(GtkWidget *w, static void gtk_filedialog_response_callback(GtkWidget *w,
int response, gint response,
wxFileDialog *dialog) wxFileDialog *dialog)
{ {
wxapp_install_idle_handler(); wxapp_install_idle_handler();
@@ -143,7 +127,7 @@ static void gtk_filedialog_response_callback(GtkWidget *w,
IMPLEMENT_DYNAMIC_CLASS(wxFileDialog,wxGenericFileDialog) IMPLEMENT_DYNAMIC_CLASS(wxFileDialog,wxGenericFileDialog)
BEGIN_EVENT_TABLE(wxFileDialog,wxGenericFileDialog) BEGIN_EVENT_TABLE(wxFileDialog,wxGenericFileDialog)
EVT_BUTTON(wxID_OK, wxFileDialog::OnFakeOk) EVT_BUTTON(wxID_OK, wxFileDialog::OnFakeOk)
END_EVENT_TABLE() END_EVENT_TABLE()
wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message, wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message,
@@ -157,6 +141,7 @@ wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message,
#ifdef __WXGTK24__ #ifdef __WXGTK24__
if (!gtk_check_version(2,4,0)) if (!gtk_check_version(2,4,0))
{ {
wxASSERT_MSG( !( (style & wxSAVE) && (style & wxMULTIPLE) ), wxT("wxFileDialog - wxMULTIPLE used on a save dialog" ) );
m_needParent = false; m_needParent = false;
m_destroyed_by_delete = false; m_destroyed_by_delete = false;
@@ -168,14 +153,13 @@ wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message,
return; return;
} }
bool multiple = (style & wxMULTIPLE) == wxMULTIPLE;
GtkFileChooserAction gtk_action; GtkFileChooserAction gtk_action;
GtkWindow* gtk_parent = NULL; GtkWindow* gtk_parent = NULL;
if (parent) if (parent)
gtk_parent = GTK_WINDOW(parent->m_widget); gtk_parent = GTK_WINDOW(parent->m_widget);
gchar* ok_btn_stock; gchar* ok_btn_stock;
if ((style & wxSAVE) == wxSAVE) if ( style & wxSAVE )
{ {
gtk_action = GTK_FILE_CHOOSER_ACTION_SAVE; gtk_action = GTK_FILE_CHOOSER_ACTION_SAVE;
ok_btn_stock = GTK_STOCK_SAVE; ok_btn_stock = GTK_STOCK_SAVE;
@@ -185,6 +169,7 @@ wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message,
gtk_action = GTK_FILE_CHOOSER_ACTION_OPEN; gtk_action = GTK_FILE_CHOOSER_ACTION_OPEN;
ok_btn_stock = GTK_STOCK_OPEN; ok_btn_stock = GTK_STOCK_OPEN;
} }
m_widget = gtk_file_chooser_dialog_new( m_widget = gtk_file_chooser_dialog_new(
wxGTK_CONV(m_message), wxGTK_CONV(m_message),
gtk_parent, gtk_parent,
@@ -193,21 +178,48 @@ wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message,
ok_btn_stock, GTK_RESPONSE_ACCEPT, ok_btn_stock, GTK_RESPONSE_ACCEPT,
NULL); NULL);
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(m_widget), multiple); if ( style & wxMULTIPLE )
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(m_widget), true);
gtk_signal_connect(GTK_OBJECT(m_widget), // local-only property could be set to false to allow non-local files to be loaded.
"response", // In that case get/set_uri(s) should be used instead of get/set_filename(s) everywhere
GTK_SIGNAL_FUNC(gtk_filedialog_response_callback), // and the GtkFileChooserDialog should probably also be created with a backend,
(gpointer*)this); // e.g "gnome-vfs", "default", ... (gtk_file_chooser_dialog_new_with_backend).
// Currently local-only is kept as the default - true:
// gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(m_widget), true);
m_path = m_dir; g_signal_connect(G_OBJECT(m_widget), "response",
if (!m_path.empty() && m_path.Last() != wxT('/')) GTK_SIGNAL_FUNC(gtk_filedialog_response_callback), (gpointer)this);
m_path += wxT('/');
m_path += m_fileName;
SetPath(m_path);
SetWildcard(wildCard); SetWildcard(wildCard);
SetFilterIndex(0);
if ( style & wxSAVE )
{
if ( !defaultDir.IsEmpty() )
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(m_widget),
wxConvFileName->cWX2MB(defaultDir));
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget),
wxConvFileName->cWX2MB(defaultFileName));
}
else
{
if ( !defaultFileName.IsEmpty() )
{
wxString dir;
if ( defaultDir.IsEmpty() )
dir = ::wxGetCwd();
else
dir = defaultDir;
gtk_file_chooser_set_filename(
GTK_FILE_CHOOSER(m_widget),
wxConvFileName->cWX2MB( wxFileName(dir, defaultFileName).GetFullPath() ) );
}
else if ( !defaultDir.IsEmpty() )
gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(m_widget),
wxConvFileName->cWX2MB(defaultDir) );
}
} }
else else
#endif #endif
@@ -255,22 +267,26 @@ bool wxFileDialog::Show( bool show )
return wxGenericFileDialog::Show( show ); return wxGenericFileDialog::Show( show );
} }
wxString wxFileDialog::GetPath() const
{
#ifdef __WXGTK24__
if (!gtk_check_version(2,4,0))
return wxConvFileName->cMB2WX(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(m_widget)));
else
#endif
return wxGenericFileDialog::GetPath();
}
void wxFileDialog::GetFilenames(wxArrayString& files) const void wxFileDialog::GetFilenames(wxArrayString& files) const
{ {
#ifdef __WXGTK24__ #ifdef __WXGTK24__
if (!gtk_check_version(2,4,0)) if (!gtk_check_version(2,4,0))
{ {
GetPaths(files); GetPaths(files);
for (size_t n = 0; n < files.GetCount(); n++ ) for (size_t n = 0; n < files.GetCount(); ++n )
{ {
wxString name,ext; wxFileName file(files[n]);
wxSplitPath(files[n], NULL, &name, &ext); files[n] = file.GetFullName();
if (!ext.empty())
{
name += wxT(".");
name += ext;
}
files[n] = name;
} }
} }
else else
@@ -284,26 +300,22 @@ void wxFileDialog::GetPaths(wxArrayString& paths) const
if (!gtk_check_version(2,4,0)) if (!gtk_check_version(2,4,0))
{ {
paths.Empty(); paths.Empty();
if (GetWindowStyle() & wxMULTIPLE) if (gtk_file_chooser_get_select_multiple(GTK_FILE_CHOOSER(m_widget)))
{ {
GSList *gpathsi = GSList *gpathsi = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(m_widget));
gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(m_widget));
GSList *gpaths = gpathsi; GSList *gpaths = gpathsi;
while (gpathsi) while (gpathsi)
{ {
wxString file = wxGTK_CONV_BACK((gchar*) gpathsi->data); wxString file(wxConvFileName->cMB2WX((gchar*) gpathsi->data));
paths.Add(file); paths.Add(file);
g_free(gpathsi->data); g_free(gpathsi->data);
gpathsi = gpathsi->next; gpathsi = gpathsi->next;
} }
if (gpaths)
g_slist_free(gpaths);
}
if ( paths.IsEmpty() ) g_slist_free(gpaths);
{
paths.Add(m_fileName);
} }
else
paths.Add(GetPath());
} }
else else
#endif #endif
@@ -330,11 +342,7 @@ void wxFileDialog::SetPath(const wxString& path)
{ {
if (path.empty()) return; if (path.empty()) return;
wxFileName fn(path); gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(m_widget), wxConvFileName->cWX2MB(path));
m_path = fn.GetFullPath();
m_dir = fn.GetPath();
m_fileName = fn.GetFullName();
UpdateDialog();
} }
else else
#endif #endif
@@ -348,9 +356,7 @@ void wxFileDialog::SetDirectory(const wxString& dir)
{ {
if (wxPathExists(dir)) if (wxPathExists(dir))
{ {
m_dir = dir; gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(m_widget), wxConvFileName->cWX2MB(dir));
m_path = wxFileName(m_dir, m_fileName).GetFullPath();
UpdateDialog();
} }
} }
else else
@@ -358,64 +364,90 @@ void wxFileDialog::SetDirectory(const wxString& dir)
wxGenericFileDialog::SetDirectory( dir ); wxGenericFileDialog::SetDirectory( dir );
} }
wxString wxFileDialog::GetDirectory() const
{
#ifdef __WXGTK24__
if (!gtk_check_version(2,4,0))
return wxConvFileName->cMB2WX(
gtk_file_chooser_get_current_folder( GTK_FILE_CHOOSER(m_widget) ) );
else
#endif
return wxGenericFileDialog::GetDirectory();
}
void wxFileDialog::SetFilename(const wxString& name) void wxFileDialog::SetFilename(const wxString& name)
{ {
#ifdef __WXGTK24__ #ifdef __WXGTK24__
if (!gtk_check_version(2,4,0)) if (!gtk_check_version(2,4,0))
{ {
m_fileName = name; if (GetStyle() & wxSAVE)
m_path = wxFileName(m_dir, m_fileName).GetFullPath(); gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget), wxConvFileName->cWX2MB(name));
UpdateDialog(); else
SetPath(wxFileName(GetDirectory(), name).GetFullPath());
} }
else else
#endif #endif
wxGenericFileDialog::SetFilename( name ); wxGenericFileDialog::SetFilename( name );
} }
wxString wxFileDialog::GetFilename() const
{
#ifdef __WXGTK24__
if (!gtk_check_version(2,4,0))
return wxFileName(
wxConvFileName->cMB2WX(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(m_widget))) ).GetFullName();
else
#endif
return wxGenericFileDialog::GetFilename();
}
void wxFileDialog::SetWildcard(const wxString& wildCard) void wxFileDialog::SetWildcard(const wxString& wildCard)
{ {
#ifdef __WXGTK24__ #ifdef __WXGTK24__
if (!gtk_check_version(2,4,0)) if (!gtk_check_version(2,4,0))
{ {
m_wildCard = wildCard;
GtkFileChooser* chooser = GTK_FILE_CHOOSER(m_widget);
// empty current filter list:
GSList* ifilters = gtk_file_chooser_list_filters(chooser);
GSList* filters = ifilters;
while (ifilters)
{
gtk_file_chooser_remove_filter(chooser,GTK_FILE_FILTER(ifilters->data));
ifilters = ifilters->next;
}
g_slist_free(filters);
// parse filters // parse filters
wxArrayString wildDescriptions, wildFilters; wxArrayString wildDescriptions, wildFilters;
if (!wxParseCommonDialogsFilter(m_wildCard, wildDescriptions, wildFilters)) if (!wxParseCommonDialogsFilter(wildCard, wildDescriptions, wildFilters))
{ {
wxFAIL_MSG( wxT("Wrong file type description") ); wxFAIL_MSG( wxT("wxFileDialog::SetWildCard - bad wildcard string") );
} }
else else
{ {
// Parsing went fine. Set m_wildCard to be returned by wxFileDialogBase::GetWildcard
m_wildCard = wildCard;
GtkFileChooser* chooser = GTK_FILE_CHOOSER(m_widget);
// empty current filter list:
GSList* ifilters = gtk_file_chooser_list_filters(chooser);
GSList* filters = ifilters;
while (ifilters)
{
gtk_file_chooser_remove_filter(chooser,GTK_FILE_FILTER(ifilters->data));
ifilters = ifilters->next;
}
g_slist_free(filters);
// add parsed to GtkChooser // add parsed to GtkChooser
for (size_t n = 0; n < wildFilters.GetCount(); n++) for (size_t n = 0; n < wildFilters.GetCount(); ++n)
{ {
GtkFileFilter* filter = gtk_file_filter_new(); GtkFileFilter* filter = gtk_file_filter_new();
gtk_file_filter_set_name(filter,wxGTK_CONV(wildDescriptions[n])); gtk_file_filter_set_name(filter, wxGTK_CONV(wildDescriptions[n]));
wxString after = wildFilters[n];
do wxStringTokenizer exttok(wildFilters[n], wxT(";"));
while (exttok.HasMoreTokens())
{ {
wxString ext = after.BeforeFirst(wxT(';')); wxString token = exttok.GetNextToken();
gtk_file_filter_add_pattern(filter,wxGTK_CONV(ext)); gtk_file_filter_add_pattern(filter, wxGTK_CONV(token));
if (after.Find(wxT(';')) == wxNOT_FOUND)
break;
after = after.AfterLast(wxT(';'));
} }
while (!after.empty());
gtk_file_chooser_add_filter(chooser, filter); gtk_file_chooser_add_filter(chooser, filter);
} }
// Reset the filter index
SetFilterIndex(0);
} }
} }
else else
@@ -428,23 +460,21 @@ void wxFileDialog::SetFilterIndex(int filterIndex)
#ifdef __WXGTK24__ #ifdef __WXGTK24__
if (!gtk_check_version(2,4,0)) if (!gtk_check_version(2,4,0))
{ {
m_filterIndex = filterIndex; gpointer filter;
GtkFileChooser *chooser = GTK_FILE_CHOOSER(m_widget); GtkFileChooser *chooser = GTK_FILE_CHOOSER(m_widget);
GSList *fnode = gtk_file_chooser_list_filters(chooser); GSList *filters = gtk_file_chooser_list_filters(chooser);
GSList *filters = fnode;
int i = 0; filter = g_slist_nth_data(filters, filterIndex);
while (fnode)
if (filter != NULL)
{ {
if (i == filterIndex) gtk_file_chooser_set_filter(chooser, GTK_FILE_FILTER(filter));
{
gtk_file_chooser_set_filter(chooser, GTK_FILE_FILTER(fnode->data));
m_filterIndex = i;
break;
}
i++;
fnode = fnode->next;
} }
else
{
wxFAIL_MSG( wxT("wxFileDialog::SetFilterIndex - bad filter index") );
}
g_slist_free(filters); g_slist_free(filters);
} }
else else
@@ -452,72 +482,28 @@ void wxFileDialog::SetFilterIndex(int filterIndex)
wxGenericFileDialog::SetFilterIndex( filterIndex ); wxGenericFileDialog::SetFilterIndex( filterIndex );
} }
void wxFileDialog::UpdateDialog() int wxFileDialog::GetFilterIndex() const
{ {
#ifdef __WXGTK24__ #ifdef __WXGTK24__
// set currently selected directory to match the path: if (!gtk_check_version(2,4,0))
if (!m_dir.empty() && wxPathExists(m_dir))
{ {
// NB: This is important -- if we set directory only and not the path, GtkFileChooser *chooser = GTK_FILE_CHOOSER(m_widget);
// then dialog will still remember old path set using previous GtkFileFilter *filter = gtk_file_chooser_get_filter(chooser);
// call to gtk_chooser_set_filename. If the previous directory GSList *filters = gtk_file_chooser_list_filters(chooser);
// was a subdirectory of the directory we want to select now, gint index = g_slist_index(filters, filter);
// the dialog would still contain directory selector controls g_slist_free(filters);
// for the subdirectory (with the parent directory selected),
// instead of showing only the parent directory as expected.
// This way, we force GtkFileChooser to really change the
// directory. Finally, it doesn't have to be done if filename
// is not empty because of the code that sets the filename below.
if (m_fileName.empty())
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(m_widget),
wxGTK_CONV(m_dir));
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(m_widget), if (index == -1)
wxGTK_CONV(m_dir));
}
// if the user set only the directory (e.g. by calling SetDirectory)
// and not the default filename, then we don't want to set the filename:
if (!m_fileName.empty())
{
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(m_widget),
wxGTK_CONV(m_path));
// pre-fill the filename when saving, too (there's no text entry
// control when opening a file, so it doesn't make sense to
// do this when opening files):
if (GetWindowStyle() & wxSAVE)
{ {
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget), wxFAIL_MSG( wxT("wxFileDialog::GetFilterIndex - bad filter index returned by gtk+") );
wxGTK_CONV(m_fileName)); return 0;
} }
else
return index;
} }
else
#endif #endif
} return wxGenericFileDialog::GetFilterIndex();
void wxFileDialog::UpdateFromDialog()
{
#ifdef __WXGTK24__
// update filterIndex
GSList *fnode = gtk_file_chooser_list_filters(GTK_FILE_CHOOSER(m_widget));
GSList *filters = fnode;
GtkFileFilter *current =
gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(m_widget));
int i = 0;
m_filterIndex = 0;
while (fnode)
{
if (fnode->data == (gpointer)current)
{
m_filterIndex = i;
break;
}
i++;
fnode = fnode->next;
}
g_slist_free(filters);
#endif
} }
#endif // wxUSE_FILEDLG #endif // wxUSE_FILEDLG

View File

@@ -1,9 +1,9 @@
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// Name: gtk/filedlg.cpp // Name: gtk/filedlg.cpp
// Purpose: native implementation of wxFileDialog // Purpose: native implementation of wxFileDialog
// Author: Robert Roebling, Zbigniew Zagorski // Author: Robert Roebling, Zbigniew Zagorski, Mart Raudsepp
// Id: $Id$ // Id: $Id$
// Copyright: (c) 1998 Robert Roebling, 2004 Zbigniew Zagorski // Copyright: (c) 1998 Robert Roebling, 2004 Zbigniew Zagorski, 2005 Mart Raudsepp
// Licence: wxWindows licence // Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
@@ -14,20 +14,26 @@
// For compilers that support precompilation, includes "wx.h". // For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h" #include "wx/wxprec.h"
// Include setup.h to get wxUSE flags for compilers that do not support precompilation of headers
#include "wx/setup.h"
#if wxUSE_FILEDLG #if wxUSE_FILEDLG
#include "wx/filedlg.h" #include "wx/filedlg.h"
#include "wx/utils.h"
#include "wx/intl.h"
#include "wx/filename.h"
#include "wx/msgdlg.h"
#include "wx/log.h"
#include <gtk/gtk.h>
#ifdef __WXGTK24__ #ifdef __WXGTK24__
#include <gtk/gtk.h>
#include "wx/gtk/private.h" #include "wx/gtk/private.h"
#include <unistd.h> // chdir
#include "wx/intl.h"
#include "wx/filename.h" // wxFilename
#include "wx/tokenzr.h" // wxStringTokenizer
#include "wx/filefn.h" // ::wxGetCwd
#include "wx/msgdlg.h" // wxMessageDialog
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// idle system // idle system
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -43,23 +49,17 @@ extern "C" {
static void gtk_filedialog_ok_callback(GtkWidget *widget, wxFileDialog *dialog) static void gtk_filedialog_ok_callback(GtkWidget *widget, wxFileDialog *dialog)
{ {
int style = dialog->GetStyle(); int style = dialog->GetStyle();
gchar* text = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget)); gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget));
wxString filename = wxConvFileName->cMB2WX( text );
if ( filename.empty() )
{
// this is totally lame but better than silent error
wxLogWarning(_("This filename can't be used by wxWidgets because it contains invalid UTF-8 characters, please rename the file."));
return;
}
if ((style & wxSAVE) && (style & wxOVERWRITE_PROMPT)) if ((style & wxSAVE) && (style & wxOVERWRITE_PROMPT))
{ {
if (wxFileExists(filename)) if ( g_file_test(filename, G_FILE_TEST_EXISTS) )
{ {
wxString msg; wxString msg;
msg.Printf( msg.Printf(
_("File '%s' already exists, do you really want to overwrite it?"), _("File '%s' already exists, do you really want to overwrite it?"),
filename.c_str()); wxString(wxConvFileName->cMB2WX(filename)).c_str());
wxMessageDialog dlg(dialog, msg, _("Confirm"), wxMessageDialog dlg(dialog, msg, _("Confirm"),
wxYES_NO | wxICON_QUESTION); wxYES_NO | wxICON_QUESTION);
@@ -67,33 +67,17 @@ static void gtk_filedialog_ok_callback(GtkWidget *widget, wxFileDialog *dialog)
return; return;
} }
} }
else if ((style & wxOPEN) && ( style & wxFILE_MUST_EXIST))
{
if (!wxFileExists( filename ))
{
wxMessageDialog dlg(dialog,
_("Please choose an existing file."),
_("Error"), wxOK | wxICON_ERROR);
dlg.ShowModal();
return;
}
}
// change to the directory where the user went if asked // change to the directory where the user went if asked
if (style & wxCHANGE_DIR) if (style & wxCHANGE_DIR)
{ {
wxString cwd; // Use chdir to not care about filename encodings
wxSplitPath(filename, &cwd, NULL, NULL); gchar* folder = g_path_get_dirname(filename);
chdir(folder);
if (cwd != wxGetCwd()) g_free(folder);
{
wxSetWorkingDirectory(cwd);
}
} }
dialog->SetPath(filename); g_free(filename);
dialog->UpdateFromDialog();
wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK); wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK);
event.SetEventObject(dialog); event.SetEventObject(dialog);
@@ -117,7 +101,7 @@ static void gtk_filedialog_cancel_callback(GtkWidget *WXUNUSED(w),
extern "C" { extern "C" {
static void gtk_filedialog_response_callback(GtkWidget *w, static void gtk_filedialog_response_callback(GtkWidget *w,
int response, gint response,
wxFileDialog *dialog) wxFileDialog *dialog)
{ {
wxapp_install_idle_handler(); wxapp_install_idle_handler();
@@ -143,7 +127,7 @@ static void gtk_filedialog_response_callback(GtkWidget *w,
IMPLEMENT_DYNAMIC_CLASS(wxFileDialog,wxGenericFileDialog) IMPLEMENT_DYNAMIC_CLASS(wxFileDialog,wxGenericFileDialog)
BEGIN_EVENT_TABLE(wxFileDialog,wxGenericFileDialog) BEGIN_EVENT_TABLE(wxFileDialog,wxGenericFileDialog)
EVT_BUTTON(wxID_OK, wxFileDialog::OnFakeOk) EVT_BUTTON(wxID_OK, wxFileDialog::OnFakeOk)
END_EVENT_TABLE() END_EVENT_TABLE()
wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message, wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message,
@@ -157,6 +141,7 @@ wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message,
#ifdef __WXGTK24__ #ifdef __WXGTK24__
if (!gtk_check_version(2,4,0)) if (!gtk_check_version(2,4,0))
{ {
wxASSERT_MSG( !( (style & wxSAVE) && (style & wxMULTIPLE) ), wxT("wxFileDialog - wxMULTIPLE used on a save dialog" ) );
m_needParent = false; m_needParent = false;
m_destroyed_by_delete = false; m_destroyed_by_delete = false;
@@ -168,14 +153,13 @@ wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message,
return; return;
} }
bool multiple = (style & wxMULTIPLE) == wxMULTIPLE;
GtkFileChooserAction gtk_action; GtkFileChooserAction gtk_action;
GtkWindow* gtk_parent = NULL; GtkWindow* gtk_parent = NULL;
if (parent) if (parent)
gtk_parent = GTK_WINDOW(parent->m_widget); gtk_parent = GTK_WINDOW(parent->m_widget);
gchar* ok_btn_stock; gchar* ok_btn_stock;
if ((style & wxSAVE) == wxSAVE) if ( style & wxSAVE )
{ {
gtk_action = GTK_FILE_CHOOSER_ACTION_SAVE; gtk_action = GTK_FILE_CHOOSER_ACTION_SAVE;
ok_btn_stock = GTK_STOCK_SAVE; ok_btn_stock = GTK_STOCK_SAVE;
@@ -185,6 +169,7 @@ wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message,
gtk_action = GTK_FILE_CHOOSER_ACTION_OPEN; gtk_action = GTK_FILE_CHOOSER_ACTION_OPEN;
ok_btn_stock = GTK_STOCK_OPEN; ok_btn_stock = GTK_STOCK_OPEN;
} }
m_widget = gtk_file_chooser_dialog_new( m_widget = gtk_file_chooser_dialog_new(
wxGTK_CONV(m_message), wxGTK_CONV(m_message),
gtk_parent, gtk_parent,
@@ -193,21 +178,48 @@ wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message,
ok_btn_stock, GTK_RESPONSE_ACCEPT, ok_btn_stock, GTK_RESPONSE_ACCEPT,
NULL); NULL);
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(m_widget), multiple); if ( style & wxMULTIPLE )
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(m_widget), true);
gtk_signal_connect(GTK_OBJECT(m_widget), // local-only property could be set to false to allow non-local files to be loaded.
"response", // In that case get/set_uri(s) should be used instead of get/set_filename(s) everywhere
GTK_SIGNAL_FUNC(gtk_filedialog_response_callback), // and the GtkFileChooserDialog should probably also be created with a backend,
(gpointer*)this); // e.g "gnome-vfs", "default", ... (gtk_file_chooser_dialog_new_with_backend).
// Currently local-only is kept as the default - true:
// gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(m_widget), true);
m_path = m_dir; g_signal_connect(G_OBJECT(m_widget), "response",
if (!m_path.empty() && m_path.Last() != wxT('/')) GTK_SIGNAL_FUNC(gtk_filedialog_response_callback), (gpointer)this);
m_path += wxT('/');
m_path += m_fileName;
SetPath(m_path);
SetWildcard(wildCard); SetWildcard(wildCard);
SetFilterIndex(0);
if ( style & wxSAVE )
{
if ( !defaultDir.IsEmpty() )
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(m_widget),
wxConvFileName->cWX2MB(defaultDir));
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget),
wxConvFileName->cWX2MB(defaultFileName));
}
else
{
if ( !defaultFileName.IsEmpty() )
{
wxString dir;
if ( defaultDir.IsEmpty() )
dir = ::wxGetCwd();
else
dir = defaultDir;
gtk_file_chooser_set_filename(
GTK_FILE_CHOOSER(m_widget),
wxConvFileName->cWX2MB( wxFileName(dir, defaultFileName).GetFullPath() ) );
}
else if ( !defaultDir.IsEmpty() )
gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(m_widget),
wxConvFileName->cWX2MB(defaultDir) );
}
} }
else else
#endif #endif
@@ -255,22 +267,26 @@ bool wxFileDialog::Show( bool show )
return wxGenericFileDialog::Show( show ); return wxGenericFileDialog::Show( show );
} }
wxString wxFileDialog::GetPath() const
{
#ifdef __WXGTK24__
if (!gtk_check_version(2,4,0))
return wxConvFileName->cMB2WX(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(m_widget)));
else
#endif
return wxGenericFileDialog::GetPath();
}
void wxFileDialog::GetFilenames(wxArrayString& files) const void wxFileDialog::GetFilenames(wxArrayString& files) const
{ {
#ifdef __WXGTK24__ #ifdef __WXGTK24__
if (!gtk_check_version(2,4,0)) if (!gtk_check_version(2,4,0))
{ {
GetPaths(files); GetPaths(files);
for (size_t n = 0; n < files.GetCount(); n++ ) for (size_t n = 0; n < files.GetCount(); ++n )
{ {
wxString name,ext; wxFileName file(files[n]);
wxSplitPath(files[n], NULL, &name, &ext); files[n] = file.GetFullName();
if (!ext.empty())
{
name += wxT(".");
name += ext;
}
files[n] = name;
} }
} }
else else
@@ -284,26 +300,22 @@ void wxFileDialog::GetPaths(wxArrayString& paths) const
if (!gtk_check_version(2,4,0)) if (!gtk_check_version(2,4,0))
{ {
paths.Empty(); paths.Empty();
if (GetWindowStyle() & wxMULTIPLE) if (gtk_file_chooser_get_select_multiple(GTK_FILE_CHOOSER(m_widget)))
{ {
GSList *gpathsi = GSList *gpathsi = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(m_widget));
gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(m_widget));
GSList *gpaths = gpathsi; GSList *gpaths = gpathsi;
while (gpathsi) while (gpathsi)
{ {
wxString file = wxGTK_CONV_BACK((gchar*) gpathsi->data); wxString file(wxConvFileName->cMB2WX((gchar*) gpathsi->data));
paths.Add(file); paths.Add(file);
g_free(gpathsi->data); g_free(gpathsi->data);
gpathsi = gpathsi->next; gpathsi = gpathsi->next;
} }
if (gpaths)
g_slist_free(gpaths);
}
if ( paths.IsEmpty() ) g_slist_free(gpaths);
{
paths.Add(m_fileName);
} }
else
paths.Add(GetPath());
} }
else else
#endif #endif
@@ -330,11 +342,7 @@ void wxFileDialog::SetPath(const wxString& path)
{ {
if (path.empty()) return; if (path.empty()) return;
wxFileName fn(path); gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(m_widget), wxConvFileName->cWX2MB(path));
m_path = fn.GetFullPath();
m_dir = fn.GetPath();
m_fileName = fn.GetFullName();
UpdateDialog();
} }
else else
#endif #endif
@@ -348,9 +356,7 @@ void wxFileDialog::SetDirectory(const wxString& dir)
{ {
if (wxPathExists(dir)) if (wxPathExists(dir))
{ {
m_dir = dir; gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(m_widget), wxConvFileName->cWX2MB(dir));
m_path = wxFileName(m_dir, m_fileName).GetFullPath();
UpdateDialog();
} }
} }
else else
@@ -358,64 +364,90 @@ void wxFileDialog::SetDirectory(const wxString& dir)
wxGenericFileDialog::SetDirectory( dir ); wxGenericFileDialog::SetDirectory( dir );
} }
wxString wxFileDialog::GetDirectory() const
{
#ifdef __WXGTK24__
if (!gtk_check_version(2,4,0))
return wxConvFileName->cMB2WX(
gtk_file_chooser_get_current_folder( GTK_FILE_CHOOSER(m_widget) ) );
else
#endif
return wxGenericFileDialog::GetDirectory();
}
void wxFileDialog::SetFilename(const wxString& name) void wxFileDialog::SetFilename(const wxString& name)
{ {
#ifdef __WXGTK24__ #ifdef __WXGTK24__
if (!gtk_check_version(2,4,0)) if (!gtk_check_version(2,4,0))
{ {
m_fileName = name; if (GetStyle() & wxSAVE)
m_path = wxFileName(m_dir, m_fileName).GetFullPath(); gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget), wxConvFileName->cWX2MB(name));
UpdateDialog(); else
SetPath(wxFileName(GetDirectory(), name).GetFullPath());
} }
else else
#endif #endif
wxGenericFileDialog::SetFilename( name ); wxGenericFileDialog::SetFilename( name );
} }
wxString wxFileDialog::GetFilename() const
{
#ifdef __WXGTK24__
if (!gtk_check_version(2,4,0))
return wxFileName(
wxConvFileName->cMB2WX(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(m_widget))) ).GetFullName();
else
#endif
return wxGenericFileDialog::GetFilename();
}
void wxFileDialog::SetWildcard(const wxString& wildCard) void wxFileDialog::SetWildcard(const wxString& wildCard)
{ {
#ifdef __WXGTK24__ #ifdef __WXGTK24__
if (!gtk_check_version(2,4,0)) if (!gtk_check_version(2,4,0))
{ {
m_wildCard = wildCard;
GtkFileChooser* chooser = GTK_FILE_CHOOSER(m_widget);
// empty current filter list:
GSList* ifilters = gtk_file_chooser_list_filters(chooser);
GSList* filters = ifilters;
while (ifilters)
{
gtk_file_chooser_remove_filter(chooser,GTK_FILE_FILTER(ifilters->data));
ifilters = ifilters->next;
}
g_slist_free(filters);
// parse filters // parse filters
wxArrayString wildDescriptions, wildFilters; wxArrayString wildDescriptions, wildFilters;
if (!wxParseCommonDialogsFilter(m_wildCard, wildDescriptions, wildFilters)) if (!wxParseCommonDialogsFilter(wildCard, wildDescriptions, wildFilters))
{ {
wxFAIL_MSG( wxT("Wrong file type description") ); wxFAIL_MSG( wxT("wxFileDialog::SetWildCard - bad wildcard string") );
} }
else else
{ {
// Parsing went fine. Set m_wildCard to be returned by wxFileDialogBase::GetWildcard
m_wildCard = wildCard;
GtkFileChooser* chooser = GTK_FILE_CHOOSER(m_widget);
// empty current filter list:
GSList* ifilters = gtk_file_chooser_list_filters(chooser);
GSList* filters = ifilters;
while (ifilters)
{
gtk_file_chooser_remove_filter(chooser,GTK_FILE_FILTER(ifilters->data));
ifilters = ifilters->next;
}
g_slist_free(filters);
// add parsed to GtkChooser // add parsed to GtkChooser
for (size_t n = 0; n < wildFilters.GetCount(); n++) for (size_t n = 0; n < wildFilters.GetCount(); ++n)
{ {
GtkFileFilter* filter = gtk_file_filter_new(); GtkFileFilter* filter = gtk_file_filter_new();
gtk_file_filter_set_name(filter,wxGTK_CONV(wildDescriptions[n])); gtk_file_filter_set_name(filter, wxGTK_CONV(wildDescriptions[n]));
wxString after = wildFilters[n];
do wxStringTokenizer exttok(wildFilters[n], wxT(";"));
while (exttok.HasMoreTokens())
{ {
wxString ext = after.BeforeFirst(wxT(';')); wxString token = exttok.GetNextToken();
gtk_file_filter_add_pattern(filter,wxGTK_CONV(ext)); gtk_file_filter_add_pattern(filter, wxGTK_CONV(token));
if (after.Find(wxT(';')) == wxNOT_FOUND)
break;
after = after.AfterLast(wxT(';'));
} }
while (!after.empty());
gtk_file_chooser_add_filter(chooser, filter); gtk_file_chooser_add_filter(chooser, filter);
} }
// Reset the filter index
SetFilterIndex(0);
} }
} }
else else
@@ -428,23 +460,21 @@ void wxFileDialog::SetFilterIndex(int filterIndex)
#ifdef __WXGTK24__ #ifdef __WXGTK24__
if (!gtk_check_version(2,4,0)) if (!gtk_check_version(2,4,0))
{ {
m_filterIndex = filterIndex; gpointer filter;
GtkFileChooser *chooser = GTK_FILE_CHOOSER(m_widget); GtkFileChooser *chooser = GTK_FILE_CHOOSER(m_widget);
GSList *fnode = gtk_file_chooser_list_filters(chooser); GSList *filters = gtk_file_chooser_list_filters(chooser);
GSList *filters = fnode;
int i = 0; filter = g_slist_nth_data(filters, filterIndex);
while (fnode)
if (filter != NULL)
{ {
if (i == filterIndex) gtk_file_chooser_set_filter(chooser, GTK_FILE_FILTER(filter));
{
gtk_file_chooser_set_filter(chooser, GTK_FILE_FILTER(fnode->data));
m_filterIndex = i;
break;
}
i++;
fnode = fnode->next;
} }
else
{
wxFAIL_MSG( wxT("wxFileDialog::SetFilterIndex - bad filter index") );
}
g_slist_free(filters); g_slist_free(filters);
} }
else else
@@ -452,72 +482,28 @@ void wxFileDialog::SetFilterIndex(int filterIndex)
wxGenericFileDialog::SetFilterIndex( filterIndex ); wxGenericFileDialog::SetFilterIndex( filterIndex );
} }
void wxFileDialog::UpdateDialog() int wxFileDialog::GetFilterIndex() const
{ {
#ifdef __WXGTK24__ #ifdef __WXGTK24__
// set currently selected directory to match the path: if (!gtk_check_version(2,4,0))
if (!m_dir.empty() && wxPathExists(m_dir))
{ {
// NB: This is important -- if we set directory only and not the path, GtkFileChooser *chooser = GTK_FILE_CHOOSER(m_widget);
// then dialog will still remember old path set using previous GtkFileFilter *filter = gtk_file_chooser_get_filter(chooser);
// call to gtk_chooser_set_filename. If the previous directory GSList *filters = gtk_file_chooser_list_filters(chooser);
// was a subdirectory of the directory we want to select now, gint index = g_slist_index(filters, filter);
// the dialog would still contain directory selector controls g_slist_free(filters);
// for the subdirectory (with the parent directory selected),
// instead of showing only the parent directory as expected.
// This way, we force GtkFileChooser to really change the
// directory. Finally, it doesn't have to be done if filename
// is not empty because of the code that sets the filename below.
if (m_fileName.empty())
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(m_widget),
wxGTK_CONV(m_dir));
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(m_widget), if (index == -1)
wxGTK_CONV(m_dir));
}
// if the user set only the directory (e.g. by calling SetDirectory)
// and not the default filename, then we don't want to set the filename:
if (!m_fileName.empty())
{
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(m_widget),
wxGTK_CONV(m_path));
// pre-fill the filename when saving, too (there's no text entry
// control when opening a file, so it doesn't make sense to
// do this when opening files):
if (GetWindowStyle() & wxSAVE)
{ {
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(m_widget), wxFAIL_MSG( wxT("wxFileDialog::GetFilterIndex - bad filter index returned by gtk+") );
wxGTK_CONV(m_fileName)); return 0;
} }
else
return index;
} }
else
#endif #endif
} return wxGenericFileDialog::GetFilterIndex();
void wxFileDialog::UpdateFromDialog()
{
#ifdef __WXGTK24__
// update filterIndex
GSList *fnode = gtk_file_chooser_list_filters(GTK_FILE_CHOOSER(m_widget));
GSList *filters = fnode;
GtkFileFilter *current =
gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(m_widget));
int i = 0;
m_filterIndex = 0;
while (fnode)
{
if (fnode->data == (gpointer)current)
{
m_filterIndex = i;
break;
}
i++;
fnode = fnode->next;
}
g_slist_free(filters);
#endif
} }
#endif // wxUSE_FILEDLG #endif // wxUSE_FILEDLG