483 lines
13 KiB
C++
483 lines
13 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/gtk/filectrl.cpp
|
|
// Purpose: wxGtkFileCtrl Implementation
|
|
// Author: Diaa M. Sami
|
|
// Created: 2007-08-10
|
|
// Copyright: (c) Diaa M. Sami
|
|
// Licence: wxWindows licence
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#if wxUSE_FILECTRL && !defined(__WXUNIVERSAL__)
|
|
|
|
#include "wx/filectrl.h"
|
|
|
|
#include "wx/gtk/private.h"
|
|
#include "wx/filename.h"
|
|
#include "wx/scopeguard.h"
|
|
#include "wx/tokenzr.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// wxGtkFileChooser implementation
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void wxGtkFileChooser::SetWidget(GtkFileChooser *w)
|
|
{
|
|
// check arguments
|
|
wxASSERT( w );
|
|
wxASSERT( GTK_FILE_CHOOSER( w ) );
|
|
|
|
this->m_widget = w;
|
|
}
|
|
|
|
wxString wxGtkFileChooser::GetPath() const
|
|
{
|
|
wxGtkString str( gtk_file_chooser_get_filename( m_widget ) );
|
|
|
|
wxString string;
|
|
if (str)
|
|
string = wxString::FromUTF8(str);
|
|
return string;
|
|
}
|
|
|
|
void wxGtkFileChooser::GetFilenames( wxArrayString& files ) const
|
|
{
|
|
GetPaths( files );
|
|
for ( size_t n = 0; n < files.GetCount(); ++n )
|
|
{
|
|
const wxFileName file( files[n] );
|
|
files[n] = file.GetFullName();
|
|
}
|
|
}
|
|
|
|
void wxGtkFileChooser::GetPaths( wxArrayString& paths ) const
|
|
{
|
|
paths.Empty();
|
|
if ( gtk_file_chooser_get_select_multiple( m_widget ) )
|
|
{
|
|
GSList *gpathsi = gtk_file_chooser_get_filenames( m_widget );
|
|
GSList *gpaths = gpathsi;
|
|
while ( gpathsi )
|
|
{
|
|
wxString file(wxString::FromUTF8(static_cast<gchar *>(gpathsi->data)));
|
|
paths.Add( file );
|
|
g_free( gpathsi->data );
|
|
gpathsi = gpathsi->next;
|
|
}
|
|
|
|
g_slist_free( gpaths );
|
|
}
|
|
else
|
|
paths.Add( GetPath() );
|
|
}
|
|
|
|
bool wxGtkFileChooser::SetPath( const wxString& path )
|
|
{
|
|
if ( path.empty() )
|
|
return true;
|
|
|
|
switch ( gtk_file_chooser_get_action( m_widget ) )
|
|
{
|
|
case GTK_FILE_CHOOSER_ACTION_SAVE:
|
|
{
|
|
wxFileName fn(path);
|
|
|
|
const wxString fname = fn.GetFullName();
|
|
gtk_file_chooser_set_current_name( m_widget, fname.utf8_str() );
|
|
|
|
// set the initial file name and/or directory
|
|
const wxString dir = fn.GetPath();
|
|
return gtk_file_chooser_set_current_folder( m_widget,
|
|
dir.utf8_str() ) != 0;
|
|
}
|
|
|
|
case GTK_FILE_CHOOSER_ACTION_OPEN:
|
|
return gtk_file_chooser_set_filename( m_widget, path.utf8_str() ) != 0;
|
|
|
|
case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
|
|
case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
|
|
break;
|
|
}
|
|
|
|
wxFAIL_MSG( "Unexpected file chooser type" );
|
|
|
|
return false;
|
|
}
|
|
|
|
bool wxGtkFileChooser::SetDirectory( const wxString& dir )
|
|
{
|
|
return gtk_file_chooser_set_current_folder( m_widget, dir.utf8_str() ) != 0;
|
|
}
|
|
|
|
wxString wxGtkFileChooser::GetDirectory() const
|
|
{
|
|
const wxGtkString str( gtk_file_chooser_get_current_folder( m_widget ) );
|
|
return wxString::FromUTF8(str);
|
|
}
|
|
|
|
wxString wxGtkFileChooser::GetFilename() const
|
|
{
|
|
return wxFileName( GetPath() ).GetFullName();
|
|
}
|
|
|
|
void wxGtkFileChooser::SetWildcard( const wxString& wildCard )
|
|
{
|
|
m_wildcards.Empty();
|
|
|
|
// parse filters
|
|
wxArrayString wildDescriptions, wildFilters;
|
|
|
|
if ( !wxParseCommonDialogsFilter( wildCard, wildDescriptions, wildFilters ) )
|
|
{
|
|
wxFAIL_MSG( wxT( "wxGtkFileChooser::SetWildcard - bad wildcard string" ) );
|
|
}
|
|
else
|
|
{
|
|
// Parsing went fine. Set m_wildCard to be returned by wxGtkFileChooserBase::GetWildcard
|
|
GtkFileChooser* chooser = m_widget;
|
|
|
|
// empty current filter list:
|
|
GSList* ifilters = gtk_file_chooser_list_filters( chooser );
|
|
GSList* filters = ifilters;
|
|
|
|
m_ignoreNextFilterEvent = true;
|
|
wxON_BLOCK_EXIT_SET(m_ignoreNextFilterEvent, false);
|
|
|
|
while ( ifilters )
|
|
{
|
|
gtk_file_chooser_remove_filter( chooser, GTK_FILE_FILTER( ifilters->data ) );
|
|
ifilters = ifilters->next;
|
|
}
|
|
g_slist_free( filters );
|
|
|
|
if (!wildCard.empty())
|
|
{
|
|
// add parsed to GtkChooser
|
|
for ( size_t n = 0; n < wildFilters.GetCount(); ++n )
|
|
{
|
|
GtkFileFilter* filter = gtk_file_filter_new();
|
|
|
|
gtk_file_filter_set_name( filter, wxGTK_CONV_SYS( wildDescriptions[n] ) );
|
|
|
|
wxStringTokenizer exttok( wildFilters[n], wxT( ";" ) );
|
|
|
|
int n1 = 1;
|
|
while ( exttok.HasMoreTokens() )
|
|
{
|
|
wxString token = exttok.GetNextToken();
|
|
gtk_file_filter_add_pattern( filter, wxGTK_CONV_SYS( token ) );
|
|
|
|
if (n1 == 1)
|
|
m_wildcards.Add( token ); // Only add first pattern to list, used later when saving
|
|
n1++;
|
|
}
|
|
|
|
gtk_file_chooser_add_filter( chooser, filter );
|
|
}
|
|
|
|
// Reset the filter index
|
|
SetFilterIndex( 0 );
|
|
}
|
|
}
|
|
}
|
|
|
|
void wxGtkFileChooser::SetFilterIndex( int filterIndex )
|
|
{
|
|
gpointer filter;
|
|
GtkFileChooser *chooser = m_widget;
|
|
GSList *filters = gtk_file_chooser_list_filters( chooser );
|
|
|
|
filter = g_slist_nth_data( filters, filterIndex );
|
|
|
|
if ( filter != NULL )
|
|
{
|
|
gtk_file_chooser_set_filter( chooser, GTK_FILE_FILTER( filter ) );
|
|
}
|
|
else
|
|
{
|
|
wxFAIL_MSG( wxT( "wxGtkFileChooser::SetFilterIndex - bad filter index" ) );
|
|
}
|
|
|
|
g_slist_free( filters );
|
|
}
|
|
|
|
int wxGtkFileChooser::GetFilterIndex() const
|
|
{
|
|
GtkFileChooser *chooser = m_widget;
|
|
GtkFileFilter *filter = gtk_file_chooser_get_filter( chooser );
|
|
GSList *filters = gtk_file_chooser_list_filters( chooser );
|
|
const gint index = g_slist_index( filters, filter );
|
|
g_slist_free( filters );
|
|
|
|
if ( index == -1 )
|
|
{
|
|
wxFAIL_MSG( wxT( "wxGtkFileChooser::GetFilterIndex - bad filter index returned by gtk+" ) );
|
|
return 0;
|
|
}
|
|
else
|
|
return index;
|
|
}
|
|
|
|
bool wxGtkFileChooser::HasFilterChoice() const
|
|
{
|
|
return gtk_file_chooser_get_filter( m_widget ) != NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// end wxGtkFileChooser Implementation
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#if wxUSE_FILECTRL
|
|
|
|
// gtk signal handlers
|
|
|
|
extern "C"
|
|
{
|
|
static void
|
|
gtkfilechooserwidget_file_activated_callback( GtkWidget *WXUNUSED( widget ), wxGtkFileCtrl *fileCtrl )
|
|
{
|
|
GenerateFileActivatedEvent( fileCtrl, fileCtrl );
|
|
}
|
|
}
|
|
|
|
extern "C"
|
|
{
|
|
static void
|
|
gtkfilechooserwidget_selection_changed_callback( GtkWidget *WXUNUSED( widget ), wxGtkFileCtrl *fileCtrl )
|
|
{
|
|
// check next selection event and ignore it if it has 0 files
|
|
// because such events are redundantly generated by gtk.
|
|
if ( fileCtrl->m_checkNextSelEvent )
|
|
{
|
|
wxArrayString filenames;
|
|
fileCtrl->GetFilenames( filenames );
|
|
|
|
if ( filenames.Count() != 0 )
|
|
fileCtrl->m_checkNextSelEvent = false;
|
|
}
|
|
|
|
if ( !fileCtrl->m_checkNextSelEvent )
|
|
GenerateSelectionChangedEvent( fileCtrl, fileCtrl );
|
|
}
|
|
}
|
|
|
|
extern "C"
|
|
{
|
|
static void
|
|
gtkfilechooserwidget_folder_changed_callback( GtkWidget *WXUNUSED( widget ), wxGtkFileCtrl *fileCtrl )
|
|
{
|
|
if ( fileCtrl->m_ignoreNextFolderChangeEvent )
|
|
{
|
|
fileCtrl->m_ignoreNextFolderChangeEvent = false;
|
|
}
|
|
else
|
|
{
|
|
GenerateFolderChangedEvent( fileCtrl, fileCtrl );
|
|
}
|
|
|
|
fileCtrl->m_checkNextSelEvent = true;
|
|
}
|
|
}
|
|
|
|
extern "C"
|
|
{
|
|
static void
|
|
gtkfilechooserwidget_notify_callback( GObject *WXUNUSED( gobject ), GParamSpec *arg1, wxGtkFileCtrl *fileCtrl )
|
|
{
|
|
const char *name = g_param_spec_get_name (arg1);
|
|
if ( strcmp( name, "filter" ) == 0 &&
|
|
fileCtrl->HasFilterChoice() &&
|
|
!fileCtrl->GTKShouldIgnoreNextFilterEvent() )
|
|
{
|
|
GenerateFilterChangedEvent( fileCtrl, fileCtrl );
|
|
}
|
|
}
|
|
}
|
|
|
|
// wxGtkFileCtrl implementation
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS( wxGtkFileCtrl, wxControl )
|
|
|
|
wxGtkFileCtrl::~wxGtkFileCtrl()
|
|
{
|
|
if (m_fcWidget)
|
|
GTKDisconnect(m_fcWidget);
|
|
}
|
|
|
|
void wxGtkFileCtrl::Init()
|
|
{
|
|
m_checkNextSelEvent = false;
|
|
|
|
// ignore the first folder change event which is fired upon startup.
|
|
m_ignoreNextFolderChangeEvent = true;
|
|
}
|
|
|
|
bool wxGtkFileCtrl::Create( wxWindow *parent,
|
|
wxWindowID id,
|
|
const wxString& defaultDirectory,
|
|
const wxString& defaultFileName,
|
|
const wxString& wildCard,
|
|
long style,
|
|
const wxPoint& pos,
|
|
const wxSize& size,
|
|
const wxString& name )
|
|
{
|
|
if ( !PreCreation( parent, pos, size ) ||
|
|
!CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ) )
|
|
{
|
|
wxFAIL_MSG( wxT( "wxGtkFileCtrl creation failed" ) );
|
|
return false;
|
|
}
|
|
|
|
GtkFileChooserAction gtkAction = GTK_FILE_CHOOSER_ACTION_OPEN;
|
|
|
|
if ( style & wxFC_SAVE )
|
|
gtkAction = GTK_FILE_CHOOSER_ACTION_SAVE;
|
|
|
|
m_widget = gtk_alignment_new ( 0, 0, 1, 1 );
|
|
g_object_ref(m_widget);
|
|
m_fcWidget = GTK_FILE_CHOOSER( gtk_file_chooser_widget_new(gtkAction) );
|
|
gtk_widget_show ( GTK_WIDGET( m_fcWidget ) );
|
|
gtk_container_add ( GTK_CONTAINER ( m_widget ), GTK_WIDGET( m_fcWidget ) );
|
|
|
|
m_focusWidget = GTK_WIDGET( m_fcWidget );
|
|
|
|
g_signal_connect ( m_fcWidget, "file-activated",
|
|
G_CALLBACK ( gtkfilechooserwidget_file_activated_callback ),
|
|
this );
|
|
|
|
g_signal_connect ( m_fcWidget, "current-folder-changed",
|
|
G_CALLBACK ( gtkfilechooserwidget_folder_changed_callback ),
|
|
this );
|
|
|
|
g_signal_connect ( m_fcWidget, "selection-changed",
|
|
G_CALLBACK ( gtkfilechooserwidget_selection_changed_callback ),
|
|
this );
|
|
|
|
g_signal_connect ( m_fcWidget, "notify",
|
|
G_CALLBACK ( gtkfilechooserwidget_notify_callback ),
|
|
this );
|
|
|
|
m_fc.SetWidget( m_fcWidget );
|
|
|
|
if ( style & wxFC_MULTIPLE )
|
|
gtk_file_chooser_set_select_multiple( m_fcWidget, true );
|
|
|
|
SetWildcard( wildCard );
|
|
|
|
// if defaultDir is specified it should contain the directory and
|
|
// defaultFileName should contain the default name of the file, however if
|
|
// directory is not given, defaultFileName contains both
|
|
wxFileName fn;
|
|
if ( defaultDirectory.empty() )
|
|
fn.Assign( defaultFileName );
|
|
else if ( !defaultFileName.empty() )
|
|
fn.Assign( defaultDirectory, defaultFileName );
|
|
else
|
|
fn.AssignDir( defaultDirectory );
|
|
|
|
// set the initial file name and/or directory
|
|
const wxString dir = fn.GetPath();
|
|
if ( !dir.empty() )
|
|
{
|
|
gtk_file_chooser_set_current_folder( m_fcWidget,
|
|
wxGTK_CONV_FN(dir) );
|
|
}
|
|
|
|
const wxString fname = fn.GetFullName();
|
|
if ( style & wxFC_SAVE )
|
|
{
|
|
if ( !fname.empty() )
|
|
{
|
|
gtk_file_chooser_set_current_name( m_fcWidget,
|
|
wxGTK_CONV_FN(fname) );
|
|
}
|
|
}
|
|
else // wxFC_OPEN
|
|
{
|
|
if ( !fname.empty() )
|
|
{
|
|
gtk_file_chooser_set_filename( m_fcWidget,
|
|
wxGTK_CONV_FN(fn.GetFullPath()) );
|
|
}
|
|
}
|
|
|
|
m_parent->DoAddChild( this );
|
|
|
|
PostCreation( size );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
bool wxGtkFileCtrl::SetPath( const wxString& path )
|
|
{
|
|
return m_fc.SetPath( path );
|
|
}
|
|
|
|
bool wxGtkFileCtrl::SetDirectory( const wxString& dir )
|
|
{
|
|
return m_fc.SetDirectory( dir );
|
|
}
|
|
|
|
bool wxGtkFileCtrl::SetFilename( const wxString& name )
|
|
{
|
|
if ( HasFlag( wxFC_SAVE ) )
|
|
{
|
|
gtk_file_chooser_set_current_name( m_fcWidget, wxGTK_CONV( name ) );
|
|
return true;
|
|
}
|
|
else
|
|
return SetPath( wxFileName( GetDirectory(), name ).GetFullPath() );
|
|
}
|
|
|
|
void wxGtkFileCtrl::SetWildcard( const wxString& wildCard )
|
|
{
|
|
m_wildCard = wildCard;
|
|
|
|
m_fc.SetWildcard( wildCard );
|
|
}
|
|
|
|
void wxGtkFileCtrl::SetFilterIndex( int filterIndex )
|
|
{
|
|
m_fc.SetFilterIndex( filterIndex );
|
|
}
|
|
|
|
wxString wxGtkFileCtrl::GetPath() const
|
|
{
|
|
return m_fc.GetPath();
|
|
}
|
|
|
|
void wxGtkFileCtrl::GetPaths( wxArrayString& paths ) const
|
|
{
|
|
m_fc.GetPaths( paths );
|
|
}
|
|
|
|
wxString wxGtkFileCtrl::GetDirectory() const
|
|
{
|
|
return m_fc.GetDirectory();
|
|
}
|
|
|
|
wxString wxGtkFileCtrl::GetFilename() const
|
|
{
|
|
return m_fc.GetFilename();
|
|
}
|
|
|
|
void wxGtkFileCtrl::GetFilenames( wxArrayString& files ) const
|
|
{
|
|
m_fc.GetFilenames( files );
|
|
}
|
|
|
|
void wxGtkFileCtrl::ShowHidden(bool show)
|
|
{
|
|
gtk_file_chooser_set_show_hidden(m_fcWidget, show);
|
|
}
|
|
|
|
#endif // wxUSE_FILECTRL
|
|
|
|
#endif // wxUSE_FILECTRL && !defined(__WXUNIVERSAL__)
|