Rework Gajim Theming
- Save all Theme settings to .css instead of the config file - Add a gajim-dark.css - Refactor the ThemesWindow
This commit is contained in:
parent
ee3cc9cbab
commit
9d5131b8b4
|
@ -160,9 +160,7 @@ class GajimApplication(Gtk.Application):
|
|||
self.interface.roster.window.present()
|
||||
return
|
||||
from gajim.gui_interface import Interface
|
||||
from gajim import gtkgui_helpers
|
||||
self.interface = Interface()
|
||||
gtkgui_helpers.load_css()
|
||||
self.interface.run(self)
|
||||
self.add_actions()
|
||||
from gajim import gui_menu_builder
|
||||
|
|
|
@ -674,7 +674,6 @@ class ChatControl(ChatControlBase):
|
|||
status_reduced = ''
|
||||
status_escaped = GLib.markup_escape_text(status_reduced)
|
||||
|
||||
font_attrs, font_attrs_small = self.get_font_attrs()
|
||||
st = app.config.get('displayed_chat_state_notifications')
|
||||
cs = contact.chatstate
|
||||
if cs and st in ('composing_only', 'all'):
|
||||
|
@ -685,22 +684,21 @@ class ChatControl(ChatControlBase):
|
|||
else:
|
||||
chatstate = ''
|
||||
|
||||
label_text = '<span %s>%s</span><span %s>%s %s</span>' \
|
||||
% (font_attrs, name, font_attrs_small, acct_info, chatstate)
|
||||
label_text = '<span>%s</span><span size="x-small" weight="light">%s %s</span>' \
|
||||
% (name, acct_info, chatstate)
|
||||
if acct_info:
|
||||
acct_info = i18n.direction_mark + ' ' + acct_info
|
||||
label_tooltip = '%s%s %s' % (name, acct_info, chatstate)
|
||||
else:
|
||||
# weight="heavy" size="x-large"
|
||||
label_text = '<span %s>%s</span><span %s>%s</span>' % \
|
||||
(font_attrs, name, font_attrs_small, acct_info)
|
||||
label_text = '<span>%s</span><span size="x-small" weight="light">%s</span>' % \
|
||||
(name, acct_info)
|
||||
if acct_info:
|
||||
acct_info = i18n.direction_mark + ' ' + acct_info
|
||||
label_tooltip = '%s%s' % (name, acct_info)
|
||||
|
||||
if status_escaped:
|
||||
status_text = self.urlfinder.sub(self.make_href, status_escaped)
|
||||
status_text = '<span %s>%s</span>' % (font_attrs_small, status_text)
|
||||
status_text = '<span size="x-small" weight="light">%s</span>' % status_text
|
||||
self.banner_status_label.set_tooltip_text(status)
|
||||
self.banner_status_label.set_no_show_all(False)
|
||||
self.banner_status_label.show()
|
||||
|
@ -881,7 +879,7 @@ class ChatControl(ChatControlBase):
|
|||
if self.correcting:
|
||||
self.correcting = False
|
||||
gtkgui_helpers.remove_css_class(
|
||||
self.msg_textview, 'msgcorrectingcolor')
|
||||
self.msg_textview, 'gajim-msg-correcting')
|
||||
|
||||
self.print_conversation(obj.message, self.contact.jid, tim=obj.timestamp,
|
||||
encrypted=obj.encrypted, xep0184_id=xep0184_id, xhtml=obj.xhtml,
|
||||
|
|
|
@ -38,6 +38,7 @@ from gi.repository import Gio
|
|||
from gajim import gtkgui_helpers
|
||||
from gajim import message_control
|
||||
from gajim.gtk import NonModalConfirmationDialog
|
||||
from gajim.gtk.util import convert_rgb_to_hex
|
||||
from gajim import notify
|
||||
import re
|
||||
|
||||
|
@ -52,6 +53,7 @@ from gajim.conversation_textview import ConversationTextview
|
|||
from gajim.message_textview import MessageTextView
|
||||
from gajim.common.contacts import GC_Contact
|
||||
from gajim.common.connection_handlers_events import MessageOutgoingEvent
|
||||
from gajim.common.const import StyleAttr
|
||||
|
||||
from gajim.command_system.implementation.middleware import ChatCommandProcessor
|
||||
from gajim.command_system.implementation.middleware import CommandTools
|
||||
|
@ -87,40 +89,13 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
|
|||
keycode_ins = None
|
||||
|
||||
def make_href(self, match):
|
||||
url_color = app.config.get('urlmsgcolor')
|
||||
url_color = app.css_config.get_value('.gajim-url', StyleAttr.COLOR)
|
||||
color = convert_rgb_to_hex(url_color)
|
||||
url = match.group()
|
||||
if not '://' in url:
|
||||
if '://' not in url:
|
||||
url = 'http://' + url
|
||||
return '<a href="%s"><span color="%s">%s</span></a>' % (url,
|
||||
url_color, match.group())
|
||||
|
||||
def get_font_attrs(self):
|
||||
"""
|
||||
Get pango font attributes for banner from theme settings
|
||||
"""
|
||||
theme = app.config.get('roster_theme')
|
||||
bannerfont = app.config.get_per('themes', theme, 'bannerfont')
|
||||
bannerfontattrs = app.config.get_per('themes', theme, 'bannerfontattrs')
|
||||
|
||||
if bannerfont:
|
||||
font = Pango.FontDescription(bannerfont)
|
||||
else:
|
||||
font = Pango.FontDescription('Normal')
|
||||
if bannerfontattrs:
|
||||
# B attribute is set by default
|
||||
if 'B' in bannerfontattrs:
|
||||
font.set_weight(Pango.Weight.HEAVY)
|
||||
if 'I' in bannerfontattrs:
|
||||
font.set_style(Pango.Style.ITALIC)
|
||||
|
||||
font_attrs = 'font_desc="%s"' % font.to_string()
|
||||
|
||||
# in case there is no font specified we use x-large font size
|
||||
if font.get_size() == 0:
|
||||
font_attrs = '%s size="x-large"' % font_attrs
|
||||
font.set_weight(Pango.Weight.NORMAL)
|
||||
font_attrs_small = 'font_desc="%s" size="small"' % font.to_string()
|
||||
return (font_attrs, font_attrs_small)
|
||||
return '<a href="%s"><span foreground="%s">%s</span></a>' % (
|
||||
url, color, match.group())
|
||||
|
||||
def get_nb_unread(self):
|
||||
jid = self.contact.jid
|
||||
|
@ -381,6 +356,8 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
|
|||
self._nec_ping)
|
||||
app.ged.register_event_handler('sec-label-received', ged.GUI1,
|
||||
self._sec_labels_received)
|
||||
app.ged.register_event_handler('style-changed', ged.GUI1,
|
||||
self._style_changed)
|
||||
|
||||
# This is basically a very nasty hack to surpass the inability
|
||||
# to properly use the super, because of the old code.
|
||||
|
@ -557,6 +534,9 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
|
|||
self._nec_our_status)
|
||||
app.ged.remove_event_handler('sec-label-received', ged.GUI1,
|
||||
self._sec_labels_received)
|
||||
app.ged.remove_event_handler('style-changed', ged.GUI1,
|
||||
self._style_changed)
|
||||
|
||||
|
||||
def on_msg_textview_populate_popup(self, textview, menu):
|
||||
"""
|
||||
|
@ -1099,6 +1079,9 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
|
|||
def on_clear_formatting_menuitem_activate(self, widget):
|
||||
self.msg_textview.clear_tags()
|
||||
|
||||
def _style_changed(self, *args):
|
||||
self.update_tags()
|
||||
|
||||
def update_tags(self):
|
||||
self.conv_textview.update_tags()
|
||||
|
||||
|
@ -1365,14 +1348,14 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
|
|||
history[pos - 1].startswith('/') or history[pos - 1].startswith('/me')):
|
||||
self.correcting = True
|
||||
gtkgui_helpers.add_css_class(
|
||||
self.msg_textview, 'msgcorrectingcolor')
|
||||
self.msg_textview, 'gajim-msg-correcting')
|
||||
message = history[pos - 1]
|
||||
msg_buf.set_text(message)
|
||||
return
|
||||
if self.correcting:
|
||||
# We were previously correcting
|
||||
gtkgui_helpers.remove_css_class(
|
||||
self.msg_textview, 'msgcorrectingcolor')
|
||||
self.msg_textview, 'gajim-msg-correcting')
|
||||
self.correcting = False
|
||||
pos += -1 if direction == 'up' else +1
|
||||
if pos == -1:
|
||||
|
|
|
@ -43,6 +43,7 @@ from gajim.common import configpaths
|
|||
from gajim.common import ged as ged_module
|
||||
from gajim.common.contacts import LegacyContactsAPI
|
||||
from gajim.common.events import Events
|
||||
from gajim.common.css_config import CSSConfig
|
||||
|
||||
interface = None # The actual interface (the gtk one for the moment)
|
||||
thread_interface = lambda *args: None # Interface to run a thread and then a callback
|
||||
|
@ -66,6 +67,8 @@ gajimpaths = configpaths.gajimpaths
|
|||
|
||||
RecentGroupchat = namedtuple('RecentGroupchat', ['room', 'server', 'nickname'])
|
||||
|
||||
css_config = None
|
||||
|
||||
os_info = None # used to cache os information
|
||||
|
||||
transport_type = {} # list the type of transport
|
||||
|
@ -625,3 +628,7 @@ def get_app_window(cls, account=None):
|
|||
continue
|
||||
return win
|
||||
return None
|
||||
|
||||
def load_css_config():
|
||||
global css_config
|
||||
css_config = CSSConfig()
|
||||
|
|
|
@ -92,13 +92,6 @@ class Config:
|
|||
'mood_iconset': [ opt_str, DEFAULT_MOOD_ICONSET, '', True ],
|
||||
'activity_iconset': [ opt_str, DEFAULT_ACTIVITY_ICONSET, '', True ],
|
||||
'use_transports_iconsets': [ opt_bool, True, '', True ],
|
||||
'inmsgcolor': [ opt_color, '#a40000', _('Incoming nickname color.'), True ],
|
||||
'outmsgcolor': [ opt_color, '#3465a4', _('Outgoing nickname color.'), True ],
|
||||
'inmsgtxtcolor': [ opt_color, '', _('Incoming text color.'), True ],
|
||||
'outmsgtxtcolor': [ opt_color, '#555753', _('Outgoing text color.'), True ],
|
||||
'statusmsgcolor': [ opt_color, '#4e9a06', _('Status message text color.'), True ],
|
||||
'markedmsgcolor': [ opt_color, '#ff8080', '', True ],
|
||||
'urlmsgcolor': [ opt_color, '#204a87', '', True ],
|
||||
'notif_signin_color': [ opt_color, '#32CD32', _('Contact signed in notification color.') ], # limegreen
|
||||
'notif_signout_color': [ opt_color, '#FF0000', _('Contact signout notification color') ], # red
|
||||
'notif_message_color': [ opt_color, '#1E90FF', _('New message notification color.') ], # dodgerblue
|
||||
|
@ -108,11 +101,6 @@ class Config:
|
|||
'notif_invite_color': [ opt_color, '#D2B48C', _('Groupchat invitation notification color') ], # tan1
|
||||
'notif_status_color': [ opt_color, '#D8BFD8', _('Background color of status changed notification') ], # thistle2
|
||||
'notif_other_color': [ opt_color, '#FFFFFF', _('Other dialogs color.') ], # white
|
||||
'inmsgfont': [ opt_str, '', _('Incoming nickname font.'), True ],
|
||||
'outmsgfont': [ opt_str, '', _('Outgoing nickname font.'), True ],
|
||||
'inmsgtxtfont': [ opt_str, '', _('Incoming text font.'), True ],
|
||||
'outmsgtxtfont': [ opt_str, '', _('Outgoing text font.'), True ],
|
||||
'statusmsgfont': [ opt_str, '', _('Status message text font.'), True ],
|
||||
'collapsed_rows': [ opt_str, '', _('List (space separated) of rows (accounts and groups) that are collapsed.'), True ],
|
||||
'roster_theme': [ opt_str, _('default'), '', True ],
|
||||
'mergeaccounts': [ opt_bool, False, '', True ],
|
||||
|
@ -205,7 +193,6 @@ class Config:
|
|||
'notify_on_file_complete': [opt_bool, True],
|
||||
'file_transfers_port': [opt_int, 28011],
|
||||
'ft_add_hosts_to_send': [opt_str, '', _('Comma separated list of sent hosts, in addition of local interfaces, for File Transfer in case of address translation/port forwarding.')],
|
||||
'conversation_font': [opt_str, ''],
|
||||
'use_kib_mib': [opt_bool, False, _('IEC standard says KiB = 1024 bytes, KB = 1000 bytes.')],
|
||||
'notify_on_all_muc_messages': [opt_bool, False],
|
||||
'trayicon_notification_on_events': [opt_bool, True, _('Notify of events in the notification area.')],
|
||||
|
@ -249,9 +236,6 @@ class Config:
|
|||
'print_status_in_muc': [opt_str, 'none', _('Can be "none", "all" or "in_and_out". If "none", Gajim will no longer print status line in groupchats when a member changes their status and/or their status message. If "all" Gajim will print all status messages. If "in_and_out", Gajim will only print FOO enters/leaves group chat.')],
|
||||
'log_contact_status_changes': [opt_bool, False],
|
||||
'log_xhtml_messages': [opt_bool, False, _('Log XHTML messages instead of plain text messages.')],
|
||||
'just_connected_bg_color': [opt_str, '#adc3c6', _('Background color of contacts when they just signed in.')],
|
||||
'just_disconnected_bg_color': [opt_str, '#ab6161', _('Background color of contacts when they just signed out.')],
|
||||
'restored_messages_color': [opt_color, '#555753'],
|
||||
'restored_messages_small': [opt_bool, True, _('If true, restored messages will use a smaller font than the default one.')],
|
||||
'hide_avatar_of_transport': [opt_bool, False, _('Don\'t show avatar for the transport itself.')],
|
||||
'roster_window_skip_taskbar': [opt_bool, False, _('Don\'t show roster in the system taskbar.')],
|
||||
|
@ -438,35 +422,7 @@ class Config:
|
|||
'bosh_http_pipelining': [ opt_bool, False ],
|
||||
'bosh_wait_for_restart_response': [ opt_bool, False ],
|
||||
}, {}),
|
||||
'themes': ({
|
||||
'accounttextcolor': [ opt_color, 'black', '', True ],
|
||||
'accountbgcolor': [ opt_color, 'white', '', True ],
|
||||
'accountfont': [ opt_str, '', '', True ],
|
||||
'accountfontattrs': [ opt_str, 'B', '', True ],
|
||||
'grouptextcolor': [ opt_color, 'black', '', True ],
|
||||
'groupbgcolor': [ opt_color, 'white', '', True ],
|
||||
'groupfont': [ opt_str, '', '', True ],
|
||||
'groupfontattrs': [ opt_str, 'I', '', True ],
|
||||
'contacttextcolor': [ opt_color, 'black', '', True ],
|
||||
'contactbgcolor': [ opt_color, 'white', '', True ],
|
||||
'contactfont': [ opt_str, '', '', True ],
|
||||
'contactfontattrs': [ opt_str, '', '', True ],
|
||||
'bannertextcolor': [ opt_color, 'black', '', True ],
|
||||
'bannerbgcolor': [ opt_color, '', '', True ],
|
||||
'bannerfont': [ opt_str, '', '', True ],
|
||||
'bannerfontattrs': [ opt_str, 'B', '', True ],
|
||||
'msgcorrectingcolor': [opt_color, '#eee8aa'],
|
||||
|
||||
# http://www.pitt.edu/~nisg/cis/web/cgi/rgb.html
|
||||
'state_inactive_color': [ opt_color, 'grey62' ],
|
||||
'state_composing_color': [ opt_color, 'green4' ],
|
||||
'state_paused_color': [ opt_color, 'mediumblue' ],
|
||||
'state_gone_color': [ opt_color, 'grey' ],
|
||||
|
||||
# MUC chat states
|
||||
'state_muc_msg_color': [ opt_color, 'mediumblue' ],
|
||||
'state_muc_directed_msg_color': [ opt_color, 'red2' ],
|
||||
}, {}),
|
||||
'contacts': ({
|
||||
'speller_language': [ opt_str, '', _('Language for which misspelled words will be checked')],
|
||||
}, {}),
|
||||
|
@ -522,29 +478,6 @@ class Config:
|
|||
'muc_message_received': [ False, 'gc_message2.wav', _('Sound to play when any MUC message arrives.') ],
|
||||
}
|
||||
|
||||
themes_default = {
|
||||
# sorted alphanum
|
||||
_('default'): [ '', '', '', 'B', '', '', '', 'I', '', '', '', '', '', '',
|
||||
'', 'B' ],
|
||||
|
||||
_('green'): [ '', '#94aa8c', '', 'B', '#0000ff', '#eff3e7',
|
||||
'', 'I', '#000000', '', '', '', '',
|
||||
'#94aa8c', '', 'B' ],
|
||||
|
||||
_('grocery'): [ '', '#6bbe18', '', 'B', '#12125a', '#ceefad',
|
||||
'', 'I', '#000000', '#efb26b', '', '', '',
|
||||
'#108abd', '', 'B' ],
|
||||
|
||||
_('human'): [ '', '#996442', '', 'B', '#ab5920', '#e3ca94',
|
||||
'', 'I', '#000000', '', '', '', '',
|
||||
'#996442', '', 'B' ],
|
||||
|
||||
_('marine'): [ '', '#918caa', '', 'B', '', '#e9e7f3',
|
||||
'', 'I', '#000000', '', '', '', '',
|
||||
'#918caa', '', 'B' ],
|
||||
|
||||
}
|
||||
|
||||
proxies_default = {
|
||||
_('Tor'): ['socks5', 'localhost', 9050],
|
||||
}
|
||||
|
|
|
@ -128,6 +128,7 @@ class ConfigPaths:
|
|||
|
||||
source_paths = [
|
||||
('DATA', os.path.join(basedir, 'data')),
|
||||
('STYLE', os.path.join(basedir, 'data', 'style')),
|
||||
('GUI', os.path.join(basedir, 'data', 'gui')),
|
||||
('ICONS', os.path.join(basedir, 'data', 'icons')),
|
||||
('HOME', os.path.expanduser('~')),
|
||||
|
@ -214,6 +215,10 @@ class ConfigPaths:
|
|||
# Cache paths
|
||||
('CACHE_DB', 'cache.db', PathLocation.CACHE, PathType.FILE),
|
||||
('AVATAR', 'avatars', PathLocation.CACHE, PathType.FOLDER),
|
||||
|
||||
# Config paths
|
||||
('MY_THEME', 'theme', PathLocation.CONFIG, PathType.FOLDER),
|
||||
|
||||
]
|
||||
|
||||
for path in paths:
|
||||
|
|
|
@ -1378,3 +1378,11 @@ class InformationEvent(nec.NetworkIncomingEvent):
|
|||
else:
|
||||
self.args = (self.args,)
|
||||
return True
|
||||
|
||||
|
||||
class StyleChanged(nec.NetworkIncomingEvent):
|
||||
name = 'style-changed'
|
||||
base_network_events = []
|
||||
|
||||
def generate(self):
|
||||
return True
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
from enum import IntEnum, unique
|
||||
from enum import IntEnum, Enum, unique
|
||||
from collections import namedtuple
|
||||
|
||||
Option = namedtuple('Option', 'kind label type value name callback data desc enabledif props')
|
||||
Option.__new__.__defaults__ = (None,) * len(Option._fields)
|
||||
|
||||
DialogButton = namedtuple('DialogButton', 'text callback action')
|
||||
DialogButton.__new__.__defaults__ = (None, None)
|
||||
|
||||
|
||||
@unique
|
||||
class OptionKind(IntEnum):
|
||||
|
@ -117,6 +120,24 @@ class JIDConstant(IntEnum):
|
|||
NORMAL_TYPE = 0
|
||||
ROOM_TYPE = 1
|
||||
|
||||
@unique
|
||||
class StyleAttr(Enum):
|
||||
COLOR = 'color'
|
||||
BACKGROUND = 'background'
|
||||
FONT = 'font'
|
||||
|
||||
@unique
|
||||
class CSSPriority(IntEnum):
|
||||
APPLICATION = 600
|
||||
APPLICATION_DARK = 601
|
||||
DEFAULT_THEME = 610
|
||||
DEFAULT_THEME_DARK = 611
|
||||
USER_THEME = 650
|
||||
|
||||
@unique
|
||||
class ButtonAction(Enum):
|
||||
DESTRUCTIVE = 'destructive-action'
|
||||
SUGGESTED = 'suggested-action'
|
||||
|
||||
@unique
|
||||
class IdleState(IntEnum):
|
||||
|
|
|
@ -0,0 +1,492 @@
|
|||
# Copyright (C) 2018 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, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
import os
|
||||
import math
|
||||
import logging
|
||||
|
||||
import cssutils
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import Pango
|
||||
|
||||
from gajim.common import app
|
||||
from gajim.common import configpaths
|
||||
from gajim.common.const import StyleAttr, CSSPriority
|
||||
|
||||
log = logging.getLogger('gajim.c.css')
|
||||
|
||||
_settings = Gtk.Settings.get_default()
|
||||
PREFER_DARK = False
|
||||
if _settings is not None:
|
||||
PREFER_DARK = _settings.get_property('gtk-application-prefer-dark-theme')
|
||||
|
||||
|
||||
class CSSConfig():
|
||||
def __init__(self):
|
||||
"""CSSConfig handles loading and storing of all relevant Gajim style files
|
||||
|
||||
The order in which CSSConfig loads the styles
|
||||
|
||||
1. gajim.css
|
||||
2. gajim-dark.css (Only if gtk-application-prefer-dark-theme = True)
|
||||
3. default.css or default-dark.css (from gajim/data/style)
|
||||
4. user-theme.css (from ~/.config/Gajim/theme)
|
||||
|
||||
# gajim.css:
|
||||
|
||||
This is the main style and the application default
|
||||
|
||||
# gajim-dark.css
|
||||
|
||||
Has only entrys which we want to override in gajim.css
|
||||
|
||||
# default.css or default-dark.css
|
||||
|
||||
Has all the values that are changeable via UI (see themes.py).
|
||||
Depending on `gtk-application-prefer-dark-theme` either default.css or
|
||||
default-dark.css gets loaded
|
||||
|
||||
# user-theme.css
|
||||
|
||||
These are the themes the Themes Dialog stores. Because they are
|
||||
loaded at last they overwrite everything else. Users should add custom
|
||||
css here."""
|
||||
|
||||
# Delete empty rules
|
||||
cssutils.ser.prefs.keepEmptyRules = False
|
||||
|
||||
# Holds the currently selected theme in the Theme Editor
|
||||
self._pre_css = None
|
||||
self._pre_css_path = None
|
||||
|
||||
# Holds the default theme, its used if values are not found
|
||||
# in the selected theme
|
||||
self._default_css = None
|
||||
self._default_css_path = None
|
||||
|
||||
# Holds the currently selected theme
|
||||
self._css = None
|
||||
self._css_path = None
|
||||
|
||||
# User Theme CSS Provider
|
||||
self._provider = Gtk.CssProvider()
|
||||
|
||||
# Cache of recently requested values
|
||||
self._cache = {}
|
||||
|
||||
# Holds all currently available themes
|
||||
self.themes = []
|
||||
|
||||
self._load_css()
|
||||
self._gather_available_themes()
|
||||
self._load_default()
|
||||
self._load_selected()
|
||||
self._activate_theme()
|
||||
Gtk.StyleContext.add_provider_for_screen(
|
||||
Gdk.Screen.get_default(),
|
||||
self._provider,
|
||||
CSSPriority.USER_THEME)
|
||||
|
||||
def _load_css(self):
|
||||
self._load_css_from_file('gajim.css', CSSPriority.APPLICATION)
|
||||
if PREFER_DARK:
|
||||
self._load_css_from_file('gajim-dark.css',
|
||||
CSSPriority.APPLICATION_DARK)
|
||||
|
||||
self._load_css_from_file('default.css', CSSPriority.DEFAULT_THEME)
|
||||
if PREFER_DARK:
|
||||
self._load_css_from_file('default-dark.css',
|
||||
CSSPriority.DEFAULT_THEME_DARK)
|
||||
|
||||
def _load_css_from_file(self, filename, priority):
|
||||
path = os.path.join(configpaths.get('STYLE'), filename)
|
||||
try:
|
||||
with open(path, "r") as f:
|
||||
css = f.read()
|
||||
except Exception as exc:
|
||||
log.error('Error loading css: %s', exc)
|
||||
return
|
||||
self._activate_css(css, priority)
|
||||
|
||||
def _activate_css(self, css, priority):
|
||||
try:
|
||||
provider = Gtk.CssProvider()
|
||||
provider.load_from_data(bytes(css.encode('utf-8')))
|
||||
Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
|
||||
provider,
|
||||
priority)
|
||||
except Exception:
|
||||
log.exception('Error loading application css')
|
||||
|
||||
@staticmethod
|
||||
def _pango_to_css_weight(number):
|
||||
# Pango allows for weight values between 100 and 1000
|
||||
# CSS allows only full hundred numbers like 100, 200 ..
|
||||
number = int(number)
|
||||
if number < 100:
|
||||
return 100
|
||||
if number > 900:
|
||||
return 900
|
||||
return int(math.ceil(number / 100.0)) * 100
|
||||
|
||||
def _gather_available_themes(self):
|
||||
files = os.listdir(configpaths.get('MY_THEME'))
|
||||
self.themes = [file[:-4] for file in files if file.endswith('.css')]
|
||||
if 'default' in self.themes:
|
||||
# Ignore user created themes that are named 'default'
|
||||
self.themes.remove('default')
|
||||
|
||||
@classmethod
|
||||
def get_theme_path(cls, theme, user=True):
|
||||
if theme == 'default' and PREFER_DARK:
|
||||
theme = 'default-dark'
|
||||
|
||||
if user:
|
||||
return os.path.join(configpaths.get('MY_THEME'), '%s.css' % theme)
|
||||
return os.path.join(configpaths.get('STYLE'), '%s.css' % theme)
|
||||
|
||||
def _determine_theme_path(self):
|
||||
# Gets the path of the currently active theme.
|
||||
# If it does not exist, it falls back to the default theme
|
||||
theme = app.config.get('roster_theme')
|
||||
if theme == 'default':
|
||||
return self.get_theme_path(theme, user=False)
|
||||
|
||||
theme_path = self.get_theme_path(theme)
|
||||
if not theme or not os.path.exists(theme_path):
|
||||
log.warning('Theme %s not found, fallback to default', theme)
|
||||
app.config.set('roster_theme', 'default')
|
||||
log.info('Use Theme: default')
|
||||
return self.get_theme_path('default', user=False)
|
||||
log.info('Use Theme: %s', theme)
|
||||
return theme_path
|
||||
|
||||
def _load_selected(self, new_path=None):
|
||||
if new_path is None:
|
||||
self._css_path = self._determine_theme_path()
|
||||
else:
|
||||
self._css_path = new_path
|
||||
self._css = cssutils.parseFile(self._css_path)
|
||||
|
||||
def _load_default(self):
|
||||
self._default_css_path = self.get_theme_path('default', user=False)
|
||||
self._default_css = cssutils.parseFile(self._default_css_path)
|
||||
|
||||
def _load_pre(self, theme):
|
||||
log.info('Preload theme %s', theme)
|
||||
self._pre_css_path = self.get_theme_path(theme)
|
||||
self._pre_css = cssutils.parseFile(self._pre_css_path)
|
||||
|
||||
def _write(self, pre):
|
||||
path = self._css_path
|
||||
css = self._css
|
||||
if pre:
|
||||
path = self._pre_css_path
|
||||
css = self._pre_css
|
||||
with open(path, 'w', encoding='utf-8') as file:
|
||||
file.write(css.cssText.decode('utf-8'))
|
||||
|
||||
active = self._pre_css_path == self._css_path
|
||||
if not pre or active:
|
||||
self._load_selected()
|
||||
self._activate_theme()
|
||||
|
||||
def set_value(self, selector, attr, value, pre=False):
|
||||
if attr == StyleAttr.FONT:
|
||||
# forward to set_font() for convenience
|
||||
return self.set_font(selector, value, pre)
|
||||
|
||||
if isinstance(attr, StyleAttr):
|
||||
attr = attr.value
|
||||
|
||||
css = self._css
|
||||
if pre:
|
||||
css = self._pre_css
|
||||
for rule in css:
|
||||
if rule.type != rule.STYLE_RULE:
|
||||
continue
|
||||
if rule.selectorText == selector:
|
||||
log.info('Set %s %s %s', selector, attr, value)
|
||||
rule.style[attr] = value
|
||||
if not pre:
|
||||
self._add_to_cache(selector, attr, value)
|
||||
self._write(pre)
|
||||
return
|
||||
|
||||
# The rule was not found, so we add it to this theme
|
||||
log.info('Set %s %s %s', selector, attr, value)
|
||||
rule = cssutils.css.CSSStyleRule(selectorText=selector)
|
||||
rule.style[attr] = value
|
||||
css.add(rule)
|
||||
self._write(pre)
|
||||
|
||||
def set_font(self, selector, description, pre=False):
|
||||
css = self._css
|
||||
if pre:
|
||||
css = self._pre_css
|
||||
family, size, style, weight = self._get_attr_from_description(
|
||||
description)
|
||||
for rule in css:
|
||||
if rule.type != rule.STYLE_RULE:
|
||||
continue
|
||||
if rule.selectorText == selector:
|
||||
log.info('Set Font for: %s %s %s %s %s',
|
||||
selector, family, size, style, weight)
|
||||
rule.style['font-family'] = family
|
||||
rule.style['font-style'] = style
|
||||
rule.style['font-size'] = '%spt' % size
|
||||
rule.style['font-weight'] = weight
|
||||
|
||||
if not pre:
|
||||
self._add_to_cache(
|
||||
selector, 'fontdescription', description)
|
||||
self._write(pre)
|
||||
return
|
||||
|
||||
# The rule was not found, so we add it to this theme
|
||||
log.info('Set Font for: %s %s %s %s %s',
|
||||
selector, family, size, style, weight)
|
||||
rule = cssutils.css.CSSStyleRule(selectorText=selector)
|
||||
rule.style['font-family'] = family
|
||||
rule.style['font-style'] = style
|
||||
rule.style['font-size'] = '%spt' % size
|
||||
rule.style['font-weight'] = weight
|
||||
css.add(rule)
|
||||
self._write(pre)
|
||||
|
||||
def _get_attr_from_description(self, description):
|
||||
size = description.get_size() / Pango.SCALE
|
||||
style = self._get_string_from_pango_style(description.get_style())
|
||||
weight = self._pango_to_css_weight(int(description.get_weight()))
|
||||
family = description.get_family()
|
||||
return family, size, style, weight
|
||||
|
||||
def _get_default_rule(self, selector, attr):
|
||||
for rule in self._default_css:
|
||||
if rule.type != rule.STYLE_RULE:
|
||||
continue
|
||||
if rule.selectorText == selector:
|
||||
log.info('Get Default Rule %s', selector)
|
||||
return rule
|
||||
|
||||
def get_font(self, selector, pre=False):
|
||||
if pre:
|
||||
css = self._pre_css
|
||||
else:
|
||||
css = self._css
|
||||
try:
|
||||
return self._get_from_cache(selector, 'fontdescription')
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
if css is None:
|
||||
return
|
||||
|
||||
for rule in css:
|
||||
if rule.type != rule.STYLE_RULE:
|
||||
continue
|
||||
if rule.selectorText == selector:
|
||||
log.info('Get Font for: %s', selector)
|
||||
style = rule.style.getPropertyValue('font-style') or None
|
||||
size = rule.style.getPropertyValue('font-size') or None
|
||||
weight = rule.style.getPropertyValue('font-weight') or None
|
||||
family = rule.style.getPropertyValue('font-family') or None
|
||||
|
||||
desc = self._get_description_from_css(
|
||||
family, size, style, weight)
|
||||
if not pre:
|
||||
self._add_to_cache(selector, 'fontdescription', desc)
|
||||
return desc
|
||||
|
||||
def _get_description_from_css(self, family, size, style, weight):
|
||||
if family is None:
|
||||
return
|
||||
desc = Pango.FontDescription()
|
||||
desc.set_family(family)
|
||||
if weight is not None:
|
||||
desc.set_weight(Pango.Weight(int(weight)))
|
||||
if style is not None:
|
||||
desc.set_style(self._get_pango_style_from_string(style))
|
||||
if size is not None:
|
||||
desc.set_size(int(size[:-2]) * Pango.SCALE)
|
||||
return desc
|
||||
|
||||
@staticmethod
|
||||
def _get_pango_style_from_string(style: str) -> int:
|
||||
if style == 'normal':
|
||||
return Pango.Style(0)
|
||||
if style == 'oblique':
|
||||
return Pango.Style(1)
|
||||
# Pango.Style.ITALIC:
|
||||
return Pango.Style(2)
|
||||
|
||||
@staticmethod
|
||||
def _get_string_from_pango_style(style: Pango.Style) -> str:
|
||||
if style == Pango.Style.NORMAL:
|
||||
return 'normal'
|
||||
if style == Pango.Style.ITALIC:
|
||||
return 'italic'
|
||||
# Pango.Style.OBLIQUE:
|
||||
return 'oblique'
|
||||
|
||||
def get_value(self, selector, attr, pre=False):
|
||||
if attr == StyleAttr.FONT:
|
||||
# forward to get_font() for convenience
|
||||
return self.get_font(selector, pre)
|
||||
|
||||
if isinstance(attr, StyleAttr):
|
||||
attr = attr.value
|
||||
|
||||
if pre:
|
||||
css = self._pre_css
|
||||
else:
|
||||
css = self._css
|
||||
try:
|
||||
return self._get_from_cache(selector, attr)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
if css is not None:
|
||||
for rule in css:
|
||||
if rule.type != rule.STYLE_RULE:
|
||||
continue
|
||||
if rule.selectorText == selector:
|
||||
log.info('Get %s %s: %s',
|
||||
selector, attr, rule.style[attr] or None)
|
||||
value = rule.style.getPropertyValue(attr) or None
|
||||
if not pre:
|
||||
self._add_to_cache(selector, attr, value)
|
||||
return value
|
||||
|
||||
# We didnt find the selector in the selected theme
|
||||
# search in default theme
|
||||
if not pre:
|
||||
rule = self._get_default_rule(selector, attr)
|
||||
if rule is not None:
|
||||
self._add_to_cache(selector, attr, rule.style[attr])
|
||||
return rule.style[attr]
|
||||
|
||||
def remove_value(self, selector, attr, pre=False):
|
||||
if attr == StyleAttr.FONT:
|
||||
# forward to remove_font() for convenience
|
||||
return self.remove_font(selector, pre)
|
||||
|
||||
if isinstance(attr, StyleAttr):
|
||||
attr = attr.value
|
||||
|
||||
css = self._css
|
||||
if pre:
|
||||
css = self._pre_css
|
||||
for rule in css:
|
||||
if rule.type != rule.STYLE_RULE:
|
||||
continue
|
||||
if rule.selectorText == selector:
|
||||
log.info('Remove %s %s', selector, attr)
|
||||
rule.style.removeProperty(attr)
|
||||
break
|
||||
self._write(pre)
|
||||
|
||||
def remove_font(self, selector, pre=False):
|
||||
css = self._css
|
||||
if pre:
|
||||
css = self._pre_css
|
||||
|
||||
for rule in css:
|
||||
if rule.type != rule.STYLE_RULE:
|
||||
continue
|
||||
if rule.selectorText == selector:
|
||||
log.info('Remove Font from: %s', selector)
|
||||
rule.style.removeProperty('font-family')
|
||||
rule.style.removeProperty('font-size')
|
||||
rule.style.removeProperty('font-style')
|
||||
rule.style.removeProperty('font-weight')
|
||||
break
|
||||
self._write(pre)
|
||||
|
||||
def change_theme(self, theme):
|
||||
user = not theme == 'default'
|
||||
theme_path = self.get_theme_path(theme, user=user)
|
||||
if not os.path.exists(theme_path):
|
||||
log.error('Change Theme: Theme %s does not exist', theme_path)
|
||||
return False
|
||||
self._load_selected(theme_path)
|
||||
self._activate_theme()
|
||||
app.config.set('roster_theme', theme)
|
||||
log.info('Change Theme: Successful switched to %s', theme)
|
||||
return True
|
||||
|
||||
def change_preload_theme(self, theme):
|
||||
theme_path = self.get_theme_path(theme)
|
||||
if not os.path.exists(theme_path):
|
||||
log.error('Change Preload Theme: Theme %s does not exist',
|
||||
theme_path)
|
||||
return False
|
||||
self._load_pre(theme)
|
||||
log.info('Successful switched to %s', theme)
|
||||
return True
|
||||
|
||||
def rename_theme(self, old_theme, new_theme):
|
||||
if old_theme not in self.themes:
|
||||
log.error('Rename Theme: Old theme %s not found', old_theme)
|
||||
return False
|
||||
|
||||
if new_theme in self.themes:
|
||||
log.error('Rename Theme: New theme %s exists already', new_theme)
|
||||
return False
|
||||
|
||||
old_theme_path = self.get_theme_path(old_theme)
|
||||
new_theme_path = self.get_theme_path(new_theme)
|
||||
os.rename(old_theme_path, new_theme_path)
|
||||
self.themes.remove(old_theme)
|
||||
self.themes.append(new_theme)
|
||||
self._load_pre(new_theme)
|
||||
log.info('Rename Theme: Successful renamed theme from %s to %s',
|
||||
old_theme, new_theme)
|
||||
return True
|
||||
|
||||
def _activate_theme(self):
|
||||
log.info('Activate theme')
|
||||
self._invalidate_cache()
|
||||
self._provider.load_from_data(self._css.cssText)
|
||||
|
||||
def add_new_theme(self, theme):
|
||||
theme_path = self.get_theme_path(theme)
|
||||
if os.path.exists(theme_path):
|
||||
log.error('Add Theme: %s exists already', theme_path)
|
||||
return False
|
||||
with open(theme_path, 'w', encoding='utf8'):
|
||||
pass
|
||||
self.themes.append(theme)
|
||||
log.info('Add Theme: Successful added theme %s', theme)
|
||||
return True
|
||||
|
||||
def remove_theme(self, theme):
|
||||
theme_path = self.get_theme_path(theme)
|
||||
if os.path.exists(theme_path):
|
||||
os.remove(theme_path)
|
||||
self.themes.remove(theme)
|
||||
log.info('Remove Theme: Successful removed theme %s', theme)
|
||||
|
||||
def _add_to_cache(self, selector, attr, value):
|
||||
self._cache[selector + attr] = value
|
||||
|
||||
def _get_from_cache(self, selector, attr):
|
||||
return self._cache[selector + attr]
|
||||
|
||||
def _invalidate_cache(self):
|
||||
self._cache = {}
|
|
@ -49,6 +49,7 @@ from gajim.common import i18n
|
|||
from calendar import timegm
|
||||
from gajim.common.fuzzyclock import FuzzyClock
|
||||
from gajim import emoticons
|
||||
from gajim.common.const import StyleAttr
|
||||
|
||||
from gajim.htmltextview import HtmlTextView
|
||||
|
||||
|
@ -216,42 +217,47 @@ class ConversationTextview(GObject.GObject):
|
|||
self.last_time_printout = 0
|
||||
|
||||
style = self.tv.get_style_context()
|
||||
style.add_class('font_custom')
|
||||
style.add_class('gajim-conversation-font')
|
||||
buffer_ = self.tv.get_buffer()
|
||||
end_iter = buffer_.get_end_iter()
|
||||
buffer_.create_mark('end', end_iter, False)
|
||||
|
||||
self.tagIn = buffer_.create_tag('incoming')
|
||||
color = app.config.get('inmsgcolor')
|
||||
font = Pango.FontDescription(app.config.get('inmsgfont'))
|
||||
color = app.css_config.get_value(
|
||||
'.gajim-incoming-nickname', StyleAttr.COLOR)
|
||||
self.tagIn.set_property('foreground', color)
|
||||
self.tagIn.set_property('font-desc', font)
|
||||
desc = app.css_config.get_font('.gajim-incoming-nickname')
|
||||
self.tagIn.set_property('font-desc', desc)
|
||||
|
||||
self.tagOut = buffer_.create_tag('outgoing')
|
||||
color = app.config.get('outmsgcolor')
|
||||
font = Pango.FontDescription(app.config.get('outmsgfont'))
|
||||
color = app.css_config.get_value(
|
||||
'.gajim-outgoing-nickname', StyleAttr.COLOR)
|
||||
self.tagOut.set_property('foreground', color)
|
||||
self.tagOut.set_property('font-desc', font)
|
||||
desc = app.css_config.get_font('.gajim-outgoing-nickname')
|
||||
self.tagOut.set_property('font-desc', desc)
|
||||
|
||||
self.tagStatus = buffer_.create_tag('status')
|
||||
color = app.config.get('statusmsgcolor')
|
||||
font = Pango.FontDescription(app.config.get('satusmsgfont'))
|
||||
color = app.css_config.get_value(
|
||||
'.gajim-status-message', StyleAttr.COLOR)
|
||||
self.tagStatus.set_property('foreground', color)
|
||||
self.tagStatus.set_property('font-desc', font)
|
||||
desc = app.css_config.get_font('.gajim-status-message')
|
||||
self.tagStatus.set_property('font-desc', desc)
|
||||
|
||||
self.tagInText = buffer_.create_tag('incomingtxt')
|
||||
color = app.config.get('inmsgtxtcolor')
|
||||
font = Pango.FontDescription(app.config.get('inmsgtxtfont'))
|
||||
color = app.css_config.get_value(
|
||||
'.gajim-incoming-message-text', StyleAttr.COLOR)
|
||||
if color:
|
||||
self.tagInText.set_property('foreground', color)
|
||||
self.tagInText.set_property('font-desc', font)
|
||||
desc = app.css_config.get_font('.gajim-incoming-message-text')
|
||||
self.tagInText.set_property('font-desc', desc)
|
||||
|
||||
self.tagOutText = buffer_.create_tag('outgoingtxt')
|
||||
color = app.config.get('outmsgtxtcolor')
|
||||
color = app.css_config.get_value(
|
||||
'.gajim-outgoing-message-text', StyleAttr.COLOR)
|
||||
if color:
|
||||
font = Pango.FontDescription(app.config.get('outmsgtxtfont'))
|
||||
self.tagOutText.set_property('foreground', color)
|
||||
self.tagOutText.set_property('font-desc', font)
|
||||
self.tagOutText.set_property('foreground', color)
|
||||
desc = app.css_config.get_font('.gajim-outgoing-message-text')
|
||||
self.tagOutText.set_property('font-desc', desc)
|
||||
|
||||
colors = app.config.get('gc_nicknames_colors')
|
||||
colors = colors.split(':')
|
||||
|
@ -261,7 +267,8 @@ class ConversationTextview(GObject.GObject):
|
|||
tag.set_property('foreground', color)
|
||||
|
||||
self.tagMarked = buffer_.create_tag('marked')
|
||||
color = app.config.get('markedmsgcolor')
|
||||
color = app.css_config.get_value(
|
||||
'.gajim-highlight-message', StyleAttr.COLOR)
|
||||
self.tagMarked.set_property('foreground', color)
|
||||
self.tagMarked.set_property('weight', Pango.Weight.BOLD)
|
||||
|
||||
|
@ -276,7 +283,7 @@ class ConversationTextview(GObject.GObject):
|
|||
tag.set_property('scale', 0.8333333333333)
|
||||
|
||||
tag = buffer_.create_tag('restored_message')
|
||||
color = app.config.get('restored_messages_color')
|
||||
color = app.css_config.get_value('.gajim-restored-message', StyleAttr.COLOR)
|
||||
tag.set_property('foreground', color)
|
||||
|
||||
self.tv.create_tags()
|
||||
|
@ -355,13 +362,13 @@ class ConversationTextview(GObject.GObject):
|
|||
self.tv.destroy()
|
||||
|
||||
def update_tags(self):
|
||||
self.tagIn.set_property('foreground', app.config.get('inmsgcolor'))
|
||||
self.tagOut.set_property('foreground', app.config.get('outmsgcolor'))
|
||||
self.tagIn.set_property('foreground', app.css_config.get_value('.gajim-incoming-nickname', StyleAttr.COLOR))
|
||||
self.tagOut.set_property('foreground', app.css_config.get_value('.gajim-outgoing-nickname', StyleAttr.COLOR))
|
||||
self.tagStatus.set_property('foreground',
|
||||
app.config.get('statusmsgcolor'))
|
||||
app.css_config.get_value('.gajim-status-message', StyleAttr.COLOR))
|
||||
self.tagMarked.set_property('foreground',
|
||||
app.config.get('markedmsgcolor'))
|
||||
color = app.config.get('urlmsgcolor')
|
||||
app.css_config.get_value('.gajim-highlight-message', StyleAttr.COLOR))
|
||||
color = app.css_config.get_value('.gajim-url', StyleAttr.COLOR)
|
||||
self.tv.tagURL.set_property('foreground', color)
|
||||
self.tv.tagMail.set_property('foreground', color)
|
||||
self.tv.tagXMPP.set_property('foreground', color)
|
||||
|
|
|
@ -567,6 +567,9 @@
|
|||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="gajim-banner"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
|
|
|
@ -1,565 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.18.3 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.12"/>
|
||||
<object class="GtkListStore" id="liststore1">
|
||||
<columns>
|
||||
<!-- column-name item -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
<data>
|
||||
<row>
|
||||
<col id="0" translatable="yes">Account row</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">Group row</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">Contact row</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">Chat Banner</col>
|
||||
</row>
|
||||
</data>
|
||||
</object>
|
||||
<object class="GtkWindow" id="gajim_themes_window">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">12</property>
|
||||
<property name="title" translatable="yes">Gajim Themes Customization</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="window_position">center-on-parent</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="vbox97">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox2979">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">6</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="vbox98">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="themes_scrolledwindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="themes_treeview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="treeview-selection1"/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButtonBox" id="hbuttonbox27">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="layout_style">center</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="add_button">
|
||||
<property name="label">gtk-add</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="on_add_button_clicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="remove_button">
|
||||
<property name="label">gtk-remove</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="on_remove_button_clicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="theme_options_vbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="options_combobox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="model">liststore1</property>
|
||||
<signal name="changed" handler="on_options_combobox_changed" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="cellrenderertext1"/>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="column_spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="textcolor_checkbutton">
|
||||
<property name="label" translatable="yes">Text _color:</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="on_textcolor_checkbutton_toggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="background_checkbutton">
|
||||
<property name="label" translatable="yes">_Background:</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="on_background_checkbutton_toggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="textfont_checkbutton">
|
||||
<property name="label" translatable="yes">Text _font:</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="on_textfont_checkbutton_toggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label334">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Font style:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColorButton" id="text_colorbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<signal name="color-set" handler="on_text_colorbutton_color_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColorButton" id="background_colorbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<signal name="color-set" handler="on_background_colorbutton_color_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFontButton" id="text_fontbutton">
|
||||
<property name="width_request">15</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="font">Sans 12</property>
|
||||
<property name="show_style">False</property>
|
||||
<signal name="font-set" handler="on_text_fontbutton_font_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="bold_togglebutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Bold</property>
|
||||
<signal name="toggled" handler="on_bold_togglebutton_toggled" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage" id="image28">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-bold</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="italic_togglebutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Italic</property>
|
||||
<signal name="toggled" handler="on_italic_togglebutton_toggled" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage" id="image29">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-italic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDrawingArea" id="drawingarea12">
|
||||
<property name="height_request">12</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator" id="vseparator7">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="theme_options_table">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="column_spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkSeparator" id="hseparator16">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label389">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Inactive</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label390">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Composing</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label391">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Paused</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label394">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Gone</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label392">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">MUC
|
||||
Messages</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label395">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">MUC Directed
|
||||
Messages</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColorButton" id="muc_directed_msg_colorbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<signal name="color-set" handler="on_muc_directed_msg_colorbutton_color_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColorButton" id="muc_msg_colorbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<signal name="color-set" handler="on_muc_msg_colorbutton_color_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColorButton" id="gone_colorbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<signal name="color-set" handler="on_gone_colorbutton_color_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColorButton" id="paused_colorbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<signal name="color-set" handler="on_paused_colorbutton_color_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColorButton" id="composing_colorbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<signal name="color-set" handler="on_composing_colorbutton_color_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColorButton" id="inactive_colorbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<signal name="color-set" handler="on_inactive_colorbutton_color_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label393">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="ypad">5</property>
|
||||
<property name="label" translatable="yes"><b>Chatstate Tab Colors</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButtonBox" id="hbuttonbox28">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">6</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="close_button">
|
||||
<property name="label">gtk-close</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="on_close_button_clicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
|
@ -159,6 +159,9 @@
|
|||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="gajim-banner"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
|
|
|
@ -1509,86 +1509,6 @@ $T will be replaced by auto-not-available timeout</property>
|
|||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkFrame" id="frame9">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid9">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_top">6</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="column_spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label4">
|
||||
<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="halign">end</property>
|
||||
<property name="label" translatable="yes">Chat message</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="ellipsize">start</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFontButton" id="conversation_fontbutton">
|
||||
<property name="width_request">200</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="font">Sans 12</property>
|
||||
<signal name="font-set" handler="on_conversation_fontbutton_font_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="default_chat_font">
|
||||
<property name="label" translatable="yes">Use system _default</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="on_default_chat_font_toggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="label23">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes"><b>Font</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFrame" id="frame3">
|
||||
|
@ -1658,11 +1578,10 @@ $T will be replaced by auto-not-available timeout</property>
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="theme_combobox">
|
||||
<object class="GtkComboBoxText" id="theme_combobox">
|
||||
<property name="width_request">200</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<signal name="changed" handler="on_theme_combobox_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
|
@ -1721,423 +1640,6 @@ $T will be replaced by auto-not-available timeout</property>
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFrame" id="frame24">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid11">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_top">6</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="column_spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label72">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Contact's nickname</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="justify">center</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label13">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Contact's message</property>
|
||||
<property name="justify">right</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label71">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">_Status message</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="justify">center</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label30">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Group chat highlight</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="justify">right</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox8">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="incoming_msg_checkbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="on_incoming_msg_checkbutton_toggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColorButton" id="incoming_msg_colorbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="rgba">rgb(0,0,0)</property>
|
||||
<signal name="color-set" handler="on_incoming_msg_colorbutton_color_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox11">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkColorButton" id="status_msg_colorbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="rgba">rgb(0,0,0)</property>
|
||||
<signal name="color-set" handler="on_status_msg_colorbutton_color_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox10">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColorButton" id="incoming_nick_colorbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="rgba">rgb(0,0,0)</property>
|
||||
<signal name="color-set" handler="on_incoming_nick_colorbutton_color_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColorButton" id="muc_highlight_colorbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="rgba">rgb(0,0,0)</property>
|
||||
<signal name="color-set" handler="on_muc_highlight_colorbutton_color_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label70">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Your nickname</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="justify">center</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">3</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label14">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Your message</property>
|
||||
<property name="justify">right</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label371">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">_URL highlight</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="justify">right</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">3</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox12">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColorButton" id="outgoing_nick_colorbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="rgba">rgb(0,0,0)</property>
|
||||
<signal name="color-set" handler="on_outgoing_nick_colorbutton_color_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">4</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox9">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="outgoing_msg_checkbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="on_outgoing_msg_checkbutton_toggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColorButton" id="outgoing_msg_colorbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="rgba">rgb(0,0,0)</property>
|
||||
<signal name="color-set" handler="on_outgoing_msg_colorbutton_color_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">4</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox13">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColorButton" id="url_msg_colorbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="rgba">rgb(0,0,0)</property>
|
||||
<signal name="color-set" handler="on_url_msg_colorbutton_color_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">4</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="width_request">6</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="reset_colors_button">
|
||||
<property name="label" translatable="yes">_Reset to Default Colors</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="focus_on_click">False</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="margin_top">6</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="clicked" handler="on_reset_colors_button_clicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="width">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="label228">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes"><b>Chat Line Colors</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
|
|
|
@ -65,6 +65,9 @@ Agent JID - node</property>
|
|||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="gajim-banner"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
|
|
|
@ -0,0 +1,208 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.22.1 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.18"/>
|
||||
<object class="GtkPopover" id="popover1">
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<property name="min_content_height">200</property>
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkListBox" id="choose_option_listbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="selection_mode">none</property>
|
||||
<signal name="row-activated" handler="_add_option" swapped="no"/>
|
||||
<style>
|
||||
<class name="theme_popover_listbox"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkListStore" id="theme_store">
|
||||
<columns>
|
||||
<!-- column-name name -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
</object>
|
||||
<object class="GtkGrid" id="theme_grid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="column_spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="theme_treeview">
|
||||
<property name="width_request">150</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="model">theme_store</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection">
|
||||
<signal name="changed" handler="_on_theme_selected" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="title" translatable="yes">Themes</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="editable">True</property>
|
||||
<signal name="edited" handler="_on_theme_name_edit" swapped="no"/>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="_on_add_new_theme" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">list-add-symbolic</property>
|
||||
<property name="icon_size">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="remove_theme_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="_on_remove_theme" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">list-remove-symbolic</property>
|
||||
<property name="icon_size">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<style>
|
||||
<class name="linked"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkListBox" id="option_listbox">
|
||||
<property name="width_request">200</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="selection_mode">none</property>
|
||||
<property name="activate_on_single_click">False</property>
|
||||
<style>
|
||||
<class name="theme_listbox"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="add_option_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="popover">popover1</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">list-add-symbolic</property>
|
||||
<property name="icon_size">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<style>
|
||||
<class name="linked"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
|
@ -0,0 +1,18 @@
|
|||
.gajim-incoming-nickname {
|
||||
color: rgb(164, 0, 0)
|
||||
}
|
||||
.gajim-outgoing-nickname {
|
||||
color: rgb(52, 101, 164)
|
||||
}
|
||||
.gajim-url {
|
||||
color: rgb(117, 80, 123)
|
||||
}
|
||||
.gajim-highlight-message {
|
||||
color: rgb(245, 121, 0)
|
||||
}
|
||||
.gajim-msg-correcting text {
|
||||
background: rgb(131, 148, 150)
|
||||
}
|
||||
.gajim-status-message {
|
||||
color: rgb(115, 210, 22)
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
.gajim-incoming-nickname {
color: rgb(164, 0, 0)
}
.gajim-outgoing-nickname {
color: rgb(52, 101, 164)
}
.gajim-outgoing-message-text {
color: rgb(85, 87, 83)
}
.gajim-status-message {
color: rgb(78, 154, 6)
}
.gajim-url {
color: rgb(32, 74, 135)
}
.gajim-highlight-message {
color: rgb(255, 128, 128)
}
.gajim-restored-message {
color: rgb(85, 87, 83)
}
.gajim-roster-disconnected {
background: rgb(171 ,97 ,97)
}
.gajim-roster-connected {
background: rgb(173, 195, 198)
}
|
|
@ -0,0 +1,2 @@
|
|||
/* Gajim Dark Application CSS File */
|
||||
|
|
@ -1,5 +1,31 @@
|
|||
/* Gajim Application CSS File */
|
||||
|
||||
.gajim-state-composing {
|
||||
color: rgb(0, 139, 0)
|
||||
}
|
||||
.gajim-state-inactive {
|
||||
color: rgb(158, 158, 158)
|
||||
}
|
||||
.gajim-state-gone {
|
||||
color: rgb(128, 128, 128)
|
||||
}
|
||||
.gajim-state-paused {
|
||||
color: rgb(0, 0, 205)
|
||||
}
|
||||
.gajim-msg-correcting text {
|
||||
background: rgb(238, 232, 170)
|
||||
}
|
||||
.gajim-state-tab-muc-directed-msg {
|
||||
color: rgb(238, 0, 0)
|
||||
}
|
||||
.gajim-state-tab-muc-msg {
|
||||
color: rgb(0, 0, 205)
|
||||
}
|
||||
.gajim-banner {
|
||||
font-size: 13pt;
|
||||
font-weight: 700
|
||||
}
|
||||
|
||||
|
||||
.chatcontrol-actionbar-button {
|
||||
padding: 0px 5px 0px 5px;
|
||||
|
@ -136,6 +162,28 @@ list.settings > row > box {
|
|||
opacity: 0.95;
|
||||
}
|
||||
|
||||
/* ThemesWindow */
|
||||
#ThemesWindow grid { padding: 12px; }
|
||||
|
||||
.theme_listbox row { border-bottom: 1px solid; border-color: @theme_unfocused_bg_color; padding: 5px 10px 5px 10px;}
|
||||
.theme_listbox row:last-child { border-bottom: 0px}
|
||||
.theme_listbox row.activatable:active { box-shadow: none; }
|
||||
.theme_listbox row:not(.activatable) label { color: @insensitive_fg_color }
|
||||
.theme_listbox row:focus { outline: none; }
|
||||
.theme_listbox row:hover { background-color: @theme_base_color }
|
||||
|
||||
.theme_remove_button {
|
||||
background-color: @theme_base_color;
|
||||
border: none;
|
||||
background-image: none; }
|
||||
|
||||
.theme_remove_button:focus {outline: none;}
|
||||
|
||||
.theme_popover_listbox { padding: 10px; }
|
||||
.theme_popover_listbox row { padding: 5px; }
|
||||
.theme_popover_listbox row:focus { outline: none; }
|
||||
|
||||
|
||||
/* Text style */
|
||||
|
||||
.bold16 { font-size: 16px; font-weight: bold; }
|
||||
|
|
|
@ -1058,7 +1058,6 @@ class SynchroniseSelectContactsDialog:
|
|||
iter_ = model.iter_next(iter_)
|
||||
self.dialog.destroy()
|
||||
|
||||
|
||||
#Action that can be done with an incoming list of contacts
|
||||
TRANSLATED_ACTION = {'add': _('add'), 'modify': _('modify'),
|
||||
'remove': _('remove')}
|
||||
|
|
|
@ -65,6 +65,7 @@ from gajim.common import app
|
|||
import nbxmpp
|
||||
from gajim.common import helpers
|
||||
from gajim.common import ged
|
||||
from gajim.common.const import StyleAttr
|
||||
|
||||
LABELS = {
|
||||
1: _('This service has not yet responded with detailed information'),
|
||||
|
@ -597,34 +598,10 @@ _('Without a connection, you can not browse available services'))
|
|||
self.banner_icon.clear()
|
||||
self.banner_icon.hide() # Just clearing it doesn't work
|
||||
|
||||
def _set_window_banner_text(self, text, text_after = None):
|
||||
theme = app.config.get('roster_theme')
|
||||
bannerfont = app.config.get_per('themes', theme, 'bannerfont')
|
||||
bannerfontattrs = app.config.get_per('themes', theme,
|
||||
'bannerfontattrs')
|
||||
|
||||
if bannerfont:
|
||||
font = Pango.FontDescription(bannerfont)
|
||||
else:
|
||||
font = Pango.FontDescription('Normal')
|
||||
if bannerfontattrs:
|
||||
# B is attribute set by default
|
||||
if 'B' in bannerfontattrs:
|
||||
font.set_weight(Pango.Weight.HEAVY)
|
||||
if 'I' in bannerfontattrs:
|
||||
font.set_style(Pango.Style.ITALIC)
|
||||
|
||||
font_attrs = 'font_desc="%s"' % font.to_string()
|
||||
font_size = font.get_size()
|
||||
|
||||
# in case there is no font specified we use x-large font size
|
||||
if font_size == 0:
|
||||
font_attrs = '%s size="large"' % font_attrs
|
||||
markup = '<span %s>%s</span>' % (font_attrs, text)
|
||||
if text_after:
|
||||
font.set_weight(Pango.Weight.NORMAL)
|
||||
markup = '%s\n<span font_desc="%s" size="small">%s</span>' % \
|
||||
(markup, font.to_string(), text_after)
|
||||
def _set_window_banner_text(self, text, text_after=None):
|
||||
markup = '<span>%s</span>' % (text)
|
||||
if text_after is not None:
|
||||
markup += '\n<span size="x-small">%s</span>' % text_after
|
||||
self.banner.set_markup(markup)
|
||||
|
||||
def destroy(self, chain = False):
|
||||
|
@ -1195,8 +1172,7 @@ class ToplevelAgentBrowser(AgentBrowser):
|
|||
# Normal/success
|
||||
cell.set_property('foreground_set', False)
|
||||
else:
|
||||
theme = app.config.get('roster_theme')
|
||||
bgcolor = app.config.get_per('themes', theme, 'groupbgcolor')
|
||||
bgcolor = app.css_config.get_value('.gajim-group-row', StyleAttr.BACKGROUND)
|
||||
if bgcolor:
|
||||
cell.set_property('cell_background_set', True)
|
||||
cell.set_property('foreground_set', False)
|
||||
|
@ -1329,8 +1305,7 @@ class ToplevelAgentBrowser(AgentBrowser):
|
|||
AgentBrowser.cleanup(self)
|
||||
|
||||
def update_theme(self):
|
||||
theme = app.config.get('roster_theme')
|
||||
bgcolor = app.config.get_per('themes', theme, 'groupbgcolor')
|
||||
bgcolor = app.css_config.get_value('.gajim-group-row', StyleAttr.BACKGROUND)
|
||||
if bgcolor:
|
||||
self._renderer.set_property('cell-background', bgcolor)
|
||||
self.window.services_treeview.queue_draw()
|
||||
|
|
|
@ -1,411 +0,0 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
## src/gajim_themes_window.py
|
||||
##
|
||||
## Copyright (C) 2003-2014 Yann Leboulanger <asterix AT lagaule.org>
|
||||
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
|
||||
## Nikos Kouremenos <kourem AT gmail.com>
|
||||
## Copyright (C) 2006 Jean-Marie Traissard <jim AT lapin.org>
|
||||
## Copyright (C) 2007 Stephan Erb <steve-e AT h3c.de>
|
||||
##
|
||||
## 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 gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import Pango
|
||||
|
||||
from gajim.common import app
|
||||
|
||||
from gajim.gtk import ErrorDialog
|
||||
from gajim.gtk.util import get_builder
|
||||
|
||||
|
||||
class GajimThemesWindow:
|
||||
|
||||
def __init__(self, transient):
|
||||
self.xml = get_builder('gajim_themes_window.ui')
|
||||
self.window = self.xml.get_object('gajim_themes_window')
|
||||
self.window.set_transient_for(transient)
|
||||
|
||||
self.options = ['account', 'group', 'contact', 'banner']
|
||||
self.options_combobox = self.xml.get_object('options_combobox')
|
||||
self.textcolor_checkbutton = self.xml.get_object('textcolor_checkbutton')
|
||||
self.background_checkbutton = self.xml.get_object('background_checkbutton')
|
||||
self.textfont_checkbutton = self.xml.get_object('textfont_checkbutton')
|
||||
self.text_colorbutton = self.xml.get_object('text_colorbutton')
|
||||
self.background_colorbutton = self.xml.get_object('background_colorbutton')
|
||||
self.text_fontbutton = self.xml.get_object('text_fontbutton')
|
||||
self.bold_togglebutton = self.xml.get_object('bold_togglebutton')
|
||||
self.italic_togglebutton = self.xml.get_object('italic_togglebutton')
|
||||
self.themes_tree = self.xml.get_object('themes_treeview')
|
||||
self.theme_options_vbox = self.xml.get_object('theme_options_vbox')
|
||||
self.theme_options_table = self.xml.get_object('theme_options_table')
|
||||
self.colorbuttons = {}
|
||||
for chatstate in ('inactive', 'composing', 'paused', 'gone',
|
||||
'muc_msg', 'muc_directed_msg'):
|
||||
self.colorbuttons[chatstate] = self.xml.get_object(chatstate + \
|
||||
'_colorbutton')
|
||||
model = Gtk.ListStore(str)
|
||||
self.themes_tree.set_model(model)
|
||||
col = Gtk.TreeViewColumn(_('Theme'))
|
||||
self.themes_tree.append_column(col)
|
||||
renderer = Gtk.CellRendererText()
|
||||
col.pack_start(renderer, True)
|
||||
col.add_attribute(renderer, 'text', 0)
|
||||
renderer.connect('edited', self.on_theme_cell_edited)
|
||||
renderer.set_property('editable', True)
|
||||
self.current_theme = app.config.get('roster_theme')
|
||||
self.no_update = False
|
||||
self.fill_themes_treeview()
|
||||
self.select_active_theme()
|
||||
self.current_option = self.options[0]
|
||||
self.set_theme_options(self.current_theme, self.current_option)
|
||||
|
||||
self.xml.connect_signals(self)
|
||||
self.window.connect('delete-event', self.on_themese_window_delete_event)
|
||||
self.themes_tree.get_selection().connect('changed',
|
||||
self.selection_changed)
|
||||
self.window.show_all()
|
||||
|
||||
def on_themese_window_delete_event(self, widget, event):
|
||||
self.window.hide()
|
||||
return True # do NOT destroy the window
|
||||
|
||||
def on_close_button_clicked(self, widget):
|
||||
window = app.get_app_window('Preferences')
|
||||
if window is not None:
|
||||
window.update_theme_list()
|
||||
self.window.hide()
|
||||
|
||||
def on_theme_cell_edited(self, cell, row, new_name):
|
||||
model = self.themes_tree.get_model()
|
||||
iter_ = model.get_iter_from_string(row)
|
||||
old_name = model.get_value(iter_, 0)
|
||||
if old_name == new_name:
|
||||
return
|
||||
if old_name == 'default':
|
||||
ErrorDialog(
|
||||
_('You cannot make changes to the default theme'),
|
||||
_('Please create a new clean theme.'))
|
||||
return
|
||||
new_config_name = new_name.replace(' ', '_')
|
||||
if new_config_name in app.config.get_per('themes'):
|
||||
return
|
||||
app.config.add_per('themes', new_config_name)
|
||||
# Copy old theme values
|
||||
old_config_name = old_name.replace(' ', '_')
|
||||
properties = ['textcolor', 'bgcolor', 'font', 'fontattrs']
|
||||
app.config.add_per('themes', new_config_name)
|
||||
for option in self.options:
|
||||
for property_ in properties:
|
||||
option_name = option + property_
|
||||
app.config.set_per('themes', new_config_name, option_name,
|
||||
app.config.get_per('themes', old_config_name, option_name))
|
||||
app.config.del_per('themes', old_config_name)
|
||||
if old_config_name == app.config.get('roster_theme'):
|
||||
app.config.set('roster_theme', new_config_name)
|
||||
model.set_value(iter_, 0, new_name)
|
||||
self.current_theme = new_name
|
||||
|
||||
def fill_themes_treeview(self):
|
||||
model = self.themes_tree.get_model()
|
||||
model.clear()
|
||||
for config_theme in app.config.get_per('themes'):
|
||||
theme = config_theme.replace('_', ' ')
|
||||
model.append([theme])
|
||||
|
||||
def select_active_theme(self):
|
||||
model = self.themes_tree.get_model()
|
||||
iter_ = model.get_iter_first()
|
||||
active_theme = app.config.get('roster_theme').replace('_', ' ')
|
||||
while iter_:
|
||||
theme = model[iter_][0]
|
||||
if theme == active_theme:
|
||||
self.themes_tree.get_selection().select_iter(iter_)
|
||||
if active_theme == 'default':
|
||||
self.xml.get_object('remove_button').set_sensitive(False)
|
||||
self.theme_options_vbox.set_sensitive(False)
|
||||
self.theme_options_table.set_sensitive(False)
|
||||
else:
|
||||
self.xml.get_object('remove_button').set_sensitive(True)
|
||||
self.theme_options_vbox.set_sensitive(True)
|
||||
self.theme_options_table.set_sensitive(True)
|
||||
break
|
||||
iter_ = model.iter_next(iter_)
|
||||
|
||||
def selection_changed(self, widget = None):
|
||||
(model, iter_) = self.themes_tree.get_selection().get_selected()
|
||||
selected = self.themes_tree.get_selection().get_selected_rows()
|
||||
if not iter_ or selected[1] == []:
|
||||
self.theme_options_vbox.set_sensitive(False)
|
||||
self.theme_options_table.set_sensitive(False)
|
||||
return
|
||||
self.current_theme = model.get_value(iter_, 0)
|
||||
self.current_theme = self.current_theme.replace(' ', '_')
|
||||
self.set_theme_options(self.current_theme)
|
||||
if self.current_theme == 'default':
|
||||
self.xml.get_object('remove_button').set_sensitive(False)
|
||||
self.theme_options_vbox.set_sensitive(False)
|
||||
self.theme_options_table.set_sensitive(False)
|
||||
else:
|
||||
self.xml.get_object('remove_button').set_sensitive(True)
|
||||
self.theme_options_vbox.set_sensitive(True)
|
||||
self.theme_options_table.set_sensitive(True)
|
||||
|
||||
def on_add_button_clicked(self, widget):
|
||||
model = self.themes_tree.get_model()
|
||||
iter_ = model.append()
|
||||
i = 0
|
||||
# don't confuse translators
|
||||
theme_name = _('theme name')
|
||||
theme_name_ns = theme_name.replace(' ', '_')
|
||||
while theme_name_ns + str(i) in app.config.get_per('themes'):
|
||||
i += 1
|
||||
model.set_value(iter_, 0, theme_name + str(i))
|
||||
app.config.add_per('themes', theme_name_ns + str(i))
|
||||
self.themes_tree.get_selection().select_iter(iter_)
|
||||
col = self.themes_tree.get_column(0)
|
||||
path = model.get_path(iter_)
|
||||
self.themes_tree.set_cursor(path, col, True)
|
||||
|
||||
def on_remove_button_clicked(self, widget):
|
||||
(model, iter_) = self.themes_tree.get_selection().get_selected()
|
||||
if not iter_:
|
||||
return
|
||||
if self.current_theme == app.config.get('roster_theme'):
|
||||
ErrorDialog(
|
||||
_('You cannot delete your current theme'),
|
||||
_('Pick another theme to use first.'))
|
||||
return
|
||||
self.theme_options_vbox.set_sensitive(False)
|
||||
self.theme_options_table.set_sensitive(False)
|
||||
self.xml.get_object('remove_button').set_sensitive(False)
|
||||
app.config.del_per('themes', self.current_theme)
|
||||
model.remove(iter_)
|
||||
|
||||
def set_theme_options(self, theme, option = 'account'):
|
||||
self.no_update = True
|
||||
self.options_combobox.set_active(self.options.index(option))
|
||||
textcolor = app.config.get_per('themes', theme, option + 'textcolor')
|
||||
if textcolor:
|
||||
state = True
|
||||
rgba = Gdk.RGBA()
|
||||
rgba.parse(textcolor)
|
||||
self.text_colorbutton.set_rgba(rgba)
|
||||
else:
|
||||
state = False
|
||||
self.textcolor_checkbutton.set_active(state)
|
||||
self.text_colorbutton.set_sensitive(state)
|
||||
bgcolor = app.config.get_per('themes', theme, option + 'bgcolor')
|
||||
if bgcolor:
|
||||
state = True
|
||||
rgba = Gdk.RGBA()
|
||||
rgba.parse(bgcolor)
|
||||
self.background_colorbutton.set_rgba(rgba)
|
||||
else:
|
||||
state = False
|
||||
self.background_checkbutton.set_active(state)
|
||||
self.background_colorbutton.set_sensitive(state)
|
||||
|
||||
# get the font name before we set widgets and it will not be overridden
|
||||
font_name = app.config.get_per('themes', theme, option + 'font')
|
||||
font_attrs = app.config.get_per('themes', theme, option + 'fontattrs')
|
||||
self._set_font_widgets(font_attrs)
|
||||
if font_name:
|
||||
state = True
|
||||
self.text_fontbutton.set_font_name(font_name)
|
||||
else:
|
||||
state = False
|
||||
self.textfont_checkbutton.set_active(state)
|
||||
self.text_fontbutton.set_sensitive(state)
|
||||
self.no_update = False
|
||||
app.interface.roster.change_roster_style(None)
|
||||
|
||||
for chatstate in ('inactive', 'composing', 'paused', 'gone',
|
||||
'muc_msg', 'muc_directed_msg'):
|
||||
color = app.config.get_per('themes', theme, 'state_' + chatstate + \
|
||||
'_color')
|
||||
rgba = Gdk.RGBA()
|
||||
rgba.parse(color)
|
||||
self.colorbuttons[chatstate].set_rgba(rgba)
|
||||
|
||||
def on_textcolor_checkbutton_toggled(self, widget):
|
||||
state = widget.get_active()
|
||||
self.text_colorbutton.set_sensitive(state)
|
||||
self._set_color(state, self.text_colorbutton,
|
||||
'textcolor')
|
||||
|
||||
def on_background_checkbutton_toggled(self, widget):
|
||||
state = widget.get_active()
|
||||
self.background_colorbutton.set_sensitive(state)
|
||||
self._set_color(state, self.background_colorbutton,
|
||||
'bgcolor')
|
||||
|
||||
def on_textfont_checkbutton_toggled(self, widget):
|
||||
self.text_fontbutton.set_sensitive(widget.get_active())
|
||||
self._set_font()
|
||||
|
||||
def on_text_colorbutton_color_set(self, widget):
|
||||
self._set_color(True, widget, 'textcolor')
|
||||
|
||||
def on_background_colorbutton_color_set(self, widget):
|
||||
self._set_color(True, widget, 'bgcolor')
|
||||
|
||||
def on_text_fontbutton_font_set(self, widget):
|
||||
self._set_font()
|
||||
|
||||
def on_options_combobox_changed(self, widget):
|
||||
index = self.options_combobox.get_active()
|
||||
if index == -1:
|
||||
return
|
||||
self.current_option = self.options[index]
|
||||
self.set_theme_options(self.current_theme,
|
||||
self.current_option)
|
||||
|
||||
def on_bold_togglebutton_toggled(self, widget):
|
||||
if not self.no_update:
|
||||
self._set_font()
|
||||
|
||||
def on_italic_togglebutton_toggled(self, widget):
|
||||
if not self.no_update:
|
||||
self._set_font()
|
||||
|
||||
def _set_color(self, state, widget, option):
|
||||
"""
|
||||
Set color value in prefs and update the UI
|
||||
"""
|
||||
if state:
|
||||
color = widget.get_rgba()
|
||||
color_string = color.to_string()
|
||||
else:
|
||||
color_string = ''
|
||||
begin_option = ''
|
||||
if not option.startswith('state'):
|
||||
begin_option = self.current_option
|
||||
app.config.set_per('themes', self.current_theme,
|
||||
begin_option + option, color_string)
|
||||
# use faster functions for this
|
||||
if self.current_option == 'banner':
|
||||
app.interface.roster.repaint_themed_widgets()
|
||||
return
|
||||
if self.no_update:
|
||||
return
|
||||
app.interface.roster.change_roster_style(self.current_option)
|
||||
|
||||
def _set_font(self):
|
||||
"""
|
||||
Set font value in prefs and update the UI
|
||||
"""
|
||||
state = self.textfont_checkbutton.get_active()
|
||||
if state:
|
||||
font_string = self.text_fontbutton.get_font_name()
|
||||
else:
|
||||
font_string = ''
|
||||
app.config.set_per('themes', self.current_theme,
|
||||
self.current_option + 'font', font_string)
|
||||
font_attrs = self._get_font_attrs()
|
||||
app.config.set_per('themes', self.current_theme,
|
||||
self.current_option + 'fontattrs', font_attrs)
|
||||
# use faster functions for this
|
||||
if self.current_option == 'banner':
|
||||
app.interface.roster.repaint_themed_widgets()
|
||||
if self.no_update:
|
||||
return
|
||||
app.interface.roster.change_roster_style(self.current_option)
|
||||
|
||||
def _toggle_font_widgets(self, font_props):
|
||||
"""
|
||||
Toggle font buttons with the bool values of font_props tuple
|
||||
"""
|
||||
self.bold_togglebutton.set_active(font_props[0])
|
||||
self.italic_togglebutton.set_active(font_props[1])
|
||||
|
||||
def _get_font_description(self):
|
||||
"""
|
||||
Return a FontDescription from togglebuttons states
|
||||
"""
|
||||
fd = Pango.FontDescription()
|
||||
if self.bold_togglebutton.get_active():
|
||||
fd.set_weight(Pango.Weight.BOLD)
|
||||
if self.italic_togglebutton.get_active():
|
||||
fd.set_style(Pango.Style.ITALIC)
|
||||
return fd
|
||||
|
||||
def _set_font_widgets(self, font_attrs):
|
||||
"""
|
||||
Set the correct toggle state of font style buttons by a font string of
|
||||
type 'BI'
|
||||
"""
|
||||
font_props = [False, False, False]
|
||||
if font_attrs:
|
||||
if font_attrs.find('B') != -1:
|
||||
font_props[0] = True
|
||||
if font_attrs.find('I') != -1:
|
||||
font_props[1] = True
|
||||
self._toggle_font_widgets(font_props)
|
||||
|
||||
def _get_font_attrs(self):
|
||||
"""
|
||||
Get a string with letters of font attribures: 'BI'
|
||||
"""
|
||||
attrs = ''
|
||||
if self.bold_togglebutton.get_active():
|
||||
attrs += 'B'
|
||||
if self.italic_togglebutton.get_active():
|
||||
attrs += 'I'
|
||||
return attrs
|
||||
|
||||
|
||||
def _get_font_props(self, font_name):
|
||||
"""
|
||||
Get tuple of font properties: weight, style
|
||||
"""
|
||||
font_props = [False, False, False]
|
||||
font_description = Pango.FontDescription(font_name)
|
||||
if font_description.get_weight() != Pango.Weight.NORMAL:
|
||||
font_props[0] = True
|
||||
if font_description.get_style() != Pango.Style.ITALIC:
|
||||
font_props[1] = True
|
||||
return font_props
|
||||
|
||||
def on_inactive_colorbutton_color_set(self, widget):
|
||||
self.no_update = True
|
||||
self._set_color(True, widget, 'state_inactive_color')
|
||||
self.no_update = False
|
||||
|
||||
def on_composing_colorbutton_color_set(self, widget):
|
||||
self.no_update = True
|
||||
self._set_color(True, widget, 'state_composing_color')
|
||||
self.no_update = False
|
||||
|
||||
def on_paused_colorbutton_color_set(self, widget):
|
||||
self.no_update = True
|
||||
self._set_color(True, widget, 'state_paused_color')
|
||||
self.no_update = False
|
||||
|
||||
def on_gone_colorbutton_color_set(self, widget):
|
||||
self.no_update = True
|
||||
self._set_color(True, widget, 'state_gone_color')
|
||||
self.no_update = False
|
||||
|
||||
def on_muc_msg_colorbutton_color_set(self, widget):
|
||||
self.no_update = True
|
||||
self._set_color(True, widget, 'state_muc_msg_color')
|
||||
self.no_update = False
|
||||
|
||||
def on_muc_directed_msg_colorbutton_color_set(self, widget):
|
||||
self.no_update = True
|
||||
self._set_color(True, widget, 'state_muc_directed_msg_color')
|
||||
self.no_update = False
|
|
@ -59,6 +59,7 @@ from gajim.common.modules import dataforms
|
|||
from gajim.common import ged
|
||||
from gajim.common import i18n
|
||||
from gajim.common import contacts
|
||||
from gajim.common.const import StyleAttr
|
||||
|
||||
from gajim.chat_control import ChatControl
|
||||
from gajim.chat_control_base import ChatControlBase
|
||||
|
@ -95,11 +96,11 @@ def cell_data_func(column, renderer, model, iter_, user_data):
|
|||
theme = app.config.get('roster_theme')
|
||||
has_parent = bool(model.iter_parent(iter_))
|
||||
if has_parent:
|
||||
bgcolor = app.config.get_per('themes', theme, 'contactbgcolor')
|
||||
renderer.set_property('cell-background', bgcolor or None)
|
||||
bgcolor = app.css_config.get_value('.gajim-contact-row', StyleAttr.BACKGROUND)
|
||||
renderer.set_property('cell-background', bgcolor)
|
||||
else:
|
||||
bgcolor = app.config.get_per('themes', theme, 'groupbgcolor')
|
||||
renderer.set_property('cell-background', bgcolor or None)
|
||||
bgcolor = app.css_config.get_value('.gajim-group-row', StyleAttr.BACKGROUND)
|
||||
renderer.set_property('cell-background', bgcolor)
|
||||
|
||||
if user_data == 'status':
|
||||
status_cell_data_func(column, renderer, model, iter_, has_parent)
|
||||
|
@ -133,18 +134,15 @@ def text_cell_data_func(column, renderer, model, iter_, has_parent, theme):
|
|||
# cell data func is global, because we don't want it to keep
|
||||
# reference to GroupchatControl instance (self)
|
||||
if has_parent:
|
||||
color = app.config.get_per('themes', theme, 'contacttextcolor')
|
||||
if color:
|
||||
renderer.set_property('foreground', color)
|
||||
else:
|
||||
renderer.set_property('foreground', None)
|
||||
renderer.set_property('font',
|
||||
gtkgui_helpers.get_theme_font_for_option(theme, 'contactfont'))
|
||||
color = app.css_config.get_value('.gajim-contact-row', StyleAttr.COLOR)
|
||||
renderer.set_property('foreground', color)
|
||||
desc = app.css_config.get_font('.gajim-contact-row')
|
||||
renderer.set_property('font-desc', desc)
|
||||
else:
|
||||
color = app.config.get_per('themes', theme, 'grouptextcolor')
|
||||
renderer.set_property('foreground', color or None)
|
||||
renderer.set_property('font',
|
||||
gtkgui_helpers.get_theme_font_for_option(theme, 'groupfont'))
|
||||
color = app.css_config.get_value('.gajim-group-row', StyleAttr.COLOR)
|
||||
renderer.set_property('foreground', color)
|
||||
desc = app.css_config.get_font('.gajim-group-row')
|
||||
renderer.set_property('font-desc', desc)
|
||||
|
||||
|
||||
class PrivateChatControl(ChatControl):
|
||||
|
@ -1023,14 +1021,14 @@ class GroupchatControl(ChatControlBase):
|
|||
color = None
|
||||
if chatstate == 'attention' and (not has_focus or not current_tab):
|
||||
self.attention_flag = True
|
||||
color = 'state_muc_directed_msg_color'
|
||||
color = 'tab-muc-directed-msg'
|
||||
elif chatstate == 'active' or (current_tab and has_focus):
|
||||
self.attention_flag = False
|
||||
# get active color from gtk
|
||||
color = 'active'
|
||||
elif chatstate == 'newmsg' and (not has_focus or not current_tab) \
|
||||
and not self.attention_flag:
|
||||
color = 'state_muc_msg_color'
|
||||
color = 'tab-muc-msg'
|
||||
|
||||
if self.is_continued:
|
||||
# if this is a continued conversation
|
||||
|
@ -1146,18 +1144,16 @@ class GroupchatControl(ChatControlBase):
|
|||
room jid, subject
|
||||
"""
|
||||
self.name_label.set_ellipsize(Pango.EllipsizeMode.END)
|
||||
font_attrs, font_attrs_small = self.get_font_attrs()
|
||||
if self.is_continued:
|
||||
name = self.get_continued_conversation_name()
|
||||
else:
|
||||
name = self.room_jid
|
||||
text = '<span %s>%s</span>' % (font_attrs, name)
|
||||
self.name_label.set_markup(text)
|
||||
|
||||
self.name_label.set_text(name)
|
||||
|
||||
if self.subject:
|
||||
subject = GLib.markup_escape_text(self.subject)
|
||||
subject_text = self.urlfinder.sub(self.make_href, subject)
|
||||
subject_text = '<span>%s</span>' % subject_text
|
||||
self.subject_button.get_popover().set_text(subject_text)
|
||||
|
||||
def _nec_vcard_published(self, obj):
|
||||
|
@ -1719,13 +1715,8 @@ class GroupchatControl(ChatControlBase):
|
|||
if status != '':
|
||||
status = helpers.reduce_chars_newlines(status, max_lines=1)
|
||||
# escape markup entities and make them small italic and fg color
|
||||
color = gtkgui_helpers.get_fade_color(self.list_treeview,
|
||||
selected, focus)
|
||||
colorstring = "#%04x%04x%04x" % (int(color.red * 65535),
|
||||
int(color.green * 65535), int(color.blue * 65535))
|
||||
name += ('\n<span size="small" style="italic" foreground="%s">'
|
||||
'%s</span>') % (colorstring, GLib.markup_escape_text(
|
||||
status))
|
||||
name += ('\n<span size="small" style="italic" alpha="70%">'
|
||||
'{}</span>'.format(GLib.markup_escape_text(status)))
|
||||
|
||||
if (gc_contact.affiliation != 'none' and
|
||||
app.config.get('show_affiliation_in_groupchat')):
|
||||
|
@ -2112,7 +2103,7 @@ class GroupchatControl(ChatControlBase):
|
|||
if self.correcting:
|
||||
self.correcting = False
|
||||
gtkgui_helpers.remove_css_class(
|
||||
self.msg_textview, 'msgcorrectingcolor')
|
||||
self.msg_textview, 'gajim-msg-correcting')
|
||||
|
||||
def send_message(self, message, xhtml=None, process_commands=True):
|
||||
"""
|
||||
|
|
|
@ -52,6 +52,7 @@ from gajim.gtk.dialogs import AspellDictError
|
|||
from gajim.gtk.dialogs import HigDialog
|
||||
from gajim.gtk.dialogs import SSLErrorDialog
|
||||
from gajim.gtk.dialogs import ChangePasswordDialog
|
||||
from gajim.gtk.dialogs import NewConfirmationDialog
|
||||
|
||||
from gajim.gtk.about import AboutDialog
|
||||
from gajim.gtk.join_groupchat import JoinGroupchatWindow
|
||||
|
|
|
@ -986,3 +986,42 @@ class ChangePasswordDialog(Gtk.Dialog):
|
|||
self._error_label.set_text(error_text)
|
||||
self._password1_entry.set_sensitive(True)
|
||||
self._password2_entry.set_sensitive(True)
|
||||
|
||||
|
||||
class NewConfirmationDialog(Gtk.MessageDialog):
|
||||
def __init__(self, text, sec_text, buttons, transient_for=None):
|
||||
Gtk.MessageDialog.__init__(self,
|
||||
transient_for=transient_for,
|
||||
message_type=Gtk.MessageType.QUESTION,
|
||||
text=text)
|
||||
|
||||
self._buttons = buttons
|
||||
|
||||
for response, button in buttons.items():
|
||||
self.add_button(button.text, response)
|
||||
if button.action is not None:
|
||||
widget = self.get_widget_for_response(response)
|
||||
widget.get_style_context().add_class(button.action.value)
|
||||
|
||||
self.format_secondary_markup(sec_text)
|
||||
|
||||
self.connect('response', self._on_response)
|
||||
|
||||
self.run()
|
||||
|
||||
def _on_response(self, dialog, response):
|
||||
if response == Gtk.ResponseType.DELETE_EVENT:
|
||||
# Look if DELETE_EVENT is mapped to another response
|
||||
response = self._buttons.get(response, None)
|
||||
if response is None:
|
||||
# If DELETE_EVENT was not mapped we assume CANCEL
|
||||
response = Gtk.ResponseType.CANCEL
|
||||
|
||||
button = self._buttons.get(response, None)
|
||||
if button is None:
|
||||
self.destroy()
|
||||
return
|
||||
|
||||
if button.callback is not None:
|
||||
button.callback()
|
||||
self.destroy()
|
||||
|
|
|
@ -25,7 +25,7 @@ from gajim.common import config as c_config
|
|||
from gajim.common import idle
|
||||
from gajim.gtk.util import get_builder
|
||||
from gajim.gtk import AspellDictError
|
||||
from gajim.gajim_themes_window import GajimThemesWindow
|
||||
from gajim.gtk.themes import Themes
|
||||
from gajim.advanced_configuration_window import AdvancedConfigurationWindow
|
||||
from gajim.chat_control_base import ChatControlBase
|
||||
from gajim.config import ManageProxiesWindow, ManageSoundsWindow
|
||||
|
@ -160,9 +160,8 @@ class Preferences(Gtk.ApplicationWindow):
|
|||
### Style tab ###
|
||||
# Themes
|
||||
theme_combobox = self.xml.get_object('theme_combobox')
|
||||
cell = Gtk.CellRendererText()
|
||||
theme_combobox.pack_start(cell, True)
|
||||
theme_combobox.add_attribute(cell, 'text', 0)
|
||||
self.changed_id = theme_combobox.connect(
|
||||
'changed', self.on_theme_combobox_changed)
|
||||
self.update_theme_list()
|
||||
|
||||
# iconset
|
||||
|
@ -207,19 +206,6 @@ class Preferences(Gtk.ApplicationWindow):
|
|||
st = app.config.get('use_transports_iconsets')
|
||||
self.xml.get_object('transports_iconsets_checkbutton').set_active(st)
|
||||
|
||||
# Color widgets
|
||||
self.draw_color_widgets()
|
||||
|
||||
# Font for messages
|
||||
font = app.config.get('conversation_font')
|
||||
# try to set default font for the current desktop env
|
||||
fontbutton = self.xml.get_object('conversation_fontbutton')
|
||||
if font == '':
|
||||
fontbutton.set_sensitive(False)
|
||||
self.xml.get_object('default_chat_font').set_active(True)
|
||||
else:
|
||||
fontbutton.set_font_name(font)
|
||||
|
||||
### Personal Events tab ###
|
||||
# outgoing send chat state notifications
|
||||
st = app.config.get('outgoing_chat_state_notifications')
|
||||
|
@ -473,8 +459,8 @@ class Preferences(Gtk.ApplicationWindow):
|
|||
self.default_msg_tree.get_model().connect('row-changed',
|
||||
self.on_default_msg_treemodel_row_changed)
|
||||
|
||||
self.theme_preferences = None
|
||||
self.sounds_preferences = None
|
||||
self.theme_preferences = None
|
||||
|
||||
self.notebook.set_current_page(0)
|
||||
|
||||
|
@ -625,36 +611,32 @@ class Preferences(Gtk.ApplicationWindow):
|
|||
def on_show_avatar_in_tabs_checkbutton_toggled(self, widget):
|
||||
self.on_checkbutton_toggled(widget, 'show_avatar_in_tabs')
|
||||
|
||||
def on_theme_combobox_changed(self, widget):
|
||||
model = widget.get_model()
|
||||
active = widget.get_active()
|
||||
config_theme = model[active][0].replace(' ', '_')
|
||||
|
||||
app.config.set('roster_theme', config_theme)
|
||||
@staticmethod
|
||||
def on_theme_combobox_changed(combobox):
|
||||
theme = combobox.get_active_id()
|
||||
app.config.set('roster_theme', theme)
|
||||
app.css_config.change_theme(theme)
|
||||
|
||||
# begin repainting themed widgets throughout
|
||||
app.interface.roster.repaint_themed_widgets()
|
||||
app.interface.roster.change_roster_style(None)
|
||||
gtkgui_helpers.load_css()
|
||||
|
||||
def update_theme_list(self):
|
||||
theme_combobox = self.xml.get_object('theme_combobox')
|
||||
model = Gtk.ListStore(str)
|
||||
theme_combobox.set_model(model)
|
||||
i = 0
|
||||
for config_theme in app.config.get_per('themes'):
|
||||
theme = config_theme.replace('_', ' ')
|
||||
model.append([theme])
|
||||
if app.config.get('roster_theme') == config_theme:
|
||||
theme_combobox.set_active(i)
|
||||
i += 1
|
||||
with theme_combobox.handler_block(self.changed_id):
|
||||
theme_combobox.remove_all()
|
||||
theme_combobox.append('default', 'default')
|
||||
for config_theme in app.css_config.themes:
|
||||
theme_combobox.append(config_theme, config_theme)
|
||||
|
||||
theme_combobox.set_active_id(app.config.get('roster_theme'))
|
||||
|
||||
def on_manage_theme_button_clicked(self, widget):
|
||||
if self.theme_preferences is None:
|
||||
self.theme_preferences = GajimThemesWindow(self)
|
||||
window = app.get_app_window(Themes)
|
||||
if window is None:
|
||||
Themes(self)
|
||||
else:
|
||||
self.theme_preferences.window.present()
|
||||
self.theme_preferences.select_active_theme()
|
||||
window.present()
|
||||
|
||||
def on_iconset_combobox_changed(self, widget):
|
||||
model = widget.get_model()
|
||||
|
@ -747,128 +729,6 @@ class Preferences(Gtk.ApplicationWindow):
|
|||
else:
|
||||
self.sounds_preferences.window.present()
|
||||
|
||||
def update_text_tags(self):
|
||||
"""
|
||||
Update color tags in opened chat windows
|
||||
"""
|
||||
for ctrl in self._get_all_controls():
|
||||
ctrl.update_tags()
|
||||
|
||||
def on_preference_widget_color_set(self, widget, text):
|
||||
color = widget.get_color()
|
||||
color_string = color.to_string()
|
||||
app.config.set(text, color_string)
|
||||
self.update_text_tags()
|
||||
|
||||
def on_preference_widget_font_set(self, widget, text):
|
||||
if widget:
|
||||
font = widget.get_font_name()
|
||||
else:
|
||||
font = ''
|
||||
app.config.set(text, font)
|
||||
gtkgui_helpers.load_css()
|
||||
|
||||
def on_incoming_nick_colorbutton_color_set(self, widget):
|
||||
self.on_preference_widget_color_set(widget, 'inmsgcolor')
|
||||
|
||||
def on_outgoing_nick_colorbutton_color_set(self, widget):
|
||||
self.on_preference_widget_color_set(widget, 'outmsgcolor')
|
||||
|
||||
def on_incoming_msg_colorbutton_color_set(self, widget):
|
||||
self.on_preference_widget_color_set(widget, 'inmsgtxtcolor')
|
||||
|
||||
def on_outgoing_msg_colorbutton_color_set(self, widget):
|
||||
self.on_preference_widget_color_set(widget, 'outmsgtxtcolor')
|
||||
|
||||
def on_url_msg_colorbutton_color_set(self, widget):
|
||||
self.on_preference_widget_color_set(widget, 'urlmsgcolor')
|
||||
|
||||
def on_status_msg_colorbutton_color_set(self, widget):
|
||||
self.on_preference_widget_color_set(widget, 'statusmsgcolor')
|
||||
|
||||
def on_muc_highlight_colorbutton_color_set(self, widget):
|
||||
self.on_preference_widget_color_set(widget, 'markedmsgcolor')
|
||||
|
||||
def on_conversation_fontbutton_font_set(self, widget):
|
||||
self.on_preference_widget_font_set(widget, 'conversation_font')
|
||||
|
||||
def on_default_chat_font_toggled(self, widget):
|
||||
font_widget = self.xml.get_object('conversation_fontbutton')
|
||||
if widget.get_active():
|
||||
font_widget.set_sensitive(False)
|
||||
font_widget = None
|
||||
else:
|
||||
font_widget.set_sensitive(True)
|
||||
self.on_preference_widget_font_set(font_widget, 'conversation_font')
|
||||
|
||||
def draw_color_widgets(self):
|
||||
col_to_widget = {'inmsgcolor': 'incoming_nick_colorbutton',
|
||||
'outmsgcolor': 'outgoing_nick_colorbutton',
|
||||
'inmsgtxtcolor': ['incoming_msg_colorbutton',
|
||||
'incoming_msg_checkbutton'],
|
||||
'outmsgtxtcolor': ['outgoing_msg_colorbutton',
|
||||
'outgoing_msg_checkbutton'],
|
||||
'statusmsgcolor': 'status_msg_colorbutton',
|
||||
'urlmsgcolor': 'url_msg_colorbutton',
|
||||
'markedmsgcolor': 'muc_highlight_colorbutton'}
|
||||
for c in col_to_widget:
|
||||
col = app.config.get(c)
|
||||
if col:
|
||||
if isinstance(col_to_widget[c], list):
|
||||
rgba = Gdk.RGBA()
|
||||
rgba.parse(col)
|
||||
self.xml.get_object(col_to_widget[c][0]).set_rgba(rgba)
|
||||
self.xml.get_object(col_to_widget[c][0]).set_sensitive(True)
|
||||
self.xml.get_object(col_to_widget[c][1]).set_active(True)
|
||||
else:
|
||||
rgba = Gdk.RGBA()
|
||||
rgba.parse(col)
|
||||
self.xml.get_object(col_to_widget[c]).set_rgba(rgba)
|
||||
else:
|
||||
rgba = Gdk.RGBA()
|
||||
rgba.parse('#000000')
|
||||
if isinstance(col_to_widget[c], list):
|
||||
self.xml.get_object(col_to_widget[c][0]).set_rgba(rgba)
|
||||
self.xml.get_object(col_to_widget[c][0]).set_sensitive(False)
|
||||
self.xml.get_object(col_to_widget[c][1]).set_active(False)
|
||||
else:
|
||||
self.xml.get_object(col_to_widget[c]).set_rgba(rgba)
|
||||
|
||||
def on_reset_colors_button_clicked(self, widget):
|
||||
col_to_widget = {'inmsgcolor': 'incoming_nick_colorbutton',
|
||||
'outmsgcolor': 'outgoing_nick_colorbutton',
|
||||
'inmsgtxtcolor': 'incoming_msg_colorbutton',
|
||||
'outmsgtxtcolor': 'outgoing_msg_colorbutton',
|
||||
'statusmsgcolor': 'status_msg_colorbutton',
|
||||
'urlmsgcolor': 'url_msg_colorbutton',
|
||||
'markedmsgcolor': 'muc_highlight_colorbutton'}
|
||||
for c in col_to_widget:
|
||||
app.config.set(c, app.interface.default_colors[c])
|
||||
self.draw_color_widgets()
|
||||
|
||||
self.update_text_tags()
|
||||
|
||||
def _set_color(self, state, widget_name, option):
|
||||
"""
|
||||
Set color value in prefs and update the UI
|
||||
"""
|
||||
if state:
|
||||
color = self.xml.get_object(widget_name).get_rgba()
|
||||
color_string = color.to_string()
|
||||
else:
|
||||
color_string = ''
|
||||
app.config.set(option, color_string)
|
||||
|
||||
def on_incoming_msg_checkbutton_toggled(self, widget):
|
||||
state = widget.get_active()
|
||||
self.xml.get_object('incoming_msg_colorbutton').set_sensitive(state)
|
||||
self._set_color(state, 'incoming_msg_colorbutton', 'inmsgtxtcolor')
|
||||
|
||||
def on_outgoing_msg_checkbutton_toggled(self, widget):
|
||||
state = widget.get_active()
|
||||
self.xml.get_object('outgoing_msg_colorbutton').set_sensitive(state)
|
||||
self._set_color(state, 'outgoing_msg_colorbutton', 'outmsgtxtcolor')
|
||||
|
||||
def on_auto_away_checkbutton_toggled(self, widget):
|
||||
self.on_checkbutton_toggled(widget, 'autoaway',
|
||||
[self.auto_away_time_spinbutton, self.auto_away_message_entry])
|
||||
|
|
|
@ -0,0 +1,415 @@
|
|||
# Copyright (C) 2018 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 collections import namedtuple
|
||||
from enum import IntEnum
|
||||
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
|
||||
from gajim.common import app
|
||||
from gajim.common.const import StyleAttr, DialogButton, ButtonAction
|
||||
from gajim.common.connection_handlers_events import StyleChanged
|
||||
from gajim.gtk import ErrorDialog
|
||||
from gajim.gtk import NewConfirmationDialog
|
||||
from gajim.gtk.util import get_builder
|
||||
|
||||
StyleOption = namedtuple('StyleOption', 'label selector attr')
|
||||
|
||||
CSS_STYLE_OPTIONS = [
|
||||
StyleOption(_('Chatstate Composing'),
|
||||
'.gajim-state-composing',
|
||||
StyleAttr.COLOR),
|
||||
|
||||
StyleOption(_('Chatstate Inactive'),
|
||||
'.gajim-state-inactive',
|
||||
StyleAttr.COLOR),
|
||||
|
||||
StyleOption(_('Chatstate Gone'),
|
||||
'.gajim-state-gone',
|
||||
StyleAttr.COLOR),
|
||||
|
||||
StyleOption(_('Chatstate Paused'),
|
||||
'.gajim-state-paused',
|
||||
StyleAttr.COLOR),
|
||||
|
||||
StyleOption(_('MUC Tab New Directed Message'),
|
||||
'.gajim-state-tab-muc-directed-msg',
|
||||
StyleAttr.COLOR),
|
||||
|
||||
StyleOption(_('MUC Tab New Message'),
|
||||
'.gajim-state-tab-muc-msg',
|
||||
StyleAttr.COLOR),
|
||||
|
||||
StyleOption(_('Banner Foreground Color'),
|
||||
'.gajim-banner',
|
||||
StyleAttr.COLOR),
|
||||
|
||||
StyleOption(_('Banner Background Color'),
|
||||
'.gajim-banner',
|
||||
StyleAttr.BACKGROUND),
|
||||
|
||||
StyleOption(_('Banner Font'),
|
||||
'.gajim-banner',
|
||||
StyleAttr.FONT),
|
||||
|
||||
StyleOption(_('Account Row Foreground Color'),
|
||||
'.gajim-account-row',
|
||||
StyleAttr.COLOR),
|
||||
|
||||
StyleOption(_('Account Row Background Color'),
|
||||
'.gajim-account-row',
|
||||
StyleAttr.BACKGROUND),
|
||||
|
||||
StyleOption(_('Account Row Font Color'),
|
||||
'.gajim-account-row',
|
||||
StyleAttr.FONT),
|
||||
|
||||
StyleOption(_('Group Row Foreground Color'),
|
||||
'.gajim-group-row',
|
||||
StyleAttr.COLOR),
|
||||
|
||||
StyleOption(_('Group Row Background Color'),
|
||||
'.gajim-group-row',
|
||||
StyleAttr.BACKGROUND),
|
||||
|
||||
StyleOption(_('Group Row Font Color'),
|
||||
'.gajim-group-row',
|
||||
StyleAttr.FONT),
|
||||
|
||||
StyleOption(_('Contact Row Foreground Color'),
|
||||
'.gajim-contact-row',
|
||||
StyleAttr.COLOR),
|
||||
|
||||
StyleOption(_('Contact Row Background Color'),
|
||||
'.gajim-contact-row',
|
||||
StyleAttr.BACKGROUND),
|
||||
|
||||
StyleOption(_('Contact Row Font Color'),
|
||||
'.gajim-contact-row',
|
||||
StyleAttr.FONT),
|
||||
|
||||
StyleOption(_('Conversation Font'),
|
||||
'.gajim-conversation-font',
|
||||
StyleAttr.FONT),
|
||||
|
||||
StyleOption(_('Incoming Nickname Color'),
|
||||
'.gajim-incoming-nickname',
|
||||
StyleAttr.COLOR),
|
||||
|
||||
StyleOption(_('Outgoing Nickname Color'),
|
||||
'.gajim-outgoing-nickname',
|
||||
StyleAttr.COLOR),
|
||||
|
||||
StyleOption(_('Incoming Message Text Color'),
|
||||
'.gajim-incoming-message-text',
|
||||
StyleAttr.COLOR),
|
||||
|
||||
StyleOption(_('Incoming Message Text Font'),
|
||||
'.gajim-incoming-message-text',
|
||||
StyleAttr.FONT),
|
||||
|
||||
StyleOption(_('Outgoing Message Text Color'),
|
||||
'.gajim-outgoing-message-text',
|
||||
StyleAttr.COLOR),
|
||||
|
||||
StyleOption(_('Outgoing Message Text Font'),
|
||||
'.gajim-outgoing-message-text',
|
||||
StyleAttr.FONT),
|
||||
|
||||
StyleOption(_('Status Message Color'),
|
||||
'.gajim-status-message',
|
||||
StyleAttr.COLOR),
|
||||
|
||||
StyleOption(_('Status Message Font'),
|
||||
'.gajim-status-message',
|
||||
StyleAttr.FONT),
|
||||
|
||||
StyleOption(_('URL Color'),
|
||||
'.gajim-url',
|
||||
StyleAttr.COLOR),
|
||||
|
||||
StyleOption(_('Highlight Message Color'),
|
||||
'.gajim-highlight-message',
|
||||
StyleAttr.COLOR),
|
||||
|
||||
StyleOption(_('Message Correcting'),
|
||||
'.gajim-msg-correcting text',
|
||||
StyleAttr.BACKGROUND),
|
||||
|
||||
StyleOption(_('Restored Message Color'),
|
||||
'.gajim-restored-message',
|
||||
StyleAttr.COLOR),
|
||||
|
||||
StyleOption(_('Contact Disconnected Background'),
|
||||
'.gajim-roster-disconnected',
|
||||
StyleAttr.BACKGROUND),
|
||||
|
||||
StyleOption(_('Contact Connected Background '),
|
||||
'.gajim-roster-connected',
|
||||
StyleAttr.BACKGROUND),
|
||||
]
|
||||
|
||||
|
||||
class Column(IntEnum):
|
||||
THEME = 0
|
||||
|
||||
|
||||
class Themes(Gtk.ApplicationWindow):
|
||||
def __init__(self, transient):
|
||||
Gtk.Window.__init__(self)
|
||||
self.set_application(app.app)
|
||||
self.set_title(_('Gajim Themes'))
|
||||
self.set_name('ThemesWindow')
|
||||
self.set_show_menubar(False)
|
||||
self.set_type_hint(Gdk.WindowTypeHint.DIALOG)
|
||||
self.set_transient_for(transient)
|
||||
self.set_resizable(True)
|
||||
self.set_default_size(600, 400)
|
||||
|
||||
self.builder = get_builder('themes_window.ui')
|
||||
self.add(self.builder.get_object('theme_grid'))
|
||||
|
||||
widgets = ['option_listbox', 'remove_theme_button', 'theme_store',
|
||||
'theme_treeview', 'choose_option_listbox',
|
||||
'add_option_button']
|
||||
for widget in widgets:
|
||||
setattr(self, '_%s' % widget, self.builder.get_object(widget))
|
||||
|
||||
# Doesnt work if we set it in Glade
|
||||
self._add_option_button.set_sensitive(False)
|
||||
|
||||
self._get_themes()
|
||||
|
||||
self.builder.connect_signals(self)
|
||||
self.connect('destroy', self._on_destroy)
|
||||
self.show_all()
|
||||
|
||||
self._fill_choose_listbox()
|
||||
|
||||
def _get_themes(self):
|
||||
for theme in app.css_config.themes:
|
||||
self._theme_store.append([theme])
|
||||
|
||||
def _on_theme_name_edit(self, renderer, path, new_name):
|
||||
iter_ = self._theme_store.get_iter(path)
|
||||
old_name = self._theme_store[iter_][Column.THEME]
|
||||
|
||||
if new_name == 'default':
|
||||
ErrorDialog(
|
||||
_('Invalid Name'),
|
||||
_('Name <b>default</b> is not allowed'),
|
||||
transient_for=self)
|
||||
return
|
||||
|
||||
if ' ' in new_name:
|
||||
ErrorDialog(
|
||||
_('Invalid Name'),
|
||||
_('Spaces are not allowed'),
|
||||
transient_for=self)
|
||||
return
|
||||
|
||||
if new_name == '':
|
||||
return
|
||||
|
||||
result = app.css_config.rename_theme(old_name, new_name)
|
||||
if result is False:
|
||||
return
|
||||
|
||||
self._theme_store.set_value(iter_, Column.THEME, new_name)
|
||||
|
||||
def _select_theme_row(self, iter_):
|
||||
self._theme_treeview.get_selection().select_iter(iter_)
|
||||
|
||||
def _on_theme_selected(self, tree_selection):
|
||||
store, iter_ = tree_selection.get_selected()
|
||||
if iter_ is None:
|
||||
self._clear_options()
|
||||
return
|
||||
theme = store[iter_][Column.THEME]
|
||||
app.css_config.change_preload_theme(theme)
|
||||
|
||||
self._add_option_button.set_sensitive(True)
|
||||
self._remove_theme_button.set_sensitive(True)
|
||||
self._load_options(theme)
|
||||
|
||||
def _load_options(self, name):
|
||||
self._option_listbox.foreach(self._remove_option)
|
||||
for option in CSS_STYLE_OPTIONS:
|
||||
value = app.css_config.get_value(
|
||||
option.selector, option.attr, pre=True)
|
||||
|
||||
if value is None:
|
||||
continue
|
||||
|
||||
row = Option(option, value)
|
||||
self._option_listbox.add(row)
|
||||
|
||||
def _add_option(self, listbox, row):
|
||||
for option in self._option_listbox.get_children():
|
||||
if option == row:
|
||||
return
|
||||
row = Option(row.option, None)
|
||||
self._option_listbox.add(row)
|
||||
|
||||
def _clear_options(self):
|
||||
self._option_listbox.foreach(self._remove_option)
|
||||
|
||||
def _fill_choose_listbox(self):
|
||||
for option in CSS_STYLE_OPTIONS:
|
||||
self._choose_option_listbox.add(ChooseOption(option))
|
||||
|
||||
def _remove_option(self, row):
|
||||
self._option_listbox.remove(row)
|
||||
row.destroy()
|
||||
|
||||
def _on_add_new_theme(self, *args):
|
||||
name = self._create_theme_name()
|
||||
if not app.css_config.add_new_theme(name):
|
||||
return
|
||||
|
||||
self._remove_theme_button.set_sensitive(True)
|
||||
iter_ = self._theme_store.append([name])
|
||||
self._select_theme_row(iter_)
|
||||
|
||||
@staticmethod
|
||||
def _create_theme_name():
|
||||
i = 0
|
||||
while 'newtheme%s' % i in app.css_config.themes:
|
||||
i += 1
|
||||
return 'newtheme%s' % i
|
||||
|
||||
def _on_remove_theme(self, *args):
|
||||
store, iter_ = self._theme_treeview.get_selection().get_selected()
|
||||
if iter_ is None:
|
||||
return
|
||||
|
||||
theme = store[iter_][Column.THEME]
|
||||
if theme == app.config.get('roster_theme'):
|
||||
ErrorDialog(
|
||||
_('Active Theme'),
|
||||
_('You tried to delete the currently active theme. '
|
||||
'Please switch to a different theme first.'),
|
||||
transient_for=self)
|
||||
return
|
||||
|
||||
def _remove_theme():
|
||||
app.css_config.remove_theme(theme)
|
||||
store.remove(iter_)
|
||||
|
||||
first = store.get_iter_first()
|
||||
if first is None:
|
||||
self._remove_theme_button.set_sensitive(False)
|
||||
self._add_option_button.set_sensitive(False)
|
||||
self._clear_options()
|
||||
|
||||
buttons = {
|
||||
Gtk.ResponseType.CANCEL: DialogButton('Keep Theme'),
|
||||
Gtk.ResponseType.OK: DialogButton('Delete',
|
||||
_remove_theme,
|
||||
ButtonAction.DESTRUCTIVE),
|
||||
}
|
||||
|
||||
NewConfirmationDialog('Delete Theme',
|
||||
'Do you want to permanently delete this theme?',
|
||||
buttons,
|
||||
transient_for=self)
|
||||
|
||||
@staticmethod
|
||||
def _on_destroy(*args):
|
||||
window = app.get_app_window('Preferences')
|
||||
if window is not None:
|
||||
window.update_theme_list()
|
||||
|
||||
|
||||
class Option(Gtk.ListBoxRow):
|
||||
def __init__(self, option, value):
|
||||
Gtk.ListBoxRow.__init__(self)
|
||||
self._option = option
|
||||
self._box = Gtk.Box(spacing=12)
|
||||
|
||||
label = Gtk.Label()
|
||||
label.set_text(option.label)
|
||||
label.set_hexpand(True)
|
||||
label.set_halign(Gtk.Align.START)
|
||||
self._box.add(label)
|
||||
|
||||
if option.attr in (StyleAttr.COLOR, StyleAttr.BACKGROUND):
|
||||
self._init_color(value)
|
||||
elif option.attr == StyleAttr.FONT:
|
||||
self._init_font(value)
|
||||
|
||||
remove_button = Gtk.Button.new_from_icon_name(
|
||||
'list-remove-symbolic', Gtk.IconSize.MENU)
|
||||
remove_button.get_style_context().add_class('theme_remove_button')
|
||||
remove_button.connect('clicked', self._on_remove)
|
||||
self._box.add(remove_button)
|
||||
|
||||
self.add(self._box)
|
||||
self.show_all()
|
||||
|
||||
def _init_color(self, color):
|
||||
color_button = Gtk.ColorButton()
|
||||
if color is not None:
|
||||
rgba = Gdk.RGBA()
|
||||
rgba.parse(color)
|
||||
color_button.set_rgba(rgba)
|
||||
color_button.set_halign(Gtk.Align.END)
|
||||
color_button.connect('color-set', self._on_color_set)
|
||||
self._box.add(color_button)
|
||||
|
||||
def _init_font(self, desc):
|
||||
font_button = Gtk.FontButton()
|
||||
if desc is not None:
|
||||
font_button.set_font_desc(desc)
|
||||
font_button.set_halign(Gtk.Align.END)
|
||||
font_button.connect('font-set', self._on_font_set)
|
||||
self._box.add(font_button)
|
||||
|
||||
def _on_color_set(self, color_button):
|
||||
color = color_button.get_rgba()
|
||||
color_string = color.to_string()
|
||||
app.css_config.set_value(
|
||||
self._option.selector, self._option.attr, color_string, pre=True)
|
||||
app.nec.push_incoming_event(StyleChanged(None))
|
||||
|
||||
def _on_font_set(self, font_button):
|
||||
desc = font_button.get_font_desc()
|
||||
app.css_config.set_font(self._option.selector, desc, pre=True)
|
||||
app.nec.push_incoming_event(StyleChanged(None,))
|
||||
|
||||
def _on_remove(self, *args):
|
||||
self.get_parent().remove(self)
|
||||
app.css_config.remove_value(
|
||||
self._option.selector, self._option.attr, pre=True)
|
||||
app.nec.push_incoming_event(StyleChanged(None))
|
||||
self.destroy()
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, ChooseOption):
|
||||
return other.option == self._option
|
||||
else:
|
||||
return other._option == self._option
|
||||
|
||||
|
||||
class ChooseOption(Gtk.ListBoxRow):
|
||||
def __init__(self, option):
|
||||
Gtk.ListBoxRow.__init__(self)
|
||||
self.option = option
|
||||
label = Gtk.Label(option.label)
|
||||
label.set_xalign(0)
|
||||
self.add(label)
|
||||
self.show_all()
|
|
@ -207,3 +207,14 @@ def python_month(month):
|
|||
|
||||
def gtk_month(month):
|
||||
return month - 1
|
||||
|
||||
|
||||
def convert_rgb_to_hex(rgb_string):
|
||||
rgb = Gdk.RGBA()
|
||||
rgb.parse(rgb_string)
|
||||
rgb.to_color()
|
||||
|
||||
red = int(rgb.red * 255)
|
||||
green = int(rgb.green * 255)
|
||||
blue = int(rgb.blue * 255)
|
||||
return '#%02x%02x%02x' % (red, green, blue)
|
||||
|
|
|
@ -21,7 +21,7 @@ from gi.repository import GLib
|
|||
|
||||
from gajim.common import app
|
||||
from gajim.common import ged
|
||||
from gajim.common.const import Option, OptionKind, OptionType
|
||||
from gajim.common.const import Option, OptionKind, OptionType, StyleAttr
|
||||
from gajim.gtk import ErrorDialog
|
||||
from gajim.gtk import util
|
||||
from gajim.gtk.util import get_builder
|
||||
|
@ -97,8 +97,10 @@ class XMLConsoleWindow(Gtk.Window):
|
|||
|
||||
def create_tags(self):
|
||||
buffer_ = self.textview.get_buffer()
|
||||
in_color = app.config.get('inmsgcolor')
|
||||
out_color = app.config.get('outmsgcolor')
|
||||
in_color = app.css_config.get_value(
|
||||
'.gajim-incoming-nickname', StyleAttr.COLOR)
|
||||
out_color = app.css_config.get_value(
|
||||
'.gajim-outgoing-nickname', StyleAttr.COLOR)
|
||||
|
||||
tags = ['presence', 'message', 'stream', 'iq']
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ import os
|
|||
import sys
|
||||
import math
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
try:
|
||||
from PIL import Image
|
||||
except:
|
||||
|
@ -172,22 +173,6 @@ def get_completion_liststore(entry):
|
|||
entry.set_completion(completion)
|
||||
return liststore
|
||||
|
||||
def get_theme_font_for_option(theme, option):
|
||||
"""
|
||||
Return string description of the font, stored in theme preferences
|
||||
"""
|
||||
font_name = app.config.get_per('themes', theme, option)
|
||||
font_desc = Pango.FontDescription()
|
||||
font_prop_str = app.config.get_per('themes', theme, option + 'attrs')
|
||||
if font_prop_str:
|
||||
if font_prop_str.find('B') != -1:
|
||||
font_desc.set_weight(Pango.Weight.BOLD)
|
||||
if font_prop_str.find('I') != -1:
|
||||
font_desc.set_style(Pango.Style.ITALIC)
|
||||
fd = Pango.FontDescription(font_name)
|
||||
fd.merge(font_desc, True)
|
||||
return fd.to_string()
|
||||
|
||||
def move_window(window, x, y):
|
||||
"""
|
||||
Move the window, but also check if out of screen
|
||||
|
@ -812,71 +797,19 @@ def __label_size_allocate(widget, allocation):
|
|||
def get_action(action):
|
||||
return app.app.lookup_action(action)
|
||||
|
||||
def load_css():
|
||||
path = os.path.join(configpaths.get('DATA'), 'style', 'gajim.css')
|
||||
try:
|
||||
with open(path, "r") as f:
|
||||
css = f.read()
|
||||
except Exception as exc:
|
||||
print('Error loading css: %s', exc)
|
||||
return
|
||||
def add_css_class(widget, class_name, prefix=None):
|
||||
if class_name and prefix:
|
||||
class_name = prefix + class_name
|
||||
|
||||
provider = Gtk.CssProvider()
|
||||
css = "\n".join((css, convert_config_to_css()))
|
||||
provider.load_from_data(bytes(css.encode()))
|
||||
Gtk.StyleContext.add_provider_for_screen(
|
||||
Gdk.Screen.get_default(),
|
||||
provider,
|
||||
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
|
||||
|
||||
def convert_config_to_css():
|
||||
css = ''
|
||||
themed_widgets = {
|
||||
'ChatControl-BannerEventBox': ('bannerbgcolor', 'background'),
|
||||
'ChatControl-BannerNameLabel': ('bannertextcolor', 'color'),
|
||||
'ChatControl-BannerLabel': ('bannertextcolor', 'color'),
|
||||
'GroupChatControl-BannerEventBox': ('bannerbgcolor', 'background'),
|
||||
'GroupChatControl-BannerNameLabel': ('bannertextcolor', 'color'),
|
||||
'GroupChatControl-BannerLabel': ('bannertextcolor', 'color'),
|
||||
'Discovery-BannerEventBox': ('bannerbgcolor', 'background'),
|
||||
'Discovery-BannerLabel': ('bannertextcolor', 'color')}
|
||||
|
||||
classes = {'state_composing_color': ('', 'color'),
|
||||
'state_inactive_color': ('', 'color'),
|
||||
'state_gone_color': ('', 'color'),
|
||||
'state_paused_color': ('', 'color'),
|
||||
'msgcorrectingcolor': ('text', 'background'),
|
||||
'state_muc_directed_msg_color': ('', 'color'),
|
||||
'state_muc_msg_color': ('', 'color')}
|
||||
|
||||
|
||||
theme = app.config.get('roster_theme')
|
||||
for key, values in themed_widgets.items():
|
||||
config, attr = values
|
||||
css += '#{} {{'.format(key)
|
||||
value = app.config.get_per('themes', theme, config)
|
||||
if value:
|
||||
css += '{attr}: {color};\n'.format(attr=attr, color=value)
|
||||
css += '}\n'
|
||||
|
||||
for key, values in classes.items():
|
||||
node, attr = values
|
||||
value = app.config.get_per('themes', theme, key)
|
||||
if value:
|
||||
css += '.theme_{cls} {node} {{ {attr}: {color}; }}\n'.format(
|
||||
cls=key, node=node, attr=attr, color=value)
|
||||
|
||||
css += add_css_font()
|
||||
|
||||
return css
|
||||
|
||||
def add_css_class(widget, class_name):
|
||||
style = widget.get_style_context()
|
||||
for css_cls in style.list_classes():
|
||||
if css_cls.startswith('theme_'):
|
||||
style.remove_class(css_cls)
|
||||
if class_name:
|
||||
style.add_class('theme_' + class_name)
|
||||
if prefix is not None:
|
||||
# Remove all css classes with prefix
|
||||
for css_cls in style.list_classes():
|
||||
if css_cls.startswith(prefix):
|
||||
style.remove_class(css_cls)
|
||||
|
||||
if class_name is not None:
|
||||
style.add_class(class_name)
|
||||
|
||||
def add_css_to_widget(widget, css):
|
||||
provider = Gtk.CssProvider()
|
||||
|
@ -887,28 +820,7 @@ def add_css_to_widget(widget, css):
|
|||
|
||||
def remove_css_class(widget, class_name):
|
||||
style = widget.get_style_context()
|
||||
style.remove_class('theme_' + class_name)
|
||||
|
||||
def add_css_font():
|
||||
conversation_font = app.config.get('conversation_font')
|
||||
if not conversation_font:
|
||||
return ''
|
||||
font = Pango.FontDescription(conversation_font)
|
||||
unit = "pt" if Gtk.check_version(3, 22, 0) is None else "px"
|
||||
css = """
|
||||
.font_custom {{
|
||||
font-family: "{family}";
|
||||
font-size: {size}{unit};
|
||||
font-weight: {weight};
|
||||
}}""".format(
|
||||
family=font.get_family(),
|
||||
size=int(round(font.get_size() / Pango.SCALE)),
|
||||
unit=unit,
|
||||
weight=pango_to_css_weight(font.get_weight()))
|
||||
css = css.replace("font-size: 0{unit};".format(unit=unit), "")
|
||||
css = css.replace("font-weight: 0;", "")
|
||||
css = "\n".join(filter(lambda x: x.strip(), css.splitlines()))
|
||||
return css
|
||||
style.remove_class(class_name)
|
||||
|
||||
def draw_affiliation(surface, affiliation):
|
||||
icon_size = 16
|
||||
|
|
|
@ -2655,15 +2655,6 @@ class Interface:
|
|||
self.gpg_passphrase = {}
|
||||
self.pass_dialog = {}
|
||||
self.db_error_dialog = None
|
||||
self.default_colors = {
|
||||
'inmsgcolor': app.config.get('inmsgcolor'),
|
||||
'outmsgcolor': app.config.get('outmsgcolor'),
|
||||
'inmsgtxtcolor': app.config.get('inmsgtxtcolor'),
|
||||
'outmsgtxtcolor': app.config.get('outmsgtxtcolor'),
|
||||
'statusmsgcolor': app.config.get('statusmsgcolor'),
|
||||
'urlmsgcolor': app.config.get('urlmsgcolor'),
|
||||
'markedmsgcolor': app.config.get('markedmsgcolor'),
|
||||
}
|
||||
|
||||
self.handlers = {}
|
||||
self.roster = None
|
||||
|
@ -2684,6 +2675,9 @@ class Interface:
|
|||
# enable plugin_installer by default when creating config file
|
||||
app.config.set_per('plugins', 'plugin_installer', 'active', True)
|
||||
|
||||
# Load CSS files
|
||||
app.load_css_config()
|
||||
|
||||
app.logger.reset_shown_unread_messages()
|
||||
# override logging settings from config (don't take care of '-q' option)
|
||||
if app.config.get('verbose'):
|
||||
|
@ -2721,24 +2715,7 @@ class Interface:
|
|||
default[msg][4])
|
||||
app.config.set_per('statusmsg', msg, 'mood_text',
|
||||
default[msg][5])
|
||||
#add default themes if there is not in the config file
|
||||
theme = app.config.get('roster_theme')
|
||||
if not theme in app.config.get_per('themes'):
|
||||
app.config.set('roster_theme', _('default'))
|
||||
if len(app.config.get_per('themes')) == 0:
|
||||
d = ['accounttextcolor', 'accountbgcolor', 'accountfont',
|
||||
'accountfontattrs', 'grouptextcolor', 'groupbgcolor',
|
||||
'groupfont', 'groupfontattrs', 'contacttextcolor',
|
||||
'contactbgcolor', 'contactfont', 'contactfontattrs',
|
||||
'bannertextcolor', 'bannerbgcolor']
|
||||
|
||||
default = app.config.themes_default
|
||||
for theme_name in default:
|
||||
app.config.add_per('themes', theme_name)
|
||||
theme = default[theme_name]
|
||||
for o in d:
|
||||
app.config.set_per('themes', theme_name, o,
|
||||
theme[d.index(o)])
|
||||
# Add Tor proxy if there is not in the config
|
||||
if len(app.config.get_per('proxies')) == 0:
|
||||
default = app.config.proxies_default
|
||||
|
|
|
@ -48,7 +48,7 @@ from gi.repository import Gio
|
|||
|
||||
from gajim.common import i18n
|
||||
from gajim.common import configpaths
|
||||
|
||||
from gajim.common.const import StyleAttr
|
||||
|
||||
def is_standalone():
|
||||
# Determine if we are in standalone mode
|
||||
|
@ -395,14 +395,14 @@ class HistoryManager:
|
|||
if kind in (KindConstant.SINGLE_MSG_RECV,
|
||||
KindConstant.CHAT_MSG_RECV, KindConstant.GC_MSG):
|
||||
# it is the other side
|
||||
color = app.config.get('inmsgcolor') # so incoming color
|
||||
color = app.css_config.get_value('.gajim-incoming-nickname', StyleAttr.COLOR) # so incoming color
|
||||
elif kind in (KindConstant.SINGLE_MSG_SENT,
|
||||
KindConstant.CHAT_MSG_SENT): # it is us
|
||||
color = app.config.get('outmsgcolor') # so outgoing color
|
||||
color = app.css_config.get_value('.gajim-outgoing-nickname', StyleAttr.COLOR) # so outgoing color
|
||||
elif kind in (KindConstant.STATUS,
|
||||
KindConstant.GCSTATUS): # is is statuses
|
||||
# so status color
|
||||
color = app.config.get('statusmsgcolor')
|
||||
color = app.css_config.get_value('.gajim-status-message', StyleAttr.COLOR)
|
||||
# include status into (status) message
|
||||
if message is None:
|
||||
message = ''
|
||||
|
|
|
@ -57,6 +57,8 @@ from gajim.gtk.util import get_builder
|
|||
from gajim.common import helpers
|
||||
from gajim.gtk import JoinGroupchatWindow
|
||||
from gajim.gtk import AddNewContactWindow
|
||||
from gajim.common.const import StyleAttr
|
||||
|
||||
|
||||
import logging
|
||||
log = logging.getLogger('gajim.htmlview')
|
||||
|
@ -514,7 +516,7 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
|||
tag.href = href
|
||||
tag.type_ = type_ # to be used by the URL handler
|
||||
tag.connect('event', self.textview.hyperlink_handler, 'url')
|
||||
tag.set_property('foreground', app.config.get('urlmsgcolor'))
|
||||
tag.set_property('foreground', app.css_config.get_value('.gajim-url', StyleAttr.COLOR))
|
||||
tag.set_property('underline', Pango.Underline.SINGLE)
|
||||
tag.is_anchor = True
|
||||
if title:
|
||||
|
@ -855,7 +857,7 @@ class HtmlTextView(Gtk.TextView):
|
|||
buffer_ = self.get_buffer()
|
||||
|
||||
self.tagURL = buffer_.create_tag('url')
|
||||
color = app.config.get('urlmsgcolor')
|
||||
color = app.css_config.get_value('.gajim-url', StyleAttr.COLOR)
|
||||
self.tagURL.set_property('foreground', color)
|
||||
self.tagURL.set_property('underline', Pango.Underline.SINGLE)
|
||||
self.tagURL.connect('event', self.hyperlink_handler, 'url')
|
||||
|
|
|
@ -55,7 +55,7 @@ class MessageTextView(Gtk.TextView):
|
|||
self.set_right_margin(2)
|
||||
self.set_pixels_above_lines(2)
|
||||
self.set_pixels_below_lines(2)
|
||||
self.get_style_context().add_class('font_custom')
|
||||
self.get_style_context().add_class('gajim-conversation-font')
|
||||
|
||||
# set undo list
|
||||
self.undo_list = []
|
||||
|
|
|
@ -643,15 +643,14 @@ class MessageWindow(object):
|
|||
if isinstance(ctrl, ChatControl):
|
||||
tab_label_str = ctrl.get_tab_label()
|
||||
# Set Label Color
|
||||
class_name = 'state_{}_color'.format(chatstate)
|
||||
gtkgui_helpers.add_css_class(nick_label, class_name)
|
||||
gtkgui_helpers.add_css_class(nick_label, chatstate, 'gajim-state-')
|
||||
else:
|
||||
tab_label_str, color = ctrl.get_tab_label(chatstate)
|
||||
# Set Label Color
|
||||
if color == 'active':
|
||||
gtkgui_helpers.add_css_class(nick_label, None)
|
||||
gtkgui_helpers.add_css_class(nick_label, None, 'gajim-state-')
|
||||
elif color is not None:
|
||||
gtkgui_helpers.add_css_class(nick_label, color)
|
||||
gtkgui_helpers.add_css_class(nick_label, color, 'gajim-state-')
|
||||
|
||||
nick_label.set_markup(tab_label_str)
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ from gajim import tooltips
|
|||
from gajim import message_control
|
||||
from gajim import adhoc_commands
|
||||
from gajim.accounts_window import AccountsWindow
|
||||
|
||||
from gajim.gtk import JoinGroupchatWindow
|
||||
from gajim.gtk import ConfirmationDialogCheck
|
||||
from gajim.gtk import ConfirmationDialog
|
||||
|
@ -73,14 +74,12 @@ from gajim.gtk import AccountCreationWizard
|
|||
from gajim.gtk import ServiceRegistration
|
||||
from gajim.gtk import HistoryWindow
|
||||
|
||||
from gajim.common.const import AvatarSize
|
||||
|
||||
from gajim.common import app
|
||||
from gajim.common import helpers
|
||||
from gajim.common import idle
|
||||
from gajim.common.exceptions import GajimGeneralException
|
||||
from gajim.common import i18n
|
||||
from gajim.common.const import PEPEventType
|
||||
from gajim.common.const import PEPEventType, AvatarSize, StyleAttr
|
||||
if app.is_installed('GEOCLUE'):
|
||||
from gajim.common import location_listener
|
||||
from gajim.common import ged
|
||||
|
@ -1265,15 +1264,11 @@ class RosterWindow:
|
|||
status = helpers.reduce_chars_newlines(status,
|
||||
max_lines = 1)
|
||||
# escape markup entities and make them small
|
||||
# italic and fg color color is calculated to be
|
||||
# always readable
|
||||
color = gtkgui_helpers.get_fade_color(self.tree, selected,
|
||||
focus)
|
||||
colorstring = '#%04x%04x%04x' % (int(color.red * 65535),
|
||||
int(color.green * 65535), int(color.blue * 65535))
|
||||
name += '\n<span size="small" style="italic" ' \
|
||||
'foreground="%s">%s</span>' % (colorstring,
|
||||
GLib.markup_escape_text(status))
|
||||
|
||||
# italic
|
||||
name += ('\n<span size="small" style="italic" '
|
||||
'alpha="70%">{}</span>'.format(
|
||||
GLib.markup_escape_text(status)))
|
||||
|
||||
icon_name = helpers.get_icon_name_to_show(contact, account)
|
||||
# look if another resource has awaiting events
|
||||
|
@ -4688,6 +4683,9 @@ class RosterWindow:
|
|||
|
||||
gtkgui_helpers.set_unset_urgency_hint(self.window, nb_unread)
|
||||
|
||||
def _style_changed(self, *args):
|
||||
self.change_roster_style(None)
|
||||
|
||||
def _change_style(self, model, path, titer, option):
|
||||
if option is None or model[titer][Column.TYPE] == option:
|
||||
# We changed style for this type of row
|
||||
|
@ -4751,18 +4749,18 @@ class RosterWindow:
|
|||
return
|
||||
theme = app.config.get('roster_theme')
|
||||
if type_ == 'account':
|
||||
color = app.config.get_per('themes', theme, 'accounttextcolor')
|
||||
renderer.set_property('foreground', color or None)
|
||||
renderer.set_property('font',
|
||||
gtkgui_helpers.get_theme_font_for_option(theme, 'accountfont'))
|
||||
color = app.css_config.get_value('.gajim-account-row', StyleAttr.COLOR)
|
||||
renderer.set_property('foreground', color)
|
||||
desc = app.css_config.get_font('.gajim-account-row')
|
||||
renderer.set_property('font-desc', desc)
|
||||
renderer.set_property('xpad', 0)
|
||||
renderer.set_property('width', 3)
|
||||
self._set_account_row_background_color(renderer)
|
||||
elif type_ == 'group':
|
||||
color = app.config.get_per('themes', theme, 'grouptextcolor')
|
||||
renderer.set_property('foreground', color or None)
|
||||
renderer.set_property('font',
|
||||
gtkgui_helpers.get_theme_font_for_option(theme, 'groupfont'))
|
||||
color = app.css_config.get_value('.gajim-group-row', StyleAttr.COLOR)
|
||||
renderer.set_property('foreground', color)
|
||||
desc = app.css_config.get_font('.gajim-group-row')
|
||||
renderer.set_property('font-desc', desc)
|
||||
parent_iter = model.iter_parent(titer)
|
||||
if model[parent_iter][Column.TYPE] == 'group':
|
||||
renderer.set_property('xpad', 8)
|
||||
|
@ -4781,19 +4779,16 @@ class RosterWindow:
|
|||
ctrl = app.interface.minimized_controls[account].get(jid,
|
||||
None)
|
||||
if ctrl and ctrl.attention_flag:
|
||||
color = app.config.get_per('themes', theme,
|
||||
'state_muc_directed_msg_color')
|
||||
renderer.set_property('foreground', 'red')
|
||||
color = app.css_config.get_value(
|
||||
'.state_muc_directed_msg_color', StyleAttr.COLOR)
|
||||
renderer.set_property('foreground', color)
|
||||
if not color:
|
||||
color = app.config.get_per('themes', theme,
|
||||
'contacttextcolor')
|
||||
if color:
|
||||
color = app.css_config.get_value('.gajim-contact-row', StyleAttr.COLOR)
|
||||
renderer.set_property('foreground', color)
|
||||
else:
|
||||
renderer.set_property('foreground', None)
|
||||
|
||||
self._set_contact_row_background_color(renderer, jid, account)
|
||||
renderer.set_property('font',
|
||||
gtkgui_helpers.get_theme_font_for_option(theme, 'contactfont'))
|
||||
desc = app.css_config.get_font('.gajim-contact-row')
|
||||
renderer.set_property('font-desc', desc)
|
||||
parent_iter = model.iter_parent(titer)
|
||||
if model[parent_iter][Column.TYPE] == 'contact':
|
||||
renderer.set_property('xpad', 16)
|
||||
|
@ -4886,25 +4881,25 @@ class RosterWindow:
|
|||
|
||||
def _set_account_row_background_color(self, renderer):
|
||||
theme = app.config.get('roster_theme')
|
||||
color = app.config.get_per('themes', theme, 'accountbgcolor')
|
||||
renderer.set_property('cell-background', color or None)
|
||||
color = app.css_config.get_value('.gajim-account-row', StyleAttr.BACKGROUND)
|
||||
renderer.set_property('cell-background', color)
|
||||
|
||||
def _set_contact_row_background_color(self, renderer, jid, account):
|
||||
theme = app.config.get('roster_theme')
|
||||
if jid in app.newly_added[account]:
|
||||
renderer.set_property('cell-background', app.config.get(
|
||||
'just_connected_bg_color'))
|
||||
renderer.set_property('cell-background', app.css_config.get_value(
|
||||
'.gajim-roster-connected', StyleAttr.BACKGROUND))
|
||||
elif jid in app.to_be_removed[account]:
|
||||
renderer.set_property('cell-background', app.config.get(
|
||||
'just_disconnected_bg_color'))
|
||||
renderer.set_property('cell-background', app.css_config.get_value(
|
||||
'.gajim-roster-disconnected', StyleAttr.BACKGROUND))
|
||||
else:
|
||||
color = app.config.get_per('themes', theme, 'contactbgcolor')
|
||||
renderer.set_property('cell-background', color or None)
|
||||
color = app.css_config.get_value('.gajim-contact-row', StyleAttr.BACKGROUND)
|
||||
renderer.set_property('cell-background', color)
|
||||
|
||||
def _set_group_row_background_color(self, renderer):
|
||||
theme = app.config.get('roster_theme')
|
||||
color = app.config.get_per('themes', theme, 'groupbgcolor')
|
||||
renderer.set_property('cell-background', color or None)
|
||||
color = app.css_config.get_value('.gajim-group-row', 'background')
|
||||
renderer.set_property('cell-background', color)
|
||||
|
||||
################################################################################
|
||||
### Everything about building menus
|
||||
|
@ -5945,3 +5940,5 @@ class RosterWindow:
|
|||
self._nec_decrypted_message_received)
|
||||
app.ged.register_event_handler('blocking', ged.GUI1,
|
||||
self._nec_blocking)
|
||||
app.ged.register_event_handler('style-changed', ged.GUI1,
|
||||
self._style_changed)
|
||||
|
|
Loading…
Reference in New Issue