From e7812cbd85d3314a1e7e923d867e0eff27315d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20H=C3=B6rist?= Date: Thu, 22 Dec 2016 23:11:19 +0100 Subject: [PATCH] Move startup code into Gtk.Application() --- src/application.py | 365 +++++++++++++++++++++++++++++++++++++++++ src/gajim.py | 375 ------------------------------------------- src/gui_interface.py | 4 +- src/roster_window.py | 8 +- 4 files changed, 372 insertions(+), 380 deletions(-) diff --git a/src/application.py b/src/application.py index b4f2da923..d023d03a4 100644 --- a/src/application.py +++ b/src/application.py @@ -18,8 +18,16 @@ ## along with Gajim. If not, see . ## +import sys +import os +import warnings +import logging from gi.repository import GLib, Gio, Gtk +from common import i18n from common import logging_helpers +logging_helpers.init(sys.stderr.isatty()) + +log = logging.getLogger('gajim.gajim') class GajimApplication(Gtk.Application): @@ -63,6 +71,363 @@ class GajimApplication(Gtk.Application): def do_activate(self): Gtk.Application.do_activate(self) + if os.name == 'nt': + import locale + import gettext + APP = 'gajim' + DIR = '../po' + lang, enc = locale.getdefaultlocale() + os.environ['LANG'] = lang + gettext.bindtextdomain(APP, DIR) + gettext.textdomain(APP) + gettext.install(APP, DIR) + + # locale.setlocale(locale.LC_ALL, '') + # import ctypes + # import ctypes.util + # libintl_path = ctypes.util.find_library('intl') + # if libintl_path == None: + # local_intl = os.path.join('gtk', 'bin', 'intl.dll') + # if os.path.exists(local_intl): + # libintl_path = local_intl + # if libintl_path == None: + # raise ImportError('intl.dll library not found') + # libintl = ctypes.cdll.LoadLibrary(libintl_path) + # libintl.bindtextdomain(APP, DIR) + # libintl.bind_textdomain_codeset(APP, 'UTF-8') + + if os.name == 'nt': + # needed for docutils + sys.path.append('.') + + import locale + + import common.configpaths + common.configpaths.gajimpaths.init( + self.config_path, self.profile, self.profile_separation) + + if os.name == 'nt': + plugins_locale_dir = os.path.join(common.configpaths.gajimpaths[ + 'PLUGINS_USER'], 'locale').encode(locale.getpreferredencoding()) + # libintl.bindtextdomain('gajim_plugins', plugins_locale_dir) + # libintl.bind_textdomain_codeset('gajim_plugins', 'UTF-8') + + class MyStderr(object): + _file = None + _error = None + def write(self, text): + fname = os.path.join(common.configpaths.gajimpaths.cache_root, + os.path.split(sys.executable)[1]+'.log') + if self._file is None and self._error is None: + try: + self._file = open(fname, 'a') + except Exception as details: + self._error = details + if self._file is not None: + self._file.write(text) + self._file.flush() + def flush(self): + if self._file is not None: + self._file.flush() + + sys.stderr = MyStderr() + + # PyGTK2.10+ only throws a warning + warnings.filterwarnings('error', module='Gtk') + try: + from gi.repository import GObject + GObject.set_prgname('gajim') + except Warning as msg2: + if str(msg2) == 'could not open display': + print(_('Gajim needs X server to run. Quiting...'), file=sys.stderr) + else: + print(_('importing PyGTK failed: %s') % str(msg2), file=sys.stderr) + sys.exit() + warnings.resetwarnings() + + if os.name == 'nt': + warnings.filterwarnings(action='ignore') + + if Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL: + i18n.direction_mark = '\u200F' + pritext = '' + + from common import exceptions + try: + from common import gajim + except exceptions.DatabaseMalformed: + pritext = _('Database Error') + sectext = _('The database file (%s) cannot be read. Try to repair it (see ' + 'http://trac.gajim.org/wiki/DatabaseBackup) or remove it (all history ' + 'will be lost).') % common.logger.LOG_DB_PATH + else: + from common import logger + gajim.logger = logger.Logger() + from common import caps_cache + caps_cache.initialize(gajim.logger) + from common import dbus_support + if dbus_support.supported: + from music_track_listener import MusicTrackListener + + from ctypes import CDLL + from ctypes.util import find_library + import platform + + sysname = platform.system() + if sysname in ('Linux', 'FreeBSD', 'OpenBSD', 'NetBSD'): + libc = CDLL(find_library('c')) + + # The constant defined in which is used to set the name + # of the process. + PR_SET_NAME = 15 + + if sysname == 'Linux': + libc.prctl(PR_SET_NAME, 'gajim') + elif sysname in ('FreeBSD', 'OpenBSD', 'NetBSD'): + libc.setproctitle('gajim') + + # if Gtk.pygtk_version < (2, 22, 0): + # pritext = _('Gajim needs PyGTK 2.22 or above') + # sectext = _('Gajim needs PyGTK 2.22 or above to run. Quiting...') + # elif Gtk.gtk_version < (2, 22, 0): + # if (Gtk.get_major_version(), Gtk.get_minor_version(), + # Gtk.get_micro_version()) < (2, 22, 0): + # pritext = _('Gajim needs GTK 2.22 or above') + # sectext = _('Gajim needs GTK 2.22 or above to run. Quiting...') + + from common import check_paths + + if os.name == 'nt': + try: + import winsound # windows-only built-in module for playing wav + import win32api # do NOT remove. we req this module + except Exception: + pritext = _('Gajim needs pywin32 to run') + sectext = _('Please make sure that Pywin32 is installed on your ' + 'system. You can get it at %s') % \ + 'http://sourceforge.net/project/showfiles.php?group_id=78018' + + if pritext: + dlg = Gtk.MessageDialog(None, + Gtk.DialogFlags.DESTROY_WITH_PARENT | Gtk.DialogFlags.MODAL, + Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, message_format = pritext) + + dlg.format_secondary_text(sectext) + dlg.run() + dlg.destroy() + sys.exit() + + del pritext + + #import gtkexcepthook + + import signal + import gtkgui_helpers + + gajimpaths = common.configpaths.gajimpaths + + pid_filename = gajimpaths['PID_FILE'] + config_filename = gajimpaths['CONFIG_FILE'] + + # Seed the OpenSSL pseudo random number generator from file and initialize + RNG_SEED = gajimpaths['RNG_SEED'] + PYOPENSSL_PRNG_PRESENT = False + try: + import OpenSSL.rand + from common import crypto + PYOPENSSL_PRNG_PRESENT = True + # Seed from file + try: + OpenSSL.rand.load_file(RNG_SEED) + except TypeError: + OpenSSL.rand.load_file(RNG_SEED.encode('utf-8')) + crypto.add_entropy_sources_OpenSSL() + try: + OpenSSL.rand.write_file(RNG_SEED) + except TypeError: + OpenSSL.rand.write_file(RNG_SEED.encode('utf-8')) + except ImportError: + log.info("PyOpenSSL PRNG not available") + + import traceback + import errno + import dialogs + + def pid_alive(): + try: + pf = open(pid_filename) + except IOError: + # probably file not found + return False + + try: + pid = int(pf.read().strip()) + pf.close() + except Exception: + traceback.print_exc() + # PID file exists, but something happened trying to read PID + # Could be 0.10 style empty PID file, so assume Gajim is running + return True + + if os.name == 'nt': + try: + from ctypes import (windll, c_ulong, c_int, Structure, c_char) + from ctypes import (POINTER, pointer, sizeof) + except Exception: + return True + + class PROCESSENTRY32(Structure): + _fields_ = [ + ('dwSize', c_ulong, ), + ('cntUsage', c_ulong, ), + ('th32ProcessID', c_ulong, ), + ('th32DefaultHeapID', c_ulong, ), + ('th32ModuleID', c_ulong, ), + ('cntThreads', c_ulong, ), + ('th32ParentProcessID', c_ulong, ), + ('pcPriClassBase', c_ulong, ), + ('dwFlags', c_ulong, ), + ('szExeFile', c_char*512, ), + ] + + kernel = windll.kernel32 + kernel.CreateToolhelp32Snapshot.argtypes = c_ulong, c_ulong, + kernel.CreateToolhelp32Snapshot.restype = c_int + kernel.Process32First.argtypes = c_int, POINTER(PROCESSENTRY32), + kernel.Process32First.restype = c_int + kernel.Process32Next.argtypes = c_int, POINTER(PROCESSENTRY32), + kernel.Process32Next.restype = c_int + + def get_p(pid_): + TH32CS_SNAPPROCESS = 2 + CreateToolhelp32Snapshot = kernel.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) + assert CreateToolhelp32Snapshot > 0, 'CreateToolhelp32Snapshot failed' + pe32 = PROCESSENTRY32() + pe32.dwSize = sizeof( PROCESSENTRY32 ) + f3 = kernel.Process32First(CreateToolhelp32Snapshot, pointer(pe32)) + while f3: + if pe32.th32ProcessID == pid_: + return pe32.szExeFile + f3 = kernel.Process32Next(CreateToolhelp32Snapshot, pointer(pe32)) + + if get_p(pid) in ('python.exe', 'gajim.exe'): + return True + return False + try: + if not os.path.exists('/proc'): + return True # no /proc, assume Gajim is running + + try: + f1 = open('/proc/%d/cmdline'% pid) + except IOError as e1: + if e1.errno == errno.ENOENT: + return False # file/pid does not exist + raise + + n = f1.read().lower() + f1.close() + if n.find('gajim') < 0: + return False + return True # Running Gajim found at pid + except Exception: + traceback.print_exc() + + # If we are here, pidfile exists, but some unexpected error occured. + # Assume Gajim is running. + return True + + def show_remote_gajim_roster(): + try: + import dbus + + OBJ_PATH = '/org/gajim/dbus/RemoteObject' + INTERFACE = 'org.gajim.dbus.RemoteInterface' + SERVICE = 'org.gajim.dbus' + + # Attempt to call show_roster + dbus.Interface(dbus.SessionBus().get_object(SERVICE, OBJ_PATH), INTERFACE).__getattr__("show_roster")() + + return True + except Exception: + return False + + if pid_alive(): + if (show_remote_gajim_roster()): + print("Gajim is already running, bringing the roster to front...") + sys.exit(0) + pixs = [] + for size in (16, 32, 48, 64, 128): + pix = gtkgui_helpers.get_icon_pixmap('gajim', size) + if pix: + pixs.append(pix) + if pixs: + # set the icon to all windows + Gtk.Window.set_default_icon_list(pixs) + pritext = _('Gajim is already running') + sectext = _('Another instance of Gajim seems to be running\nRun anyway?') + dialog = dialogs.YesNoDialog(pritext, sectext) + dialog.popup() + if dialog.run() != Gtk.ResponseType.YES: + sys.exit(3) + dialog.destroy() + # run anyway, delete pid and useless global vars + if os.path.exists(pid_filename): + os.remove(pid_filename) + del pix + del pritext + del sectext + dialog.destroy() + + # Create .gajim dir + pid_dir = os.path.dirname(pid_filename) + if not os.path.exists(pid_dir): + check_paths.create_path(pid_dir) + # Create pid file + try: + f2 = open(pid_filename, 'w') + f2.write(str(os.getpid())) + f2.close() + except IOError as e2: + dlg = dialogs.ErrorDialog(_('Disk Write Error'), str(e2)) + dlg.run() + dlg.destroy() + sys.exit() + del pid_dir + + def on_exit(): + # Save the entropy from OpenSSL PRNG + if PYOPENSSL_PRNG_PRESENT: + try: + OpenSSL.rand.write_file(RNG_SEED) + except TypeError: + OpenSSL.rand.write_file(RNG_SEED.encode('utf-8')) + # delete pid file on normal exit + if os.path.exists(pid_filename): + os.remove(pid_filename) + # Shutdown GUI and save config + if hasattr(gajim.interface, 'roster') and gajim.interface.roster: + gajim.interface.roster.prepare_quit() + + import atexit + atexit.register(on_exit) + + from gui_interface import Interface + + def sigint_cb(num, stack): + sys.exit(5) + # ^C exits the application normally to delete pid file + signal.signal(signal.SIGINT, sigint_cb) + signal.signal(signal.SIGTERM, sigint_cb) + + log.info("Encodings: d:%s, fs:%s, p:%s", sys.getdefaultencoding(), \ + sys.getfilesystemencoding(), locale.getpreferredencoding()) + + check_paths.check_and_possibly_create_paths() + + interface = Interface() + interface.run(self) + + def do_command_line(self, command_line: Gio.ApplicationCommandLine) -> int: Gtk.Application.do_command_line(self, command_line) options = command_line.get_options_dict() diff --git a/src/gajim.py b/src/gajim.py index 580b2b085..b87804132 100644 --- a/src/gajim.py +++ b/src/gajim.py @@ -44,7 +44,6 @@ if '--version' in sys.argv or '-V' in sys.argv: import os import warnings -import OpenSSL if os.name == 'nt': log_path = os.path.join(os.environ['APPDATA'], 'Gajim') @@ -80,381 +79,7 @@ if V(nbxmpp.__version__) < V(MIN_NBXMPP_VER): print('Gajim needs python-nbxmpp >= %s to run. Quiting...' % MIN_NBXMPP_VER) sys.exit(1) -if os.name == 'nt': - import locale - import gettext - APP = 'gajim' - DIR = '../po' - lang, enc = locale.getdefaultlocale() - os.environ['LANG'] = lang - gettext.bindtextdomain(APP, DIR) - gettext.textdomain(APP) - gettext.install(APP, DIR) - -# locale.setlocale(locale.LC_ALL, '') -# import ctypes -# import ctypes.util -# libintl_path = ctypes.util.find_library('intl') -# if libintl_path == None: -# local_intl = os.path.join('gtk', 'bin', 'intl.dll') -# if os.path.exists(local_intl): -# libintl_path = local_intl -# if libintl_path == None: -# raise ImportError('intl.dll library not found') -# libintl = ctypes.cdll.LoadLibrary(libintl_path) -# libintl.bindtextdomain(APP, DIR) -# libintl.bind_textdomain_codeset(APP, 'UTF-8') - -if os.name == 'nt': - # needed for docutils - sys.path.append('.') - -from common import logging_helpers -logging_helpers.init(sys.stderr.isatty()) - -import logging -# gajim.gui or gajim.gtk more appropriate ? -log = logging.getLogger('gajim.gajim') - - -from common import i18n -import locale from application import GajimApplication app = GajimApplication() app.run(sys.argv) - -import common.configpaths -common.configpaths.gajimpaths.init( - app.config_path, app.profile, app.profile_separation) - -if os.name == 'nt': - plugins_locale_dir = os.path.join(common.configpaths.gajimpaths[ - 'PLUGINS_USER'], 'locale').encode(locale.getpreferredencoding()) -# libintl.bindtextdomain('gajim_plugins', plugins_locale_dir) -# libintl.bind_textdomain_codeset('gajim_plugins', 'UTF-8') - - class MyStderr(object): - _file = None - _error = None - def write(self, text): - fname = os.path.join(common.configpaths.gajimpaths.cache_root, - os.path.split(sys.executable)[1]+'.log') - if self._file is None and self._error is None: - try: - self._file = open(fname, 'a') - except Exception as details: - self._error = details - if self._file is not None: - self._file.write(text) - self._file.flush() - def flush(self): - if self._file is not None: - self._file.flush() - - sys.stderr = MyStderr() - -# PyGTK2.10+ only throws a warning -warnings.filterwarnings('error', module='Gtk') -try: - from gi.repository import GObject - GObject.set_prgname('gajim') - from gi.repository import Gtk - from gi.repository import Gdk - from gi.repository import GLib -except Warning as msg2: - if str(msg2) == 'could not open display': - print(_('Gajim needs X server to run. Quiting...'), file=sys.stderr) - else: - print(_('importing PyGTK failed: %s') % str(msg2), file=sys.stderr) - sys.exit() -warnings.resetwarnings() - - -if os.name == 'nt': - warnings.filterwarnings(action='ignore') - -if Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL: - i18n.direction_mark = '\u200F' -pritext = '' - -from common import exceptions -try: - from common import gajim -except exceptions.DatabaseMalformed: - pritext = _('Database Error') - sectext = _('The database file (%s) cannot be read. Try to repair it (see ' - 'http://trac.gajim.org/wiki/DatabaseBackup) or remove it (all history ' - 'will be lost).') % common.logger.LOG_DB_PATH -else: - from common import logger - gajim.logger = logger.Logger() - from common import caps_cache - caps_cache.initialize(gajim.logger) - from common import dbus_support - if dbus_support.supported: - from music_track_listener import MusicTrackListener - - from ctypes import CDLL - from ctypes.util import find_library - import platform - - sysname = platform.system() - if sysname in ('Linux', 'FreeBSD', 'OpenBSD', 'NetBSD'): - libc = CDLL(find_library('c')) - - # The constant defined in which is used to set the name - # of the process. - PR_SET_NAME = 15 - - if sysname == 'Linux': - libc.prctl(PR_SET_NAME, 'gajim') - elif sysname in ('FreeBSD', 'OpenBSD', 'NetBSD'): - libc.setproctitle('gajim') - -# if Gtk.pygtk_version < (2, 22, 0): -# pritext = _('Gajim needs PyGTK 2.22 or above') -# sectext = _('Gajim needs PyGTK 2.22 or above to run. Quiting...') -# elif Gtk.gtk_version < (2, 22, 0): -# if (Gtk.get_major_version(), Gtk.get_minor_version(), -# Gtk.get_micro_version()) < (2, 22, 0): -# pritext = _('Gajim needs GTK 2.22 or above') -# sectext = _('Gajim needs GTK 2.22 or above to run. Quiting...') - - from common import check_paths - - if os.name == 'nt': - try: - import winsound # windows-only built-in module for playing wav - import win32api # do NOT remove. we req this module - except Exception: - pritext = _('Gajim needs pywin32 to run') - sectext = _('Please make sure that Pywin32 is installed on your ' - 'system. You can get it at %s') % \ - 'http://sourceforge.net/project/showfiles.php?group_id=78018' - -if pritext: - dlg = Gtk.MessageDialog(None, - Gtk.DialogFlags.DESTROY_WITH_PARENT | Gtk.DialogFlags.MODAL, - Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, message_format = pritext) - - dlg.format_secondary_text(sectext) - dlg.run() - dlg.destroy() - sys.exit() - -del pritext - -#import gtkexcepthook - -import signal -import gtkgui_helpers - -gajimpaths = common.configpaths.gajimpaths - -pid_filename = gajimpaths['PID_FILE'] -config_filename = gajimpaths['CONFIG_FILE'] - -# Seed the OpenSSL pseudo random number generator from file and initialize -RNG_SEED = gajimpaths['RNG_SEED'] -PYOPENSSL_PRNG_PRESENT = False -try: - import OpenSSL.rand - from common import crypto - PYOPENSSL_PRNG_PRESENT = True - # Seed from file - try: - OpenSSL.rand.load_file(RNG_SEED) - except TypeError: - OpenSSL.rand.load_file(RNG_SEED.encode('utf-8')) - crypto.add_entropy_sources_OpenSSL() - try: - OpenSSL.rand.write_file(RNG_SEED) - except TypeError: - OpenSSL.rand.write_file(RNG_SEED.encode('utf-8')) -except ImportError: - log.info("PyOpenSSL PRNG not available") - -import traceback -import errno -import dialogs - -def pid_alive(): - try: - pf = open(pid_filename) - except IOError: - # probably file not found - return False - - try: - pid = int(pf.read().strip()) - pf.close() - except Exception: - traceback.print_exc() - # PID file exists, but something happened trying to read PID - # Could be 0.10 style empty PID file, so assume Gajim is running - return True - - if os.name == 'nt': - try: - from ctypes import (windll, c_ulong, c_int, Structure, c_char) - from ctypes import (POINTER, pointer, sizeof) - except Exception: - return True - - class PROCESSENTRY32(Structure): - _fields_ = [ - ('dwSize', c_ulong, ), - ('cntUsage', c_ulong, ), - ('th32ProcessID', c_ulong, ), - ('th32DefaultHeapID', c_ulong, ), - ('th32ModuleID', c_ulong, ), - ('cntThreads', c_ulong, ), - ('th32ParentProcessID', c_ulong, ), - ('pcPriClassBase', c_ulong, ), - ('dwFlags', c_ulong, ), - ('szExeFile', c_char*512, ), - ] - - kernel = windll.kernel32 - kernel.CreateToolhelp32Snapshot.argtypes = c_ulong, c_ulong, - kernel.CreateToolhelp32Snapshot.restype = c_int - kernel.Process32First.argtypes = c_int, POINTER(PROCESSENTRY32), - kernel.Process32First.restype = c_int - kernel.Process32Next.argtypes = c_int, POINTER(PROCESSENTRY32), - kernel.Process32Next.restype = c_int - - def get_p(pid_): - TH32CS_SNAPPROCESS = 2 - CreateToolhelp32Snapshot = kernel.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) - assert CreateToolhelp32Snapshot > 0, 'CreateToolhelp32Snapshot failed' - pe32 = PROCESSENTRY32() - pe32.dwSize = sizeof( PROCESSENTRY32 ) - f3 = kernel.Process32First(CreateToolhelp32Snapshot, pointer(pe32)) - while f3: - if pe32.th32ProcessID == pid_: - return pe32.szExeFile - f3 = kernel.Process32Next(CreateToolhelp32Snapshot, pointer(pe32)) - - if get_p(pid) in ('python.exe', 'gajim.exe'): - return True - return False - try: - if not os.path.exists('/proc'): - return True # no /proc, assume Gajim is running - - try: - f1 = open('/proc/%d/cmdline'% pid) - except IOError as e1: - if e1.errno == errno.ENOENT: - return False # file/pid does not exist - raise - - n = f1.read().lower() - f1.close() - if n.find('gajim') < 0: - return False - return True # Running Gajim found at pid - except Exception: - traceback.print_exc() - - # If we are here, pidfile exists, but some unexpected error occured. - # Assume Gajim is running. - return True - -def show_remote_gajim_roster(): - try: - import dbus - - OBJ_PATH = '/org/gajim/dbus/RemoteObject' - INTERFACE = 'org.gajim.dbus.RemoteInterface' - SERVICE = 'org.gajim.dbus' - - # Attempt to call show_roster - dbus.Interface(dbus.SessionBus().get_object(SERVICE, OBJ_PATH), INTERFACE).__getattr__("show_roster")() - - return True - except Exception: - return False - -if pid_alive(): - if (show_remote_gajim_roster()): - print("Gajim is already running, bringing the roster to front...") - sys.exit(0) - pixs = [] - for size in (16, 32, 48, 64, 128): - pix = gtkgui_helpers.get_icon_pixmap('gajim', size) - if pix: - pixs.append(pix) - if pixs: - # set the icon to all windows - Gtk.Window.set_default_icon_list(pixs) - pritext = _('Gajim is already running') - sectext = _('Another instance of Gajim seems to be running\nRun anyway?') - dialog = dialogs.YesNoDialog(pritext, sectext) - dialog.popup() - if dialog.run() != Gtk.ResponseType.YES: - sys.exit(3) - dialog.destroy() - # run anyway, delete pid and useless global vars - if os.path.exists(pid_filename): - os.remove(pid_filename) - del pix - del pritext - del sectext - dialog.destroy() - -# Create .gajim dir -pid_dir = os.path.dirname(pid_filename) -if not os.path.exists(pid_dir): - check_paths.create_path(pid_dir) -# Create pid file -try: - f2 = open(pid_filename, 'w') - f2.write(str(os.getpid())) - f2.close() -except IOError as e2: - dlg = dialogs.ErrorDialog(_('Disk Write Error'), str(e2)) - dlg.run() - dlg.destroy() - sys.exit() -del pid_dir - -def on_exit(): - # Save the entropy from OpenSSL PRNG - if PYOPENSSL_PRNG_PRESENT: - try: - OpenSSL.rand.write_file(RNG_SEED) - except TypeError: - OpenSSL.rand.write_file(RNG_SEED.encode('utf-8')) - # delete pid file on normal exit - if os.path.exists(pid_filename): - os.remove(pid_filename) - # Shutdown GUI and save config - if hasattr(gajim.interface, 'roster') and gajim.interface.roster: - gajim.interface.roster.prepare_quit() - -import atexit -atexit.register(on_exit) - -from gui_interface import Interface - -if __name__.endswith('__main__'): - def sigint_cb(num, stack): - sys.exit(5) - # ^C exits the application normally to delete pid file - signal.signal(signal.SIGINT, sigint_cb) - signal.signal(signal.SIGTERM, sigint_cb) - - log.info("Encodings: d:%s, fs:%s, p:%s", sys.getdefaultencoding(), \ - sys.getfilesystemencoding(), locale.getpreferredencoding()) - - check_paths.check_and_possibly_create_paths() - - interface = Interface() - interface.run() - - try: - Gtk.main() - except KeyboardInterrupt: - print('KeyboardInterrupt', file=sys.stderr) diff --git a/src/gui_interface.py b/src/gui_interface.py index 7967fefb5..a1f1068d5 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -2719,11 +2719,11 @@ class Interface: view.updateNamespace({'gajim': gajim}) gajim.ipython_window = window - def run(self): + def run(self, app): if gajim.config.get('trayicon') != 'never': self.show_systray() - self.roster = roster_window.RosterWindow() + self.roster = roster_window.RosterWindow(app) if self.msg_win_mgr.mode == \ MessageWindowMgr.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER: self.msg_win_mgr.create_window(None, None, None) diff --git a/src/roster_window.py b/src/roster_window.py index f54b95d99..4ca0a644e 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -94,7 +94,7 @@ empty_pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 1, 1) empty_pixbuf.fill(0xffffff00) -class RosterWindow: +class RosterWindow(Gtk.ApplicationWindow): """ Class for main window of the GTK+ interface """ @@ -2479,7 +2479,7 @@ class RosterWindow: When we quit the gtk interface - exit gtk """ self.prepare_quit() - Gtk.main_quit() + self.application.quit() def on_quit_request(self, widget=None): """ @@ -6178,7 +6178,8 @@ class RosterWindow: ### ################################################################################ - def __init__(self): + def __init__(self, app): + self.application = app self.filtering = False self.starting = False self.starting_filtering = False @@ -6195,6 +6196,7 @@ class RosterWindow: self.xml = gtkgui_helpers.get_gtk_builder('roster_window.ui') self.window = self.xml.get_object('roster_window') self.hpaned = self.xml.get_object('roster_hpaned') + self.window.set_application(app) gajim.interface.msg_win_mgr = MessageWindowMgr(self.window, self.hpaned) gajim.interface.msg_win_mgr.connect('window-delete', self.on_message_window_delete)