[hotssh] Clean up page UI, fix several state transitions
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [hotssh] Clean up page UI, fix several state transitions
- Date: Sun, 17 Nov 2013 21:46:12 +0000 (UTC)
commit c27e13552dc11273d4bd2bd7a0fc98d880cee071
Author: Colin Walters <walters verbum org>
Date: Sun Nov 17 16:43:22 2013 -0500
Clean up page UI, fix several state transitions
Separate a "status" page from the error page. While we're doing async
ops, we bounce to the status page. For example, this now occurs
between approving the hostkey and requesting a channel, when trying
noninteractive authentication mechanisms, etc.
Switch to the new error page on all errors.
To make this all saner, don't do transitions on connection state
changes; instead, make all transitions as the result of async
operations.
libgssh/gssh-connection.c | 27 ++++--
src/hotssh-tab.c | 66 +++++++++-----
src/tab.ui | 231 +++++++++++++++++++++++++++++++++++---------
3 files changed, 246 insertions(+), 78 deletions(-)
---
diff --git a/libgssh/gssh-connection.c b/libgssh/gssh-connection.c
index 34d78b2..2de3474 100644
--- a/libgssh/gssh-connection.c
+++ b/libgssh/gssh-connection.c
@@ -370,11 +370,21 @@ garray_append_uint (GArray *array, guint val)
g_array_append_val (array, val);
}
-/* This evil function is necessary because we can recurse into the
+/* These evil functions are necessary because we can recurse into the
* iteration function via g_task_return_error() calling the callback
* immediately.
*/
static void
+return_task_success_and_clear (GTask **taskptr)
+{
+ GTask *task = *taskptr;
+
+ *taskptr = NULL;
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
+static void
return_task_error_and_clear (GTask **taskptr,
GError *error)
{
@@ -425,10 +435,8 @@ gssh_connection_iteration_internal (GSshConnection *self,
return;
}
- g_task_return_boolean (self->handshake_task, TRUE);
- g_clear_object (&self->handshake_task);
-
state_transition (self, GSSH_CONNECTION_STATE_PREAUTH);
+ return_task_success_and_clear (&self->handshake_task);
/* Fall through */
}
case GSSH_CONNECTION_STATE_PREAUTH:
@@ -447,13 +455,14 @@ gssh_connection_iteration_internal (GSshConnection *self,
}
else if (rc == SSH_AUTH_SUCCESS)
{
+ return_task_success_and_clear (&self->negotiate_task);
state_transition (self, GSSH_CONNECTION_STATE_CONNECTED);
goto repeat;
}
else if (rc == SSH_AUTH_ERROR)
{
_gssh_set_error_from_libssh (error, "NONE authentication failed", self->session);
- return_task_error_and_clear (&self->auth_task, local_error);
+ return_task_error_and_clear (&self->negotiate_task, local_error);
}
else
{
@@ -477,7 +486,8 @@ gssh_connection_iteration_internal (GSshConnection *self,
;
state_transition (self, GSSH_CONNECTION_STATE_AUTHENTICATION_REQUIRED);
- /* Fall through */
+ return_task_success_and_clear (&self->negotiate_task);
+ break;
}
case GSSH_CONNECTION_STATE_AUTHENTICATION_REQUIRED:
{
@@ -591,8 +601,7 @@ gssh_connection_iteration_internal (GSshConnection *self,
}
else
{
- g_task_return_boolean (self->auth_task, TRUE);
- g_clear_object (&self->auth_task);
+ return_task_success_and_clear (&self->auth_task);
state_transition (self, GSSH_CONNECTION_STATE_CONNECTED);
goto repeat;
}
@@ -754,8 +763,10 @@ gssh_connection_negotiate_async (GSshConnection *self,
gpointer user_data)
{
g_return_if_fail (self->state == GSSH_CONNECTION_STATE_PREAUTH);
+ g_return_if_fail (self->negotiate_task == NULL);
state_transition (self, GSSH_CONNECTION_STATE_NEGOTIATE_AUTH);
self->paused = FALSE;
+ self->negotiate_task = g_task_new (self, cancellable, callback, user_data);
gssh_connection_iteration_default (self);
}
diff --git a/src/hotssh-tab.c b/src/hotssh-tab.c
index cdf9854..755fe30 100644
--- a/src/hotssh-tab.c
+++ b/src/hotssh-tab.c
@@ -53,8 +53,10 @@ typedef struct _HotSshTabPrivate HotSshTabPrivate;
typedef enum {
HOTSSH_TAB_PAGE_NEW_CONNECTION,
- HOTSSH_TAB_PAGE_INTERSTITAL,
- HOTSSH_TAB_PAGE_AUTH,
+ HOTSSH_TAB_PAGE_CONNECTING,
+ HOTSSH_TAB_PAGE_ERROR,
+ HOTSSH_TAB_PAGE_HOSTKEY,
+ HOTSSH_TAB_PAGE_PASSWORD,
HOTSSH_TAB_PAGE_TERMINAL
} HotSshTabPage;
@@ -70,6 +72,8 @@ struct _HotSshTabPrivate
GtkWidget *connect_button;
GtkWidget *connection_text_container;
GtkWidget *connection_text;
+ GtkWidget *error_text;
+ GtkWidget *error_disconnect;
GtkWidget *password_container;
GtkWidget *password_entry;
GtkWidget *password_submit;
@@ -78,6 +82,7 @@ struct _HotSshTabPrivate
GtkWidget *hostkey_container;
GtkWidget *hostkey_fingerprint_label;
GtkWidget *approve_hostkey_button;
+ GtkWidget *disapprove_hostkey_button;
GtkWidget *terminal_box;
/* State */
@@ -107,6 +112,7 @@ set_status (HotSshTab *self,
const char *text)
{
HotSshTabPrivate *priv = hotssh_tab_get_instance_private (self);
+ g_debug ("status: %s", text);
gtk_label_set_text ((GtkLabel*)priv->connection_text, text);
}
@@ -155,7 +161,8 @@ page_transition (HotSshTab *self,
new_page <= HOTSSH_TAB_PAGE_TERMINAL);
priv->active_page = new_page;
- if (priv->active_page == HOTSSH_TAB_PAGE_NEW_CONNECTION)
+ if (priv->active_page == HOTSSH_TAB_PAGE_NEW_CONNECTION
+ || priv->active_page == HOTSSH_TAB_PAGE_ERROR)
state_reset_for_new_connection (self);
gtk_notebook_set_current_page ((GtkNotebook*)self, (guint)new_page);
@@ -168,8 +175,10 @@ static void
page_transition_take_error (HotSshTab *self,
GError *error)
{
+ HotSshTabPrivate *priv = hotssh_tab_get_instance_private (self);
g_debug ("Caught error: %s", error->message);
- set_status (self, error->message);
+ page_transition (self, HOTSSH_TAB_PAGE_ERROR);
+ gtk_label_set_text ((GtkLabel*)priv->error_text, error->message);
g_error_free (error);
}
@@ -243,28 +252,18 @@ on_connection_state_notify (GSshConnection *conn,
HotSshTabPrivate *priv = hotssh_tab_get_instance_private (self);
GSshConnectionState new_state = gssh_connection_get_state (conn);
- g_debug ("connection state: %u", new_state);
-
switch (new_state)
{
case GSSH_CONNECTION_STATE_DISCONNECTED:
- page_transition (self, HOTSSH_TAB_PAGE_NEW_CONNECTION);
- break;
case GSSH_CONNECTION_STATE_CONNECTING:
case GSSH_CONNECTION_STATE_HANDSHAKING:
- page_transition (self, HOTSSH_TAB_PAGE_INTERSTITAL);
- break;
case GSSH_CONNECTION_STATE_PREAUTH:
case GSSH_CONNECTION_STATE_NEGOTIATE_AUTH:
break;
case GSSH_CONNECTION_STATE_AUTHENTICATION_REQUIRED:
- page_transition (self, HOTSSH_TAB_PAGE_AUTH);
- iterate_authentication_modes (self);
break;
case GSSH_CONNECTION_STATE_ERROR:
- gtk_widget_hide (priv->hostkey_container);
- gtk_widget_show (priv->connection_text_container);
- page_transition (self, HOTSSH_TAB_PAGE_INTERSTITAL);
+ g_debug ("connection in state ERROR!");
break;
case GSSH_CONNECTION_STATE_CONNECTED:
gssh_connection_open_shell_async (priv->connection, priv->cancellable,
@@ -287,6 +286,8 @@ on_auth_complete (GObject *src,
if (!gssh_connection_auth_finish ((GSshConnection*)src, res, &local_error))
goto out;
+ set_status (self, "Authenticated, requesting channel...");
+
g_debug ("auth complete");
out:
@@ -330,11 +331,15 @@ iterate_authentication_modes (HotSshTab *self)
&n_mechanisms);
if (priv->have_outstanding_auth)
- return;
+ {
+ return;
+ }
if (priv->awaiting_password_entry &&
!priv->submitted_password)
- return;
+ {
+ return;
+ }
while (priv->authmechanism_index < G_N_ELEMENTS (default_authentication_order) &&
!have_mechanism (available_authmechanisms, n_mechanisms,
@@ -365,7 +370,14 @@ iterate_authentication_modes (HotSshTab *self)
{
priv->awaiting_password_entry = TRUE;
if (!priv->submitted_password)
- return;
+ {
+ page_transition (self, HOTSSH_TAB_PAGE_PASSWORD);
+ return;
+ }
+ }
+ else
+ {
+ set_status (self, authmsg);
}
gssh_connection_auth_async (priv->connection,
@@ -416,7 +428,7 @@ on_connection_handshake (GObject *object,
hostkey_sha1_text);
gtk_widget_hide (priv->connection_text_container);
gtk_widget_show (priv->hostkey_container);
- page_transition (self, HOTSSH_TAB_PAGE_INTERSTITAL);
+ page_transition (self, HOTSSH_TAB_PAGE_HOSTKEY);
out:
if (local_error)
@@ -433,7 +445,7 @@ on_connect (GtkButton *button,
const char *hostname;
const char *username;
- page_transition (self, HOTSSH_TAB_PAGE_INTERSTITAL);
+ page_transition (self, HOTSSH_TAB_PAGE_CONNECTING);
gtk_notebook_set_current_page ((GtkNotebook*)self, 1);
hostname = gtk_entry_get_text (GTK_ENTRY (priv->host_entry));
@@ -566,6 +578,8 @@ on_negotiate_complete (GObject *src,
if (!gssh_connection_negotiate_finish ((GSshConnection*)src, result, &local_error))
goto out;
+ set_status (self, "Authenticating...");
+
iterate_authentication_modes (self);
out:
@@ -580,10 +594,11 @@ on_approve_hostkey_clicked (GtkButton *button,
HotSshTab *self = user_data;
HotSshTabPrivate *priv = hotssh_tab_get_instance_private (self);
- gtk_widget_set_sensitive ((GtkWidget*)button, FALSE);
-
gssh_connection_negotiate_async (priv->connection, priv->cancellable,
on_negotiate_complete, self);
+
+ page_transition (self, HOTSSH_TAB_PAGE_CONNECTING);
+ set_status (self, "Negotiating authentication...");
}
static void
@@ -694,10 +709,14 @@ hotssh_tab_init (HotSshTab *self)
gtk_widget_init_template (GTK_WIDGET (self));
+ gtk_notebook_set_show_tabs ((GtkNotebook*)self, FALSE);
+
g_signal_connect (priv->connect_button, "clicked", G_CALLBACK (on_connect), self);
g_signal_connect (priv->connect_cancel_button, "clicked", G_CALLBACK (on_connect_cancel), self);
+ g_signal_connect (priv->error_disconnect, "clicked", G_CALLBACK (on_connect_cancel), self);
g_signal_connect (priv->auth_cancel_button, "clicked", G_CALLBACK (on_connect_cancel), self);
g_signal_connect (priv->approve_hostkey_button, "clicked", G_CALLBACK (on_approve_hostkey_clicked), self);
+ g_signal_connect (priv->disapprove_hostkey_button, "clicked", G_CALLBACK (on_connect_cancel), self);
g_signal_connect_swapped (priv->password_entry, "activate", G_CALLBACK (submit_password), self);
g_signal_connect_swapped (priv->password_submit, "clicked", G_CALLBACK (submit_password), self);
@@ -738,6 +757,8 @@ hotssh_tab_class_init (HotSshTabClass *class)
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), HotSshTab, connect_button);
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), HotSshTab,
connection_text_container);
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), HotSshTab, connection_text);
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), HotSshTab, error_text);
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), HotSshTab, error_disconnect);
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), HotSshTab, password_container);
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), HotSshTab, password_entry);
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), HotSshTab, password_submit);
@@ -746,6 +767,7 @@ hotssh_tab_class_init (HotSshTabClass *class)
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), HotSshTab, hostkey_container);
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), HotSshTab,
hostkey_fingerprint_label);
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), HotSshTab, approve_hostkey_button);
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), HotSshTab,
disapprove_hostkey_button);
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), HotSshTab, terminal_box);
GTK_WIDGET_CLASS (class)->grab_focus = hotssh_tab_grab_focus;
diff --git a/src/tab.ui b/src/tab.ui
index 05832bd..27cf52c 100644
--- a/src/tab.ui
+++ b/src/tab.ui
@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.16.0 on Sat Nov 16 18:58:37 2013 -->
+<!-- Generated with glade 3.16.0 on Sun Nov 17 16:27:47 2013 -->
<interface>
<!-- interface-requires gtk+ 3.10 -->
<template class="HotSshTab" parent="GtkNotebook">
<property name="can_focus">False</property>
- <property name="show_tabs">False</property>
<child>
<object class="GtkBox" id="content_box">
<property name="visible">True</property>
@@ -129,47 +128,165 @@
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">page 1</property>
+ <property name="label" translatable="yes">Host</property>
</object>
<packing>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
- <object class="GtkBox" id="box4">
+ <object class="GtkAlignment" id="connection_text_container">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="box7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="connection_text">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Connecting...</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="connect_cancel_button">
+ <property name="label">gtk-cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <property name="margin_right">8</property>
+ <property name="margin_bottom">8</property>
+ <property name="use_stock">True</property>
+ <property name="image_position">right</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Status</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box2">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="valign">center</property>
<property name="orientation">vertical</property>
<child>
- <object class="GtkBox" id="interstital_box">
+ <object class="GtkBox" id="abox">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">8</property>
<child>
- <object class="GtkAlignment" id="connection_text_container">
+ <object class="GtkLabel" id="error_text">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="label" translatable="yes">Error:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box10">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="spacing">8</property>
<child>
- <object class="GtkLabel" id="connection_text">
+ <object class="GtkButton" id="error_disconnect">
+ <property name="label" translatable="yes">Disconnect</property>
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Connecting...</property>
- <property name="justify">center</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="xalign">0.55000001192092896</property>
+ <property name="yalign">0.57999998331069946</property>
</object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
</child>
</object>
<packing>
- <property name="expand">True</property>
+ <property name="expand">False</property>
<property name="fill">True</property>
- <property name="position">0</property>
+ <property name="position">1</property>
</packing>
</child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label9">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Error</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="interstital_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
<child>
<object class="GtkBox" id="hostkey_container">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="orientation">vertical</property>
+ <property name="spacing">8</property>
<child>
<object class="GtkLabel" id="hostkey_label_text">
<property name="visible">True</property>
@@ -195,19 +312,49 @@
</packing>
</child>
<child>
- <object class="GtkButton" id="approve_hostkey_button">
- <property name="label" translatable="yes">Approve and Connect</property>
+ <object class="GtkBox" id="box5">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
+ <property name="can_focus">False</property>
<property name="halign">center</property>
- <property name="valign">center</property>
- <property name="xalign">0.55000001192092896</property>
- <property name="yalign">0.57999998331069946</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkButton" id="approve_hostkey_button">
+ <property name="label" translatable="yes">Approve and Connect</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="xalign">0.55000001192092896</property>
+ <property name="yalign">0.57999998331069946</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="disapprove_hostkey_button">
+ <property name="label" translatable="yes">Disconnect</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="xalign">0.55000001192092896</property>
+ <property name="yalign">0.57999998331069946</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="expand">False</property>
- <property name="fill">False</property>
+ <property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
@@ -225,35 +372,19 @@
<property name="position">0</property>
</packing>
</child>
- <child>
- <object class="GtkButton" id="connect_cancel_button">
- <property name="label">gtk-cancel</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="halign">end</property>
- <property name="use_stock">True</property>
- <property name="image_position">right</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
</object>
<packing>
- <property name="position">1</property>
+ <property name="position">3</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">page 2</property>
+ <property name="label" translatable="yes">Hostkey</property>
</object>
<packing>
- <property name="position">1</property>
+ <property name="position">3</property>
<property name="tab_fill">False</property>
</packing>
</child>
@@ -309,6 +440,9 @@
<property name="valign">center</property>
<property name="margin_left">8</property>
<property name="use_stock">True</property>
+ <style>
+ <class name="suggested-action"/>
+ </style>
</object>
<packing>
<property name="expand">False</property>
@@ -332,12 +466,13 @@
</child>
<child>
<object class="GtkButton" id="auth_cancel_button">
- <property name="label">gtk-cancel</property>
+ <property name="label">Disconnect</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="halign">end</property>
- <property name="use_stock">True</property>
+ <property name="margin_right">8</property>
+ <property name="margin_bottom">8</property>
<property name="image_position">right</property>
</object>
<packing>
@@ -348,17 +483,17 @@
</child>
</object>
<packing>
- <property name="position">2</property>
+ <property name="position">4</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">page 2</property>
+ <property name="label" translatable="yes">Password</property>
</object>
<packing>
- <property name="position">2</property>
+ <property name="position">4</property>
<property name="tab_fill">False</property>
</packing>
</child>
@@ -384,17 +519,17 @@
</child>
</object>
<packing>
- <property name="position">3</property>
+ <property name="position">5</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">page 3</property>
+ <property name="label" translatable="yes">Terminal</property>
</object>
<packing>
- <property name="position">3</property>
+ <property name="position">5</property>
<property name="tab_fill">False</property>
</packing>
</child>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]