Gtk2-Ex-DBI

 view release on metacpan or  search on metacpan

lib/Gtk2/Ex/DBI.pm  view on Meta::CPAN

            }
            $self->{read_only} = TRUE;
        }
        
    } else {
        
        while ( my $column_info_row = $sth->fetchrow_hashref ) {
            # Loop through the list of columns from the database, and
            # add only columns that we're actually dealing with
            for my $fieldname ( keys %{$self->{sql_to_widget_map}} ) {
                if ( $column_info_row->{COLUMN_NAME} eq ( $fieldname ) ) {
                    # Note that we want to store this against the fieldname and NOT the sql_fieldname
                    $self->{column_info}->{ $self->{sql_to_widget_map}->{$fieldname} } = $column_info_row;
                    last;
                }
            }
        }
        
    }
    
    # Make sure we've got the primary key in the widgets hash and the sql_to_widget_map hash
    # It will NOT be here unless it's been specified in the SQL select string or the widgets hash already
    # Note that we test the sql_to_widget_map, and NOT the widgets hash, as we don't know what
    # the widget might be called, but we DO know what the name of the key in the sql_to_widget_map
    # should be
    foreach my $primary_key ( @{$self->{primary_keys}} ) {
        if ( ! exists $self->{sql_to_widget_map}->{ $primary_key } ) {
            $self->{widgets}->{ $primary_key } = {};
            $self->{sql_to_widget_map}->{ $primary_key } = $primary_key;
        }
        if ( $self->{dont_update_keys} ) {
            $self->{widgets}->{ $primary_key }->{dont_update} = 1;
        }
    }
    
    # If things failed above, we mightn't have a $sth to finish, so
    # check we do first ...
    if ( $sth ) {
        $sth->finish;
    }
    
    if ( ! $self->{skip_query} ) {
        $self->query;
    }
    
    # We connect a few little goodies to various widgets ...
    
    # - Connect our 'changed' method to whatever signal each widget emits when it's 'changed'
    
    # - Gtk's ComboBoxEntry has a bug where it only registers a change and set's the currect iter if
    # the combo box functionality is used. If the Entry functionality is used ( ie someone types a
    # string that matches one in the list ), NOTHING is registered, and the active iter is not set.
    # We *NEED* to work around this until the bug is fixed, otherwise ComboBoxEntrys are horribly broken.
    # Therefore we connect the sub set_active_iter_for_broken_combo_box to the on_focus_out event.
    
    # See http://bugzilla.gnome.org/show_bug.cgi?id=156017
    # Note that while the above bug page shows this bug as being 'FIXED', I've yet to see this
    # fix materialise in Gtk2 - when it does I will limit our work-around to those affected
    # versions of Gtk2.
    
    # - Use the populate-popup signal of Gtk2::Entry widgets to add the 'find' menu item
    
    # - Connect to the 'key-press-event' signal of various widgets to move the focus along
    # ( ie as if the TAB key was pressed )
    
    # We also keep an array of widgets and signal ids so that we can disconnect all signal handlers
    # and cleanly destroy ourselves when requested
    
    # We also set up input / output formatters based on widget ( ie $self->{widgets} )
        
	# Set up some defaults for different widget types
    foreach my $fieldname ( keys %{$self->{widgets}} ) {
    
    	# Get hold of the widget def ...
        my $widget_def = $self->{widgets}->{$fieldname};
        
        if ( exists $widget_def->{number} ) {
        	
        	# Properties of the number format:
            # - decimals				- number of decimal places
            # - decimal_fill			- whether to pad decimals out to the number of decimals
            # - separate_thousands		- whether to separate thousands groups with a comma
            # - currency				- whether to apply currency formatting
            
            # Set some defaults for properties that haven't been specified ...
            
            if ( ! exists $widget_def->{number}->{decimal_fill} ) {
            	$widget_def->{number}->{decimal_fill} = TRUE;
            }
            
            if ( ! exists $widget_def->{number}->{separate_thousands} ) {
            	$widget_def->{number}->{separate_thousands} = TRUE;
            }
            
            # If this is a currency widget, default to 2 decial places
            if ( exists $widget_def->{currency} && $widget_def->{currency} && ! exists $widget_def->{number}->{decimals} ) {
            	$widget_def->{number}->{decimals} = 2;
            }
            
        }
        
        my @widgets;
        my $this_widget = $self->get_widget( $fieldname );
        
        if ( $this_widget ) {
            
            push @widgets, $this_widget;
            
        } else {
        	
        	# TODO Remove dodgy split-widget support and replace with custom widgets
            # Check for split-widget widgets ... at present, TimeSpinners
            foreach my $type qw / hh mm ss / {
                $this_widget = $self->get_widget( $fieldname . "_" . $type );
                if ( $this_widget ) {
                    push @widgets, $this_widget;
                }
            }
            
        }
        

lib/Gtk2/Ex/DBI.pm  view on Meta::CPAN

                push @signals, $widget->signal_connect_after(
                    toggled =>              sub { $self->changed( $fieldname ) } );
                
            } elsif ( $type eq "Gtk2::TextView" ) {
                
                # In this case, we don't connect to the widget, but to the widget's buffer ...
                # ... so we swap the buffer into $widget, so we can disconnect our signal later
                $widget = $widget->get_buffer;
                push @signals, $widget->signal_connect_after(
                    changed =>              sub { $self->changed( $fieldname ) } );
                
            } elsif ( $type eq "Gtk2::ComboBoxEntry" ) {
                
                push @signals, $widget->signal_connect_after(
                    changed =>              sub { $self->changed( $fieldname ) } );
                
                # Append our work-around for broken combo directly to the objects_and_signals array ...
                #  ... We can't use the code below to append more than 1 widget at a time
                my $child_widget = $widget->get_child;
                
                my $signal = $child_widget->signal_connect_after(
                    changed =>              sub { $self->set_active_iter_for_broken_combo_box($widget) } );
                
                if ( $self->{debug} ) {
                    warn "Remembering object / signal pair for later disconnection ...\n"
                        . " Field:  $fieldname\n"
                        . " Widget: $child_widget\n"
                        . " Signal: $signal\n\n";
                }
                
                push @{$self->{objects_and_signals}},
                [
                    $child_widget,
                    $signal
                ];
                
                # Trigger 2 tab-forward events;
                #  1 to get to the combo part ( ie the child's parent widget )
                #  and 1 to get to the next widget
                $signal = $child_widget->signal_connect(
                    'activate' => sub { 
                        $self->{window}->child_focus('tab-forward');
                        $self->{window}->child_focus('tab-forward');
                } );
                
                if ( $self->{debug} ) {
                    warn "Remembering object / signal pair for later disconnection ...\n"
                        . " Field:  $fieldname\n"
                        . " Widget: $child_widget\n"
                        . " Signal: $signal\n\n";
                }
                
                push @{$self->{objects_and_signals}},
                [
                    $child_widget,
                    $signal
                ];
                
                # We also want a right-click menu for a Combo's child ( entry )
                $signal = $child_widget->signal_connect_after(
                    'populate-popup' =>     sub { $self->build_right_click_menu(@_) } );
                
                if ( $self->{debug} ) {
                    warn "Remembering object / signal pair for later disconnection ...\n"
                        . " Field:  $fieldname\n"
                        . " Widget: $child_widget\n"
                        . " Signal: $signal\n\n";
                }
                push @{$self->{objects_and_signals}},
                [
                    $child_widget,
                    $signal
                ];
                
            } elsif ( $type eq "Gtk2::CheckButton" ) {
                
                push @signals, $widget->signal_connect_after(
                    toggled =>              sub { $self->changed( $fieldname ) } );
                
            } elsif ( $type eq "Gtk2::Entry" ) {
                
                push @signals, $widget->signal_connect_after(
                    changed =>              sub { $self->changed( $fieldname ) } );
                push @signals, $widget->signal_connect_after(
                    'populate-popup' =>     sub { $self->build_right_click_menu(@_) } );
                push @signals, $widget->signal_connect(
                    'activate' => sub { $self->{window}->child_focus('tab-forward') } );
                
            } elsif ( $type eq "Gtk2::SpinButton" ) {
                
                push @signals, $widget->signal_connect_after(
                    changed =>              sub { $self->changed( $fieldname ) } );
                push @signals, $widget->signal_connect_after(
                    'populate-popup' =>     sub { $self->build_right_click_menu(@_) } );
                push @signals, $widget->signal_connect(
                    'key-press-event' =>    sub { $self->process_entry_keypress(@_) } );
                
            } else {
                
                push @signals, $widget->signal_connect_after(
                    changed =>              sub { $self->changed( $fieldname ) } );
                
            }
            # ... and then warn() some info about what we're doing, and also append
            # the objects and signals to the *real* list
            foreach my $signal ( @signals ) {
                if ( $self->{debug} ) {
                    warn "Remembering object / signal pair for later disconnection ...\n"
                        . " Field:  $fieldname\n"
                        . " Widget: $widget\n"
                        . " Signal: $signal\n\n";
                }
                push @{$self->{objects_and_signals}},
                [
                    $widget,
                    $signal
                ];
            }
        }
    }
    
    $self->{spinner} = $self->get_widget( $self->{record_spinner} );
    
    if ( $self->{spinner} ) {
        
        $self->{record_spinner_value_changed_signal}
            = $self->{spinner}->signal_connect_after( value_changed => sub {
                        $self->{spinner}->signal_handler_block( $self->{record_spinner_value_changed_signal} );
                        $self->move( undef, $self->{spinner}->get_text - 1 );
                        $self->{spinner}->signal_handler_unblock( $self->{record_spinner_value_changed_signal} );
                        return TRUE;
                    }
              );
        
        push @{$self->{objects_and_signals}},
        [
            $self->{spinner},
            $self->{record_spinner_value_changed_signal}
        ];
        
    }
    
    # Check recordset status when window is destroyed
    push @{$self->{objects_and_signals}},
    [
        $self->{window},
        $self->{window}->signal_connect( delete_event   => sub {
            if ( $self->{changed} ) {
                my $answer = TRUE;
                if ( ! $self->{auto_apply} ) {
                    my $answer = Gtk2::Ex::Dialogs::Question->new_and_run(
                        title   => "Apply changes to " . $self->{friendly_table_name} . " before closing?",
                        icon    => "question",
                        text    => $self->{custom_changed_text} ? $self->{custom_changed_text} : 



( run in 0.695 second using v1.01-cache-2.11-cpan-364913b4093 )