14 июня 2009 г.

Программа управления веб-сервером Apache. Часть 1

Сегодня предлагаю написать программу, которая предоставит пользователю возможность запускать, останавливать и перезапускать веб-сервер Apache. Программа будет отображать значок в системном трее, при нажатии на который правой кнопкой мыши будет отображаться контекстное меню, как на скриншоте.



За отображение иконки в трее отвечает класс GtkStatusIcon:
$tray = new GtkStatusIcon;


С помощью метода set_tooltip() можно установить подсказку, которая будет отображаться при наведении указателя мыши на иконку:
$tray->set_tooltip('Программа управления веб-сервером Apache');


Иконку можно установить несколькими способами. Один из них - это взять из предустановленных в PHP-GTK:
$tray->set_from_stock(Gtk::STOCK_EXECUTE);


При нажатии правой кнопкой мыши по значку в трее издаётся сигнал 'popup-menu' (в рамки данной статьи это не входит, но я всё же скажу, что при нажатии левой кнопкой издаётся сигнал 'activate'):
$tray->connect('popup-menu', 'on_popup_menu');


Теперь создадим контекстное меню. Оно практически ничем не отличается от обычного, которое находится в верхней части окна. О нём я рассказывал в статьях Часть 1 и Часть 2. Нам только необходимо применить к нему метод popup().
function on_popup_menu()
{
$menu = new GtkMenu;
 
$start = new GtkMenuItem('Запустить Apache');
$start->connect_simple('activate', 'apache', 'start');
$menu->append($start);
$restart = new GtkMenuItem('Перезапустить Apache');
$restart->connect_simple('activate', 'apache', 'restart');
$menu->append($restart);
$stop = new GtkMenuItem('Остановить Apache');
$stop->connect_simple('activate', 'apache', 'stop');
$menu->append($stop);
 
$menu->show_all();
$menu->popup();
}


При нажатии на любой пункт меню вызывается функция apache(), которая запускает/перезапускает/останавливает веб-сервер. Команда в exec() может отличаться от приведённой мною в зависимости от ОС и дистрибьютива. В моём случае она подходит для Ubuntu. Обратите внимание, что для выполнения любого действия необходимо наличие прав суперпользователя, поэтому используется команда gksu, которая выводит на экран окно для ввода пароля от root.
function apache($comand)
{
exec('gksu /etc/init.d/apache2 '.$comand);
}


Полный код программы:
<?php
 
$tray = new GtkStatusIcon;
$tray->set_tooltip('Программа управления веб-сервером Apache');
$tray->set_from_stock(Gtk::STOCK_EXECUTE);
$tray->connect('popup-menu', 'on_popup_menu');
Gtk::main();
 
function on_popup_menu()
{
$menu = new GtkMenu;
 
$start = new GtkMenuItem('Запустить Apache');
$start->connect_simple('activate', 'apache', 'start');
$menu->append($start);
$restart = new GtkMenuItem('Перезапустить Apache');
$restart->connect_simple('activate', 'apache', 'restart');
$menu->append($restart);
$stop = new GtkMenuItem('Остановить Apache');
$stop->connect_simple('activate', 'apache', 'stop');
$menu->append($stop);
 
$menu->show_all();
$menu->popup();
}
 
function apache($comand)
{
exec('gksu /etc/init.d/apache2 '.$comand);
}
 
?>

10 комментариев:

SViver88 комментирует...

У меня ругается на
Fatal error: Class 'GtkStatusIcon' not found in

Установлены:
Ubuntu 9.04
PHP 5.2.10
php-gtk-2.0.1
libgtk+-2.16.1

Даже не знаю что делать...

Shecspi комментирует...

А как Вы устанавливали PHP-GTK? Возможно не все модули были включены при компиляции. Попробуйте воспользоваться следующим репозиторием: deb http://downloads.kaspernj.org/ubuntu/repository intrepid main

SViver88 комментирует...

Устанавливал по документации с офф.сайта... потом ещё как то, всё из исходников в основном =)

Спасибо! С этого репозитория, всё установилось, всё заработало.

Gene комментирует...

Спасибо!
Есть такой вопрос - контекстная менюшка в трее не пропадает, если я кликаю мимо нее (допустим, я передумал кликать меню). Она пропадает только если у приложения есть основное окно (в данном примере его нет) и я кликаю именно по этому окну. А как добиться пропадания менюшки в любом случае? (У меня в трее так работают все программы).

Shecspi комментирует...

Извини, что так долго не отвечал.
Не знаю, у меня на убунте менюшка пропадает при клике по любому месту на дисплее.

Gene комментирует...

Ясно, а я работаю под WinXP и такое наблюдается под Виндой не только у меня. Один человек предложил убирать меню по истечении определенного времени после увода курсора мыши от менюшки (как workaround), хотя это не решает вопрос. Попробую сам докопаться :)

Gene комментирует...

Видимо, под Линуксом GTK управляет всем, поэтому знает обо всех событиях и автоматически контролирует отображение меню, а здесь нужно думать.

Кстати, а есть ли в PHP-GTK событие клика кнопки мыши как таковое? Не на конкретном элементе, а в принципе, подобному клавиатурному событию?

Shecspi комментирует...

Да, при нажатии клавиши на мышке издается сигнал 'button-press-event'. Естественно, его необходимо привязать к какому-либо виджету. Для глобального перехвата, как в твоем случае, нужно привязывать к окну GtkWindow. Обработка этого сигнала довольна проста, в качестве примера можешь посмотреть обработчик on_button() в FlightFiles - http://code.google.com/p/flight-files/source/browse/trunk/FlightFiles.data.php Думаю, сам сможешь разобраться.
А для скрытия меню можно поиграться с фокусировкой: если фокус ушел с меню, то закрываем его.

Gene комментирует...

Спасибо за ответ!
Как раз метод с фокусировкой и предлагался в том примере, что я упоминал - по событию leave-notify-event выполняется $menu->popdown(); Но не сразу, а по таймауту, скажем через секунду. Соответственно, если пользователь снова возрвращается в течении это секунды, то происходит enter-notify-event и $menu->popdown(); отменяется. В принципе, приемлемое решение, наверное на нем и остановлюсь.

Shecspi комментирует...

Я имел ввиду не уход указателя с меню, а именно потерю фокуса, т.е. когда происходит щелчок вне пределов данного виджета. На сколько я помню, такая возможность в PHP-GTK имеется.