features_window.py 9.22 KB
Newer Older
1 2
##	features_window.py
##
Yann Leboulanger's avatar
Yann Leboulanger committed
3
## Copyright (C) 2007 Yann Leboulanger <asterix@lagaule.org>
steve-e's avatar
steve-e committed
4
##                    Stephan Erb <steve-e@h3c.de> 
5
##
6 7 8
## This file is part of Gajim.
##
## Gajim is free software; you can redistribute it and/or modify
9
## it under the terms of the GNU General Public License as published
10
## by the Free Software Foundation; version 3 only.
11
##
12
## Gajim is distributed in the hope that it will be useful,
13 14 15 16
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
17 18 19
## You should have received a copy of the GNU General Public License
## along with Gajim.  If not, see <http://www.gnu.org/licenses/>.
##
20 21

import os
22
import sys
23 24 25 26 27 28 29 30 31
import gtk
import gobject
import gtkgui_helpers

import dialogs

from common import gajim
from common import helpers

32 33 34 35
import random
from tempfile import gettempdir
from subprocess import Popen

36 37 38 39 40 41 42
class FeaturesWindow:
	'''Class for features window'''

	def __init__(self):
		self.xml = gtkgui_helpers.get_glade('features_window.glade')
		self.window = self.xml.get_widget('features_window')
		treeview = self.xml.get_widget('features_treeview')
43
		self.desc_label = self.xml.get_widget('feature_desc_label')
44 45 46 47

		# {name: (available_function, unix_text, windows_text)}
		self.features = {
			_('PyOpenSSL'): (self.pyopenssl_available,
48 49 50
				_('A library used to validate server certificates to ensure a secure connection.'),
				_('Requires python-pyopenssl.'),
				_('Requires python-pyopenssl.')),
51
			_('Bonjour / Zeroconf'): (self.zeroconf_available,
52
				_('Serverless chatting with autodetected clients in a local network.'),
sb's avatar
sb committed
53
				_('Requires python-avahi.'),
54
				_('Requires pybonjour (http://o2s.csail.mit.edu/o2s-wiki/pybonjour).')),
55 56 57 58
			_('gajim-remote'): (self.dbus_available,
				_('A script to controle gajim via commandline.'),
				_('Requires python-dbus.'),
				_('Feature not available under Windows.')),
59
			_('OpenGPG'): (self.gpg_available,
60 61 62 63 64 65 66
				_('Encrypting chatmessages with gpg keys.'),
				_('Requires gpg and python-GnuPGInterface.'),
				_('Feature not available under Windows.')),
			_('network-manager'): (self.network_manager_available,
				_('Autodetection of network status.'),
				_('Requires gnome-network-manager and python-dbus.'),
				_('Feature not available under Windows.')),
67
			_('Session Management'): (self.session_management_available,
68 69 70 71 72 73 74
				_('Gajim session is stored on logout and restored on login.'),
				_('Requires python-gnome2.'),
				_('Feature not available under Windows.')),
			_('gnome-keyring'): (self.gnome_keyring_available,
				_('Passwords can be stored securely and not just in plaintext.'),
				_('Requires gnome-keyring and python-gnome2-desktop.'),
				_('Feature not available under Windows.')),
75
			_('SRV'): (self.srv_available,
Yann Leboulanger's avatar
Yann Leboulanger committed
76
				_('Ability to connect to servers which are using SRV records.'),
77 78
				_('Requires dnsutils.'),
				_('Requires nslookup to use SRV records.')),
79
			_('Spell Checker'): (self.speller_available,
80 81 82
				_('Spellchecking of composed messages.'),
				_('Requires python-gnome2-extras or compilation of gtkspell module from Gajim sources.'),
				_('Feature not available under Windows.')),
83
			_('Notification-daemon'): (self.notification_available,
84 85 86
				_('Passive popups notifying for new events.'),	
				_('Requires python-notify or instead python-dbus in conjunction with notification-daemon.'),
				_('Feature not available under Windows.')),
87
			_('Trayicon'): (self.trayicon_available,
88 89 90
				_('A icon in systemtray reflecting the current presence.'), 
				_('Requires python-gnome2-extras or compiled  trayicon module from Gajim sources.'),
				_('Requires PyGTK >= 2.10.')),
91
			_('Idle'): (self.idle_available,
92 93 94
				_('Ability to measure idle time, in order to set auto status.'),
				_('Requires compilation of the idle module from Gajim sources.'),
				_('Requires compilation of the idle module from Gajim sources.')),
95 96
			_('LaTeX'): (self.latex_available,
				_('Transform LaTeX espressions between $$ $$.'),
97
				_('Requires texlive-latex-base, dvips and imagemagick. You have to set \'use_latex\' to True in the Advanced Configuration Editor.'),
98
				_('Feature not available under Windows.')),
99 100 101 102
			_('End to end encryption'): (self.pycrypto_available,
				_('Encrypting chatmessages.'),
				_('Requires python-crypto.'),
				_('Requires python-crypto.')),
103 104 105 106
			_('RST Generator'): (self.docutils_available,
				_('Generate XHTML output from RST code (see http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html).'),
				_('Requires python-docutils.'),
				_('Requires python-docutils.')),
107 108 109 110
			_('libsexy'): (self.pysexy_available,
				_('Ability to have clickable URLs in chat window.'),
				_('Requires python-sexy.'),
				_('Requires python-sexy.')),
111 112 113 114 115 116 117 118 119
		}

		# name, supported
		self.model = gtk.ListStore(str, bool)
		treeview.set_model(self.model)

		col = gtk.TreeViewColumn(_('Available'))
		treeview.append_column(col)
		cell = gtk.CellRendererToggle()
120
		cell.set_property('radio', True)
121 122 123
		col.pack_start(cell)
		col.set_attributes(cell, active = 1)

124 125 126 127 128 129
		col = gtk.TreeViewColumn(_('Feature'))
		treeview.append_column(col)
		cell = gtk.CellRendererText()
		col.pack_start(cell, expand = True)
		col.add_attribute(cell, 'text', 0)

130 131 132 133 134 135 136 137 138 139 140 141
		# Fill model
		for feature in self.features:
			func = self.features[feature][0]
			rep = func()
			self.model.append([feature, rep])
		self.xml.signal_autoconnect(self)
		self.window.show_all()
		self.xml.get_widget('close_button').grab_focus()

	def on_close_button_clicked(self, widget):
		self.window.destroy()

142 143 144
	def on_features_treeview_cursor_changed(self, widget):
		selection = widget.get_selection()
		path = selection.get_selected_rows()[1][0]
145 146
		available = self.model[path][1]
		feature = self.model[path][0]
147
		text = self.features[feature][1] + '\n'
148
		if os.name == 'nt':
149
			text = text + self.features[feature][3]
150
		else:
151
			text = text + self.features[feature][2]
152
		self.desc_label.set_text(text)
153 154 155 156 157 158 159 160 161 162 163 164 165

	def pyopenssl_available(self):
		try:
			import OpenSSL.SSL
			import OpenSSL.crypto
		except:
			return False
		return True

	def zeroconf_available(self):
		try:
			import avahi
		except:
166 167 168 169
			try:
				import pybonjour
			except:
				return False
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
		return True

	def dbus_available(self):
		if os.name == 'nt':
			return False
		from common import dbus_support
		return dbus_support.supported

	def gpg_available(self):
		if os.name == 'nt':
			return False
		from common import GnuPG
		return GnuPG.USE_GPG

	def network_manager_available(self):
		if os.name == 'nt':
			return False
		import network_manager_listener
		return network_manager_listener.supported

	def session_management_available(self):
		if os.name == 'nt':
			return False
		try:
			import gnome.ui
		except:
			return False
		return True

	def gnome_keyring_available(self):
		if os.name == 'nt':
			return False
		try:
			import gnomekeyring
		except:
			return False
		return True

	def srv_available(self):
		return helpers.is_in_path('nslookup')

	def speller_available(self):
		if os.name == 'nt':
			return False
		try:
			import gtkspell
		except:
			return False
		return True

	def notification_available(self):
		if os.name == 'nt':
			return False
223 224 225 226 227 228
		elif sys.platform == 'darwin':
			try:
				import osx.growler
			except:
				return False
			return True
Yann Leboulanger's avatar
Yann Leboulanger committed
229
		from common import dbus_support
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
		if self.dbus_available() and dbus_support.get_notifications_interface():
			return True
		try:
			import pynotify
		except:
			return False
		return True

	def trayicon_available(self):
		if os.name == 'nt' and gtk.pygtk_version >= (2, 10, 0) and \
		gtk.gtk_version >= (2, 10, 0):
			return True
		try:
			import systray
		except:
			return False
		return True

	def idle_available(self):
		from common import sleepy
		return sleepy.SUPPORTED
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272

	def latex_available(self):
		'''check is latex is available and if it can create a picture.'''

		if os.name == 'nt':
			return False

		exitcode = 0
		random.seed()
		tmpfile = os.path.join(gettempdir(), "gajimtex_" + \
			random.randint(0,100).__str__())

		# build latex string
		texstr = '\\documentclass[12pt]{article}\\usepackage[dvips]{graphicx}'
		texstr += '\\usepackage{amsmath}\\usepackage{amssymb}\\pagestyle{empty}'
		texstr += '\\begin{document}\\begin{large}\\begin{gather*}test'
		texstr += '\\end{gather*}\\end{large}\\end{document}'

		file = open(os.path.join(tmpfile + ".tex"), "w+")
		file.write(texstr)
		file.flush()
		file.close()
273 274
		try:
			p = Popen(['latex', '--interaction=nonstopmode', tmpfile + '.tex'],
275 276
				cwd=gettempdir())
			exitcode = p.wait()
277 278
		except:
			exitcode = 1
279
		if exitcode == 0:
280 281 282 283 284 285 286 287 288 289 290 291 292
			try:
				p = Popen(['dvips', '-E', '-o', tmpfile + '.ps', tmpfile + '.dvi'],
					cwd=gettempdir())
				exitcode = p.wait()
			except:
				exitcode = 1
		if exitcode == 0:
			try:
				p = Popen(['convert', tmpfile + '.ps', tmpfile + '.png'],
					cwd=gettempdir())
				exitcode = p.wait()
			except:
				exitcode = 1
293 294 295 296 297 298 299 300
		extensions = [".tex", ".log", ".aux", ".dvi", ".ps", ".png"]
		for ext in extensions:
			try:
				os.remove(tmpfile + ext)
			except Exception:
				pass
		if exitcode == 0:
			return True
301
		return False
302 303 304 305

	def pycrypto_available(self):
		from common import gajim
		return gajim.HAVE_PYCRYPTO
306 307 308 309 310 311 312

	def docutils_available(self):
		try:
			import docutils
		except:
			return False
		return True
313 314 315 316

	def pysexy_available(self):
		from common import gajim
		return gajim.HAVE_PYSEXY