Port application menu to GMenu

This commit is contained in:
Philipp Hörist 2017-01-26 21:34:54 +01:00
parent eec1a69efd
commit 6f8452667d
14 changed files with 660 additions and 869 deletions

View File

@ -1,84 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
<requires lib="gtk+" version="3.12"/>
<object class="GtkMenu" id="advanced_menuitem_menu">
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="xml_console_menuitem">
<property name="can_focus">False</property>
<property name="label" translatable="yes">Show _XML Console</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="archiving_preferences_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Edit Archi_ving Preferences</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="privacy_lists_menuitem">
<property name="can_focus">False</property>
<property name="label" translatable="yes">Edit _Privacy Lists...</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="separator8">
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="administrator_menuitem">
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Administrator</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="administrator_menuitem_menu">
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="send_server_message_menuitem">
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Sends a message to users currently connected to this server</property>
<property name="label" translatable="yes">_Send Server Message...</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="separator9">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="set_motd_menuitem">
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Sets Message of the Day</property>
<property name="label" translatable="yes">Set MOTD...</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="update_motd_menuitem">
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Updates Message of the Day</property>
<property name="label" translatable="yes">Update MOTD...</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="delete_motd_menuitem">
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Deletes Message of the Day</property>
<property name="label" translatable="yes">Delete MOTD</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>

View File

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<menu id="menubar">
<submenu>
<attribute name="label" translatable="yes">Accounts</attribute>
</submenu>
<submenu>
<attribute name="label" translatable="yes">View</attribute>
<section>
<item>
<attribute name="label" translatable="yes">Show Roster</attribute>
<attribute name="action">win.show-roster</attribute>
<attribute name="accel">&lt;Primary&gt;R</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Show Offline Contacts</attribute>
<attribute name="action">win.show-offline</attribute>
<attribute name="accel">&lt;Primary&gt;O</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Show Active Contacts</attribute>
<attribute name="action">win.show-active</attribute>
<attribute name="accel">&lt;Primary&gt;Y</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Show Transports</attribute>
<attribute name="action">win.show-transports</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">File Transfer</attribute>
<attribute name="action">app.file-transfer</attribute>
<attribute name="accel">&lt;Primary&gt;T</attribute>
</item>
<item>
<attribute name="label" translatable="yes">History</attribute>
<attribute name="action">app.history</attribute>
</item>
</section>
</submenu>
<submenu>
<attribute name="label" translatable="yes">Help</attribute>
<section>
<item>
<attribute name="label" translatable="yes">Contents</attribute>
<attribute name="action">app.content</attribute>
</item>
<item>
<attribute name="label" translatable="yes">FAQ</attribute>
<attribute name="action">app.faq</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Keyboard Shortcuts</attribute>
<attribute name="action">app.shortcuts</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Features</attribute>
<attribute name="action">app.features</attribute>
</item>
<item>
<attribute name="label" translatable="yes">About</attribute>
<attribute name="action">app.about</attribute>
</item>
</section>
</submenu>
</menu>
<menu id="appmenu">
<section>
<item>
<attribute name="label" translatable="yes">Accounts</attribute>
<attribute name="action">app.accounts</attribute>
<attribute name="accel">&lt;Primary&gt;&lt;Shift&gt;A</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Bookmarks</attribute>
<attribute name="action">app.bookmarks</attribute>
<attribute name="accel">&lt;Primary&gt;B</attribute>
</item>
<item>
<attribute name="label" translatable="yes">History Manager</attribute>
<attribute name="action">app.history-manager</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Plugins</attribute>
<attribute name="action">app.plugins</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Preferences</attribute>
<attribute name="action">app.preferences</attribute>
<attribute name="accel">&lt;Primary&gt;P</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Quit</attribute>
<attribute name="action">app.quit</attribute>
<attribute name="accel">&lt;Primary&gt;Q</attribute>
</item>
</section>
</menu>
</interface>

View File

@ -25,304 +25,7 @@
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkMenuBar" id="menubar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="actions_menu">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Actions</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_actions_menuitem_activate" swapped="no"/>
<child type="submenu">
<object class="GtkMenu" id="actions_menu_menu">
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="new_chat_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Start Chat...</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="send_single_message_menuitem">
<property name="can_focus">False</property>
<property name="label" translatable="yes">Send Single _Message...</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="join_gc_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Join _Group Chat</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="add_new_contact_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Add _Contact...</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="service_disco_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Discover Services</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="advanced_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Advanced</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="separator1">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="quit_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label">_Quit</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_quit_request" swapped="no"/>
<accelerator key="Q" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="edit_menu">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Edit</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_edit_menuitem_activate" swapped="no"/>
<child type="submenu">
<object class="GtkMenu" id="edit_menu_menu">
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="accounts_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Accounts</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_accounts_menuitem_activate" swapped="no"/>
<accelerator key="A" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
</object>
</child>
<child>
<object class="GtkMenuItem" id="profile_avatar_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Profile, A_vatar</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="separator2">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="preferences_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label">_Preferences</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_preferences_menuitem_activate" swapped="no"/>
<accelerator key="P" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
<object class="GtkMenuItem" id="plugins_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">P_lugins</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_plugins_menuitem_activate" swapped="no"/>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="view_menu">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_View</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_view_menu_activate" swapped="no"/>
<child type="submenu">
<object class="GtkMenu" id="view_menu_menu">
<property name="can_focus">False</property>
<child>
<object class="GtkCheckMenuItem" id="show_offline_contacts_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Show _Offline Contacts</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_show_offline_contacts_menuitem_activate" swapped="no"/>
<accelerator key="O" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
<object class="GtkCheckMenuItem" id="show_only_active_contacts_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Show Only _Active Contacts</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_show_only_active_contacts_menuitem_activate" swapped="no"/>
<accelerator key="Y" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
<object class="GtkCheckMenuItem" id="show_transports_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Show T_ransports</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_show_transports_menuitem_activate" swapped="no"/>
</object>
</child>
<child>
<object class="GtkCheckMenuItem" id="show_roster_menuitem">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Show _Roster</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<signal name="toggled" handler="on_show_roster_menuitem_toggled" swapped="no"/>
<accelerator key="R" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="separator3">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="file_transfers_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">File _Transfers</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_file_transfers_menuitem_activate" swapped="no"/>
<accelerator key="T" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
<object class="GtkMenuItem" id="history_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">_History</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_history_menuitem_activate" swapped="no"/>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="help_menu">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Help</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="help_menu_menu">
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="contents_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Help online</property>
<property name="label" translatable="yes">_Contents</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_contents_menuitem_activate" swapped="no"/>
</object>
</child>
<child>
<object class="GtkMenuItem" id="faq_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Frequently Asked Questions (online)</property>
<property name="label" translatable="yes">_FAQ</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_faq_menuitem_activate" swapped="no"/>
</object>
</child>
<child>
<object class="GtkMenuItem" id="keyboard_shortcuts_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Keyboard Shortcuts</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_keyboard_shortcuts_menuitem_activate" swapped="no"/>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="menuitem1">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="features_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Fea_tures</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_features_menuitem_activate" swapped="no"/>
</object>
</child>
<child>
<object class="GtkMenuItem" id="about_menuitem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label">_About</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_about_menuitem_activate" swapped="no"/>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
<placeholder/>
</child>
<child>
<object class="GtkPaned" id="roster_hpaned">

223
src/app_actions.py Normal file
View File

@ -0,0 +1,223 @@
# -*- coding: utf-8 -*-
## src/app_actions.py
##
## Copyright (C) 2017 Philipp Hörist <philipp AT hoerist.com>
##
## This file is part of Gajim.
##
## Gajim is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation; version 3 only.
##
## Gajim is distributed in the hope that it will be useful,
## 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.
##
## You should have received a copy of the GNU General Public License
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
##
from common import helpers
from common import gajim
from common.exceptions import GajimGeneralException
from gi.repository import Gtk
import sys
import os
import config
import dialogs
import features_window
import shortcuts_window
import plugins.gui
import history_window
import disco
class AppActions():
''' Action Callbacks '''
def __init__(self, app: Gtk.Application):
self.application = app
# Application Menu Actions
def on_preferences(self, action, param):
if 'preferences' in gajim.interface.instances:
gajim.interface.instances['preferences'].window.present()
else:
gajim.interface.instances['preferences'] = \
config.PreferencesWindow()
def on_plugins(self, action, param):
if 'plugins' in gajim.interface.instances:
gajim.interface.instances['plugins'].window.present()
else:
gajim.interface.instances['plugins'] = plugins.gui.PluginsWindow()
def on_accounts(self, action, param):
if 'accounts' in gajim.interface.instances:
gajim.interface.instances['accounts'].window.present()
else:
gajim.interface.instances['accounts'] = config.AccountsWindow()
def on_history_manager(self, action, param):
if os.name == 'nt':
if os.path.exists('history_manager.exe'):
# user is running frozen application
helpers.exec_command('history_manager.exe')
else:
# user is running from source
helpers.exec_command('%s history_manager.py' % sys.executable)
else:
# Unix user
helpers.exec_command('%s history_manager.py' % sys.executable)
def on_manage_bookmarks(self, action, param):
config.ManageBookmarksWindow()
def on_quit(self, action, param):
gajim.interface.roster.on_quit_request()
# Accounts Actions
def on_profile(self, action, param):
gajim.interface.edit_own_details(param.get_string())
def on_activate_bookmark(self, action, param):
dict_ = param.unpack()
account, jid, nick, password = \
dict_['account'], dict_['jid'], None, None
if 'nick' in dict_:
nick = dict_['nick']
if 'password' in dict_:
password = dict_['password']
gajim.interface.join_gc_room(account, jid, nick, password)
def on_send_server_message(self, action, param):
account = param.get_string()
server = gajim.config.get_per('accounts', account, 'hostname')
server += '/announce/online'
dialogs.SingleMessageWindow(account, server, 'send')
def on_service_disco(self, action, param):
account = param.get_string()
server_jid = gajim.config.get_per('accounts', account, 'hostname')
if server_jid in gajim.interface.instances[account]['disco']:
gajim.interface.instances[account]['disco'][server_jid].\
window.present()
else:
try:
# Object will add itself to the window dict
disco.ServiceDiscoveryWindow(account, address_entry=True)
except GajimGeneralException:
pass
def on_join_gc(self, action, param):
account = param.get_string()
invisible_show = gajim.SHOW_LIST.index('invisible')
if gajim.connections[account].connected == invisible_show:
dialogs.ErrorDialog(_(
'You cannot join a group chat while you are invisible'))
return
if 'join_gc' in gajim.interface.instances[account]:
gajim.interface.instances[account]['join_gc'].window.present()
else:
try:
gajim.interface.instances[account]['join_gc'] = \
dialogs.JoinGroupchatWindow(account)
except GajimGeneralException:
pass
def on_add_contact(self, action, param):
dialogs.AddNewContactWindow(param.get_string())
def on_new_chat(self, action, param):
dialogs.NewChatDialog(param.get_string())
def on_single_message(self, action, param):
dialogs.SingleMessageWindow(param.get_string(), action='send')
# Advanced Actions
def on_archiving_preferences(self, action, param):
account = param.get_string()
if 'archiving_preferences' in gajim.interface.instances[account]:
gajim.interface.instances[account]['archiving_preferences'].window.\
present()
else:
if gajim.connections[account].archiving_313_supported:
gajim.interface.instances[account]['archiving_preferences'] = \
dialogs.Archiving313PreferencesWindow(account)
else:
gajim.interface.instances[account]['archiving_preferences'] = \
dialogs.ArchivingPreferencesWindow(account)
def on_privacy_lists(self, action, param):
account = param.get_string()
if 'privacy_lists' in gajim.interface.instances[account]:
gajim.interface.instances[account]['privacy_lists'].window.present()
else:
gajim.interface.instances[account]['privacy_lists'] = \
dialogs.PrivacyListsWindow(account)
def on_xml_console(self, action, param):
account = param.get_string()
if 'xml_console' in gajim.interface.instances[account]:
gajim.interface.instances[account]['xml_console'].window.present()
else:
gajim.interface.instances[account]['xml_console'] = \
dialogs.XMLConsoleWindow(account)
# Admin Actions
def on_set_motd(self, action, param):
account = param.get_string()
server = gajim.config.get_per('accounts', account, 'hostname')
server += '/announce/motd'
dialogs.SingleMessageWindow(account, server, 'send')
def on_update_motd(self, action, param):
account = param.get_string()
server = gajim.config.get_per('accounts', account, 'hostname')
server += '/announce/motd/update'
dialogs.SingleMessageWindow(account, server, 'send')
def on_delete_motd(self, action, param):
account = param.get_string()
server = gajim.config.get_per('accounts', account, 'hostname')
server += '/announce/motd/delete'
gajim.connections[account].send_motd(server)
# Help Actions
def on_contents(self, action, param):
helpers.launch_browser_mailer(
'url', 'https://dev.gajim.org/gajim/gajim/wikis')
def on_faq(self, action, param):
helpers.launch_browser_mailer(
'url', 'https://dev.gajim.org/gajim/gajim/wikis/help/gajimfaq')
def on_keyboard_shortcuts(self, action, param):
shortcuts_window.show(self.application.get_active_window())
def on_features(self, action, param):
features_window.FeaturesWindow()
def on_about(self, action, param):
dialogs.AboutDialog()
# View Actions
def on_file_transfers(self, action, param):
if gajim.interface.instances['file_transfers']. \
window.get_property('visible'):
gajim.interface.instances['file_transfers'].window.present()
else:
gajim.interface.instances['file_transfers'].window.show_all()
def on_history(self, action, param):
if 'logs' in gajim.interface.instances:
gajim.interface.instances['logs'].window.present()
else:
gajim.interface.instances['logs'] = history_window.\
HistoryWindow()

View File

@ -62,6 +62,8 @@ from common import exceptions
from common import check_X509
from common.connection_handlers import *
from gtkgui_helpers import get_action
if gajim.HAVE_PYOPENSSL:
import OpenSSL.crypto
@ -2033,6 +2035,7 @@ class Connection(CommonConnection, ConnectionHandlers):
break
if nbxmpp.NS_VCARD in obj.features:
self.vcard_supported = True
get_action(self.name + '-profile').set_enabled(True)
if nbxmpp.NS_PUBSUB in obj.features:
self.pubsub_supported = True
if nbxmpp.NS_PUBSUB_PUBLISH_OPTIONS in obj.features:
@ -2044,6 +2047,7 @@ class Connection(CommonConnection, ConnectionHandlers):
if nbxmpp.NS_MAM in obj.features:
self.archiving_supported = True
self.archiving_313_supported = True
get_action(self.name + '-archive').set_enabled(True)
if nbxmpp.NS_ARCHIVE in obj.features:
self.archiving_supported = True
self.archiving_136_supported = True
@ -2069,6 +2073,7 @@ class Connection(CommonConnection, ConnectionHandlers):
self.connection.send(iq)
if nbxmpp.NS_PRIVACY in obj.features:
self.privacy_rules_supported = True
get_action(self.name + '-privacylists').set_enabled(True)
if nbxmpp.NS_BYTESTREAM in obj.features and \
gajim.config.get_per('accounts', self.name, 'use_ft_proxies'):

View File

@ -43,6 +43,7 @@ config = config.Config()
version = config.get('version')
connections = {} # 'account name': 'account (connection.Connection) instance'
ipython_window = None
app = None # Gtk.Application
ged = ged_module.GlobalEventsDispatcher() # Global Events Dispatcher
nec = None # Network Events Controller

View File

@ -48,6 +48,7 @@ import message_control
from chat_control_base import ChatControlBase
import dataforms_widget
import profile_window
import gui_menu_builder
try:
import gtkspell
@ -2566,7 +2567,8 @@ class AccountsWindow:
else:
gajim.interface.roster.regroup = False
gajim.interface.roster.setup_and_draw_roster()
gajim.interface.roster.set_actions_menu_needs_rebuild()
gajim.app.remove_account_actions(account)
gui_menu_builder.build_accounts_menu()
def _enable_account(self, account):
if account == gajim.ZEROCONF_ACC_NAME:
@ -2612,7 +2614,8 @@ class AccountsWindow:
else:
gajim.interface.roster.regroup = False
gajim.interface.roster.setup_and_draw_roster()
gajim.interface.roster.set_actions_menu_needs_rebuild()
gajim.app.add_account_actions(account)
gui_menu_builder.build_accounts_menu()
def on_enable_zeroconf_checkbutton2_toggled(self, widget):
# don't do anything if there is an account with the local name but is a
@ -3154,7 +3157,8 @@ class RemoveAccountWindow:
else:
gajim.interface.roster.regroup = False
gajim.interface.roster.setup_and_draw_roster()
gajim.interface.roster.set_actions_menu_needs_rebuild()
gajim.app.remove_account_actions(self.account)
gui_menu_builder.build_accounts_menu()
if 'accounts' in gajim.interface.instances:
gajim.interface.instances['accounts'].init_accounts()
gajim.interface.instances['accounts'].init_account()
@ -3356,7 +3360,7 @@ class ManageBookmarksWindow:
gajim.connections[acct].bookmarks.append(bmdict)
gajim.connections[acct].store_bookmarks()
gajim.interface.roster.set_actions_menu_needs_rebuild()
gui_menu_builder.build_bookmark_menu(acct)
self.window.destroy()
def on_cancel_button_clicked(self, widget):
@ -4091,7 +4095,8 @@ class AccountCreationWizardWindow:
else:
gajim.interface.roster.regroup = False
gajim.interface.roster.setup_and_draw_roster()
gajim.interface.roster.set_actions_menu_needs_rebuild()
gajim.app.add_account_actions(self.account)
gui_menu_builder.build_accounts_menu()
class ManagePEPServicesWindow:
def __init__(self, account):

View File

@ -57,6 +57,7 @@ import gtkgui_helpers
import groups
import adhoc_commands
import search_window
import gui_menu_builder
from common import gajim
import nbxmpp
@ -1852,7 +1853,7 @@ class MucBrowser(AgentBrowser):
gajim.connections[self.account].bookmarks.append(bm)
gajim.connections[self.account].store_bookmarks()
gajim.interface.roster.set_actions_menu_needs_rebuild()
gui_menu_builder.build_bookmark_menu(self.account)
dialogs.InformationDialog(
_('Bookmark has been added successfully'),

View File

@ -233,11 +233,23 @@ class GajimApplication(Gtk.Application):
print("Encodings: d:{}, fs:{}, p:{}".format(sys.getdefaultencoding(),
sys.getfilesystemencoding(), locale.getpreferredencoding()))
# Set Application Menu
gajim.app = self
path = os.path.join(configpaths.get('GUI'), 'application_menu.ui')
builder = Gtk.Builder()
builder.set_translation_domain(i18n.APP)
builder.add_from_file(path)
self.set_menubar(builder.get_object("menubar"))
self.set_app_menu(builder.get_object("appmenu"))
def do_activate(self):
Gtk.Application.do_activate(self)
from gui_interface import Interface
self.interface = Interface()
self.interface.run(self)
self.add_actions()
import gui_menu_builder
gui_menu_builder.build_accounts_menu()
def do_shutdown(self, *args):
Gtk.Application.do_shutdown(self)
@ -315,6 +327,91 @@ class GajimApplication(Gtk.Application):
sys.stderr = outerr
warnings.filterwarnings(action='ignore')
def add_actions(self):
''' Build Application Actions '''
from app_actions import AppActions
action = AppActions(self)
self.account_actions = [
('-start-single-chat', action.on_single_message, 'online', 's'),
('-start-chat', action.on_new_chat, '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'),
('-archive', action.on_archiving_preferences, 'feature', 's'),
('-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',
action.on_activate_bookmark, 'online', 'a{sv}')
]
self.general_actions = [
('quit', action.on_quit),
('accounts', action.on_accounts),
('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),
('faq', action.on_faq)
]
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)
from common import gajim
accounts_list = sorted(gajim.contacts.get_accounts())
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)
app = GajimApplication()
app.run(sys.argv)

View File

@ -1085,3 +1085,6 @@ def __label_size_allocate(widget, allocation):
if lh_old != lh:
widget.set_size_request (-1, lh / Pango.SCALE)
def get_action(action):
return gajim.app.lookup_action(action)

View File

@ -56,7 +56,7 @@ if dbus_support.supported:
import dbus
import gtkgui_helpers
import gui_menu_builder
import dialogs
import notify
import message_control
@ -843,7 +843,7 @@ class Interface:
# We received a bookmark item from the server (JEP48)
# Auto join GC windows if neccessary
self.roster.set_actions_menu_needs_rebuild()
gui_menu_builder.build_bookmark_menu(obj.conn.name)
invisible_show = gajim.SHOW_LIST.index('invisible')
# do not autojoin if we are invisible
if obj.conn.connected == invisible_show:
@ -2661,7 +2661,7 @@ class Interface:
else:
gajim.connections[account].bookmarks.append(bm)
gajim.connections[account].store_bookmarks()
self.roster.set_actions_menu_needs_rebuild()
gui_menu_builder.build_bookmark_menu(account)
dialogs.InformationDialog(
_('Bookmark has been added successfully'),
_('You can manage your bookmarks via Actions menu in your roster.'))

View File

@ -18,15 +18,17 @@
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
##
from gi.repository import Gtk
from gi.repository import Gtk, Gio, GLib
import os
import gtkgui_helpers
import message_control
from common import gajim
from common import helpers
from common import i18n
from nbxmpp.protocol import NS_COMMANDS, NS_FILE, NS_MUC, NS_ESESSION
from nbxmpp.protocol import NS_JINGLE_FILE_TRANSFER, NS_CONFERENCE
from gtkgui_helpers import get_action
def build_resources_submenu(contacts, account, action, room_jid=None,
room_account=None, cap=None):
@ -636,3 +638,146 @@ def get_transport_menu(contact, account):
menu.show_all()
return menu
'''
Build dynamic Application Menus
'''
def get_bookmarks_menu(account, rebuild=False):
if not gajim.connections[account].bookmarks:
return None
menu = Gio.Menu()
# Build Join Groupchat
action = 'app.{}-join-groupchat'.format(account)
menuitem = Gio.MenuItem.new(_('Join Group Chat'), action)
variant = GLib.Variant('s', account)
menuitem.set_action_and_target_value(action, variant)
menu.append_item(menuitem)
# Build Bookmarks
section = Gio.Menu()
for bookmark in gajim.connections[account].bookmarks:
name = bookmark['name']
if not name:
# No name was given for this bookmark.
# Use the first part of JID instead...
name = bookmark['jid'].split("@")[0]
# Shorten long names
name = (name[:42] + '..') if len(name) > 42 else name
action = 'app.{}-activate-bookmark'.format(account)
menuitem = Gio.MenuItem.new(name, action)
# Create Variant Dict
dict_ = {'account': GLib.Variant('s', account),
'jid': GLib.Variant('s', bookmark['jid'])}
if bookmark['nick']:
dict_['nick'] = GLib.Variant('s', bookmark['nick'])
if bookmark['password']:
dict_['password'] = GLib.Variant('s', bookmark['password'])
variant_dict = GLib.Variant('a{sv}', dict_)
menuitem.set_action_and_target_value(action, variant_dict)
section.append_item(menuitem)
menu.append_section(None, section)
if not rebuild:
get_action(account + '-activate-bookmark').set_enabled(True)
return menu
def get_account_menu(account):
'''
[(action, label/sub_menu)]
action: string
label: string
sub menu: list
'''
account_menu = [
('-add-contact', _('Add Contact...')),
('-join-groupchat', _('Join Group Chat')),
('-profile', _('Profile')),
('-services', _('Discover Services')),
('-start-chat', _('Start Chat...')),
('-start-single-chat', _('Send Single Message...')),
('Advanced', [
('-archive', _('Archiving Preferences')),
('-privacylists', _('Privacy Lists')),
('-xml-console', _('XML Console'))
]),
('Admin', [
('-send-server-message', _('Send Server Message...')),
('-set-motd', _('Set MOTD...')),
('-update-motd', _('Update MOTD...')),
('-delete-motd', _('Delete MOTD...'))
]),
]
def build_menu(preset):
menu = Gio.Menu()
for item in preset:
if isinstance(item[1], str):
action, label = item
if action == '-join-groupchat':
bookmark_menu = get_bookmarks_menu(account, True)
if bookmark_menu:
menu.append_submenu(label, bookmark_menu)
continue
action = 'app.{}{}'.format(account, action)
menuitem = Gio.MenuItem.new(label, action)
variant = GLib.Variant('s', account)
menuitem.set_action_and_target_value(action, variant)
menu.append_item(menuitem)
else:
label, sub_menu = item
# This is a submenu
submenu = build_menu(sub_menu)
menu.append_submenu(label, submenu)
return menu
return build_menu(account_menu)
def build_accounts_menu():
menubar = gajim.app.get_menubar()
# Accounts Submenu
acc_menu = menubar.get_item_link(0, 'submenu')
acc_menu.remove_all()
accounts_list = sorted(gajim.contacts.get_accounts())
if not accounts_list:
no_accounts = _('No Accounts available')
acc_menu.append_item(Gio.MenuItem.new(no_accounts, None))
return
if len(accounts_list) > 1:
for acc in accounts_list:
acc_menu.append_submenu(
acc, get_account_menu(acc))
else:
acc_menu = get_account_menu(accounts_list[0])
menubar.remove(0)
menubar.insert_submenu(0, 'Accounts', acc_menu)
def build_bookmark_menu(account):
menubar = gajim.app.get_menubar()
bookmark_menu = get_bookmarks_menu(account)
if not bookmark_menu:
return
# Accounts Submenu
acc_menu = menubar.get_item_link(0, 'submenu')
# We have more than one Account active
if acc_menu.get_item_link(0, 'submenu'):
for i in range(acc_menu.get_n_items()):
label = acc_menu.get_item_attribute_value(i, 'label')
if label.get_string() == account:
menu = acc_menu.get_item_link(i, 'submenu')
else:
# We have only one Account active
menu = acc_menu
label = menu.get_item_attribute_value(1, 'label').get_string()
menu.remove(1)
menu.insert_submenu(1, label, bookmark_menu)

View File

@ -41,6 +41,7 @@ import dialogs
from chat_control_base import ChatControlBase
from common import gajim
from gtkgui_helpers import get_action
####################
@ -97,8 +98,7 @@ class MessageWindow(object):
else:
self.parent_paned.add(self.notebook)
self.parent_paned.pack2(self.notebook, resize=True, shrink=True)
gajim.interface.roster.xml.get_object('show_roster_menuitem').\
set_sensitive(True)
get_action('show-roster').set_enabled(True)
orig_window.destroy()
del orig_window
@ -626,8 +626,7 @@ class MessageWindow(object):
# Don't close parent window, just remove the child
child = self.parent_paned.get_child2()
self.parent_paned.remove(child)
gajim.interface.roster.xml.get_object('show_roster_menuitem').\
set_sensitive(False)
get_action('show-roster').set_enabled(False)
else:
self.window.destroy()
return # don't show_title, we are dead
@ -1273,8 +1272,7 @@ class MessageWindowMgr(GObject.GObject):
# Don't close parent window, just remove the child
child = w.parent_paned.get_child2()
w.parent_paned.remove(child)
gajim.interface.roster.xml.get_object('show_roster_menuitem').\
set_sensitive(False)
get_action('show-roster').set_enabled(False)
gtkgui_helpers.resize_window(w.window,
gajim.config.get('roster_width'),
gajim.config.get('roster_height'))

View File

@ -38,8 +38,8 @@ from gi.repository import GdkPixbuf
from gi.repository import Pango
from gi.repository import GObject
from gi.repository import GLib
from gi.repository import Gio
import os
import sys
import time
import locale
@ -57,10 +57,6 @@ import cell_renderer_image
import tooltips
import message_control
import adhoc_commands
import features_window
import shortcuts_window
import plugins
import plugins.gui
from common import gajim
from common import helpers
@ -69,11 +65,10 @@ from common import i18n
from common import location_listener
from common import ged
from common import dbus_support
from message_window import MessageWindowMgr
from nbxmpp.protocol import NS_FILE, NS_ROSTERX, NS_CONFERENCE
class Column(IntEnum):
IMG = 0 # image to show state (online, new message etc)
NAME = 1 # cellrenderer text that holds contact nickame
@ -2297,7 +2292,6 @@ class RosterWindow:
for contact in [c for c in lcontact if (
(c.show != 'offline' or c.is_transport()) and not ctrl)]:
self.chg_contact_status(contact, 'offline', '', account)
self.set_actions_menu_needs_rebuild()
self.update_status_combobox()
def get_status_message(self, show, on_response, show_pep=True,
@ -2676,6 +2670,7 @@ class RosterWindow:
# sensitivity for this menuitem
if gajim.get_number_of_connected_accounts() == 0:
model[self.status_message_menuitem_iter][3] = False
self.application.set_account_actions_state(obj.conn.name)
else:
# sensitivity for this menuitem
model[self.status_message_menuitem_iter][3] = True
@ -2714,7 +2709,7 @@ class RosterWindow:
self.redraw_metacontacts(obj.conn.name)
def _nec_signed_in(self, obj):
self.set_actions_menu_needs_rebuild()
self.application.set_account_actions_state(obj.conn.name, True)
self.draw_account(obj.conn.name)
def _nec_decrypted_message_received(self, obj):
@ -2776,74 +2771,10 @@ class RosterWindow:
### FIXME: order callbacks in itself...
################################################################################
def on_actions_menuitem_activate(self, widget):
self.make_menu()
def on_edit_menuitem_activate(self, widget):
"""
Need to call make_menu to build profile, avatar item
"""
self.make_menu()
def on_bookmark_menuitem_activate(self, widget, account, bookmark):
gajim.interface.join_gc_room(account, bookmark['jid'], bookmark['nick'],
bookmark['password'])
def on_send_server_message_menuitem_activate(self, widget, account):
server = gajim.config.get_per('accounts', account, 'hostname')
server += '/announce/online'
dialogs.SingleMessageWindow(account, server, 'send')
def on_xml_console_menuitem_activate(self, widget, account):
if 'xml_console' in gajim.interface.instances[account]:
gajim.interface.instances[account]['xml_console'].window.present()
else:
gajim.interface.instances[account]['xml_console'] = \
dialogs.XMLConsoleWindow(account)
def on_archiving_preferences_menuitem_activate(self, widget, account):
if 'archiving_preferences' in gajim.interface.instances[account]:
gajim.interface.instances[account]['archiving_preferences'].window.\
present()
else:
if gajim.connections[account].archiving_313_supported:
gajim.interface.instances[account]['archiving_preferences'] = \
dialogs.Archiving313PreferencesWindow(account)
else:
gajim.interface.instances[account]['archiving_preferences'] = \
dialogs.ArchivingPreferencesWindow(account)
def on_privacy_lists_menuitem_activate(self, widget, account):
if 'privacy_lists' in gajim.interface.instances[account]:
gajim.interface.instances[account]['privacy_lists'].window.present()
else:
gajim.interface.instances[account]['privacy_lists'] = \
dialogs.PrivacyListsWindow(account)
def on_set_motd_menuitem_activate(self, widget, account):
server = gajim.config.get_per('accounts', account, 'hostname')
server += '/announce/motd'
dialogs.SingleMessageWindow(account, server, 'send')
def on_update_motd_menuitem_activate(self, widget, account):
server = gajim.config.get_per('accounts', account, 'hostname')
server += '/announce/motd/update'
dialogs.SingleMessageWindow(account, server, 'send')
def on_delete_motd_menuitem_activate(self, widget, account):
server = gajim.config.get_per('accounts', account, 'hostname')
server += '/announce/motd/delete'
gajim.connections[account].send_motd(server)
def on_history_manager_menuitem_activate(self, widget):
if os.name == 'nt':
if os.path.exists('history_manager.exe'): # user is running stable
helpers.exec_command('history_manager.exe')
else: # user is running svn
helpers.exec_command('%s history_manager.py' % sys.executable)
else: # Unix user
helpers.exec_command('%s history_manager.py' % sys.executable)
def on_info(self, widget, contact, account):
"""
Call vcard_information_window class to display contact's information
@ -3765,19 +3696,6 @@ class RosterWindow:
self.get_status_message(status, on_continue)
def on_preferences_menuitem_activate(self, widget):
if 'preferences' in gajim.interface.instances:
gajim.interface.instances['preferences'].window.present()
else:
gajim.interface.instances['preferences'] = config.PreferencesWindow(
)
def on_plugins_menuitem_activate(self, widget):
if 'plugins' in gajim.interface.instances:
gajim.interface.instances['plugins'].window.present()
else:
gajim.interface.instances['plugins'] = plugins.gui.PluginsWindow()
def on_publish_tune_toggled(self, widget, account):
active = widget.get_active()
gajim.config.set_per('accounts', account, 'publish_tune', active)
@ -3841,52 +3759,14 @@ class RosterWindow:
def on_new_chat_menuitem_activate(self, widget, account):
dialogs.NewChatDialog(account)
def on_contents_menuitem_activate(self, widget):
helpers.launch_browser_mailer('url', 'http://trac.gajim.org/wiki')
def on_faq_menuitem_activate(self, widget):
helpers.launch_browser_mailer('url',
'http://trac.gajim.org/wiki/GajimFaq')
def on_keyboard_shortcuts_menuitem_activate(self, widget):
shortcuts_window.show(self.window)
def on_features_menuitem_activate(self, widget):
features_window.FeaturesWindow()
def on_about_menuitem_activate(self, widget):
dialogs.AboutDialog()
def on_accounts_menuitem_activate(self, widget):
if 'accounts' in gajim.interface.instances:
gajim.interface.instances['accounts'].window.present()
else:
gajim.interface.instances['accounts'] = config.AccountsWindow()
def on_file_transfers_menuitem_activate(self, widget):
if gajim.interface.instances['file_transfers'].window.get_property(
'visible'):
gajim.interface.instances['file_transfers'].window.present()
else:
gajim.interface.instances['file_transfers'].window.show_all()
def on_history_menuitem_activate(self, widget):
if 'logs' in gajim.interface.instances:
gajim.interface.instances['logs'].window.present()
else:
gajim.interface.instances['logs'] = history_window.\
HistoryWindow()
def on_show_transports_menuitem_activate(self, widget):
gajim.config.set('show_transports_group', widget.get_active())
def on_show_transports_action(self, action, param):
gajim.config.set('show_transports_group', param.get_boolean())
action.set_state(param)
self.refilter_shown_roster_items()
def on_manage_bookmarks_menuitem_activate(self, widget):
config.ManageBookmarksWindow()
def on_profile_avatar_menuitem_activate(self, widget, account):
gajim.interface.edit_own_details(account)
def on_execute_command(self, widget, contact, account, resource=None):
"""
Execute command. Full JID needed; if it is other contact, resource is
@ -4216,6 +4096,7 @@ class RosterWindow:
# account = row[Column.ACCOUNT]
# self._last_selected_contact.append((jid, account))
# GLib.idle_add(self.draw_contact, jid, account, True)
def on_service_disco_menuitem_activate(self, widget, account):
server_jid = gajim.config.get_per('accounts', account, 'hostname')
@ -4229,50 +4110,43 @@ class RosterWindow:
except GajimGeneralException:
pass
def on_show_offline_contacts_menuitem_activate(self, widget):
def on_show_offline_contacts_action(self, action, param):
"""
When show offline option is changed: redraw the treeview
"""
gajim.config.set('showoffline', not gajim.config.get('showoffline'))
action.set_state(param)
gajim.config.set('showoffline', param.get_boolean())
self.refilter_shown_roster_items()
w = self.xml.get_object('show_only_active_contacts_menuitem')
if gajim.config.get('showoffline'):
if param.get_boolean():
# We need to filter twice to show groups with no contacts inside
# in the correct expand state
self.refilter_shown_roster_items()
w.set_sensitive(False)
self.window.lookup_action('show-active').set_enabled(False)
else:
w.set_sensitive(True)
self.window.lookup_action('show-active').set_enabled(True)
def on_show_only_active_contacts_menuitem_activate(self, widget):
def on_show_active_contacts_action(self, action, param):
"""
When show only active contact option is changed: redraw the treeview
"""
gajim.config.set('show_only_chat_and_online', not gajim.config.get(
'show_only_chat_and_online'))
action.set_state(param)
gajim.config.set('show_only_chat_and_online', param.get_boolean())
self.refilter_shown_roster_items()
w = self.xml.get_object('show_offline_contacts_menuitem')
if gajim.config.get('show_only_chat_and_online'):
if param.get_boolean():
# We need to filter twice to show groups with no contacts inside
# in the correct expand state
self.refilter_shown_roster_items()
w.set_sensitive(False)
self.window.lookup_action('show-offline').set_enabled(False)
else:
w.set_sensitive(True)
self.window.lookup_action('show-offline').set_enabled(True)
def on_view_menu_activate(self, widget):
self.make_menu()
# Hide the show roster menu if we are not in the right windowing mode.
if self.hpaned.get_child2() is not None:
self.xml.get_object('show_roster_menuitem').show()
else:
self.xml.get_object('show_roster_menuitem').hide()
def on_show_roster_menuitem_toggled(self, widget):
def on_show_roster_action(self, action, param):
# when num controls is 0 this menuitem is hidden, but still need to
# disable keybinding
action.set_state(param)
if self.hpaned.get_child2() is not None:
self.show_roster_vbox(widget.get_active())
self.show_roster_vbox(param.get_boolean())
def on_rfilter_entry_changed(self, widget):
""" When we update the content of the filter """
@ -4337,7 +4211,9 @@ class RosterWindow:
self._readjust_expand_collapse_state()
# If roster was hidden before enable_rfilter was called, hide it back.
self.on_show_roster_menuitem_toggled(self.xml.get_object('show_roster_menuitem'))
state = self.window.lookup_action('show-roster').get_state().get_boolean()
if state is False and self.hpaned.get_child2() is not None:
self.show_roster_vbox(False)
def on_roster_hpaned_notify(self, pane, gparamspec):
"""
@ -5164,276 +5040,6 @@ class RosterWindow:
### FIXME: We really need to make it simpler! 1465 lines are a few to much....
################################################################################
def make_menu(self, force=False):
"""
Create the main window's menus
"""
if not force and not self.actions_menu_needs_rebuild:
return
history_menuitem = self.xml.get_object('history_menuitem')
new_chat_menuitem = self.xml.get_object('new_chat_menuitem')
single_message_menuitem = self.xml.get_object(
'send_single_message_menuitem')
join_gc_menuitem = self.xml.get_object('join_gc_menuitem')
add_new_contact_menuitem = self.xml.get_object(
'add_new_contact_menuitem')
service_disco_menuitem = self.xml.get_object('service_disco_menuitem')
advanced_menuitem = self.xml.get_object('advanced_menuitem')
profile_avatar_menuitem = self.xml.get_object('profile_avatar_menuitem')
# destroy old advanced menus
for m in self.advanced_menus:
m.destroy()
# make it sensitive. it is insensitive only if no accounts are
# *available*
advanced_menuitem.set_sensitive(True)
if self.add_new_contact_handler_id:
add_new_contact_menuitem.handler_disconnect(
self.add_new_contact_handler_id)
self.add_new_contact_handler_id = None
if self.service_disco_handler_id:
service_disco_menuitem.handler_disconnect(
self.service_disco_handler_id)
self.service_disco_handler_id = None
if self.single_message_menuitem_handler_id:
single_message_menuitem.handler_disconnect(
self.single_message_menuitem_handler_id)
self.single_message_menuitem_handler_id = None
if self.profile_avatar_menuitem_handler_id:
profile_avatar_menuitem.handler_disconnect(
self.profile_avatar_menuitem_handler_id)
self.profile_avatar_menuitem_handler_id = None
# remove the existing submenus
add_new_contact_menuitem.set_submenu(None)
service_disco_menuitem.set_submenu(None)
join_gc_menuitem.set_submenu(None)
single_message_menuitem.set_submenu(None)
advanced_menuitem.set_submenu(None)
profile_avatar_menuitem.set_submenu(None)
gc_sub_menu = Gtk.Menu() # gc is always a submenu
join_gc_menuitem.set_submenu(gc_sub_menu)
connected_accounts = gajim.get_number_of_connected_accounts()
connected_accounts_with_private_storage = 0
# items that get shown whether an account is zeroconf or not
accounts_list = sorted(gajim.contacts.get_accounts())
if connected_accounts > 2 or \
(connected_accounts > 1 and not gajim.zeroconf_is_connected()):
# 2 or more "real" (no zeroconf) accounts? make submenus
new_chat_sub_menu = Gtk.Menu()
for account in accounts_list:
if gajim.connections[account].connected <= 1 or \
gajim.config.get_per('accounts', account, 'is_zeroconf'):
# if offline or connecting or zeroconf
continue
# new chat
new_chat_item = Gtk.MenuItem.new_with_label(
_('using account %s') % account)
new_chat_item.set_use_underline(False)
new_chat_sub_menu.append(new_chat_item)
new_chat_item.connect('activate',
self.on_new_chat_menuitem_activate, account)
new_chat_menuitem.set_submenu(new_chat_sub_menu)
new_chat_sub_menu.show_all()
# menu items that don't apply to zeroconf connections
if connected_accounts == 1 or (connected_accounts == 2 and \
gajim.zeroconf_is_connected()):
# only one 'real' (non-zeroconf) account is connected, don't need
# submenus
for account in accounts_list:
if gajim.account_is_connected(account) and \
not gajim.config.get_per('accounts', account, 'is_zeroconf'):
# gc
if gajim.connections[account].private_storage_supported:
connected_accounts_with_private_storage += 1
self.add_bookmarks_list(gc_sub_menu, account)
gc_sub_menu.show_all()
# add
if not self.add_new_contact_handler_id:
self.add_new_contact_handler_id = \
add_new_contact_menuitem.connect(
'activate', self.on_add_new_contact, account)
# disco
if not self.service_disco_handler_id:
self.service_disco_handler_id = service_disco_menuitem.\
connect('activate',
self.on_service_disco_menuitem_activate, account)
# single message
if not self.single_message_menuitem_handler_id:
self.single_message_menuitem_handler_id = \
single_message_menuitem.connect('activate', \
self.on_send_single_message_menuitem_activate, account)
break # No other account connected
else:
# 2 or more 'real' accounts are connected, make submenus
single_message_sub_menu = Gtk.Menu()
add_sub_menu = Gtk.Menu()
disco_sub_menu = Gtk.Menu()
for account in accounts_list:
if gajim.connections[account].connected <= 1 or \
gajim.config.get_per('accounts', account, 'is_zeroconf'):
# skip account if it's offline or connecting or is zeroconf
continue
# single message
single_message_item = Gtk.MenuItem.new_with_label(
_('using account %s') % account)
single_message_item.set_use_underline(False)
single_message_sub_menu.append(single_message_item)
single_message_item.connect('activate',
self.on_send_single_message_menuitem_activate, account)
# join gc
if gajim.connections[account].private_storage_supported:
connected_accounts_with_private_storage += 1
gc_item = Gtk.MenuItem.new_with_label(
_('using account %s') % account)
gc_item.set_use_underline(False)
gc_sub_menu.append(gc_item)
gc_menuitem_menu = Gtk.Menu()
self.add_bookmarks_list(gc_menuitem_menu, account)
gc_item.set_submenu(gc_menuitem_menu)
# add
add_item = Gtk.MenuItem.new_with_label(
_('to %s account') % account)
add_item.set_use_underline(False)
add_sub_menu.append(add_item)
add_item.connect('activate', self.on_add_new_contact, account)
# disco
disco_item = Gtk.MenuItem.new_with_label(
_('using %s account') % account)
disco_item.set_use_underline(False)
disco_sub_menu.append(disco_item)
disco_item.connect('activate',
self.on_service_disco_menuitem_activate, account)
single_message_menuitem.set_submenu(single_message_sub_menu)
single_message_sub_menu.show_all()
gc_sub_menu.show_all()
add_new_contact_menuitem.set_submenu(add_sub_menu)
add_sub_menu.show_all()
service_disco_menuitem.set_submenu(disco_sub_menu)
disco_sub_menu.show_all()
if connected_accounts == 0:
# no connected accounts, make the menuitems insensitive
for item in (new_chat_menuitem, join_gc_menuitem,
add_new_contact_menuitem, service_disco_menuitem,
single_message_menuitem):
item.set_sensitive(False)
else: # we have one or more connected accounts
for item in (new_chat_menuitem, join_gc_menuitem,
add_new_contact_menuitem, service_disco_menuitem,
single_message_menuitem):
item.set_sensitive(True)
# disable some fields if only local account is there
if connected_accounts == 1:
for account in gajim.connections:
if gajim.account_is_connected(account) and \
gajim.connections[account].is_zeroconf:
for item in (new_chat_menuitem, join_gc_menuitem,
add_new_contact_menuitem, service_disco_menuitem,
single_message_menuitem):
item.set_sensitive(False)
# Manage GC bookmarks
newitem = Gtk.SeparatorMenuItem.new() # separator
gc_sub_menu.append(newitem)
newitem = Gtk.MenuItem.new_with_mnemonic(_('_Manage Bookmarks…'))
newitem.connect('activate', self.on_manage_bookmarks_menuitem_activate)
gc_sub_menu.append(newitem)
gc_sub_menu.show_all()
if connected_accounts_with_private_storage == 0:
newitem.set_sensitive(False)
connected_accounts_with_vcard = []
for account in gajim.connections:
if gajim.account_is_connected(account) and \
gajim.connections[account].vcard_supported:
connected_accounts_with_vcard.append(account)
if len(connected_accounts_with_vcard) > 1:
# 2 or more accounts? make submenus
profile_avatar_sub_menu = Gtk.Menu()
for account in connected_accounts_with_vcard:
# profile, avatar
profile_avatar_item = Gtk.MenuItem.new_with_label(
_('of account %s') % account)
profile_avatar_item.set_use_underline(False)
profile_avatar_sub_menu.append(profile_avatar_item)
profile_avatar_item.connect('activate',
self.on_profile_avatar_menuitem_activate, account)
profile_avatar_menuitem.set_submenu(profile_avatar_sub_menu)
profile_avatar_sub_menu.show_all()
elif len(connected_accounts_with_vcard) == 1:
# user has only one account
account = connected_accounts_with_vcard[0]
# profile, avatar
if not self.profile_avatar_menuitem_handler_id:
self.profile_avatar_menuitem_handler_id = \
profile_avatar_menuitem.connect('activate',
self.on_profile_avatar_menuitem_activate, account)
if len(connected_accounts_with_vcard) == 0:
profile_avatar_menuitem.set_sensitive(False)
else:
profile_avatar_menuitem.set_sensitive(True)
# Advanced Actions
if len(gajim.connections) == 0: # user has no accounts
advanced_menuitem.set_sensitive(False)
elif len(gajim.connections) == 1: # we have one acccount
account = list(gajim.connections.keys())[0]
advanced_menuitem_menu = \
self.get_and_connect_advanced_menuitem_menu(account)
self.advanced_menus.append(advanced_menuitem_menu)
self.add_history_manager_menuitem(advanced_menuitem_menu)
advanced_menuitem.set_submenu(advanced_menuitem_menu)
advanced_menuitem_menu.show_all()
else: # user has *more* than one account : build advanced submenus
advanced_sub_menu = Gtk.Menu()
accounts = [] # Put accounts in a list to sort them
for account in gajim.connections:
accounts.append(account)
accounts.sort()
for account in accounts:
advanced_item = Gtk.MenuItem.new_with_label(
_('for account %s') % account)
advanced_item.set_use_underline(False)
advanced_sub_menu.append(advanced_item)
advanced_menuitem_menu = \
self.get_and_connect_advanced_menuitem_menu(account)
self.advanced_menus.append(advanced_menuitem_menu)
advanced_item.set_submenu(advanced_menuitem_menu)
self.add_history_manager_menuitem(advanced_sub_menu)
advanced_menuitem.set_submenu(advanced_sub_menu)
advanced_sub_menu.show_all()
self.actions_menu_needs_rebuild = False
def build_account_menu(self, account):
# we have to create our own set of icons for the menu
# using self.jabber_status_images is poopoo
@ -6032,34 +5638,6 @@ class RosterWindow:
account, bookmark)
gc_sub_menu.append(item)
def set_actions_menu_needs_rebuild(self):
self.actions_menu_needs_rebuild = True
# Just handle new_chat_menuitem to have ctrl+N working even if we don't
# open the menu
new_chat_menuitem = self.xml.get_object('new_chat_menuitem')
ag = Gtk.accel_groups_from_object(self.window)#[0]
if self.new_chat_menuitem_handler_id:
new_chat_menuitem.handler_disconnect(
self.new_chat_menuitem_handler_id)
self.new_chat_menuitem_handler_id = None
new_chat_menuitem.set_submenu(None)
connected_accounts = gajim.get_number_of_connected_accounts()
if connected_accounts == 1 or (connected_accounts == 2 and \
gajim.zeroconf_is_connected()):
# only one 'real' (non-zeroconf) account is connected, don't need
# submenus
accounts_list = sorted(gajim.contacts.get_accounts())
for account in accounts_list:
if gajim.account_is_connected(account) and \
not gajim.config.get_per('accounts', account, 'is_zeroconf'):
if not self.new_chat_menuitem_handler_id:
self.new_chat_menuitem_handler_id = new_chat_menuitem.\
connect('activate',
self.on_new_chat_menuitem_activate, account)
def show_appropriate_context_menu(self, event, iters):
# iters must be all of the same type
model = self.modelfilter
@ -6170,6 +5748,36 @@ class RosterWindow:
tooltip.populate(connected_contacts, account, typ)
return True
def add_actions(self):
action = Gio.SimpleAction.new_stateful(
"show-roster", None,
GLib.Variant.new_boolean(
not self.xml.get_object('roster_vbox2').get_no_show_all()))
action.connect("change-state",
self.on_show_roster_action)
self.window.add_action(action)
action = Gio.SimpleAction.new_stateful(
"show-offline", None,
GLib.Variant.new_boolean(gajim.config.get('showoffline')))
action.connect("change-state",
self.on_show_offline_contacts_action)
self.window.add_action(action)
action = Gio.SimpleAction.new_stateful(
"show-active", None,
GLib.Variant.new_boolean(
gajim.config.get('show_only_chat_and_online')))
action.connect("change-state",
self.on_show_active_contacts_action)
self.window.add_action(action)
action = Gio.SimpleAction.new_stateful(
"show-transports", None,
GLib.Variant.new_boolean(gajim.config.get('show_transports_group')))
action.connect("change-state", self.on_show_transports_action)
self.window.add_action(action)
################################################################################
###
################################################################################
@ -6192,6 +5800,7 @@ class RosterWindow:
self.xml = gtkgui_helpers.get_gtk_builder('roster_window.ui')
self.window = self.xml.get_object('roster_window')
app.add_window(self.window)
self.add_actions()
self.hpaned = self.xml.get_object('roster_hpaned')
gajim.interface.msg_win_mgr = MessageWindowMgr(self.window, self.hpaned)
gajim.interface.msg_win_mgr.connect('window-delete',
@ -6223,7 +5832,6 @@ class RosterWindow:
#FIXME: When list_accel_closures will be wrapped in pygtk
# no need of this variable
self.have_new_chat_accel = False # Is the "Ctrl+N" shown ?
self.set_actions_menu_needs_rebuild()
self.regroup = gajim.config.get('mergeaccounts')
self.clicked_path = None # Used remember on wich row we clicked
if len(gajim.connections) < 2:
@ -6314,24 +5922,15 @@ class RosterWindow:
# selected item and not stay with that item selected
self.previous_status_combobox_active = number_of_menuitem
showOffline = gajim.config.get('showoffline')
showOnlyChatAndOnline = gajim.config.get('show_only_chat_and_online')
# Enable/Disable checkboxes at start
if gajim.config.get('showoffline'):
self.window.lookup_action('show-active').set_enabled(False)
w = self.xml.get_object('show_offline_contacts_menuitem')
w.set_active(showOffline)
if showOnlyChatAndOnline:
w.set_sensitive(False)
if gajim.config.get('show_only_chat_and_online'):
self.window.lookup_action('show-offline').set_enabled(False)
w = self.xml.get_object('show_only_active_contacts_menuitem')
w.set_active(showOnlyChatAndOnline)
if showOffline:
w.set_sensitive(False)
show_transports_group = gajim.config.get('show_transports_group')
self.xml.get_object('show_transports_menuitem').set_active(
show_transports_group)
self.xml.get_object('show_roster_menuitem').set_active(True)
if self.hpaned.get_child2() is None:
self.window.lookup_action('show-roster').set_enabled(False)
# columns
col = Gtk.TreeViewColumn()
@ -6460,11 +6059,6 @@ class RosterWindow:
accel_group.connect(Gdk.KEY_j, Gdk.ModifierType.CONTROL_MASK,
Gtk.AccelFlags.MASK, self.on_ctrl_j)
# Setting CTRL+N to be the shortcut for show Start chat dialog
new_chat_menuitem = self.xml.get_object('new_chat_menuitem')
new_chat_menuitem.add_accelerator('activate', accel_group,
Gdk.KEY_n, Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE)
# Setting CTRL+S to be the shortcut to change status message
accel_group = Gtk.AccelGroup()
keyval, mod = Gtk.accelerator_parse('<Control>s')