2008-08-15 19:31:51 +02:00
|
|
|
# -*- coding:utf-8 -*-
|
2008-08-15 05:20:23 +02:00
|
|
|
## src/gajim.py
|
2003-11-30 23:40:24 +01:00
|
|
|
##
|
2017-02-11 21:32:13 +01:00
|
|
|
## Copyright (C) 2003-2017 Yann Leboulanger <asterix AT lagaule.org>
|
2008-08-15 05:20:23 +02:00
|
|
|
## Copyright (C) 2004-2005 Vincent Hanquez <tab AT snarc.org>
|
|
|
|
## Copyright (C) 2005 Alex Podaras <bigpod AT gmail.com>
|
|
|
|
## Norman Rasmussen <norman AT rasmussen.co.za>
|
2008-08-15 19:31:51 +02:00
|
|
|
## Stéphan Kochen <stephan AT kochen.nl>
|
2008-08-15 05:20:23 +02:00
|
|
|
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
|
|
|
|
## Alex Mauer <hawke AT hawkesnest.net>
|
|
|
|
## Copyright (C) 2005-2007 Travis Shirk <travis AT pobox.com>
|
|
|
|
## Nikos Kouremenos <kourem AT gmail.com>
|
2008-08-15 19:31:51 +02:00
|
|
|
## Copyright (C) 2006 Junglecow J <junglecow AT gmail.com>
|
2008-08-15 05:20:23 +02:00
|
|
|
## Stefan Bethge <stefan AT lanpartei.de>
|
|
|
|
## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org>
|
|
|
|
## Copyright (C) 2007 Lukas Petrovicky <lukas AT petrovicky.net>
|
|
|
|
## James Newton <redshodan AT gmail.com>
|
|
|
|
## Copyright (C) 2007-2008 Brendan Taylor <whateley AT gmail.com>
|
|
|
|
## Julien Pivotto <roidelapluie AT gmail.com>
|
|
|
|
## Stephan Erb <steve-e AT h3c.de>
|
|
|
|
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
|
2017-02-11 21:32:13 +01:00
|
|
|
## Copyright (C) 2016-2017 Emmanuel Gil Peyrot <linkmauve AT linkmauve.fr>
|
|
|
|
## Philipp Hörist <philipp AT hoerist.com>
|
2003-11-30 23:40:24 +01:00
|
|
|
##
|
2007-12-12 09:44:46 +01:00
|
|
|
## This file is part of Gajim.
|
|
|
|
##
|
|
|
|
## Gajim is free software; you can redistribute it and/or modify
|
2003-11-30 23:40:24 +01:00
|
|
|
## it under the terms of the GNU General Public License as published
|
2007-12-12 09:44:46 +01:00
|
|
|
## by the Free Software Foundation; version 3 only.
|
2003-11-30 23:40:24 +01:00
|
|
|
##
|
2007-12-12 09:44:46 +01:00
|
|
|
## Gajim is distributed in the hope that it will be useful,
|
2003-11-30 23:40:24 +01:00
|
|
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2008-08-15 05:20:23 +02:00
|
|
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2003-11-30 23:40:24 +01:00
|
|
|
## GNU General Public License for more details.
|
|
|
|
##
|
2007-12-12 09:44:46 +01:00
|
|
|
## You should have received a copy of the GNU General Public License
|
2008-08-15 05:20:23 +02:00
|
|
|
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
2007-12-12 09:44:46 +01:00
|
|
|
##
|
2005-11-13 15:55:52 +01:00
|
|
|
|
2011-09-12 23:52:22 +02:00
|
|
|
import sys
|
2017-02-11 21:25:43 +01:00
|
|
|
import os
|
|
|
|
import signal
|
|
|
|
import locale
|
2018-02-14 21:11:25 +01:00
|
|
|
from urllib.parse import unquote
|
|
|
|
|
2017-01-03 23:08:32 +01:00
|
|
|
import gi
|
|
|
|
gi.require_version('GLib', '2.0')
|
|
|
|
gi.require_version('Gio', '2.0')
|
|
|
|
gi.require_version('Gtk', '3.0')
|
|
|
|
gi.require_version('Gdk', '3.0')
|
|
|
|
gi.require_version('GObject', '2.0')
|
|
|
|
gi.require_version('Pango', '1.0')
|
2017-02-11 21:25:43 +01:00
|
|
|
from gi.repository import GLib, Gio, Gtk
|
2018-02-14 21:11:25 +01:00
|
|
|
|
2017-06-13 23:58:06 +02:00
|
|
|
from gajim.common import i18n
|
2018-04-21 12:44:10 +02:00
|
|
|
from gajim.common import configpaths
|
2017-06-13 23:58:06 +02:00
|
|
|
from gajim.common import logging_helpers
|
2017-02-11 21:25:43 +01:00
|
|
|
|
2018-03-17 17:57:27 +01:00
|
|
|
MIN_NBXMPP_VER = "0.6.4"
|
2018-03-26 19:40:41 +02:00
|
|
|
MIN_GTK_VER = "3.22.0"
|
2017-02-11 21:25:43 +01:00
|
|
|
|
|
|
|
|
|
|
|
class GajimApplication(Gtk.Application):
|
|
|
|
'''Main class handling activation and command line.'''
|
|
|
|
|
|
|
|
def __init__(self):
|
2017-11-25 15:33:54 +01:00
|
|
|
Gtk.Application.__init__(self, application_id='org.gajim.Gajim',
|
2018-02-03 09:36:21 +01:00
|
|
|
flags=(
|
|
|
|
Gio.ApplicationFlags.HANDLES_COMMAND_LINE |
|
2018-03-14 22:10:29 +01:00
|
|
|
Gio.ApplicationFlags.HANDLES_OPEN))
|
2017-02-11 21:25:43 +01:00
|
|
|
|
|
|
|
self.add_main_option('version', ord('V'), GLib.OptionFlags.NONE,
|
|
|
|
GLib.OptionArg.NONE,
|
|
|
|
_('Show the application\'s version'))
|
|
|
|
self.add_main_option('quiet', ord('q'), GLib.OptionFlags.NONE,
|
|
|
|
GLib.OptionArg.NONE,
|
|
|
|
_('Show only critical errors'))
|
|
|
|
self.add_main_option('separate', ord('s'), GLib.OptionFlags.NONE,
|
|
|
|
GLib.OptionArg.NONE,
|
|
|
|
_('Separate profile files completely (even '
|
2018-03-25 18:20:37 +02:00
|
|
|
'history database and plugins)'))
|
2017-02-11 21:25:43 +01:00
|
|
|
self.add_main_option('verbose', ord('v'), GLib.OptionFlags.NONE,
|
|
|
|
GLib.OptionArg.NONE,
|
|
|
|
_('Print XML stanzas and other debug '
|
|
|
|
'information'))
|
|
|
|
self.add_main_option('profile', ord('p'), GLib.OptionFlags.NONE,
|
|
|
|
GLib.OptionArg.STRING,
|
|
|
|
_('Use defined profile in configuration '
|
|
|
|
'directory'), 'NAME')
|
|
|
|
self.add_main_option('config-path', ord('c'), GLib.OptionFlags.NONE,
|
|
|
|
GLib.OptionArg.STRING,
|
|
|
|
_('Set configuration directory'), 'PATH')
|
|
|
|
self.add_main_option('loglevel', ord('l'), GLib.OptionFlags.NONE,
|
|
|
|
GLib.OptionArg.STRING,
|
|
|
|
_('Configure logging system'), 'LEVEL')
|
2017-03-03 00:27:19 +01:00
|
|
|
self.add_main_option('warnings', ord('w'), GLib.OptionFlags.NONE,
|
|
|
|
GLib.OptionArg.NONE,
|
|
|
|
_('Show all warnings'))
|
2018-02-02 00:18:10 +01:00
|
|
|
self.add_main_option('ipython', ord('i'), GLib.OptionFlags.NONE,
|
|
|
|
GLib.OptionArg.NONE,
|
2018-02-13 19:18:40 +01:00
|
|
|
_('Open IPython shell'))
|
|
|
|
self.add_main_option('show-next-pending-event', 0, GLib.OptionFlags.NONE,
|
|
|
|
GLib.OptionArg.NONE,
|
|
|
|
_('Pops up a window with the next pending event'))
|
2018-02-19 21:18:04 +01:00
|
|
|
self.add_main_option('start-chat', 0, GLib.OptionFlags.NONE,
|
|
|
|
GLib.OptionArg.NONE,
|
|
|
|
_('Start a new chat'))
|
2017-02-11 21:25:43 +01:00
|
|
|
|
2018-03-17 17:11:07 +01:00
|
|
|
self.add_main_option_entries(self._get_remaining_entry())
|
|
|
|
|
2017-10-31 16:43:52 +01:00
|
|
|
self.connect('handle-local-options', self._handle_local_options)
|
2018-02-03 09:36:21 +01:00
|
|
|
self.connect('command-line', self._handle_remote_options)
|
2017-10-31 16:55:45 +01:00
|
|
|
self.connect('startup', self._startup)
|
|
|
|
self.connect('activate', self._activate)
|
2017-10-31 16:43:52 +01:00
|
|
|
|
2017-02-11 21:25:43 +01:00
|
|
|
self.interface = None
|
|
|
|
|
|
|
|
GLib.set_prgname('gajim')
|
2017-08-09 15:34:58 +02:00
|
|
|
if GLib.get_application_name() != 'Gajim':
|
|
|
|
GLib.set_application_name('Gajim')
|
2017-02-11 21:25:43 +01:00
|
|
|
|
2018-03-17 17:11:07 +01:00
|
|
|
@staticmethod
|
|
|
|
def _get_remaining_entry():
|
|
|
|
option = GLib.OptionEntry()
|
|
|
|
option.arg = GLib.OptionArg.STRING_ARRAY
|
|
|
|
option.arg_data = None
|
|
|
|
option.arg_description = ('[URI …]')
|
|
|
|
option.flags = GLib.OptionFlags.NONE
|
|
|
|
option.long_name = GLib.OPTION_REMAINING
|
|
|
|
option.short_name = 0
|
|
|
|
return [option]
|
|
|
|
|
2017-10-31 16:55:45 +01:00
|
|
|
def _startup(self, application):
|
2017-06-13 23:58:06 +02:00
|
|
|
from gajim import gtkexcepthook
|
2017-02-11 21:25:43 +01:00
|
|
|
gtkexcepthook.init()
|
|
|
|
|
|
|
|
try:
|
|
|
|
import nbxmpp
|
|
|
|
except ImportError:
|
|
|
|
print('Gajim needs python-nbxmpp to run. Quitting…')
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
from distutils.version import LooseVersion as V
|
|
|
|
if V(nbxmpp.__version__) < V(MIN_NBXMPP_VER):
|
|
|
|
print('Gajim needs python-nbxmpp >= %s to run. '
|
2017-06-08 19:58:40 +02:00
|
|
|
'Quitting...' % MIN_NBXMPP_VER)
|
2017-02-11 21:25:43 +01:00
|
|
|
sys.exit(1)
|
|
|
|
|
2017-12-16 23:20:37 +01:00
|
|
|
gtk_ver = '%s.%s.%s' % (Gtk.get_major_version(),
|
|
|
|
Gtk.get_minor_version(),
|
|
|
|
Gtk.get_micro_version())
|
|
|
|
if V(gtk_ver) < V(MIN_GTK_VER):
|
|
|
|
print('Gajim needs GTK+ >= %s to run. '
|
|
|
|
'Quitting...' % MIN_GTK_VER)
|
|
|
|
sys.exit(1)
|
|
|
|
|
2017-02-11 21:25:43 +01:00
|
|
|
# Create and initialize Application Paths & Databases
|
2017-08-13 13:18:56 +02:00
|
|
|
from gajim.common import app
|
2017-06-13 23:58:06 +02:00
|
|
|
from gajim.common import check_paths
|
|
|
|
from gajim.common import exceptions
|
|
|
|
from gajim.common import logger
|
|
|
|
from gajim.common import caps_cache
|
2017-02-11 21:25:43 +01:00
|
|
|
try:
|
2017-08-13 13:18:56 +02:00
|
|
|
app.logger = logger.Logger()
|
|
|
|
caps_cache.initialize(app.logger)
|
2017-02-11 21:25:43 +01:00
|
|
|
check_paths.check_and_possibly_create_paths()
|
2017-04-08 22:53:50 +02:00
|
|
|
except exceptions.DatabaseMalformed as error:
|
2017-02-11 21:25:43 +01:00
|
|
|
dlg = Gtk.MessageDialog(
|
|
|
|
None,
|
|
|
|
Gtk.DialogFlags.DESTROY_WITH_PARENT | Gtk.DialogFlags.MODAL,
|
|
|
|
Gtk.MessageType.ERROR,
|
|
|
|
Gtk.ButtonsType.OK,
|
|
|
|
_('Database Error'))
|
2017-04-08 22:53:50 +02:00
|
|
|
dlg.format_secondary_text(str(error))
|
2017-02-11 21:25:43 +01:00
|
|
|
dlg.run()
|
|
|
|
dlg.destroy()
|
|
|
|
sys.exit()
|
|
|
|
|
|
|
|
if os.name == 'nt':
|
|
|
|
import gettext
|
|
|
|
# needed for docutils
|
|
|
|
sys.path.append('.')
|
|
|
|
APP = 'gajim'
|
|
|
|
DIR = '../po'
|
2017-08-24 00:06:34 +02:00
|
|
|
lang = locale.getdefaultlocale()[0]
|
2017-02-11 21:25:43 +01:00
|
|
|
os.environ['LANG'] = lang
|
|
|
|
gettext.bindtextdomain(APP, DIR)
|
|
|
|
gettext.textdomain(APP)
|
|
|
|
gettext.install(APP, DIR)
|
|
|
|
|
|
|
|
# This is for Windows translation which is currently not
|
|
|
|
# working on GTK 3.18.9
|
|
|
|
# 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')
|
2018-04-21 12:44:10 +02:00
|
|
|
# plugins_locale_dir = os.path.join(common.configpaths[
|
2017-02-11 21:25:43 +01:00
|
|
|
# 'PLUGINS_USER'], 'locale').encode(locale.getpreferredencoding())
|
|
|
|
# libintl.bindtextdomain('gajim_plugins', plugins_locale_dir)
|
|
|
|
# libintl.bind_textdomain_codeset('gajim_plugins', 'UTF-8')
|
|
|
|
|
|
|
|
if Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL:
|
|
|
|
i18n.direction_mark = '\u200F'
|
|
|
|
|
2018-04-01 15:05:06 +02:00
|
|
|
from ctypes import CDLL, byref, create_string_buffer
|
2017-02-11 21:25:43 +01:00
|
|
|
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 <linux/prctl.h> which is used to set the name
|
|
|
|
# of the process.
|
|
|
|
PR_SET_NAME = 15
|
|
|
|
|
|
|
|
if sysname == 'Linux':
|
2018-04-01 15:05:06 +02:00
|
|
|
proc_name = b'gajim'
|
|
|
|
buff = create_string_buffer(len(proc_name)+1)
|
|
|
|
buff.value = proc_name
|
|
|
|
libc.prctl(PR_SET_NAME, byref(buff), 0, 0, 0)
|
2017-02-11 21:25:43 +01:00
|
|
|
elif sysname in ('FreeBSD', 'OpenBSD', 'NetBSD'):
|
|
|
|
libc.setproctitle('gajim')
|
|
|
|
|
|
|
|
def sigint_cb(num, stack):
|
|
|
|
print('SIGINT/SIGTERM received')
|
|
|
|
self.quit()
|
|
|
|
# ^C exits the application normally
|
|
|
|
signal.signal(signal.SIGINT, sigint_cb)
|
|
|
|
signal.signal(signal.SIGTERM, sigint_cb)
|
|
|
|
|
2017-01-26 21:34:54 +01:00
|
|
|
# Set Application Menu
|
2017-08-13 13:18:56 +02:00
|
|
|
app.app = self
|
2017-01-26 21:34:54 +01:00
|
|
|
path = os.path.join(configpaths.get('GUI'), 'application_menu.ui')
|
|
|
|
builder = Gtk.Builder()
|
|
|
|
builder.set_translation_domain(i18n.APP)
|
|
|
|
builder.add_from_file(path)
|
2017-10-03 13:08:06 +02:00
|
|
|
menubar = builder.get_object("menubar")
|
|
|
|
appmenu = builder.get_object("appmenu")
|
2017-11-24 18:54:30 +01:00
|
|
|
if app.prefers_app_menu():
|
2017-10-03 13:08:06 +02:00
|
|
|
self.set_app_menu(appmenu)
|
|
|
|
else:
|
|
|
|
# Add it to the menubar instead
|
|
|
|
menubar.prepend_submenu('Gajim', appmenu)
|
|
|
|
self.set_menubar(menubar)
|
2017-01-26 21:34:54 +01:00
|
|
|
|
2017-10-31 16:55:45 +01:00
|
|
|
def _activate(self, application):
|
2017-10-31 17:28:30 +01:00
|
|
|
if self.interface is not None:
|
|
|
|
self.interface.roster.window.present()
|
|
|
|
return
|
2017-06-13 23:58:06 +02:00
|
|
|
from gajim.gui_interface import Interface
|
|
|
|
from gajim import gtkgui_helpers
|
2017-02-11 21:25:43 +01:00
|
|
|
self.interface = Interface()
|
2017-03-02 18:01:52 +01:00
|
|
|
gtkgui_helpers.load_css()
|
2017-02-11 21:25:43 +01:00
|
|
|
self.interface.run(self)
|
2017-01-26 21:34:54 +01:00
|
|
|
self.add_actions()
|
2017-06-13 23:58:06 +02:00
|
|
|
from gajim import gui_menu_builder
|
2017-01-26 21:34:54 +01:00
|
|
|
gui_menu_builder.build_accounts_menu()
|
2017-02-11 21:25:43 +01:00
|
|
|
|
2018-02-06 20:41:24 +01:00
|
|
|
def _open_uris(self, uris):
|
2017-12-14 20:18:30 +01:00
|
|
|
from gajim.common import app
|
2018-02-06 20:41:24 +01:00
|
|
|
for uri in uris:
|
2017-12-14 20:18:30 +01:00
|
|
|
app.log('uri_handler').info('open %s', uri)
|
2017-12-15 02:40:53 +01:00
|
|
|
if not uri.startswith('xmpp:'):
|
|
|
|
continue
|
|
|
|
# remove xmpp:
|
|
|
|
uri = uri[5:]
|
2017-12-14 20:18:30 +01:00
|
|
|
try:
|
|
|
|
jid, cmd = uri.split('?')
|
|
|
|
except ValueError:
|
2017-12-15 02:40:53 +01:00
|
|
|
# No query argument
|
|
|
|
jid, cmd = uri, 'message'
|
2017-11-25 15:33:54 +01:00
|
|
|
if cmd == 'join':
|
|
|
|
self.interface.join_gc_minimal(None, jid)
|
2017-11-30 19:47:39 +01:00
|
|
|
elif cmd == 'roster':
|
|
|
|
self.activate_action('add-contact', GLib.Variant('s', jid))
|
2018-02-14 21:11:25 +01:00
|
|
|
elif cmd.startswith('message'):
|
|
|
|
attributes = cmd.split(';')
|
|
|
|
message = None
|
|
|
|
for key in attributes:
|
|
|
|
if key.startswith('body'):
|
|
|
|
try:
|
|
|
|
message = unquote(key.split('=')[1])
|
|
|
|
except Exception:
|
|
|
|
app.log('uri_handler').error('Invalid URI: %s', cmd)
|
2017-12-04 00:16:58 +01:00
|
|
|
accounts = list(app.connections.keys())
|
|
|
|
if not accounts:
|
|
|
|
continue
|
|
|
|
if len(accounts) == 1:
|
2018-02-14 21:11:25 +01:00
|
|
|
app.interface.new_chat_from_jid(accounts[0], jid, message)
|
2017-12-04 00:16:58 +01:00
|
|
|
else:
|
|
|
|
self.activate_action('start-chat')
|
|
|
|
start_chat_window = app.interface.instances['start_chat']
|
|
|
|
start_chat_window.search_entry.set_text(jid)
|
2017-11-25 15:33:54 +01:00
|
|
|
|
2017-02-11 21:25:43 +01:00
|
|
|
def do_shutdown(self, *args):
|
|
|
|
Gtk.Application.do_shutdown(self)
|
|
|
|
# Shutdown GUI and save config
|
|
|
|
if hasattr(self.interface, 'roster') and self.interface.roster:
|
|
|
|
self.interface.roster.prepare_quit()
|
|
|
|
|
2017-07-21 12:34:38 +02:00
|
|
|
# Commit any outstanding SQL transactions
|
2017-08-13 13:18:56 +02:00
|
|
|
from gajim.common import app
|
|
|
|
app.logger.commit()
|
2017-07-21 12:34:38 +02:00
|
|
|
|
2018-02-03 09:36:21 +01:00
|
|
|
def _handle_remote_options(self, application, command_line):
|
|
|
|
# Parse all options that should be executed on a remote instance
|
|
|
|
options = command_line.get_options_dict()
|
|
|
|
|
2018-02-13 19:18:40 +01:00
|
|
|
remote_commands = ['ipython',
|
|
|
|
'show-next-pending-event',
|
2018-02-19 21:18:04 +01:00
|
|
|
'start-chat',
|
2018-02-13 19:18:40 +01:00
|
|
|
]
|
|
|
|
|
2018-03-17 17:11:07 +01:00
|
|
|
remaining = options.lookup_value(GLib.OPTION_REMAINING,
|
|
|
|
GLib.VariantType.new('as'))
|
|
|
|
|
2018-02-13 19:18:40 +01:00
|
|
|
for cmd in remote_commands:
|
|
|
|
if options.contains(cmd):
|
|
|
|
self.activate_action(cmd)
|
|
|
|
return 0
|
2018-02-03 09:36:21 +01:00
|
|
|
|
2018-03-17 17:11:07 +01:00
|
|
|
if remaining is not None:
|
|
|
|
self._open_uris(remaining.unpack())
|
2018-02-03 09:36:21 +01:00
|
|
|
return 0
|
|
|
|
|
|
|
|
self.activate()
|
|
|
|
return 0
|
|
|
|
|
2017-10-31 16:43:52 +01:00
|
|
|
def _handle_local_options(self, application,
|
|
|
|
options: GLib.VariantDict) -> int:
|
2018-02-03 09:36:21 +01:00
|
|
|
# Parse all options that have to be executed before ::startup
|
2017-02-11 21:25:43 +01:00
|
|
|
if options.contains('profile'):
|
|
|
|
# Incorporate profile name into application id
|
|
|
|
# to have a single app instance for each profile.
|
|
|
|
profile = options.lookup_value('profile').get_string()
|
|
|
|
app_id = '%s.%s' % (self.get_application_id(), profile)
|
|
|
|
self.set_application_id(app_id)
|
2018-04-21 12:44:10 +02:00
|
|
|
configpaths.set_profile(profile)
|
2017-02-11 21:25:43 +01:00
|
|
|
if options.contains('separate'):
|
2018-04-21 12:44:10 +02:00
|
|
|
configpaths.set_separation(True)
|
2017-02-11 21:25:43 +01:00
|
|
|
if options.contains('config-path'):
|
2018-04-21 12:44:10 +02:00
|
|
|
path = options.lookup_value('config-path').get_string()
|
|
|
|
configpaths.set_config_root(path)
|
|
|
|
|
|
|
|
configpaths.init()
|
|
|
|
logging_helpers.init()
|
|
|
|
|
2017-02-25 17:21:03 +01:00
|
|
|
if options.contains('quiet'):
|
2017-03-01 16:33:09 +01:00
|
|
|
logging_helpers.set_quiet()
|
2017-02-25 17:21:03 +01:00
|
|
|
if options.contains('verbose'):
|
2017-03-01 16:33:09 +01:00
|
|
|
logging_helpers.set_verbose()
|
2017-02-25 17:21:03 +01:00
|
|
|
if options.contains('loglevel'):
|
|
|
|
loglevel = options.lookup_value('loglevel').get_string()
|
|
|
|
logging_helpers.set_loglevels(loglevel)
|
2017-03-03 00:27:19 +01:00
|
|
|
if options.contains('warnings'):
|
|
|
|
self.show_warnings()
|
2018-02-03 09:36:21 +01:00
|
|
|
|
2017-02-11 21:25:43 +01:00
|
|
|
return -1
|
|
|
|
|
2017-03-03 00:27:19 +01:00
|
|
|
def show_warnings(self):
|
|
|
|
import traceback
|
|
|
|
import warnings
|
|
|
|
|
|
|
|
def warn_with_traceback(message, category, filename, lineno,
|
|
|
|
file=None, line=None):
|
|
|
|
traceback.print_stack(file=sys.stderr)
|
|
|
|
sys.stderr.write(warnings.formatwarning(message, category,
|
|
|
|
filename, lineno, line))
|
|
|
|
|
|
|
|
warnings.showwarning = warn_with_traceback
|
|
|
|
warnings.filterwarnings(action="always")
|
|
|
|
|
2017-01-26 21:34:54 +01:00
|
|
|
def add_actions(self):
|
|
|
|
''' Build Application Actions '''
|
2017-06-13 23:58:06 +02:00
|
|
|
from gajim.app_actions import AppActions
|
2017-08-15 19:12:30 +02:00
|
|
|
from gajim.common import app
|
2017-01-26 21:34:54 +01:00
|
|
|
action = AppActions(self)
|
|
|
|
|
|
|
|
self.account_actions = [
|
|
|
|
('-start-single-chat', action.on_single_message, 'online', 's'),
|
|
|
|
('-join-groupchat', action.on_join_gc, 'online', 's'),
|
|
|
|
('-add-contact', action.on_add_contact, 'online', 's'),
|
|
|
|
('-services', action.on_service_disco, 'online', 's'),
|
|
|
|
('-profile', action.on_profile, 'feature', 's'),
|
|
|
|
('-xml-console', action.on_xml_console, 'always', 's'),
|
2017-07-20 00:01:24 +02:00
|
|
|
('-server-info', action.on_server_info, 'online', 's'),
|
2017-01-26 21:34:54 +01:00
|
|
|
('-archive', action.on_archiving_preferences, 'feature', 's'),
|
2017-07-21 16:53:58 +02:00
|
|
|
('-sync-history', action.on_history_sync, 'online', 's'),
|
2017-01-26 21:34:54 +01:00
|
|
|
('-privacylists', action.on_privacy_lists, 'feature', 's'),
|
|
|
|
('-send-server-message',
|
|
|
|
action.on_send_server_message, 'online', 's'),
|
|
|
|
('-set-motd', action.on_set_motd, 'online', 's'),
|
|
|
|
('-update-motd', action.on_update_motd, 'online', 's'),
|
|
|
|
('-delete-motd', action.on_delete_motd, 'online', 's'),
|
|
|
|
('-activate-bookmark',
|
2017-08-30 20:43:50 +02:00
|
|
|
action.on_activate_bookmark, 'online', 'a{sv}'),
|
|
|
|
('-open-event', action.on_open_event, 'always', 'a{sv}'),
|
2017-09-21 20:44:18 +02:00
|
|
|
('-import-contacts', action.on_import_contacts, 'online', 's'),
|
2017-01-26 21:34:54 +01:00
|
|
|
]
|
|
|
|
|
2017-08-15 19:12:30 +02:00
|
|
|
# General Stateful Actions
|
|
|
|
|
|
|
|
act = Gio.SimpleAction.new_stateful(
|
|
|
|
'merge', None,
|
|
|
|
GLib.Variant.new_boolean(app.config.get('mergeaccounts')))
|
|
|
|
act.connect('change-state', action.on_merge_accounts)
|
|
|
|
self.add_action(act)
|
|
|
|
|
|
|
|
act = Gio.SimpleAction.new_stateful(
|
|
|
|
'agent', None,
|
|
|
|
GLib.Variant.new_boolean(app.config.get('use_gpg_agent')))
|
|
|
|
self.add_action(act)
|
|
|
|
|
|
|
|
# General Actions
|
|
|
|
|
2017-01-26 21:34:54 +01:00
|
|
|
self.general_actions = [
|
|
|
|
('quit', action.on_quit),
|
|
|
|
('accounts', action.on_accounts),
|
2017-08-15 19:12:30 +02:00
|
|
|
('add-account', action.on_add_account),
|
|
|
|
('manage-proxies', action.on_manage_proxies),
|
2017-11-30 22:55:06 +01:00
|
|
|
('start-chat', action.on_new_chat),
|
2017-01-26 21:34:54 +01:00
|
|
|
('bookmarks', action.on_manage_bookmarks),
|
|
|
|
('history-manager', action.on_history_manager),
|
|
|
|
('preferences', action.on_preferences),
|
|
|
|
('plugins', action.on_plugins),
|
|
|
|
('file-transfer', action.on_file_transfers),
|
|
|
|
('history', action.on_history),
|
|
|
|
('shortcuts', action.on_keyboard_shortcuts),
|
|
|
|
('features', action.on_features),
|
|
|
|
('content', action.on_contents),
|
|
|
|
('about', action.on_about),
|
2017-08-30 20:43:50 +02:00
|
|
|
('faq', action.on_faq),
|
2018-02-02 00:18:10 +01:00
|
|
|
('ipython', action.toggle_ipython),
|
2018-02-13 19:18:40 +01:00
|
|
|
('show-next-pending-event', action.show_next_pending_event),
|
2017-01-26 21:34:54 +01:00
|
|
|
]
|
|
|
|
|
2017-11-30 19:47:39 +01:00
|
|
|
act = Gio.SimpleAction.new('add-contact', GLib.VariantType.new('s'))
|
|
|
|
act.connect("activate", action.on_add_contact_jid)
|
|
|
|
self.add_action(act)
|
|
|
|
|
2017-01-26 21:34:54 +01:00
|
|
|
for action in self.general_actions:
|
|
|
|
action_name, func = action
|
|
|
|
act = Gio.SimpleAction.new(action_name, None)
|
|
|
|
act.connect("activate", func)
|
|
|
|
self.add_action(act)
|
|
|
|
|
2017-08-15 19:12:30 +02:00
|
|
|
accounts_list = sorted(app.config.get_per('accounts'))
|
2017-01-26 21:34:54 +01:00
|
|
|
if not accounts_list:
|
|
|
|
return
|
|
|
|
if len(accounts_list) > 1:
|
|
|
|
for acc in accounts_list:
|
|
|
|
self.add_account_actions(acc)
|
|
|
|
else:
|
|
|
|
self.add_account_actions(accounts_list[0])
|
|
|
|
|
|
|
|
def add_account_actions(self, account):
|
|
|
|
for action in self.account_actions:
|
|
|
|
action_name, func, state, type_ = action
|
|
|
|
action_name = account + action_name
|
|
|
|
if self.lookup_action(action_name):
|
|
|
|
# We already added this action
|
|
|
|
continue
|
|
|
|
act = Gio.SimpleAction.new(
|
|
|
|
action_name, GLib.VariantType.new(type_))
|
|
|
|
act.connect("activate", func)
|
|
|
|
if state != 'always':
|
|
|
|
act.set_enabled(False)
|
|
|
|
self.add_action(act)
|
|
|
|
|
|
|
|
def remove_account_actions(self, account):
|
|
|
|
for action in self.account_actions:
|
|
|
|
action_name = account + action[0]
|
|
|
|
self.remove_action(action_name)
|
|
|
|
|
|
|
|
def set_account_actions_state(self, account, new_state=False):
|
|
|
|
for action in self.account_actions:
|
|
|
|
action_name, _, state, _ = action
|
|
|
|
if not new_state and state in ('online', 'feature'):
|
|
|
|
# We go offline
|
|
|
|
self.lookup_action(account + action_name).set_enabled(False)
|
|
|
|
elif new_state and state == 'online':
|
|
|
|
# We go online
|
|
|
|
self.lookup_action(account + action_name).set_enabled(True)
|
|
|
|
|
2016-12-22 19:48:48 +01:00
|
|
|
|
2018-01-13 22:07:25 +01:00
|
|
|
def main():
|
|
|
|
if sys.platform != 'win32':
|
|
|
|
if os.geteuid() == 0:
|
|
|
|
sys.exit("You must not launch gajim as root, it is insecure.")
|
|
|
|
|
2017-08-24 00:06:34 +02:00
|
|
|
appli = GajimApplication()
|
|
|
|
appli.run(sys.argv)
|
2018-01-13 22:07:25 +01:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|