Philipp Hörist pushed to branch master at gajim / gajim
Commits:
-
42d4aa2a
by Philipp Hörist at 2017-01-03T23:08:32+01:00
-
2298af9d
by Emmanuel Gil Peyrot at 2017-01-03T23:08:47+01:00
-
9d2223ea
by Emmanuel Gil Peyrot at 2017-01-03T23:08:48+01:00
-
e7812cbd
by Philipp Hörist at 2017-01-03T23:08:48+01:00
-
815ecdcf
by Philipp Hörist at 2017-01-03T23:08:48+01:00
-
2676d7ea
by Philipp Hörist at 2017-01-03T23:08:49+01:00
-
079b5346
by Philipp Hörist at 2017-01-03T23:08:49+01:00
-
0443d5a6
by Philipp Hörist at 2017-01-03T23:08:50+01:00
-
1c8f08a3
by Philipp Hörist at 2017-01-03T23:08:50+01:00
-
d5bb5d40
by Philipp Hörist at 2017-01-03T23:08:51+01:00
-
f1693fa5
by Philipp Hörist at 2017-01-03T23:08:51+01:00
-
33041619
by Philipp Hörist at 2017-01-03T23:08:51+01:00
-
32604e99
by Philipp Hörist at 2017-01-03T23:08:52+01:00
-
39ec724e
by Philipp Hörist at 2017-01-03T23:08:52+01:00
-
503c295e
by Philipp Hörist at 2017-01-03T23:10:50+01:00
-
9b0be66b
by Philipp Hörist at 2017-01-03T23:10:57+01:00
-
a6bda765
by Philipp Hörist at 2017-01-03T23:10:58+01:00
-
2b1b461e
by Philipp Hörist at 2017-01-03T23:51:23+01:00
8 changed files:
- + src/application.py
- src/common/configpaths.py
- src/common/helpers.py
- src/common/logger.py
- src/dialogs.py
- src/gajim.py
- src/gui_interface.py
- src/roster_window.py
Changes:
| 1 |
+# -*- coding:utf-8 -*-
|
|
| 2 |
+## src/application.py
|
|
| 3 |
+##
|
|
| 4 |
+## Copyright (C) 2016 Emmanuel Gil Peyrot <linkmauve AT linkmauve.fr>
|
|
| 5 |
+##
|
|
| 6 |
+## This file is part of Gajim.
|
|
| 7 |
+##
|
|
| 8 |
+## 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 |
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| 14 |
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
| 15 |
+## GNU General Public License for more details.
|
|
| 16 |
+##
|
|
| 17 |
+## You should have received a copy of the GNU General Public License
|
|
| 18 |
+## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
|
| 19 |
+##
|
|
| 20 |
+ |
|
| 21 |
+import sys
|
|
| 22 |
+import os
|
|
| 23 |
+import logging
|
|
| 24 |
+import signal
|
|
| 25 |
+import locale
|
|
| 26 |
+from gi.repository import GLib, Gio, Gtk
|
|
| 27 |
+from common import i18n
|
|
| 28 |
+from common import logging_helpers
|
|
| 29 |
+from common import crypto
|
|
| 30 |
+try:
|
|
| 31 |
+ PYOPENSSL_PRNG_PRESENT = True
|
|
| 32 |
+ import OpenSSL.rand
|
|
| 33 |
+except ImportError:
|
|
| 34 |
+ print('PyOpenSSL not available, impossible to generate entropy', file=sys.stderr)
|
|
| 35 |
+ PYOPENSSL_PRNG_PRESENT = False
|
|
| 36 |
+ |
|
| 37 |
+logging_helpers.init(sys.stderr.isatty())
|
|
| 38 |
+log = logging.getLogger('gajim.gajim')
|
|
| 39 |
+ |
|
| 40 |
+ |
|
| 41 |
+class GajimApplication(Gtk.Application):
|
|
| 42 |
+ '''Main class handling activation and command line.'''
|
|
| 43 |
+ |
|
| 44 |
+ def __init__(self):
|
|
| 45 |
+ Gtk.Application.__init__(self, application_id='org.gajim.Gajim',
|
|
| 46 |
+ flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE)
|
|
| 47 |
+ self.add_main_option('version', ord('V'), GLib.OptionFlags.NONE,
|
|
| 48 |
+ GLib.OptionArg.NONE,
|
|
| 49 |
+ _('Show the application\'s version'))
|
|
| 50 |
+ self.add_main_option('quiet', ord('q'), GLib.OptionFlags.NONE,
|
|
| 51 |
+ GLib.OptionArg.NONE,
|
|
| 52 |
+ _('Show only critical errors'))
|
|
| 53 |
+ self.add_main_option('separate', ord('s'), GLib.OptionFlags.NONE,
|
|
| 54 |
+ GLib.OptionArg.NONE,
|
|
| 55 |
+ _('Separate profile files completely (even '
|
|
| 56 |
+ 'history db and plugins)'))
|
|
| 57 |
+ self.add_main_option('verbose', ord('v'), GLib.OptionFlags.NONE,
|
|
| 58 |
+ GLib.OptionArg.NONE,
|
|
| 59 |
+ _('Print xml stanzas and other debug '
|
|
| 60 |
+ 'information'))
|
|
| 61 |
+ self.add_main_option('windev', ord('w'), GLib.OptionFlags.NONE,
|
|
| 62 |
+ GLib.OptionArg.NONE,
|
|
| 63 |
+ _('Print stdout/stderr to the console '
|
|
| 64 |
+ 'on Windows'))
|
|
| 65 |
+ self.add_main_option('profile', ord('p'), GLib.OptionFlags.NONE,
|
|
| 66 |
+ GLib.OptionArg.STRING,
|
|
| 67 |
+ _('Use defined profile in configuration '
|
|
| 68 |
+ 'directory'), 'NAME')
|
|
| 69 |
+ self.add_main_option('config-path', ord('c'), GLib.OptionFlags.NONE,
|
|
| 70 |
+ GLib.OptionArg.STRING,
|
|
| 71 |
+ _('Set configuration directory'), 'PATH')
|
|
| 72 |
+ self.add_main_option('loglevel', ord('l'), GLib.OptionFlags.NONE,
|
|
| 73 |
+ GLib.OptionArg.STRING,
|
|
| 74 |
+ _('Configure logging system'), 'LEVEL')
|
|
| 75 |
+ |
|
| 76 |
+ self.profile = ''
|
|
| 77 |
+ self.config_path = None
|
|
| 78 |
+ self.profile_separation = False
|
|
| 79 |
+ self.interface = None
|
|
| 80 |
+ self.rng_seed = None
|
|
| 81 |
+ |
|
| 82 |
+ GLib.set_prgname('gajim')
|
|
| 83 |
+ GLib.set_application_name('Gajim')
|
|
| 84 |
+ |
|
| 85 |
+ def do_startup(self):
|
|
| 86 |
+ Gtk.Application.do_startup(self)
|
|
| 87 |
+ |
|
| 88 |
+ def do_activate(self):
|
|
| 89 |
+ # If a second instance starts do_activate() is called
|
|
| 90 |
+ # We bringt the Roster window to the front, GTK exits afterwards.
|
|
| 91 |
+ if self.interface:
|
|
| 92 |
+ self.interface.roster.window.present()
|
|
| 93 |
+ return
|
|
| 94 |
+ |
|
| 95 |
+ Gtk.Application.do_activate(self)
|
|
| 96 |
+ |
|
| 97 |
+ # Create and initialize Application Paths & Databases
|
|
| 98 |
+ import common.configpaths
|
|
| 99 |
+ common.configpaths.gajimpaths.init(
|
|
| 100 |
+ self.config_path, self.profile, self.profile_separation)
|
|
| 101 |
+ from common import gajim
|
|
| 102 |
+ from common import check_paths
|
|
| 103 |
+ from common import exceptions
|
|
| 104 |
+ from common import logger
|
|
| 105 |
+ from common import caps_cache
|
|
| 106 |
+ try:
|
|
| 107 |
+ gajim.logger = logger.Logger()
|
|
| 108 |
+ caps_cache.initialize(gajim.logger)
|
|
| 109 |
+ check_paths.check_and_possibly_create_paths()
|
|
| 110 |
+ except exceptions.DatabaseMalformed:
|
|
| 111 |
+ dlg = Gtk.MessageDialog(
|
|
| 112 |
+ None,
|
|
| 113 |
+ Gtk.DialogFlags.DESTROY_WITH_PARENT | Gtk.DialogFlags.MODAL,
|
|
| 114 |
+ Gtk.MessageType.ERROR,
|
|
| 115 |
+ Gtk.ButtonsType.OK,
|
|
| 116 |
+ _('Database Error'))
|
|
| 117 |
+ dlg.format_secondary_text(
|
|
| 118 |
+ _('The database file (%s) cannot be read. Try to repair it '
|
|
| 119 |
+ '(see http://trac.gajim.org/wiki/DatabaseBackup) or remove it '
|
|
| 120 |
+ '(all history will be lost).') % gajim.gajimpaths['LOG_DB'])
|
|
| 121 |
+ dlg.run()
|
|
| 122 |
+ dlg.destroy()
|
|
| 123 |
+ sys.exit()
|
|
| 124 |
+ |
|
| 125 |
+ if os.name == 'nt':
|
|
| 126 |
+ import gettext
|
|
| 127 |
+ # needed for docutils
|
|
| 128 |
+ sys.path.append('.')
|
|
| 129 |
+ APP = 'gajim'
|
|
| 130 |
+ DIR = '../po'
|
|
| 131 |
+ lang, enc = locale.getdefaultlocale()
|
|
| 132 |
+ os.environ['LANG'] = lang
|
|
| 133 |
+ gettext.bindtextdomain(APP, DIR)
|
|
| 134 |
+ gettext.textdomain(APP)
|
|
| 135 |
+ gettext.install(APP, DIR)
|
|
| 136 |
+ |
|
| 137 |
+ # This is for Windows translation which is currently not
|
|
| 138 |
+ # working on GTK 3.18.9
|
|
| 139 |
+ # locale.setlocale(locale.LC_ALL, '')
|
|
| 140 |
+ # import ctypes
|
|
| 141 |
+ # import ctypes.util
|
|
| 142 |
+ # libintl_path = ctypes.util.find_library('intl')
|
|
| 143 |
+ # if libintl_path == None:
|
|
| 144 |
+ # local_intl = os.path.join('gtk', 'bin', 'intl.dll')
|
|
| 145 |
+ # if os.path.exists(local_intl):
|
|
| 146 |
+ # libintl_path = local_intl
|
|
| 147 |
+ # if libintl_path == None:
|
|
| 148 |
+ # raise ImportError('intl.dll library not found')
|
|
| 149 |
+ # libintl = ctypes.cdll.LoadLibrary(libintl_path)
|
|
| 150 |
+ # libintl.bindtextdomain(APP, DIR)
|
|
| 151 |
+ # libintl.bind_textdomain_codeset(APP, 'UTF-8')
|
|
| 152 |
+ # plugins_locale_dir = os.path.join(common.configpaths.gajimpaths[
|
|
| 153 |
+ # 'PLUGINS_USER'], 'locale').encode(locale.getpreferredencoding())
|
|
| 154 |
+ # libintl.bindtextdomain('gajim_plugins', plugins_locale_dir)
|
|
| 155 |
+ # libintl.bind_textdomain_codeset('gajim_plugins', 'UTF-8')
|
|
| 156 |
+ |
|
| 157 |
+ if Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL:
|
|
| 158 |
+ i18n.direction_mark = '\u200F'
|
|
| 159 |
+ |
|
| 160 |
+ from ctypes import CDLL
|
|
| 161 |
+ from ctypes.util import find_library
|
|
| 162 |
+ import platform
|
|
| 163 |
+ |
|
| 164 |
+ sysname = platform.system()
|
|
| 165 |
+ if sysname in ('Linux', 'FreeBSD', 'OpenBSD', 'NetBSD'):
|
|
| 166 |
+ libc = CDLL(find_library('c'))
|
|
| 167 |
+ |
|
| 168 |
+ # The constant defined in <linux/prctl.h> which is used to set the name
|
|
| 169 |
+ # of the process.
|
|
| 170 |
+ PR_SET_NAME = 15
|
|
| 171 |
+ |
|
| 172 |
+ if sysname == 'Linux':
|
|
| 173 |
+ libc.prctl(PR_SET_NAME, 'gajim')
|
|
| 174 |
+ elif sysname in ('FreeBSD', 'OpenBSD', 'NetBSD'):
|
|
| 175 |
+ libc.setproctitle('gajim')
|
|
| 176 |
+ |
|
| 177 |
+ # Seed the OpenSSL pseudo random number generator from file and initialize
|
|
| 178 |
+ if PYOPENSSL_PRNG_PRESENT:
|
|
| 179 |
+ self.rng_seed = gajim.gajimpaths['RNG_SEED']
|
|
| 180 |
+ # Seed from file
|
|
| 181 |
+ try:
|
|
| 182 |
+ OpenSSL.rand.load_file(self.rng_seed)
|
|
| 183 |
+ except TypeError:
|
|
| 184 |
+ OpenSSL.rand.load_file(self.rng_seed.encode('utf-8'))
|
|
| 185 |
+ crypto.add_entropy_sources_OpenSSL()
|
|
| 186 |
+ try:
|
|
| 187 |
+ OpenSSL.rand.write_file(self.rng_seed)
|
|
| 188 |
+ except TypeError:
|
|
| 189 |
+ OpenSSL.rand.write_file(self.rng_seed.encode('utf-8'))
|
|
| 190 |
+ |
|
| 191 |
+ def sigint_cb(num, stack):
|
|
| 192 |
+ print('SIGINT/SIGTERM received')
|
|
| 193 |
+ self.quit()
|
|
| 194 |
+ # ^C exits the application normally
|
|
| 195 |
+ signal.signal(signal.SIGINT, sigint_cb)
|
|
| 196 |
+ signal.signal(signal.SIGTERM, sigint_cb)
|
|
| 197 |
+ |
|
| 198 |
+ log.info("Encodings: d:%s, fs:%s, p:%s", sys.getdefaultencoding(),
|
|
| 199 |
+ sys.getfilesystemencoding(), locale.getpreferredencoding())
|
|
| 200 |
+ |
|
| 201 |
+ from gui_interface import Interface
|
|
| 202 |
+ self.interface = Interface()
|
|
| 203 |
+ self.interface.run(self)
|
|
| 204 |
+ |
|
| 205 |
+ def do_shutdown(self, *args):
|
|
| 206 |
+ Gtk.Application.do_shutdown(self)
|
|
| 207 |
+ # Save the entropy from OpenSSL PRNG
|
|
| 208 |
+ if PYOPENSSL_PRNG_PRESENT and self.rng_seed:
|
|
| 209 |
+ try:
|
|
| 210 |
+ OpenSSL.rand.write_file(self.rng_seed)
|
|
| 211 |
+ except TypeError:
|
|
| 212 |
+ OpenSSL.rand.write_file(self.rng_seed.encode('utf-8'))
|
|
| 213 |
+ # Shutdown GUI and save config
|
|
| 214 |
+ if hasattr(self.interface, 'roster') and self.interface.roster:
|
|
| 215 |
+ self.interface.roster.prepare_quit()
|
|
| 216 |
+ |
|
| 217 |
+ def do_command_line(self, command_line: Gio.ApplicationCommandLine) -> int:
|
|
| 218 |
+ Gtk.Application.do_command_line(self, command_line)
|
|
| 219 |
+ options = command_line.get_options_dict()
|
|
| 220 |
+ if options.contains('quiet'):
|
|
| 221 |
+ logging_helpers.set_quiet()
|
|
| 222 |
+ if options.contains('separate'):
|
|
| 223 |
+ self.profile_separation = True
|
|
| 224 |
+ if options.contains('verbose'):
|
|
| 225 |
+ logging_helpers.set_verbose()
|
|
| 226 |
+ if options.contains('profile'):
|
|
| 227 |
+ variant = options.lookup_value('profile')
|
|
| 228 |
+ self.profile = variant.get_string()
|
|
| 229 |
+ if options.contains('loglevel'):
|
|
| 230 |
+ variant = options.lookup_value('loglevel')
|
|
| 231 |
+ string = variant.get_string()
|
|
| 232 |
+ logging_helpers.set_loglevels(string)
|
|
| 233 |
+ if options.contains('config-path'):
|
|
| 234 |
+ variant = options.lookup_value('config-path')
|
|
| 235 |
+ self.config_path = variant.get_string()
|
|
| 236 |
+ self.activate()
|
|
| 237 |
+ return 0
|
| ... | ... | @@ -180,7 +180,6 @@ class ConfigPaths: |
| 180 | 180 |
|
| 181 | 181 |
def init_profile(self, profile):
|
| 182 | 182 |
conffile = windowsify('config')
|
| 183 |
- pidfile = windowsify('gajim')
|
|
| 184 | 183 |
secretsfile = windowsify('secrets')
|
| 185 | 184 |
pluginsconfdir = windowsify('pluginsconfig')
|
| 186 | 185 |
certsdir = windowsify(u'certs')
|
| ... | ... | @@ -188,16 +187,13 @@ class ConfigPaths: |
| 188 | 187 |
|
| 189 | 188 |
if len(profile) > 0:
|
| 190 | 189 |
conffile += '.' + profile
|
| 191 |
- pidfile += '.' + profile
|
|
| 192 | 190 |
secretsfile += '.' + profile
|
| 193 | 191 |
pluginsconfdir += '.' + profile
|
| 194 | 192 |
certsdir += u'.' + profile
|
| 195 | 193 |
localcertsdir += u'.' + profile
|
| 196 | 194 |
|
| 197 |
- pidfile += '.pid'
|
|
| 198 | 195 |
self.add('SECRETS_FILE', TYPE_DATA, secretsfile)
|
| 199 | 196 |
self.add('MY_PEER_CERTS', TYPE_DATA, certsdir)
|
| 200 |
- self.add('PID_FILE', TYPE_CACHE, pidfile)
|
|
| 201 | 197 |
self.add('CONFIG_FILE', TYPE_CONFIG, conffile)
|
| 202 | 198 |
self.add('PLUGINS_CONFIG_DIR', TYPE_CONFIG, pluginsconfdir)
|
| 203 | 199 |
self.add('MY_CERT', TYPE_CONFIG, localcertsdir)
|
| ... | ... | @@ -52,10 +52,16 @@ from string import Template |
| 52 | 52 |
from common.i18n import Q_
|
| 53 | 53 |
from common.i18n import ngettext
|
| 54 | 54 |
|
| 55 |
+if os.name == 'nt':
|
|
| 56 |
+ try:
|
|
| 57 |
+ HAS_WINSOUND = True
|
|
| 58 |
+ import winsound # windows-only built-in module for playing wav
|
|
| 59 |
+ except ImportError:
|
|
| 60 |
+ HAS_WINSOUND = False
|
|
| 61 |
+ print('Gajim is not able to playback sound because'
|
|
| 62 |
+ 'pywin32 is missing', file=sys.stderr)
|
|
| 63 |
+ |
|
| 55 | 64 |
try:
|
| 56 |
- import winsound # windows-only built-in module for playing wav
|
|
| 57 |
- import win32api
|
|
| 58 |
- import win32con
|
|
| 59 | 65 |
import wave # posix-only fallback wav playback
|
| 60 | 66 |
import ossaudiodev as oss
|
| 61 | 67 |
except Exception:
|
| ... | ... | @@ -462,52 +468,6 @@ def get_output_of_command(command): |
| 462 | 468 |
|
| 463 | 469 |
return output
|
| 464 | 470 |
|
| 465 |
-def get_windows_reg_env(varname, default=''):
|
|
| 466 |
- r"""
|
|
| 467 |
- Ask for paths commonly used but not exposed as ENVs in english Windows 2003
|
|
| 468 |
- those are:
|
|
| 469 |
- 'AppData' = %USERPROFILE%\Application Data (also an ENV)
|
|
| 470 |
- 'Desktop' = %USERPROFILE%\Desktop
|
|
| 471 |
- 'Favorites' = %USERPROFILE%\Favorites
|
|
| 472 |
- 'NetHood' = %USERPROFILE%\ NetHood
|
|
| 473 |
- 'Personal' = D:\My Documents (PATH TO MY DOCUMENTS)
|
|
| 474 |
- 'PrintHood' = %USERPROFILE%\PrintHood
|
|
| 475 |
- 'Programs' = %USERPROFILE%\Start Menu\Programs
|
|
| 476 |
- 'Recent' = %USERPROFILE%\Recent
|
|
| 477 |
- 'SendTo' = %USERPROFILE%\SendTo
|
|
| 478 |
- 'Start Menu' = %USERPROFILE%\Start Menu
|
|
| 479 |
- 'Startup' = %USERPROFILE%\Start Menu\Programs\Startup
|
|
| 480 |
- 'Templates' = %USERPROFILE%\Templates
|
|
| 481 |
- 'My Pictures' = D:\My Documents\My Pictures
|
|
| 482 |
- 'Local Settings' = %USERPROFILE%\Local Settings
|
|
| 483 |
- 'Local AppData' = %USERPROFILE%\Local Settings\Application Data
|
|
| 484 |
- 'Cache' = %USERPROFILE%\Local Settings\Temporary Internet Files
|
|
| 485 |
- 'Cookies' = %USERPROFILE%\Cookies
|
|
| 486 |
- 'History' = %USERPROFILE%\Local Settings\History
|
|
| 487 |
- """
|
|
| 488 |
- if os.name != 'nt':
|
|
| 489 |
- return ''
|
|
| 490 |
- |
|
| 491 |
- val = default
|
|
| 492 |
- try:
|
|
| 493 |
- rkey = win32api.RegOpenKey(win32con.HKEY_CURRENT_USER,
|
|
| 494 |
-r'Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders')
|
|
| 495 |
- try:
|
|
| 496 |
- val = str(win32api.RegQueryValueEx(rkey, varname)[0])
|
|
| 497 |
- val = win32api.ExpandEnvironmentStrings(val) # expand using environ
|
|
| 498 |
- except Exception:
|
|
| 499 |
- pass
|
|
| 500 |
- finally:
|
|
| 501 |
- win32api.RegCloseKey(rkey)
|
|
| 502 |
- return val
|
|
| 503 |
- |
|
| 504 |
-def get_documents_path():
|
|
| 505 |
- if os.name == 'nt':
|
|
| 506 |
- path = get_windows_reg_env('Personal')
|
|
| 507 |
- else:
|
|
| 508 |
- path = os.path.expanduser('~')
|
|
| 509 |
- return path
|
|
| 510 |
- |
|
| 511 | 471 |
def sanitize_filename(filename):
|
| 512 | 472 |
"""
|
| 513 | 473 |
Make sure the filename we will write does contain only acceptable and latin
|
| ... | ... | @@ -787,12 +747,12 @@ def play_sound_file(path_to_soundfile): |
| 787 | 747 |
path_to_soundfile = check_soundfile_path(path_to_soundfile)
|
| 788 | 748 |
if path_to_soundfile is None:
|
| 789 | 749 |
return
|
| 790 |
- elif os.name == 'nt':
|
|
| 750 |
+ elif os.name == 'nt' and HAS_WINSOUND:
|
|
| 791 | 751 |
try:
|
| 792 | 752 |
winsound.PlaySound(path_to_soundfile,
|
| 793 | 753 |
winsound.SND_FILENAME|winsound.SND_ASYNC)
|
| 794 | 754 |
except Exception:
|
| 795 |
- pass
|
|
| 755 |
+ log.exception('Sound Playback Error')
|
|
| 796 | 756 |
elif os.name == 'posix':
|
| 797 | 757 |
if gajim.config.get('soundplayer') == '':
|
| 798 | 758 |
def _oss_play():
|
| ... | ... | @@ -43,10 +43,9 @@ from common import ged |
| 43 | 43 |
|
| 44 | 44 |
import sqlite3 as sqlite
|
| 45 | 45 |
|
| 46 |
-from common import configpaths
|
|
| 47 |
-LOG_DB_PATH = configpaths.gajimpaths['LOG_DB']
|
|
| 46 |
+LOG_DB_PATH = gajim.gajimpaths['LOG_DB']
|
|
| 48 | 47 |
LOG_DB_FOLDER, LOG_DB_FILE = os.path.split(LOG_DB_PATH)
|
| 49 |
-CACHE_DB_PATH = configpaths.gajimpaths['CACHE_DB']
|
|
| 48 |
+CACHE_DB_PATH = gajim.gajimpaths['CACHE_DB']
|
|
| 50 | 49 |
|
| 51 | 50 |
import logging
|
| 52 | 51 |
log = logging.getLogger('gajim.c.logger')
|
| ... | ... | @@ -1495,7 +1495,7 @@ class FileChooserDialog(Gtk.FileChooserDialog): |
| 1495 | 1495 |
if current_folder and os.path.isdir(current_folder):
|
| 1496 | 1496 |
self.set_current_folder(current_folder)
|
| 1497 | 1497 |
else:
|
| 1498 |
- self.set_current_folder(helpers.get_documents_path())
|
|
| 1498 |
+ self.set_current_folder(os.path.expanduser('~'))
|
|
| 1499 | 1499 |
self.response_ok, self.response_cancel = \
|
| 1500 | 1500 |
on_response_ok, on_response_cancel
|
| 1501 | 1501 |
# in gtk+-2.10 clicked signal on some of the buttons in a dialog
|
| ... | ... | @@ -5047,7 +5047,7 @@ class ArchiveChooserDialog(FileChooserDialog): |
| 5047 | 5047 |
callback(path_to_file)
|
| 5048 | 5048 |
self.destroy()
|
| 5049 | 5049 |
|
| 5050 |
- path = helpers.get_documents_path()
|
|
| 5050 |
+ path = os.path.expanduser('~')
|
|
| 5051 | 5051 |
|
| 5052 | 5052 |
FileChooserDialog.__init__(self,
|
| 5053 | 5053 |
title_text=_('Choose Archive'),
|
| ... | ... | @@ -35,467 +35,76 @@ |
| 35 | 35 |
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
| 36 | 36 |
##
|
| 37 | 37 |
|
| 38 |
-import os
|
|
| 39 | 38 |
import sys
|
| 40 |
-import warnings
|
|
| 41 |
-import OpenSSL
|
|
| 39 |
+import os
|
|
| 40 |
+ |
|
| 41 |
+if '--version' in sys.argv or '-V' in sys.argv:
|
|
| 42 |
+ from common.defs import version
|
|
| 43 |
+ print(version)
|
|
| 44 |
+ sys.exit(0)
|
|
| 42 | 45 |
|
| 43 |
-if os.name == 'nt':
|
|
| 46 |
+WINDEV = False
|
|
| 47 |
+if '--windev' in sys.argv or '-w' in sys.argv:
|
|
| 48 |
+ WINDEV = True
|
|
| 49 |
+ |
|
| 50 |
+if os.name == 'nt' and not WINDEV:
|
|
| 51 |
+ import warnings
|
|
| 44 | 52 |
log_path = os.path.join(os.environ['APPDATA'], 'Gajim')
|
| 45 | 53 |
if not os.path.exists(log_path):
|
| 46 | 54 |
os.mkdir(log_path, 0o700)
|
| 47 | 55 |
log_file = os.path.join(log_path, 'gajim.log')
|
| 48 |
- fout = open(log_file, 'a')
|
|
| 49 |
- sys.stdout = fout
|
|
| 50 |
- sys.stderr = fout
|
|
| 51 |
- |
|
| 52 |
- warnings.filterwarnings(action='ignore')
|
|
| 53 |
- |
|
| 54 |
-MIN_NBXMPP_VER = "0.5.3"
|
|
| 55 |
-from gi.repository import GLib
|
|
| 56 |
-try:
|
|
| 57 |
- import nbxmpp
|
|
| 58 |
-except ImportError:
|
|
| 59 |
- print('Gajim needs python-nbxmpp to run. Quiting...')
|
|
| 60 |
- sys.exit(1)
|
|
| 61 |
- |
|
| 62 |
-from distutils.version import LooseVersion as V
|
|
| 63 |
-if V(nbxmpp.__version__) < V(MIN_NBXMPP_VER):
|
|
| 64 |
- print('Gajim needs python-nbxmpp >= %s to run. Quiting...' % MIN_NBXMPP_VER)
|
|
| 65 |
- sys.exit(1)
|
|
| 66 |
- |
|
| 67 |
-if os.name == 'nt':
|
|
| 68 |
- import locale
|
|
| 69 |
- import gettext
|
|
| 70 |
- APP = 'gajim'
|
|
| 71 |
- DIR = '../po'
|
|
| 72 |
- lang, enc = locale.getdefaultlocale()
|
|
| 73 |
- os.environ['LANG'] = lang
|
|
| 74 |
- gettext.bindtextdomain(APP, DIR)
|
|
| 75 |
- gettext.textdomain(APP)
|
|
| 76 |
- gettext.install(APP, DIR)
|
|
| 77 |
- |
|
| 78 |
-# locale.setlocale(locale.LC_ALL, '')
|
|
| 79 |
-# import ctypes
|
|
| 80 |
-# import ctypes.util
|
|
| 81 |
-# libintl_path = ctypes.util.find_library('intl')
|
|
| 82 |
-# if libintl_path == None:
|
|
| 83 |
-# local_intl = os.path.join('gtk', 'bin', 'intl.dll')
|
|
| 84 |
-# if os.path.exists(local_intl):
|
|
| 85 |
-# libintl_path = local_intl
|
|
| 86 |
-# if libintl_path == None:
|
|
| 87 |
-# raise ImportError('intl.dll library not found')
|
|
| 88 |
-# libintl = ctypes.cdll.LoadLibrary(libintl_path)
|
|
| 89 |
-# libintl.bindtextdomain(APP, DIR)
|
|
| 90 |
-# libintl.bind_textdomain_codeset(APP, 'UTF-8')
|
|
| 91 |
- |
|
| 92 |
-if os.name == 'nt':
|
|
| 93 |
- # needed for docutils
|
|
| 94 |
- sys.path.append('.')
|
|
| 95 |
- |
|
| 96 |
-from common import logging_helpers
|
|
| 97 |
-logging_helpers.init(sys.stderr.isatty())
|
|
| 98 |
- |
|
| 99 |
-import logging
|
|
| 100 |
-# gajim.gui or gajim.gtk more appropriate ?
|
|
| 101 |
-log = logging.getLogger('gajim.gajim')
|
|
| 102 | 56 |
|
| 103 |
-import gi
|
|
| 104 |
-gi.require_version('Gtk', '3.0')
|
|
| 105 |
-gi.require_version('Gdk', '3.0')
|
|
| 106 |
-gi.require_version('GObject', '2.0')
|
|
| 107 |
-gi.require_version('Pango', '1.0')
|
|
| 108 |
- |
|
| 109 |
-import getopt
|
|
| 110 |
-from common import i18n
|
|
| 111 |
- |
|
| 112 |
-def parseOpts():
|
|
| 113 |
- profile_ = ''
|
|
| 114 |
- config_path_ = None
|
|
| 115 |
- profile_separation_ = False
|
|
| 116 |
-
|
|
| 117 |
- try:
|
|
| 118 |
- shortargs = 'hqsvl:p:c:'
|
|
| 119 |
- # add gtk/gnome session option as gtk_get_option_group is not wrapped
|
|
| 120 |
- longargs = 'help quiet separate verbose loglevel= profile= config-path='
|
|
| 121 |
- longargs += ' class= name= screen= gtk-module= sync g-fatal-warnings'
|
|
| 122 |
- longargs += ' sm-client-id= sm-client-state-file= sm-disable'
|
|
| 123 |
- opts = getopt.getopt(sys.argv[1:], shortargs, longargs.split())[0]
|
|
| 124 |
- except getopt.error as msg1:
|
|
| 125 |
- print(str(msg1))
|
|
| 126 |
- print('for help use --help')
|
|
| 127 |
- sys.exit(2)
|
|
| 128 |
- for o, a in opts:
|
|
| 129 |
- if o in ('-h', '--help'):
|
|
| 130 |
- out = _('Usage:') + \
|
|
| 131 |
- '\n gajim [options] filename\n\n' + \
|
|
| 132 |
- _('Options:') + \
|
|
| 133 |
- '\n -h, --help ' + \
|
|
| 134 |
- _('Show this help message and exit') + \
|
|
| 135 |
- '\n -q, --quiet ' + \
|
|
| 136 |
- _('Show only critical errors') + \
|
|
| 137 |
- '\n -s, --separate ' + \
|
|
| 138 |
- _('Separate profile files completely (even history db and plugins)') + \
|
|
| 139 |
- '\n -v, --verbose ' + \
|
|
| 140 |
- _('Print xml stanzas and other debug information') + \
|
|
| 141 |
- '\n -p, --profile ' + \
|
|
| 142 |
- _('Use defined profile in configuration directory') + \
|
|
| 143 |
- '\n -c, --config-path ' + \
|
|
| 144 |
- _('Set configuration directory') + \
|
|
| 145 |
- '\n -l, --loglevel ' + \
|
|
| 146 |
- _('Configure logging system') + '\n'
|
|
| 147 |
- print(out)
|
|
| 148 |
- sys.exit()
|
|
| 149 |
- elif o in ('-q', '--quiet'):
|
|
| 150 |
- logging_helpers.set_quiet()
|
|
| 151 |
- elif o in ('-s', '--separate'):
|
|
| 152 |
- profile_separation_ = True
|
|
| 153 |
- elif o in ('-v', '--verbose'):
|
|
| 154 |
- logging_helpers.set_verbose()
|
|
| 155 |
- elif o in ('-p', '--profile'): # gajim --profile name
|
|
| 156 |
- profile_ = a
|
|
| 157 |
- elif o in ('-l', '--loglevel'):
|
|
| 158 |
- logging_helpers.set_loglevels(a)
|
|
| 159 |
- elif o in ('-c', '--config-path'):
|
|
| 160 |
- config_path_ = a
|
|
| 161 |
- return profile_, config_path_, profile_separation_
|
|
| 162 |
- |
|
| 163 |
-import locale
|
|
| 164 |
-profile, config_path, profile_separation = parseOpts()
|
|
| 165 |
-del parseOpts
|
|
| 166 |
- |
|
| 167 |
-import common.configpaths
|
|
| 168 |
-common.configpaths.gajimpaths.init(config_path, profile, profile_separation)
|
|
| 169 |
-del config_path
|
|
| 170 |
-del profile
|
|
| 171 |
- |
|
| 172 |
-if os.name == 'nt':
|
|
| 173 |
- plugins_locale_dir = os.path.join(common.configpaths.gajimpaths[
|
|
| 174 |
- 'PLUGINS_USER'], 'locale').encode(locale.getpreferredencoding())
|
|
| 175 |
-# libintl.bindtextdomain('gajim_plugins', plugins_locale_dir)
|
|
| 176 |
-# libintl.bind_textdomain_codeset('gajim_plugins', 'UTF-8')
|
|
| 177 |
- |
|
| 178 |
- class MyStderr(object):
|
|
| 57 |
+ class MyStd(object):
|
|
| 179 | 58 |
_file = None
|
| 180 | 59 |
_error = None
|
| 60 |
+ |
|
| 181 | 61 |
def write(self, text):
|
| 182 |
- fname = os.path.join(common.configpaths.gajimpaths.cache_root,
|
|
| 183 |
- os.path.split(sys.executable)[1]+'.log')
|
|
| 184 | 62 |
if self._file is None and self._error is None:
|
| 185 | 63 |
try:
|
| 186 |
- self._file = open(fname, 'a')
|
|
| 64 |
+ self._file = open(log_file, 'a')
|
|
| 187 | 65 |
except Exception as details:
|
| 188 | 66 |
self._error = details
|
| 189 | 67 |
if self._file is not None:
|
| 190 | 68 |
self._file.write(text)
|
| 191 | 69 |
self._file.flush()
|
| 70 |
+ |
|
| 192 | 71 |
def flush(self):
|
| 193 | 72 |
if self._file is not None:
|
| 194 | 73 |
self._file.flush()
|
| 195 | 74 |
|
| 196 |
- sys.stderr = MyStderr()
|
|
| 197 |
- |
|
| 198 |
-# PyGTK2.10+ only throws a warning
|
|
| 199 |
-warnings.filterwarnings('error', module='Gtk')
|
|
| 200 |
-try:
|
|
| 201 |
- from gi.repository import GObject
|
|
| 202 |
- GObject.set_prgname('gajim')
|
|
| 203 |
- from gi.repository import Gtk
|
|
| 204 |
- from gi.repository import Gdk
|
|
| 205 |
- from gi.repository import GLib
|
|
| 206 |
-except Warning as msg2:
|
|
| 207 |
- if str(msg2) == 'could not open display':
|
|
| 208 |
- print(_('Gajim needs X server to run. Quiting...'), file=sys.stderr)
|
|
| 209 |
- else:
|
|
| 210 |
- print(_('importing PyGTK failed: %s') % str(msg2), file=sys.stderr)
|
|
| 211 |
- sys.exit()
|
|
| 212 |
-warnings.resetwarnings()
|
|
| 213 |
- |
|
| 75 |
+ def isatty(self):
|
|
| 76 |
+ return False
|
|
| 214 | 77 |
|
| 215 |
-if os.name == 'nt':
|
|
| 78 |
+ outerr = MyStd()
|
|
| 79 |
+ sys.stdout = outerr
|
|
| 80 |
+ sys.stderr = outerr
|
|
| 216 | 81 |
warnings.filterwarnings(action='ignore')
|
| 217 | 82 |
|
| 218 |
-if Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL:
|
|
| 219 |
- i18n.direction_mark = '\u200F'
|
|
| 220 |
-pritext = ''
|
|
| 221 |
- |
|
| 222 |
-from common import exceptions
|
|
| 223 |
-try:
|
|
| 224 |
- from common import gajim
|
|
| 225 |
-except exceptions.DatabaseMalformed:
|
|
| 226 |
- pritext = _('Database Error')
|
|
| 227 |
- sectext = _('The database file (%s) cannot be read. Try to repair it (see '
|
|
| 228 |
- 'http://trac.gajim.org/wiki/DatabaseBackup) or remove it (all history '
|
|
| 229 |
- 'will be lost).') % common.logger.LOG_DB_PATH
|
|
| 230 |
-else:
|
|
| 231 |
- from common import logger
|
|
| 232 |
- gajim.logger = logger.Logger()
|
|
| 233 |
- from common import caps_cache
|
|
| 234 |
- caps_cache.initialize(gajim.logger)
|
|
| 235 |
- from common import dbus_support
|
|
| 236 |
- if dbus_support.supported:
|
|
| 237 |
- from music_track_listener import MusicTrackListener
|
|
| 238 |
- |
|
| 239 |
- from ctypes import CDLL
|
|
| 240 |
- from ctypes.util import find_library
|
|
| 241 |
- import platform
|
|
| 242 |
- |
|
| 243 |
- sysname = platform.system()
|
|
| 244 |
- if sysname in ('Linux', 'FreeBSD', 'OpenBSD', 'NetBSD'):
|
|
| 245 |
- libc = CDLL(find_library('c'))
|
|
| 246 |
- |
|
| 247 |
- # The constant defined in <linux/prctl.h> which is used to set the name
|
|
| 248 |
- # of the process.
|
|
| 249 |
- PR_SET_NAME = 15
|
|
| 250 |
- |
|
| 251 |
- if sysname == 'Linux':
|
|
| 252 |
- libc.prctl(PR_SET_NAME, 'gajim')
|
|
| 253 |
- elif sysname in ('FreeBSD', 'OpenBSD', 'NetBSD'):
|
|
| 254 |
- libc.setproctitle('gajim')
|
|
| 255 | 83 |
|
| 256 |
-# if Gtk.pygtk_version < (2, 22, 0):
|
|
| 257 |
-# pritext = _('Gajim needs PyGTK 2.22 or above')
|
|
| 258 |
-# sectext = _('Gajim needs PyGTK 2.22 or above to run. Quiting...')
|
|
| 259 |
-# elif Gtk.gtk_version < (2, 22, 0):
|
|
| 260 |
-# if (Gtk.get_major_version(), Gtk.get_minor_version(),
|
|
| 261 |
-# Gtk.get_micro_version()) < (2, 22, 0):
|
|
| 262 |
-# pritext = _('Gajim needs GTK 2.22 or above')
|
|
| 263 |
-# sectext = _('Gajim needs GTK 2.22 or above to run. Quiting...')
|
|
| 264 |
- |
|
| 265 |
- from common import check_paths
|
|
| 266 |
- |
|
| 267 |
- if os.name == 'nt':
|
|
| 268 |
- try:
|
|
| 269 |
- import winsound # windows-only built-in module for playing wav
|
|
| 270 |
- import win32api # do NOT remove. we req this module
|
|
| 271 |
- except Exception:
|
|
| 272 |
- pritext = _('Gajim needs pywin32 to run')
|
|
| 273 |
- sectext = _('Please make sure that Pywin32 is installed on your '
|
|
| 274 |
- 'system. You can get it at %s') % \
|
|
| 275 |
- 'http://sourceforge.net/project/showfiles.php?group_id=78018'
|
|
| 276 |
- |
|
| 277 |
-if pritext:
|
|
| 278 |
- dlg = Gtk.MessageDialog(None,
|
|
| 279 |
- Gtk.DialogFlags.DESTROY_WITH_PARENT | Gtk.DialogFlags.MODAL,
|
|
| 280 |
- Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, message_format = pritext)
|
|
| 281 |
- |
|
| 282 |
- dlg.format_secondary_text(sectext)
|
|
| 283 |
- dlg.run()
|
|
| 284 |
- dlg.destroy()
|
|
| 285 |
- sys.exit()
|
|
| 286 |
- |
|
| 287 |
-del pritext
|
|
| 288 |
- |
|
| 289 |
-#import gtkexcepthook
|
|
| 290 |
- |
|
| 291 |
-import signal
|
|
| 292 |
-import gtkgui_helpers
|
|
| 293 |
- |
|
| 294 |
-gajimpaths = common.configpaths.gajimpaths
|
|
| 84 |
+# Test here for all required versions so we dont have to
|
|
| 85 |
+# test multiple times in every module. nbxmpp also needs GLib.
|
|
| 86 |
+import gi
|
|
| 87 |
+gi.require_version('GLib', '2.0')
|
|
| 88 |
+gi.require_version('Gio', '2.0')
|
|
| 89 |
+gi.require_version('Gtk', '3.0')
|
|
| 90 |
+gi.require_version('Gdk', '3.0')
|
|
| 91 |
+gi.require_version('GObject', '2.0')
|
|
| 92 |
+gi.require_version('Pango', '1.0')
|
|
| 295 | 93 |
|
| 296 |
-pid_filename = gajimpaths['PID_FILE']
|
|
| 297 |
-config_filename = gajimpaths['CONFIG_FILE']
|
|
| 94 |
+MIN_NBXMPP_VER = "0.5.3"
|
|
| 298 | 95 |
|
| 299 |
-# Seed the OpenSSL pseudo random number generator from file and initialize
|
|
| 300 |
-RNG_SEED = gajimpaths['RNG_SEED']
|
|
| 301 |
-PYOPENSSL_PRNG_PRESENT = False
|
|
| 302 | 96 |
try:
|
| 303 |
- import OpenSSL.rand
|
|
| 304 |
- from common import crypto
|
|
| 305 |
- PYOPENSSL_PRNG_PRESENT = True
|
|
| 306 |
- # Seed from file
|
|
| 307 |
- try:
|
|
| 308 |
- OpenSSL.rand.load_file(RNG_SEED)
|
|
| 309 |
- except TypeError:
|
|
| 310 |
- OpenSSL.rand.load_file(RNG_SEED.encode('utf-8'))
|
|
| 311 |
- crypto.add_entropy_sources_OpenSSL()
|
|
| 312 |
- try:
|
|
| 313 |
- OpenSSL.rand.write_file(RNG_SEED)
|
|
| 314 |
- except TypeError:
|
|
| 315 |
- OpenSSL.rand.write_file(RNG_SEED.encode('utf-8'))
|
|
| 97 |
+ import nbxmpp
|
|
| 316 | 98 |
except ImportError:
|
| 317 |
- log.info("PyOpenSSL PRNG not available")
|
|
| 318 |
- |
|
| 319 |
-import traceback
|
|
| 320 |
-import errno
|
|
| 321 |
-import dialogs
|
|
| 322 |
- |
|
| 323 |
-def pid_alive():
|
|
| 324 |
- try:
|
|
| 325 |
- pf = open(pid_filename)
|
|
| 326 |
- except IOError:
|
|
| 327 |
- # probably file not found
|
|
| 328 |
- return False
|
|
| 329 |
- |
|
| 330 |
- try:
|
|
| 331 |
- pid = int(pf.read().strip())
|
|
| 332 |
- pf.close()
|
|
| 333 |
- except Exception:
|
|
| 334 |
- traceback.print_exc()
|
|
| 335 |
- # PID file exists, but something happened trying to read PID
|
|
| 336 |
- # Could be 0.10 style empty PID file, so assume Gajim is running
|
|
| 337 |
- return True
|
|
| 338 |
- |
|
| 339 |
- if os.name == 'nt':
|
|
| 340 |
- try:
|
|
| 341 |
- from ctypes import (windll, c_ulong, c_int, Structure, c_char)
|
|
| 342 |
- from ctypes import (POINTER, pointer, sizeof)
|
|
| 343 |
- except Exception:
|
|
| 344 |
- return True
|
|
| 345 |
- |
|
| 346 |
- class PROCESSENTRY32(Structure):
|
|
| 347 |
- _fields_ = [
|
|
| 348 |
- ('dwSize', c_ulong, ),
|
|
| 349 |
- ('cntUsage', c_ulong, ),
|
|
| 350 |
- ('th32ProcessID', c_ulong, ),
|
|
| 351 |
- ('th32DefaultHeapID', c_ulong, ),
|
|
| 352 |
- ('th32ModuleID', c_ulong, ),
|
|
| 353 |
- ('cntThreads', c_ulong, ),
|
|
| 354 |
- ('th32ParentProcessID', c_ulong, ),
|
|
| 355 |
- ('pcPriClassBase', c_ulong, ),
|
|
| 356 |
- ('dwFlags', c_ulong, ),
|
|
| 357 |
- ('szExeFile', c_char*512, ),
|
|
| 358 |
- ]
|
|
| 359 |
- |
|
| 360 |
- kernel = windll.kernel32
|
|
| 361 |
- kernel.CreateToolhelp32Snapshot.argtypes = c_ulong, c_ulong,
|
|
| 362 |
- kernel.CreateToolhelp32Snapshot.restype = c_int
|
|
| 363 |
- kernel.Process32First.argtypes = c_int, POINTER(PROCESSENTRY32),
|
|
| 364 |
- kernel.Process32First.restype = c_int
|
|
| 365 |
- kernel.Process32Next.argtypes = c_int, POINTER(PROCESSENTRY32),
|
|
| 366 |
- kernel.Process32Next.restype = c_int
|
|
| 367 |
- |
|
| 368 |
- def get_p(pid_):
|
|
| 369 |
- TH32CS_SNAPPROCESS = 2
|
|
| 370 |
- CreateToolhelp32Snapshot = kernel.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
|
|
| 371 |
- assert CreateToolhelp32Snapshot > 0, 'CreateToolhelp32Snapshot failed'
|
|
| 372 |
- pe32 = PROCESSENTRY32()
|
|
| 373 |
- pe32.dwSize = sizeof( PROCESSENTRY32 )
|
|
| 374 |
- f3 = kernel.Process32First(CreateToolhelp32Snapshot, pointer(pe32))
|
|
| 375 |
- while f3:
|
|
| 376 |
- if pe32.th32ProcessID == pid_:
|
|
| 377 |
- return pe32.szExeFile
|
|
| 378 |
- f3 = kernel.Process32Next(CreateToolhelp32Snapshot, pointer(pe32))
|
|
| 379 |
- |
|
| 380 |
- if get_p(pid) in ('python.exe', 'gajim.exe'):
|
|
| 381 |
- return True
|
|
| 382 |
- return False
|
|
| 383 |
- try:
|
|
| 384 |
- if not os.path.exists('/proc'):
|
|
| 385 |
- return True # no /proc, assume Gajim is running
|
|
| 386 |
- |
|
| 387 |
- try:
|
|
| 388 |
- f1 = open('/proc/%d/cmdline'% pid)
|
|
| 389 |
- except IOError as e1:
|
|
| 390 |
- if e1.errno == errno.ENOENT:
|
|
| 391 |
- return False # file/pid does not exist
|
|
| 392 |
- raise
|
|
| 393 |
- |
|
| 394 |
- n = f1.read().lower()
|
|
| 395 |
- f1.close()
|
|
| 396 |
- if n.find('gajim') < 0:
|
|
| 397 |
- return False
|
|
| 398 |
- return True # Running Gajim found at pid
|
|
| 399 |
- except Exception:
|
|
| 400 |
- traceback.print_exc()
|
|
| 401 |
- |
|
| 402 |
- # If we are here, pidfile exists, but some unexpected error occured.
|
|
| 403 |
- # Assume Gajim is running.
|
|
| 404 |
- return True
|
|
| 405 |
- |
|
| 406 |
-def show_remote_gajim_roster():
|
|
| 407 |
- try:
|
|
| 408 |
- import dbus
|
|
| 409 |
- |
|
| 410 |
- OBJ_PATH = '/org/gajim/dbus/RemoteObject'
|
|
| 411 |
- INTERFACE = 'org.gajim.dbus.RemoteInterface'
|
|
| 412 |
- SERVICE = 'org.gajim.dbus'
|
|
| 413 |
- |
|
| 414 |
- # Attempt to call show_roster
|
|
| 415 |
- dbus.Interface(dbus.SessionBus().get_object(SERVICE, OBJ_PATH), INTERFACE).__getattr__("show_roster")()
|
|
| 416 |
- |
|
| 417 |
- return True
|
|
| 418 |
- except Exception:
|
|
| 419 |
- return False
|
|
| 420 |
- |
|
| 421 |
-if pid_alive():
|
|
| 422 |
- if (show_remote_gajim_roster()):
|
|
| 423 |
- print("Gajim is already running, bringing the roster to front...")
|
|
| 424 |
- sys.exit(0)
|
|
| 425 |
- pixs = []
|
|
| 426 |
- for size in (16, 32, 48, 64, 128):
|
|
| 427 |
- pix = gtkgui_helpers.get_icon_pixmap('gajim', size)
|
|
| 428 |
- if pix:
|
|
| 429 |
- pixs.append(pix)
|
|
| 430 |
- if pixs:
|
|
| 431 |
- # set the icon to all windows
|
|
| 432 |
- Gtk.Window.set_default_icon_list(pixs)
|
|
| 433 |
- pritext = _('Gajim is already running')
|
|
| 434 |
- sectext = _('Another instance of Gajim seems to be running\nRun anyway?')
|
|
| 435 |
- dialog = dialogs.YesNoDialog(pritext, sectext)
|
|
| 436 |
- dialog.popup()
|
|
| 437 |
- if dialog.run() != Gtk.ResponseType.YES:
|
|
| 438 |
- sys.exit(3)
|
|
| 439 |
- dialog.destroy()
|
|
| 440 |
- # run anyway, delete pid and useless global vars
|
|
| 441 |
- if os.path.exists(pid_filename):
|
|
| 442 |
- os.remove(pid_filename)
|
|
| 443 |
- del pix
|
|
| 444 |
- del pritext
|
|
| 445 |
- del sectext
|
|
| 446 |
- dialog.destroy()
|
|
| 447 |
- |
|
| 448 |
-# Create .gajim dir
|
|
| 449 |
-pid_dir = os.path.dirname(pid_filename)
|
|
| 450 |
-if not os.path.exists(pid_dir):
|
|
| 451 |
- check_paths.create_path(pid_dir)
|
|
| 452 |
-# Create pid file
|
|
| 453 |
-try:
|
|
| 454 |
- f2 = open(pid_filename, 'w')
|
|
| 455 |
- f2.write(str(os.getpid()))
|
|
| 456 |
- f2.close()
|
|
| 457 |
-except IOError as e2:
|
|
| 458 |
- dlg = dialogs.ErrorDialog(_('Disk Write Error'), str(e2))
|
|
| 459 |
- dlg.run()
|
|
| 460 |
- dlg.destroy()
|
|
| 461 |
- sys.exit()
|
|
| 462 |
-del pid_dir
|
|
| 463 |
- |
|
| 464 |
-def on_exit():
|
|
| 465 |
- # Save the entropy from OpenSSL PRNG
|
|
| 466 |
- if PYOPENSSL_PRNG_PRESENT:
|
|
| 467 |
- try:
|
|
| 468 |
- OpenSSL.rand.write_file(RNG_SEED)
|
|
| 469 |
- except TypeError:
|
|
| 470 |
- OpenSSL.rand.write_file(RNG_SEED.encode('utf-8'))
|
|
| 471 |
- # delete pid file on normal exit
|
|
| 472 |
- if os.path.exists(pid_filename):
|
|
| 473 |
- os.remove(pid_filename)
|
|
| 474 |
- # Shutdown GUI and save config
|
|
| 475 |
- if hasattr(gajim.interface, 'roster') and gajim.interface.roster:
|
|
| 476 |
- gajim.interface.roster.prepare_quit()
|
|
| 477 |
- |
|
| 478 |
-import atexit
|
|
| 479 |
-atexit.register(on_exit)
|
|
| 480 |
- |
|
| 481 |
-from gui_interface import Interface
|
|
| 482 |
- |
|
| 483 |
-if __name__.endswith('__main__'):
|
|
| 484 |
- def sigint_cb(num, stack):
|
|
| 485 |
- sys.exit(5)
|
|
| 486 |
- # ^C exits the application normally to delete pid file
|
|
| 487 |
- signal.signal(signal.SIGINT, sigint_cb)
|
|
| 488 |
- signal.signal(signal.SIGTERM, sigint_cb)
|
|
| 489 |
- |
|
| 490 |
- log.info("Encodings: d:%s, fs:%s, p:%s", sys.getdefaultencoding(), \
|
|
| 491 |
- sys.getfilesystemencoding(), locale.getpreferredencoding())
|
|
| 99 |
+ print('Gajim needs python-nbxmpp to run. Quiting...')
|
|
| 100 |
+ sys.exit(1)
|
|
| 492 | 101 |
|
| 493 |
- check_paths.check_and_possibly_create_paths()
|
|
| 102 |
+from distutils.version import LooseVersion as V
|
|
| 103 |
+if V(nbxmpp.__version__) < V(MIN_NBXMPP_VER):
|
|
| 104 |
+ print('Gajim needs python-nbxmpp >= %s to run. Quiting...' % MIN_NBXMPP_VER)
|
|
| 105 |
+ sys.exit(1)
|
|
| 494 | 106 |
|
| 495 |
- interface = Interface()
|
|
| 496 |
- interface.run()
|
|
| 107 |
+from application import GajimApplication
|
|
| 497 | 108 |
|
| 498 |
- try:
|
|
| 499 |
- Gtk.main()
|
|
| 500 |
- except KeyboardInterrupt:
|
|
| 501 |
- print('KeyboardInterrupt', file=sys.stderr)
|
|
| 109 |
+app = GajimApplication()
|
|
| 110 |
+app.run(sys.argv)
|
| ... | ... | @@ -2719,11 +2719,11 @@ class Interface: |
| 2719 | 2719 |
view.updateNamespace({'gajim': gajim})
|
| 2720 | 2720 |
gajim.ipython_window = window
|
| 2721 | 2721 |
|
| 2722 |
- def run(self):
|
|
| 2722 |
+ def run(self, app):
|
|
| 2723 | 2723 |
if gajim.config.get('trayicon') != 'never':
|
| 2724 | 2724 |
self.show_systray()
|
| 2725 | 2725 |
|
| 2726 |
- self.roster = roster_window.RosterWindow()
|
|
| 2726 |
+ self.roster = roster_window.RosterWindow(app)
|
|
| 2727 | 2727 |
if self.msg_win_mgr.mode == \
|
| 2728 | 2728 |
MessageWindowMgr.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER:
|
| 2729 | 2729 |
self.msg_win_mgr.create_window(None, None, None)
|
| ... | ... | @@ -94,7 +94,7 @@ empty_pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 1, 1) |
| 94 | 94 |
empty_pixbuf.fill(0xffffff00)
|
| 95 | 95 |
|
| 96 | 96 |
|
| 97 |
-class RosterWindow:
|
|
| 97 |
+class RosterWindow(Gtk.ApplicationWindow):
|
|
| 98 | 98 |
"""
|
| 99 | 99 |
Class for main window of the GTK+ interface
|
| 100 | 100 |
"""
|
| ... | ... | @@ -2479,7 +2479,7 @@ class RosterWindow: |
| 2479 | 2479 |
When we quit the gtk interface - exit gtk
|
| 2480 | 2480 |
"""
|
| 2481 | 2481 |
self.prepare_quit()
|
| 2482 |
- Gtk.main_quit()
|
|
| 2482 |
+ self.application.quit()
|
|
| 2483 | 2483 |
|
| 2484 | 2484 |
def on_quit_request(self, widget=None):
|
| 2485 | 2485 |
"""
|
| ... | ... | @@ -6178,7 +6178,8 @@ class RosterWindow: |
| 6178 | 6178 |
###
|
| 6179 | 6179 |
################################################################################
|
| 6180 | 6180 |
|
| 6181 |
- def __init__(self):
|
|
| 6181 |
+ def __init__(self, app):
|
|
| 6182 |
+ self.application = app
|
|
| 6182 | 6183 |
self.filtering = False
|
| 6183 | 6184 |
self.starting = False
|
| 6184 | 6185 |
self.starting_filtering = False
|
| ... | ... | @@ -6195,6 +6196,7 @@ class RosterWindow: |
| 6195 | 6196 |
self.xml = gtkgui_helpers.get_gtk_builder('roster_window.ui')
|
| 6196 | 6197 |
self.window = self.xml.get_object('roster_window')
|
| 6197 | 6198 |
self.hpaned = self.xml.get_object('roster_hpaned')
|
| 6199 |
+ self.window.set_application(app)
|
|
| 6198 | 6200 |
gajim.interface.msg_win_mgr = MessageWindowMgr(self.window, self.hpaned)
|
| 6199 | 6201 |
gajim.interface.msg_win_mgr.connect('window-delete',
|
| 6200 | 6202 |
self.on_message_window_delete)
|