 | Системная информация
Апплет системной информации
Просматривая сайт OpenMoko, я нашел документ для разработки апплета системной информации, использующего стилус. Звучит заманчиво! Оказывается, написать программу, которая считывает некоторую информацию о системе и выводит её, очень просто, и такая программа выглядит полезной.
Компоновка с помощью таблиц
Обычно я использую компоновку с помощью таблиц, поэтому я поступлю так же и здесь. Компоновка с помощью таблиц в GTK+ позволяет вам организовать в окне сетку и вставить объекты в ячейки этой сетки. Для нас интересна часть API gtk_table_attach(), содержащая следующий прототип:
Листинг 5. Полный прототип gtk_table_attach
GtkWidget* gtk_table_attach(GtkTable* table, GtkWidget* child,
guint left_side, guint right_side,
guint top_side, guint bottom_side,
GtkAttachOptions xoptions, GtkAttachOptions yoptions,
guint xpadding, guint ypadding);
|
В нашем примере программы я использовал такие же разрывы строк, как и в этом прототипе, при каждом вызове функций, чтобы было легче увидеть, какой из аргументов что значит. Теперь у нас будет очень простая таблица; в верхней ячейке будет обозначена версия ядра, а в нижней - кнопка Quit (добавлена на случай, если вы используете эмулятор).
Создание и наполнение таблицы
Первая версия программы очень проста. Всё, что нужно сделать - создать две метки и кнопку, поместить их в таблицу и вывести на экран. Просто, не так ли? Во-первых, нам нужно создать таблицу и вставить её в окно:
Листинг 6. Создание таблицы
table = gtk_table_new(8, 3, TRUE);
gtk_container_add(GTK_CONTAINER(window), table);
gtk_container_set_border_width(GTK_CONTAINER(table), 10);
|
В таблице 8 строк и 3 столбца, все ячейки имеют одинаковый размер (это верно, если аргумент gtk_table_new(); имеет значение TRUE, если он имеет значение FALSE, размеры могут отличаться).
Добавление кнопки Quit
Вот код кнопки Quit, которую я добавил для облегчения закрытия приложений:
Листинг 7. Наполнение таблицы
button = gtk_button_new_with_label("Quit");
gtk_table_attach(GTK_TABLE(table), button,
1, 2,
7, 8,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
0, 0);
|
Этот код выводит кнопку Quit, но что она делает? Если нажать на неё, ничего не произойдёт.
Функции обратного вызова
Для обеспечения чистого закрытия окна требуется несколько функций обратного вызова. Первая, delete_event(), используется для обозначения того, что кто-то пытается завершить приложение; возвращенное значение FALSE говорит о том, что приложение нужно уничтожить, значение TRUE о том, что ничего делать не нужно. Вторая, destroy(), просто выполняет выход. Обратите внимание, что эти имена необязательны; однако они использовались в коде учебного пособия по GTK+, поэтому читателям будет проще узнать их и понять их работу.
Листинг 8. Выход из приложения GTK
static gboolean
delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
{
return FALSE;
}
static gboolean
destroy(void)
{
gtk_main_quit();
}
|
Подключение проводов
Теперь, когда у нас есть и кнопка, и функции для закрытия приложения, имеет смысл объединить их, регистрируя сигналы функций обратного вызова. Ниже приведен код для обработки нажатия кнопки и обычных событий закрытия окна:
Листинг 9. Подключение кнопки к вызываемым ей функциям
g_signal_connect(G_OBJECT(button), "clicked",
G_CALLBACK(destroy), NULL);
g_signal_connect(G_OBJECT(window), "delete_event",
G_CALLBACK(delete_event), NULL);
g_signal_connect(G_OBJECT(window), "destroy",
G_CALLBACK(destroy), NULL);
|
А теперь немного данных
Начнем с вывода версии ядра. Вы можете поинтересоваться, как узнать версию ядра. Конечно же, с помощью uname()! Написать этот код очень легко:
Листинг 10. Получение информации о версии системы
struct utsname u;
[...]
uname(&u);
label = gtk_label_new(u.release);
|
struct utsname заполняется строками C, обозначающими характеристики текущей среды. Обычно строка "release" главным образом содержит номер версии ядра. Данные мы получили, но как вывести их на экран?
Добавление меток в таблицу
В листинге 11 показан код, добавляющий метки (на самом деле в нашем примере это просто текстовые поля) в таблицу. Первая метка в левой колонке является простым заголовком; вторая, занимающая центральную и правую колонки, содержит значение версии, полученное через uname().
Листинг 11. Вывод метки
label = gtk_label_new("Kernel version:");
gtk_table_attach(GTK_TABLE(table), label,
0, 1,
0, 1,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
0, 0);
uname(&u);
label = gtk_label_new(u.release);
gtk_table_attach(GTK_TABLE(table), label,
1, 3,
0, 1,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
0, 0);
|
Переписывание переменной "label" вторым вызовом gtk_label_new() может показаться странным, но выделенный ранее объект уже был размещен в таблице, поэтому он не потеряется.
Соединяем детали
Осталось только заменить gtk_widget_show()
на gtk_widget_show_all(), потому как gtk_widget_show_all(), судя по имени, показывает не только окно, но и все его содержимое (в данном случае таблицу, две метки и кнопку). Итоговый код будет выглядеть примерно таким образом:
Листинг 12. Минимальная прогармма целиком
#include <gtk/gtk.h>
#include <sys/utsname.h>
static gboolean
delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
{
return FALSE;
}
static gboolean
destroy(void)
{
gtk_main_quit();
}
int
main(int argc, char *argv[]) {
GtkWidget *window;
GtkWidget *table;
GtkWidget *button;
GtkWidget *label;
struct utsname u;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(G_OBJECT(window), "delete_event",
G_CALLBACK(delete_event), NULL);
g_signal_connect(G_OBJECT(window), "destroy",
G_CALLBACK(destroy), NULL);
gtk_window_set_title(GTK_WINDOW(window), "Hello, System!");
table = gtk_table_new(6, 3, TRUE);
gtk_container_add(GTK_CONTAINER(window), table);
gtk_container_set_border_width(GTK_CONTAINER(table), 10);
button = gtk_button_new_with_label("Quit");
gtk_table_attach(GTK_TABLE(table), button,
1, 2,
7, 8,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
0, 0);
g_signal_connect(G_OBJECT(button), "clicked",
G_CALLBACK(destroy), NULL);
/* uname */
label = gtk_label_new("Kernel version:");
gtk_table_attach(GTK_TABLE(table), label,
0, 1,
0, 1,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
0, 0);
uname(&u);
label = gtk_label_new(u.release);
gtk_table_attach(GTK_TABLE(table), label,
1, 3,
0, 1,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
0, 0);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
|
|  |