試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

libnotifyをVala言語で使用する(例)

libnotifyをVala言語で使用する(メモ)」の内容を踏まえて作成したlibnotifyの使用例を貼り付ける。
GTK+も用いているため、コンパイルをするにはGTK+ 2とlibnotifyの両方の(C言語の)開発パッケージが別途必要。
[任意]ファイル名: libnotifytest.vala

using Notify;
using GLib;
using Gtk;

/*
 * valac --pkg libnotify --pkg gtk+-2.0 -o libnotifytest libnotifytest.vala
 */

namespace LibnotifyTest
{
  class MainWindow : Gtk.Window
  {
    Gtk.AccelGroup accelgroup;
    Gtk.ImageMenuItem item_quit;
    Gtk.Menu menu_file;
    Gtk.MenuItem item_file;
    Gtk.MenuBar menubar;
    Gtk.Button button_show;
    Gtk.VBox vbox;
    Notify.Notification n_btn;  // ボタンから吹き出しを出すもの
    public MainWindow ()
    {
      /* ショートカットキー(アクセラレータ) */
      this.accelgroup = new Gtk.AccelGroup ();
      this.add_accel_group (this.accelgroup);
      /* メニュー項目 */
      this.item_quit = new Gtk.ImageMenuItem.from_stock (Gtk.STOCK_QUIT, accelgroup);
      this.menu_file = new Gtk.Menu ();
      this.menu_file.prepend (item_quit);
      this.item_file = new Gtk.MenuItem.with_mnemonic ("_File");
      this.item_file.set_submenu (menu_file);
      this.menubar = new Gtk.MenuBar ();
      this.menubar.append (item_file);
      /* GUI部品 */
      this.button_show = new Gtk.Button.with_mnemonic ("_Show");
      this.vbox = new Gtk.VBox (false, 0);
      this.vbox.pack_start (this.menubar, false, false, 0);
      this.vbox.pack_start (this.button_show, true, true, 0);
      this.add (this.vbox);
      this.resize (150, 100);
      /* 通知 */
      /* 最初の引数(概要)は必須、その後ろの本文,アイコン,吹き出しを出す部品はnull可 */
      this.n_btn = new Notify.Notification ("Summary", "Body", null, this.button_show);
      /* update()で概要/本文/アイコンを更新 */
      this.n_btn.update ("Good Summary", "Great Body", "apple-green");
      /*
       * add_action()で通知ポップアップ内のアクションボタンを作成できる
       * 同じ通知オブジェクトで以前追加したアクションボタンを消すには
       * clear_actions()を用いる
       */
      /*
       * 最初の引数で「open」「edit」「save」「delete」などの文字列を入れると
       * アイコンが付く(ストックアイコンの一部が対応)
       * 次にボタン文字列と呼ばれる関数が続く
       */
      this.n_btn.add_action ("open", "Let's open", (Notify.ActionCallback) this.on_open);
      this.n_btn.add_action ("delete", "Let's delete", (Notify.ActionCallback) this.on_delete);
      /* 重要度指定(LOW/NORMAL/CRITICAL) */
      this.n_btn.set_urgency (Notify.Urgency.CRITICAL);
      /* 時間 */
      this.n_btn.set_timeout (20000);  // 20秒
      /* シグナル */
      this.button_show.clicked.connect (() =>
      {
        try
        {
          this.n_btn.show ();
        }
        catch (GLib.Error e)
        {
          GLib.warning ("this.n_btn.show () [%s]", e.message);
        }
      });
      this.item_quit.activate.connect (Gtk.main_quit);
      this.destroy.connect (Gtk.main_quit);
    }
    /* 通知のアクションハンドラ(ボタンが押されたときに呼ばれる) */
    void on_open ()
    {
      GLib.debug ("\"open\" button clicked");
    }
    void on_delete ()
    {
      GLib.debug ("\"delete\" button clicked");
    }
  }
  class TrayMenu : Gtk.Menu
  {
    Gtk.ImageMenuItem item_show_trayicon;
    Gtk.ImageMenuItem item_show_stack;
    Gtk.ImageMenuItem item_quit;
    Notify.Notification n_trayicon;  // システムトレイアイコンから吹き出しを出すもの
    Notify.Notification n_stack;     // 画面の隅のポップアップスタックに表示するもの
    public TrayMenu (Gtk.StatusIcon status_icon)
    {
      /* メニュー項目 */
      this.item_show_trayicon = new Gtk.ImageMenuItem.with_mnemonic ("_Trayicon");
      this.item_show_stack = new Gtk.ImageMenuItem.with_mnemonic ("_Stack");
      this.item_quit = new Gtk.ImageMenuItem.from_stock (Gtk.STOCK_QUIT, null);
      this.append (this.item_show_trayicon);
      this.append (this.item_show_stack);
      this.append (new Gtk.SeparatorMenuItem ());
      this.append (this.item_quit);
      /* 通知 */
      /*
       * コンストラクタNotification.with_status_icon()を使わずに
       * 通常のコンストラクタを使用後attach_to_status_icon()を使用することもできる
       */
      this.n_trayicon = new Notify.Notification.with_status_icon ("Marvelous Summary", "Awesome Body", "gnome-gmush", status_icon);
      /*
       * 通常コンストラクタで最後の引数をnullにすると
       * 画面隅のポップアップスタックに表示される
       * これは複数の通知があると重なっていくが
       * このプログラム内ではこの1つだけなので重なることはない
       * (他のプログラムのものと重なることはある)
       */
      this.n_stack = new Notify.Notification ("Fantastic Summary", "Integral Body", "gnome-aorta", null);
      /* シグナル */
      this.item_show_trayicon.activate.connect (() =>
      {
        try
        {
          this.n_trayicon.show ();
        }
        catch (GLib.Error e)
        {
          GLib.warning ("this.n_trayicon.show () [%s]", e.message);
        }
      });
      this.item_show_stack.activate.connect (() =>
      {
        try
        {
          this.n_stack.show ();
        }
        catch (GLib.Error e)
        {
          GLib.warning ("this.n_stack.show () [%s]", e.message);
        }
      });
      this.item_quit.activate.connect (Gtk.main_quit);
    }
  }
  class MainClass
  {
    public static int main (string[] args)
    {
      MainWindow win;
      Gtk.StatusIcon status_icon;
      TrayMenu menu;
      Gtk.init (ref args);
      /* !! libnotifyの初期化が必須 !! */
      if (!Notify.init ("libnotifytest"))
      {
        GLib.critical ("Couldn't initialize libnotify");
        /* 今回は初期化失敗したらそのまま終了することにする */
        return 1;
      }
      win = new MainWindow ();
      status_icon = new Gtk.StatusIcon.from_stock (Gtk.STOCK_HELP);
      menu = new TrayMenu (status_icon);
      menu.show_all ();
      status_icon.popup_menu.connect ((source, button, activate_time) =>
      {  // クロージャ
        menu.popup (null, null, source.position_menu, button, activate_time);
      });
      win.show_all ();
      Gtk.main ();
      return 0;
    }
  }
}


ボタンを押すとここに関連付けた通知が表示され、アクションのボタンも表示される・クリックすると端末にメッセージが表示される・CRITICAL指定なので色は赤い

システムトレイアイコンに関連付けたもの

GUI部品とシステムトレイアイコンのいずれにも関連付けないときの通知スタックへの表示

関連記事:

使用したバージョン:

  • libnotify 0.4.4
  • Vala 0.7.7