041. How to have a login prompt before main program starts - Part 3?

Problem

You have set up a login prompt in Part 1. However, there are a number of "annoyances":

  1. Pressing Enter does not automatically go to next field, or activates the "OK" button. This has been fixed in Part 2
  2. Suppose the user enters an invalid username or password, the login form gets destroyed, the alert box appears, and the login form re-appears agian. Ideally the login form should only disappear after the user has keyed in the correct username and password.

We will fix (2) in this article.


Solution

To fix (2), we just need to rearrange the code in Part 2.

The key is to do the validation check and alert the user of incorrect username or password BEFORE we destroy the login form.


Sample Code

Note: If you have installed php-gtk2 using Gnope Installer on Windows, and if running the sample code below gives you warning that the Symbolic names for keys (e.g. Gdk::KEY_Return) is not defined, you might want to update your php-gtk2 with the latest php-gtk2.dll available here. Simply download the php-gtk2.dll and replace the copy in the folder php-gtk2xt. The latest compilation has put in the Symbolic names for keys listed here.

1   
2   
3   
4   
5   
6   
7   
8   
9   
10   
11   
12   
13   
14   
15   
16   
17   
18   
19   
20   
21   
22   
23   
27   
38   
39   
40   
41   
42   
43   
44   
45   
46   
47   
48   
50   
51   
52   
53   
54   
55   
56   
57   
59   
60   
62   
63   
64   
65   
66   
68   
69   
70   
77   
78   
79   
80   
81   
82   
83   
84   
85   
86   
87   
88   
89   
90   
91   
92   
93   
94   
95   
96   
97   
98   
99   
101   
102   
103   
104   
108   
109   
110   
111   
112   
113   
116   
118   
119   
121   
122   
123   
124   
125   
126   
127   
128   
129   
132   
133   
134   
135   
136   
137   
138   
139   
140   
141   
142   
143   
144   
145   
147   
148   
149   
150   
151   
152   
153   
154   
155   
156   
157   
<?php

$login_success = login(); // calls the login function
if (!$login_success) exit(0); // exit if login not successful

// starts the main program only if login successful
$window = new GtkWindow();
$window->set_size_request(400, 150);
$window->connect_simple('destroy', array('Gtk','main_quit'));
$window->add($vbox = new GtkVBox());

// display title
$title = new GtkLabel("Login prompt - Part 3");
$title->modify_font(new PangoFontDescription("Times New Roman Italic 10"));
$title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff"));
$title->set_size_request(-1, 40);
$vbox->pack_start($title, 0, 0);

$vbox->pack_start(new GtkLabel("User verified"));
$vbox->pack_start(new GtkLabel("Main program starts..."));

// the login function
function login() {
    $ok = get_data("Login", array("Username:", "Password:"));
    return $ok;
}

// display a popup dialog box to prompt for data
function get_data($title, $field_labels) {
    $dialog = new GtkDialog($title, null, Gtk::DIALOG_MODAL);
    $dialog->set_position(Gtk::WIN_POS_CENTER_ALWAYS);
    $top_area = $dialog->vbox;
    $top_area->pack_start($hbox = new GtkHBox());
    $stock = GtkImage::new_from_stock(Gtk::STOCK_DIALOG_QUESTION, Gtk::ICON_SIZE_DIALOG);
    $hbox->pack_start($stock, 0, 0);

    $table = new GtkTable();
    $row = 0;
    $input = array();
    foreach ($field_labels as $field_label) {
        $label = new GtkLabel($field_label);
        $label->set_alignment(0,0);
        $table->attach($label, 0, 1, $row, $row+1);
        $input[$row] = new GtkEntry();
        $table->attach($input[$row], 1, 2, $row, $row+1);
        if (eregi("password", $field_label))
            $input[$row]->set_visibility(false);
        ++$row;
    }
    $hbox->pack_start($table);
    $dialog->add_button(Gtk::STOCK_OK, Gtk::RESPONSE_OK);
    $buttons = $dialog->action_area->get_children();
    $button_ok = $buttons[0];
    $dialog->connect('key-press-event', 'on_key', $input, $button_ok);
    $dialog->set_has_separator(false);
    $dialog->show_all();

    //do the login check before we destroy the login form
    $count = 0;
    $ok = 0;
    while ($count<3) { 
// allow user to try 3 times
        $dialog->run(); // prompt for username and password - note 1

        
// get the data entered by user
        $data = array();
        for ($i=0; $i<count($input); ++$i) {
            $data[] = $input[$i]->get_text();
        }

        
// login check here
        list($username, $password) = $data;
        if ($username=='user1' && $password=='phpgtk2') {
            $ok = 1; 
// login ok
            break;
        } else {
            alert("Incorrect username and password!\nHint: username=user1\npassword=phpgtk2");
        }
        ++$count;
    }


    $dialog->destroy(); // destroy the dialog
    return $ok;
}

// process key press
function on_key($widget, $event, $input, $button) {
    if ($event->keyval!=Gdk::KEY_Return) return false;
    $username = $input[0]->get_text();
    $passwd = $input[1]->get_text();
    if ($username=='') {
        $input[0]->grab_focus();
        return true;
    }
    if ($passwd=='') {
        $input[1]->grab_focus();
        return true;
    }
    if ($username!='' && $passwd!='') {
        $button->clicked();
    }

}

function alert($msg) {
    $dialog = new GtkDialog('Alert', null, Gtk::DIALOG_MODAL);
    $dialog->set_position(Gtk::WIN_POS_CENTER_ALWAYS);
    $top_area = $dialog->vbox;
    $top_area->pack_start($hbox = new GtkHBox());
    $stock = GtkImage::new_from_stock(Gtk::STOCK_DIALOG_WARNING,
        Gtk::ICON_SIZE_DIALOG);
    $hbox->pack_start($stock, 0, 0);
    $hbox->pack_start(new GtkLabel($msg));
    $dialog->add_button(Gtk::STOCK_OK, Gtk::RESPONSE_OK);
    $dialog->set_has_separator(false);
    $dialog->show_all();
    $dialog->run();
    $dialog->destroy();
}

$window->show_all();
Gtk::main();

?>

Output

How to have a login prompt before main program starts - Part 3?

 

Explanation

  1. You can keep "re-running" the dialog when user did not enter the correcct username and password.

Related Articles

Add comment


Security code
Refresh