diff options
Diffstat (limited to 'UGnome.pas')
| -rw-r--r-- | UGnome.pas | 316 |
1 files changed, 314 insertions, 2 deletions
@@ -22,7 +22,8 @@ unit UGnome; interface uses glib2, gdk2, gdk2pixbuf, gtk2, Classes, ULibc, - GTKForms, GTKControls, GTKStdCtrls, GTKExtCtrls, GTKClasses, GTKDialogs, GTKUtils, GTKConsts; + GTKForms, GTKControls, GTKStdCtrls, GTKExtCtrls, GTKClasses, GTKDialogs, GTKUtils, GTKConsts, + uVFSprototypes; type TGnomeColorButton = class(TGTKButton) private @@ -147,6 +148,22 @@ function MessageBoxShowOnce(const Text: string; const DontShowAgainText: string; Buttons: TMessageButtons = [mbOK]; Style: TMessageStyle = mbInfo; Default: TMessageButton = mbNone; Escape: TMessageButton = mbNone): TMessageButton; +procedure HandleVFSAskQuestionCallback(DialogParent: PGtkWidget; + const AMessage: PChar; + const Choices: PPChar; + choice: PInteger); + +function HandleVFSAskPasswordCallback(DialogParent: PGtkWidget; + const AMessage: PChar; + const default_user: PChar; + const default_domain: PChar; + flags: TVFSAskPasswordFlags; + username: PPChar; + password: PPChar; + anonymous: PInteger; + domain: PPChar; + password_save: PVFSPasswordSave): LongBool; + type PGnomeColorPicker = PGtkWidget; @@ -177,9 +194,20 @@ var libGlib2Handle, libGtk2Handle, libGnome2Handle, libGnomeUI2Handle: Pointer; gnome_date_edit_new: function (the_time: time_t; show_time, use_24_format: gboolean): PGtkWidget; cdecl; gnome_date_edit_set_time: procedure (gde: PGnomeDateEdit; the_time: time_t); cdecl; gnome_date_edit_get_time: function (gde: PGnomeDateEdit): time_t; cdecl; + gtk_event_box_set_visible_window: procedure (event_box: PGtkEventBox; visible_window: gboolean); cdecl; gtk_icon_size_lookup_for_settings: function (settings: PGtkSettings; size: TGtkIconSize; width, height: Pgint): gboolean; cdecl; g_filename_display_name: function (const filename: PChar): PChar; cdecl; +{$IFDEF KYLIX} + gtk_message_dialog_new_with_markup: function (parent:PGtkWindow; flags:TGtkDialogFlags; + _type:TGtkMessageType; buttons:TGtkButtonsType; + message_format:Pgchar; const format1: PChar; const format2: PChar):PGtkWidget; cdecl; +{$ELSE} + gtk_message_dialog_new_with_markup: function (parent:PGtkWindow; flags:TGtkDialogFlags; + _type:TGtkMessageType; buttons:TGtkButtonsType; + message_format:Pgchar):PGtkWidget; varargs; cdecl; +{$ENDIF} + @@ -187,7 +215,7 @@ procedure LoadGnomeLibs; implementation -uses SysUtils, DateUtils, UConfig, UCoreUtils, ULocale; +uses SysUtils, DateUtils, UConfig, UCoreUtils, ULocale, UFileAssoc; (********************************************************************************************************************************) @@ -1194,6 +1222,289 @@ begin gtk_widget_destroy(Dialog); end; + +(********************************************************************************************************************************) +(********************************************************************************************************************************) +// The following code has been stolen from gtkmountoperation.c +// Copyright (C) Christian Kellner <gicmo@gnome.org> +procedure HandleVFSAskQuestionCallback(DialogParent: PGtkWidget; + const AMessage: PChar; + const Choices: PPChar; + choice: PInteger); +var dialog: PGtkWidget; + secondary: PChar; + primary: PChar; + count, len: integer; +begin + len := 0; + secondary := nil; + if (AMessage = nil) or (choices = nil) or Application.Terminated then Exit; + + primary := strstr (AMessage, #10); + if primary <> nil then begin + secondary := primary + 1; + primary := g_strndup (AMessage, primary - AMessage); + end; + + if (primary <> nil) and (secondary <> nil) and (@gtk_message_dialog_new_with_markup <> nil) + then dialog := gtk_message_dialog_new_with_markup (PGtkWindow(DialogParent), 0, + GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, + '<span size="large" weight="ultrabold">%s</span>'#10'%s', + primary, secondary) + else dialog := gtk_message_dialog_new (PGtkWindow(DialogParent), 0, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_NONE, '%s', AMessage); + if primary <> nil then g_free (primary); + + gtk_window_set_title (PGtkWindow(dialog), 'VFS Question'); + + // First count the items in the list then add the buttons in reverse order + while (TOpenPCharArray(choices)[len] <> nil) + do Inc(len); + + for count := len - 1 downto 0 do + gtk_dialog_add_button (PGtkDialog(dialog), TOpenPCharArray(choices)[count], count); + + choice^ := gtk_dialog_run(PGtkDialog(Dialog)); + + gtk_widget_destroy (PGtkWidget(Dialog)); +end; + +(********************************************************************************************************************************) +type PVFSAskPasswordCallbackPriv = ^TVFSAskPasswordCallbackPriv; + TVFSAskPasswordCallbackPriv = record + dialog: PGtkDialog; + entry_container: PGtkWidget; + choice_anon, choice_user: PGtkWidget; + username_entry, domain_entry, password_entry: PGtkEntry; + end; + +function entry_has_input(entry_widget: PGtkEntry): boolean; +var text: PChar; +begin + if entry_widget = nil then Result := True + else begin + text := gtk_entry_get_text (entry_widget); + Result := (text <> nil) and (strlen(text) > 0); + end; +end; + +function pw_dialog_input_is_valid (priv: PVFSAskPasswordCallbackPriv): boolean; +begin + Result := entry_has_input(priv^.username_entry) and + entry_has_input(priv^.domain_entry) and + entry_has_input(priv^.password_entry); +end; + +procedure pw_dialog_verify_input(editable: PGtkEditable; priv: PVFSAskPasswordCallbackPriv); cdecl; +begin + gtk_dialog_set_response_sensitive (GTK_DIALOG (priv^.dialog), + GTK_RESPONSE_OK, + pw_dialog_input_is_valid(priv)); +end; + +procedure pw_dialog_anonymous_toggled(widget: PGtkWidget; priv: PVFSAskPasswordCallbackPriv); cdecl; +var is_valid, anonymous: boolean; +begin + anonymous := widget = priv^.choice_anon; + if anonymous then is_valid := True + else is_valid := pw_dialog_input_is_valid(priv); + gtk_widget_set_sensitive (priv^.entry_container, not anonymous); + gtk_dialog_set_response_sensitive(GTK_DIALOG (priv^.dialog), GTK_RESPONSE_OK, is_valid); +end; + +procedure pw_dialog_cycle_focus (widget: PGtkWidget; priv: PVFSAskPasswordCallbackPriv); cdecl; +var next_widget: PGtkWidget; +begin + next_widget := nil; + if widget = PGtkWidget(priv^.username_entry) then begin + if priv^.domain_entry <> nil then next_widget := PGtkWidget(priv^.domain_entry) + else if priv^.password_entry <> nil then next_widget := PGtkWidget(priv^.password_entry); + end else if (widget = PGtkWidget(priv^.domain_entry)) and (priv^.password_entry <> nil) + then next_widget := PGtkWidget(priv^.password_entry); + if next_widget <> nil then gtk_widget_grab_focus(next_widget) + else if pw_dialog_input_is_valid(priv) + then gtk_window_activate_default(GTK_WINDOW(priv^.dialog)); +end; + + +// The following code has been stolen from gtkmountoperation.c +// Copyright (C) Christian Kellner <gicmo@gnome.org> +function HandleVFSAskPasswordCallback(DialogParent: PGtkWidget; + const AMessage: PChar; + const default_user: PChar; + const default_domain: PChar; + flags: TVFSAskPasswordFlags; + username: PPChar; + password: PPChar; + anonymous: PInteger; + domain: PPChar; + password_save: PVFSPasswordSave): LongBool; + +function table_add_entry(table: PGtkWidget; row: integer; const label_text: PChar; const value: PChar; user_data: PVFSAskPasswordCallbackPriv): PGtkEntry; +var entry: PGtkEntry; + alabel: PGtkWidget; +begin + alabel := gtk_label_new_with_mnemonic (label_text); + gtk_misc_set_alignment (GTK_MISC (alabel), 0.0, 0.5); + entry := PGtkEntry(gtk_entry_new ()); + if value <> nil then gtk_entry_set_text (PGtkEntry(entry), value); + gtk_table_attach (GTK_TABLE (table), alabel, 0, 1, row, row + 1, GTK_FILL, GTK_EXPAND or GTK_FILL, 0, 0); + gtk_table_attach_defaults (GTK_TABLE (table), PGtkWidget(entry), 1, 2, row, row + 1); + gtk_label_set_mnemonic_widget (PGtkLabel(alabel), PGtkWidget(entry)); + g_signal_connect (entry, 'changed', G_CALLBACK (@pw_dialog_verify_input), user_data); + g_signal_connect (entry, 'activate', G_CALLBACK (@pw_dialog_cycle_focus), user_data); + Result := entry; +end; + +var widget: PGtkWidget; + window: PGtkWindow; + hbox, main_vbox, vbox, icon: PGtkWidget; + table: PGtkWidget; + message_label: PGtkWidget; + can_anonymous: boolean; + Rows: integer; + anon_box: PGtkWidget; + radio_forget, radio_session, radio_remember: PGtkWidget; + group: PGSList; + remember_box: PGtkWidget; + priv: TVFSAskPasswordCallbackPriv; +begin + FillChar(priv, sizeof(priv), 0); + radio_forget := nil; + radio_session := nil; + radio_remember := nil; + + widget := gtk_dialog_new (); + priv.dialog := PGtkDialog(widget); + window := PGtkWindow(widget); + gtk_window_set_title (window, 'VFS Question'); + + // Set the dialog up with HIG properties + gtk_dialog_set_has_separator (priv.dialog, False); + gtk_container_set_border_width (GTK_CONTAINER (priv.dialog), 5); + gtk_box_set_spacing (GTK_BOX (priv.dialog^.vbox), 2); // 2 * 5 + 2 = 12 + gtk_container_set_border_width (GTK_CONTAINER (priv.dialog^.action_area), 5); + gtk_box_set_spacing (GTK_BOX (priv.dialog^.action_area), 6); + + gtk_window_set_resizable (window, False); +// gtk_window_set_icon_name (window, 'gtk-dialog-authentication'); + + gtk_dialog_add_buttons (priv.dialog, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + 'Co_nnect', GTK_RESPONSE_OK, + nil); + gtk_dialog_set_default_response (priv.dialog, GTK_RESPONSE_OK); + + // Build contents + hbox := gtk_hbox_new (FALSE, 12); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); + gtk_box_pack_start (GTK_BOX (priv.dialog^.vbox), hbox, TRUE, TRUE, 0); + + if gtk_style_lookup_icon_set(gtk_widget_get_style(PGtkWidget(priv.dialog)), 'gtk-dialog-authentication') <> nil + then icon := gtk_image_new_from_stock('gtk-dialog-authentication', GTK_ICON_SIZE_DIALOG) + else icon := gtk_image_new_from_pixbuf(StockLock48.FPixbuf); + + gtk_misc_set_alignment (GTK_MISC (icon), 0.5, 0.0); + gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0); + + main_vbox := gtk_vbox_new (FALSE, 18); + gtk_box_pack_start (GTK_BOX (hbox), main_vbox, TRUE, TRUE, 0); + + message_label := gtk_label_new (AMessage); + gtk_misc_set_alignment (GTK_MISC (message_label), 0.0, 0.5); + gtk_label_set_line_wrap (GTK_LABEL (message_label), TRUE); + gtk_box_pack_start (GTK_BOX (main_vbox), GTK_WIDGET (message_label), FALSE, FALSE, 0); + + vbox := gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0); + + can_anonymous := (Integer(flags) and Integer(VFS_ASK_PASSWORD_ANONYMOUS_SUPPORTED)) = Integer(VFS_ASK_PASSWORD_ANONYMOUS_SUPPORTED); + + if can_anonymous then begin + anon_box := gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (vbox), anon_box, FALSE, FALSE, 0); + + priv.choice_anon := gtk_radio_button_new_with_mnemonic (nil, 'Connect _anonymously'); + gtk_box_pack_start (GTK_BOX (anon_box), priv.choice_anon, FALSE, FALSE, 0); + g_signal_connect (priv.choice_anon, 'toggled', G_CALLBACK (@pw_dialog_anonymous_toggled), @priv); + + group := gtk_radio_button_get_group (GTK_RADIO_BUTTON (priv.choice_anon)); + priv.choice_user := gtk_radio_button_new_with_mnemonic (group, 'Connect as u_ser:'); + gtk_box_pack_start (GTK_BOX (anon_box), priv.choice_user, FALSE, FALSE, 0); + g_signal_connect (priv.choice_user, 'toggled', G_CALLBACK (@pw_dialog_anonymous_toggled), @priv); + end; + + rows := 0; + if (Integer(flags) and Integer(VFS_ASK_PASSWORD_NEED_PASSWORD)) = Integer(VFS_ASK_PASSWORD_NEED_PASSWORD) then Inc(rows); + if (Integer(flags) and Integer(VFS_ASK_PASSWORD_NEED_USERNAME)) = Integer(VFS_ASK_PASSWORD_NEED_USERNAME) then Inc(rows); + if (Integer(flags) and Integer(VFS_ASK_PASSWORD_NEED_DOMAIN)) = Integer(VFS_ASK_PASSWORD_NEED_DOMAIN) then Inc(rows); + + // The table that holds the entries + priv.entry_container := gtk_alignment_new (0.0, 0.0, 1.0, 1.0); + + if can_anonymous and Application.GTKVersion_2_4_0_Up then g_object_set (priv.entry_container, 'left-padding', 12, nil); + gtk_box_pack_start (GTK_BOX (vbox), priv.entry_container, FALSE, FALSE, 0); + + table := gtk_table_new (rows, 2, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 12); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_container_add (GTK_CONTAINER (priv.entry_container), table); + + Rows := 0; + if (Integer(flags) and Integer(VFS_ASK_PASSWORD_NEED_USERNAME)) = Integer(VFS_ASK_PASSWORD_NEED_USERNAME) then begin + priv.username_entry := table_add_entry (table, rows, '_Username:', default_user, @priv); + Inc(Rows); + end; + if (Integer(flags) and Integer(VFS_ASK_PASSWORD_NEED_DOMAIN)) = Integer(VFS_ASK_PASSWORD_NEED_DOMAIN) then begin + priv.domain_entry := table_add_entry (table, rows, '_Domain:', default_domain, @priv); + Inc(Rows); + end; + if (Integer(flags) and Integer(VFS_ASK_PASSWORD_NEED_PASSWORD)) = Integer(VFS_ASK_PASSWORD_NEED_PASSWORD) then begin + priv.password_entry := table_add_entry (table, rows, '_Password:', nil, @priv); +// Inc(Rows); + gtk_entry_set_visibility (GTK_ENTRY (priv.password_entry), FALSE); + end; + + if (Integer(flags) and Integer(VFS_ASK_PASSWORD_SAVING_SUPPORTED)) = Integer(VFS_ASK_PASSWORD_SAVING_SUPPORTED) then begin + remember_box := gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (vbox), remember_box, FALSE, FALSE, 0); + + radio_forget := gtk_radio_button_new_with_mnemonic (nil, 'Forget password _immediately'); + gtk_box_pack_start (GTK_BOX (remember_box), radio_forget, FALSE, FALSE, 0); + + group := gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_forget)); + radio_session := gtk_radio_button_new_with_mnemonic (group, 'Remember password until you _logout'); + gtk_box_pack_start (GTK_BOX (remember_box), radio_session, FALSE, FALSE, 0); + + group := gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_session)); + radio_remember := gtk_radio_button_new_with_mnemonic (group, 'Remember _forever'); + gtk_box_pack_start (GTK_BOX (remember_box), radio_remember, FALSE, FALSE, 0); + end; + + // The anonymous option will be active by default, ensure the toggled signal is emitted for it. + if can_anonymous then gtk_toggle_button_toggled (GTK_TOGGLE_BUTTON (priv.choice_anon)) else + if not pw_dialog_input_is_valid(@priv) then gtk_dialog_set_response_sensitive(priv.dialog, GTK_RESPONSE_OK, False); + + gtk_widget_show_all (GTK_WIDGET (priv.dialog)); + gtk_window_set_transient_for (window, PGtkWindow(DialogParent)); + + Result := gtk_dialog_run(PGtkDialog(priv.dialog)) = GTK_RESPONSE_OK; + if Result then begin + if (priv.username_entry <> nil) and (username <> nil) then username^ := g_strdup(gtk_entry_get_text(priv.username_entry)); + if (priv.domain_entry <> nil) and (domain <> nil) then domain^ := g_strdup(gtk_entry_get_text(priv.domain_entry)); + if (priv.password_entry <> nil) and (password <> nil) then password^ := g_strdup(gtk_entry_get_text(priv.password_entry)); + if (priv.choice_anon <> nil) and (anonymous <> nil) then anonymous^ := Ord(gtk_toggle_button_get_active(PGtkToggleButton(priv.choice_anon))); + if (password_save <> nil) and (radio_forget <> nil) and (radio_session <> nil) and (radio_remember <> nil) then begin + if gtk_toggle_button_get_active(PGtkToggleButton(radio_forget)) then password_save^ := VFS_PASSWORD_SAVE_NEVER else + if gtk_toggle_button_get_active(PGtkToggleButton(radio_session)) then password_save^ := VFS_PASSWORD_SAVE_FOR_SESSION else + if gtk_toggle_button_get_active(PGtkToggleButton(radio_remember)) then password_save^ := VFS_PASSWORD_SAVE_PERMANENTLY; + end; + end; + gtk_widget_destroy (PGtkWidget(priv.dialog)); +end; + + (********************************************************************************************************************************) (********************************************************************************************************************************) (********************************************************************************************************************************) @@ -1245,6 +1556,7 @@ begin if libGtk2Handle <> nil then begin @gtk_event_box_set_visible_window := dlsym(libGtk2Handle, 'gtk_event_box_set_visible_window'); @gtk_icon_size_lookup_for_settings := dlsym(libGtk2Handle, 'gtk_icon_size_lookup_for_settings'); + @gtk_message_dialog_new_with_markup := dlsym(libGtk2Handle, 'gtk_message_dialog_new_with_markup'); DebugMsg(['libgtk-x11-2.0.so loaded, @gtk_event_box_set_visible_window = 0x', IntToHex(QWORD(@gtk_event_box_set_visible_window), 8), ', @gtk_icon_size_lookup_for_settings = 0x', IntToHex(QWORD(@gtk_icon_size_lookup_for_settings), 8)]); end; |
