Logo Search packages:      
Sourcecode: efax-gtk version File versions

tray_icon.cpp

/* Copyright (C) 2004 Chris Vine

This program is distributed under the General Public Licence, version 2.
For particulars of this and relevant disclaimers see the file
COPYING distributed with the source files.

*/

#include <string>

#include <gtkmm/stock.h>
#include <gtkmm/image.h>
#include <gdkmm/pixbuf.h>

#include <gtk/gtkeventbox.h>
#include <gtk/gtkimage.h>
#include <gdk/gdkpixbuf.h>

#include "tray_icon.h"
#include "efax_controller.h"

#ifdef ENABLE_NLS
#include <libintl.h>
#endif

TrayItem* TrayItem::tray_item_p = 0;

TrayItem::TrayItem(Gtk::Window& window): prog_window(window),
                               embedded(false) {

  if (tray_item_p) {  // something has gone wrong - report the error and return
    write_error("TrayItem object has already been created - cannot create another\n");
    return;
  }

  tray_item_p = this;

  // build menu for right mouse button
  {
    using namespace Gtk::Menu_Helpers;
    MenuList& menu_list = popup_menu.items();
    
    Gtk::Image* image_p = manage(new Gtk::Image(Gtk::Stock::INDEX, Gtk::ICON_SIZE_MENU));
    menu_list.push_back(ImageMenuElem(gettext("List received faxes"), *image_p,
      sigc::bind(sigc::mem_fun(*this, &TrayItem::popup_menu_slot), TrayItem::list_received_faxes)));

    image_p = manage(new Gtk::Image(Gtk::Stock::INDEX, Gtk::ICON_SIZE_MENU));
    menu_list.push_back(ImageMenuElem(gettext("List sent faxes"), *image_p,
      sigc::bind(sigc::mem_fun(*this, &TrayItem::popup_menu_slot), TrayItem::list_sent_faxes)));

    menu_list.push_back(SeparatorElem());

    menu_list.push_back(MenuElem(gettext("Take over call"),
      sigc::bind(sigc::mem_fun(*this, &TrayItem::popup_menu_slot), TrayItem::receive_takeover)));
    receive_takeover_item_p = &menu_list.back();

    menu_list.push_back(MenuElem(gettext("Answer call"),
      sigc::bind(sigc::mem_fun(*this, &TrayItem::popup_menu_slot), TrayItem::receive_answer)));
    receive_answer_item_p = &menu_list.back();

    menu_list.push_back(MenuElem(gettext("Receive standby"),
      sigc::bind(sigc::mem_fun(*this, &TrayItem::popup_menu_slot), TrayItem::receive_standby)));
    receive_standby_item_p = &menu_list.back();

    image_p = manage(new Gtk::Image(Gtk::Stock::STOP, Gtk::ICON_SIZE_MENU));
    menu_list.push_back(ImageMenuElem(gettext("Stop"), *image_p,
      sigc::bind(sigc::mem_fun(*this, &TrayItem::popup_menu_slot), TrayItem::stop)));
    stop_item_p = &menu_list.back();

    menu_list.push_back(SeparatorElem());

    image_p = manage(new Gtk::Image(Gtk::Stock::QUIT, Gtk::ICON_SIZE_MENU));
    menu_list.push_back(ImageMenuElem(gettext("Quit"), *image_p,
      sigc::bind(sigc::mem_fun(*this, &TrayItem::popup_menu_slot), TrayItem::quit)));
  }

  // now create and register the tray icon container (parcel out the
  // C stuff to another method to make it more bearable)
  tray_icon_init();
}

void TrayItem::button_press_handler(GdkEventButton* event_p) {

  if (event_p->button == 1 || event_p->button == 2) left_button_pressed();
  if (event_p->button == 3) {

    if (get_state() == EfaxController::inactive) {
      stop_item_p->set_sensitive(false);
      receive_takeover_item_p->set_sensitive(true);
      receive_answer_item_p->set_sensitive(true);
      receive_standby_item_p->set_sensitive(true);
    }
    else  {
      stop_item_p->set_sensitive(true);
      receive_takeover_item_p->set_sensitive(false);
      receive_answer_item_p->set_sensitive(false);
      receive_standby_item_p->set_sensitive(false);
    }
    popup_menu.popup(event_p->button, event_p->time);
  }
}

void TrayItem::popup_menu_slot(int item) {
  menu_item_chosen(item);
}

///////////////////// start of the raw GTK+ C stuff //////////////////

///////////////////////////// callbacks /////////////////////////////

void embedded_cback(GtkWidget*, gpointer) {
  TrayItem::tray_item_p->embedded = true;

  // for debugging - there is no error, we use write_error() for reporting
  //write_error("In embedded callback\n");
}

void destroy_cback(GtkWidget*, gpointer) {
  TrayItem::tray_item_p->embedded = false;
  TrayItem::tray_item_p->tray_icon_destroy();
  // now bring up the program window in case it was hidden when the system tray
  // was removed from the panel
  TrayItem::tray_item_p->prog_window.present();

  // for debugging - there is no error, we use write_error() for reporting
  //write_error("In destroy callback\n");
}

gboolean button_press_cback(GtkWidget* widget_p, GdkEventButton* event_p, gpointer) {
  
  TrayItem::tray_item_p->button_press_handler(event_p);
  return true; // processing stops here
}

/////////////////////////// tray icon code //////////////////////////

void TrayItem::tray_icon_init(void) {

  Glib::RefPtr<Gdk::Pixbuf> icon_r(prog_config.window_icon_r->scale_simple(18, 18, Gdk::INTERP_HYPER));

  // we can use icon_r->gobj() rather than icon_r->gobj_copy() here, as
  // gtk_image_new_from_pixbuf() will increase the reference count
  GtkWidget* image_p = gtk_image_new_from_pixbuf(icon_r->gobj());
  event_box_p = gtk_event_box_new();
  gtk_container_add (GTK_CONTAINER(event_box_p), GTK_WIDGET(image_p));

  gtk_widget_add_events(event_box_p, GDK_BUTTON_PRESS_MASK);

  // set a tooltip
  tooltips_p = gtk_tooltips_new();
  // we have now initialised event_box_p and tooltips_p, so we can call set_tooltip_slot()
  set_tooltip_slot(gettext("Inactive"));
  
  g_signal_connect(G_OBJECT(event_box_p), "button_press_event", G_CALLBACK(button_press_cback), 0);

  tray_icon_p = egg_tray_icon_new("efax-gtk");

  g_signal_connect(G_OBJECT(tray_icon_p), "embedded", G_CALLBACK(embedded_cback), 0);
  g_signal_connect(G_OBJECT(tray_icon_p), "destroy", G_CALLBACK(destroy_cback), 0);

  gtk_container_add(GTK_CONTAINER(tray_icon_p), GTK_WIDGET(event_box_p));

  gtk_widget_show_all(GTK_WIDGET(tray_icon_p));

  // add a reference count to the tray icon container so that we that we keep
  // ownership of its destiny - we will need this for tray_icon_destroy() below
  g_object_ref(G_OBJECT(tray_icon_p));
}

void TrayItem::tray_icon_destroy(void) {

  // extract this event box from the defunct tray icon container
  // first we need to add a reference count to our event box so that
  // extracting it from the container doesn't destroy it
  g_object_ref(G_OBJECT(event_box_p));
  gtk_container_remove(GTK_CONTAINER(tray_icon_p), GTK_WIDGET(event_box_p));
  // now destroy the old tray icon
  g_object_unref(G_OBJECT(tray_icon_p));

  // create a new tray icon in case another GNOME notification area (system tray)
  // is inserted in the panel by the user, or the user has more than one tray
  tray_icon_p = egg_tray_icon_new("efax-gtk");
  gtk_container_add(GTK_CONTAINER(tray_icon_p), GTK_WIDGET(event_box_p));
  
  // now remove the additional reference count we added at the outset to the
  // the event box
  g_object_unref(G_OBJECT(event_box_p));

  g_signal_connect(G_OBJECT(tray_icon_p), "embedded", G_CALLBACK(embedded_cback), 0);
  g_signal_connect(G_OBJECT(tray_icon_p), "destroy", G_CALLBACK(destroy_cback), 0);

  gtk_widget_show_all(GTK_WIDGET(tray_icon_p));

  // add a reference count to the tray icon container so that we that we keep ownership
  // of its destiny - we will need this for any further calls to tray_icon_destroy()
  g_object_ref(G_OBJECT(tray_icon_p));
}

void TrayItem::set_tooltip_slot(const char* text) {

  // we might as well use a std::string rather than a Glib::ustring here
  // as it is just a temporary transparent holder of any UTF-8 encoding
  std::string tooltip_text(gettext("efax-gtk: "));
  tooltip_text += text;
  
  gtk_tooltips_set_tip(tooltips_p, event_box_p, tooltip_text.c_str(), 0);
}

Generated by  Doxygen 1.6.0   Back to index