3 # This is a dbus script to show a docklet for Finch. This should work
4 # for any 'compatible' purple client.
6 # By 'compatible', I mean any client that sets and updates the
7 # "unseen-count" data on the conversations.
9 # It allows doing the following things:
10 # - It allows changing status.
11 # - It shows the current status and info about unread messages in
13 # - It can blink on unread IM/Chat messages, and it allows canging
14 # the preference for that.
16 # It requires GTK+ 2.10 or above, since it uses GtkStatusIcon.
18 # Sadrul <sadrul@pidgin.im>
23 import dbus
, gobject
, dbus
.glib
24 import os
# to get the pkg-config output
26 bus
= dbus
.SessionBus()
28 "im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject")
29 purple
= dbus
.Interface(obj
, "im.pidgin.purple.PurpleInterface")
31 def pack_image_label(menu
, image
, label
):
32 item
= gtk
.ImageMenuItem(label
)
35 img
.set_from_stock(image
, 1)
40 def activate_primitive_status(item
, status
):
41 saved
= purple
.PurpleSavedstatusFindTransientByTypeAndMessage(status
, "")
43 saved
= purple
.PurpleSavedstatusNew("", status
)
44 purple
.PurpleSavedstatusActivate(saved
)
46 def activate_popular_status(item
, time
):
47 saved
= purple
.PurpleSavedstatusFindByCreationTime(time
)
49 purple
.PurpleSavedstatusActivate(saved
)
51 def generate_status_menu(menu
):
52 item
= gtk
.MenuItem("Available")
53 item
.connect("activate", activate_primitive_status
, 2)
56 item
= gtk
.MenuItem("Away")
57 item
.connect("activate", activate_primitive_status
, 5)
60 item
= gtk
.MenuItem("Invisible")
61 item
.connect("activate", activate_primitive_status
, 4)
64 item
= gtk
.MenuItem("Offline")
65 item
.connect("activate", activate_primitive_status
, 1)
68 menu
.append(gtk
.MenuItem())
70 popular
= purple
.PurpleSavedstatusesGetPopular(10)
72 title
= purple
.PurpleSavedstatusGetTitle(pop
).replace('_', '__')
73 item
= gtk
.MenuItem(title
)
74 item
.set_data("timestamp", purple
.PurpleSavedstatusGetCreationTime(pop
))
75 item
.connect("activate", activate_popular_status
, purple
.PurpleSavedstatusGetCreationTime(pop
))
78 def toggle_pref(item
, pref
):
79 purple
.PurplePrefsSetBool(pref
, item
.get_active())
81 def quit_finch(item
, null
):
83 purple
.PurpleCoreQuit()
86 def close_docklet(item
, null
):
89 def popup_menu(icon
, button
, tm
, none
):
92 #item = gtk.ImageMenuItem(gtk.STOCK_QUIT)
93 #item.connect("activate", quit_finch, None)
96 item
= gtk
.ImageMenuItem(gtk
.STOCK_CLOSE
)
97 item
.connect("activate", close_docklet
, None)
100 menu
.append(gtk
.MenuItem())
102 item
= gtk
.CheckMenuItem("Blink for unread IM")
103 item
.set_active(purple
.PurplePrefsGetBool("/plugins/dbus/docklet/blink/im"))
104 item
.connect("activate", toggle_pref
, "/plugins/dbus/docklet/blink/im")
107 item
= gtk
.CheckMenuItem("Blink for unread Chats")
108 item
.set_active(purple
.PurplePrefsGetBool("/plugins/dbus/docklet/blink/chat"))
109 item
.connect("activate", toggle_pref
, "/plugins/dbus/docklet/blink/chat")
112 menu
.append(gtk
.MenuItem())
114 #item = pack_image_label(menu, None, "Change Status...")
115 item
= gtk
.MenuItem("Change Status...")
118 item
.set_submenu(submenu
)
119 generate_status_menu(submenu
)
122 menu
.popup(None, None, None, button
, tm
)
124 def get_status_message():
125 status
= purple
.PurpleSavedstatusGetCurrent()
126 msg
= purple
.PurpleSavedstatusGetMessage(status
)
127 if msg
and len(msg
) > 0:
131 text
= text
+ "(" + {
136 }[purple
.PurpleSavedstatusGetType(status
)] + ")"
139 def detect_unread_conversations():
140 im
= purple
.PurplePrefsGetBool("/plugins/dbus/docklet/blink/im")
141 chat
= purple
.PurplePrefsGetBool("/plugins/dbus/docklet/blink/chat")
145 convs
= purple
.PurpleGetConversations()
147 convs
= purple
.PurpleGetIms()
149 convs
= purple
.PurpleGetChats()
153 count
= purple
.PurpleConversationGetData(conv
, "unseen-count")
154 if count
and count
> 0:
156 tooltip
= tooltip
+ "\n" + purple
.PurpleConversationGetName(conv
) + " (" + str(count
) + ")"
157 t
.set_from_file(path
+ "/share/pixmaps/pidgin.png")
160 # t.set_from_file(path + "/share/pixmaps/pidgin/tray/22/tray-message.png")
161 tooltip
= "\nUnread Messages:" + tooltip
162 # There's going to be some way to expose the client's display name in 2.1.0.
163 # Use that instead of hardcoding Finch here.
164 t
.set_tooltip("Finch: " + get_status_message() + tooltip
)
165 t
.set_blinking(blink
)
167 def conversation_updated(conv
, type):
168 detect_unread_conversations()
170 def savedstatus_changed(new
, old
):
171 # Change the icon for status perhaps?
172 detect_unread_conversations()
175 if not purple
.PurplePrefsExists("/plugins/dbus/docklet/blink"):
176 purple
.PurplePrefsAddNone("/plugins")
177 purple
.PurplePrefsAddNone("/plugins/dbus")
178 purple
.PurplePrefsAddNone("/plugins/dbus/docklet")
179 purple
.PurplePrefsAddNone("/plugins/dbus/docklet/blink")
180 purple
.PurplePrefsAddBool("/plugins/dbus/docklet/blink/im", True)
181 purple
.PurplePrefsAddBool("/plugins/dbus/docklet/blink/chat", True)
183 pkg
= os
.popen("pkg-config --variable=prefix pidgin")
184 path
= pkg
.readline().rstrip()
186 bus
.add_signal_receiver(conversation_updated
,
187 dbus_interface
="im.pidgin.purple.PurpleInterface",
188 signal_name
="ConversationUpdated")
190 bus
.add_signal_receiver(savedstatus_changed
,
191 dbus_interface
="im.pidgin.purple.PurpleInterface",
192 signal_name
="SavedstatusChanged")
195 t
.connect("popup-menu", popup_menu
, None)
199 detect_unread_conversations()
202 dialog
= gtk
.Dialog("pietray: Error", None, gtk
.DIALOG_NO_SEPARATOR | gtk
.DIALOG_MODAL
, ("Close", gtk
.RESPONSE_CLOSE
))
203 dialog
.set_resizable(False)
204 dialog
.vbox
.pack_start(gtk
.Label("There was some error. Perhaps a purple client is not running."), False, False, 0)