039. How to have a login prompt before main program starts - Part 1?

Problem

You would like to have a login prompt before your main program starts as shown below:

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


Solution

We can easily use a GtkDialog to display the popup dialog box that prompts for username and password.

However, since a dialog box to prompt for data is frequently used, we will wrap this into a generic function called get_data(). We simply pass in the title of the dialog, and an array containing the field labels, the function will automatically display a dialog prompting user to enter the data.

When the user clicks the OK button, the data entered by the user will be returned to you as an array.


Sample Code

1   
2   
3   
4   
5   
6   
7   
8   
9   
10   
11   
12   
13   
14   
15   
16   
17   
18   
19   
20   
21   
22   
23   
24   
25   
27   
29   
30   
31   
32   
33   
34   
35   
36   
37   
38   
39   
40   
41   
42   
43   
44   
45   
46   
47   
48   
50   
51   
52   
53   
54   
55   
56   
57   
58   
60   
61   
63   
64   
65   
66   
67   
69   
70   
71   
72   
73   
74   
75   
76   
77   
78   
82   
83   
84   
85   
86   
87   
88   
89   
90   
91   
92   
93   
94   
95   
97   
98   
99   
100   
101   
102   
103   
104   
105   
106   
107   
<?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 1");
$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() {
    $count = 0;
    while ($count<3) {
        $data = get_data("Login", array("Username:", "Password:")); // get username and passwd
        list($username, $password) = $data; // result of user input is returned as an array
        if ($username=='user1' && $password=='phpgtk2') { // validate username and password
            return true; // ok!
        } else {
            alert("Incorrect username and password!\nHint: username=user1\npassword=phpgtk2");
            // not ok. alert user - note 2
        }
        ++$count;
    }
    return false;
}

// display a popup dialog box to prompt for data
function get_data($title, $field_labels) {
    $dialog = new GtkDialog($title, null, Gtk::DIALOG_MODAL); 
// create a new dialog
    $dialog->set_position(Gtk::WIN_POS_CENTER_ALWAYS);
    $top_area = $dialog->vbox; 
// get the top area
    $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); 
// stuff in the icon

    
// display the data entry form as table
    $table = new GtkTable(); // create a new table
    $row = 0;
    $input = array(); 
// holds the ID of each GtkEntry
    foreach ($field_labels as $field_label) {
        $label = new GtkLabel($field_label);
        $label->set_alignment(0,0); 
// left-justify the label
        $table->attach($label, 0, 1, $row, $row+1); // insert the label into table
        $input[$row] = new GtkEntry(); // create a new input field
        $table->attach($input[$row], 1, 2, $row, $row+1); // add this besides the label
        if (eregi("password", $field_label))
            $input[$row]->set_visibility(false); 
// show password entry as '*'
        ++$row;
    }
    $hbox->pack_start($table);
    $dialog->add_button(Gtk::STOCK_OK, Gtk::RESPONSE_OK); 
// add an OK button
    $dialog->set_has_separator(false); // don't display the set_has_separator
    $dialog->show_all(); // show the dialog
    $dialog->run(); // the dialog in action

    
// grab the user input before destroying the dialog - note 1
    $data = array(); // put user input in an array
    for ($i=0; $i<count($input); ++$i) {
        $data[] = $input[$i]->get_text();
    }
    $dialog->destroy(); 
// done. close the dialog box.
    return $data; // returns the user input as array
}

// display popup alert box - note 2
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

As shown above. Note: Don't press Enter. You have to click the "OK" button.

 

Explanation

  1. When the user clicks "OK", we need to grab the user input before the dialog is destroyed. Since we have stored the ID of each GtkEntry in $input[$row], we can easily get the value of the user input with GtkEntry::get_text().
  2. When user enters an invalid username or password, we alert the user with the alert() function we have written in How to display a popup alert for required fields - Part 1?

Note

This is a very useful function. For example, you can use a one-liner:
get_data("Item Details", array("Item number", "Item description", "quantity", "unit price")); to prompt user to enter the details of an item as shown below:

Of course, you can improve on the function to allow specification of the width of each field.

Please also note that there are a number of "annoyances" in this program:

  1. Pressing Enter does not automatically go to next field, or activates the "OK" button.
  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 this in the Part 2.

Related Articles

Add comment


Security code
Refresh