9578053 Jan 22 2022 distfiles.gentoo.org/distfiles/gajim-1.3.3-2.tar.gz
This commit is contained in:
parent
a5b3822651
commit
4c1b226bff
1045 changed files with 753037 additions and 18 deletions
778
gajim/gtk/vcard_grid.py
Normal file
778
gajim/gtk/vcard_grid.py
Normal file
|
|
@ -0,0 +1,778 @@
|
|||
# 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/>.
|
||||
|
||||
import datetime
|
||||
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import GLib
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GObject
|
||||
|
||||
from gajim.common.i18n import _
|
||||
from gajim.common.i18n import Q_
|
||||
from gajim.common.const import URIType
|
||||
from gajim.common.helpers import open_uri
|
||||
from gajim.common.helpers import parse_uri
|
||||
from gajim.common.structs import URI
|
||||
from gajim.gui.util import gtk_month
|
||||
from gajim.gui.util import python_month
|
||||
|
||||
|
||||
LABEL_DICT = {
|
||||
'fn': _('Full Name'),
|
||||
'n': _('Name'),
|
||||
'bday': _('Birthday'),
|
||||
'gender': _('Gender'),
|
||||
'adr': Q_('?profile:Address'),
|
||||
'tel': _('Phone No.'),
|
||||
'email': _('Email'),
|
||||
'impp': _('IM Address'),
|
||||
'title': Q_('?profile:Title'),
|
||||
'role': Q_('?profile:Role'),
|
||||
'org': _('Organisation'),
|
||||
'note': Q_('?profile:Note'),
|
||||
'url': _('URL'),
|
||||
'key': Q_('?profile:Public Encryption Key'),
|
||||
}
|
||||
|
||||
|
||||
FIELD_TOOLTIPS = {
|
||||
'key': _('Your public key or authentication certificate')
|
||||
}
|
||||
|
||||
|
||||
ADR_FIELDS = ['street', 'ext', 'pobox', 'code', 'locality', 'region', 'country']
|
||||
|
||||
|
||||
ADR_PLACEHOLDER_TEXT = {
|
||||
'pobox': _('Post Office Box'),
|
||||
'street': _('Street'),
|
||||
'ext': _('Extended Address'),
|
||||
'locality': _('City'),
|
||||
'region': _('State'),
|
||||
'code': _('Postal Code'),
|
||||
'country': _('Country'),
|
||||
}
|
||||
|
||||
|
||||
DEFAULT_KWARGS = {
|
||||
'fn': {'value': ''},
|
||||
'bday': {'value': '', 'value_type': 'date'},
|
||||
'gender': {'sex': '', 'identity': ''},
|
||||
'adr': {},
|
||||
'email': {'value': ''},
|
||||
'impp': {'value': ''},
|
||||
'tel': {'value': '', 'value_type': 'text'},
|
||||
'org': {'values': []},
|
||||
'title': {'value': ''},
|
||||
'role': {'value': ''},
|
||||
'url': {'value': ''},
|
||||
'key': {'value': '', 'value_type': 'text'},
|
||||
'note': {'value': ''},
|
||||
}
|
||||
|
||||
|
||||
PROPERTIES_WITH_TYPE = [
|
||||
'adr',
|
||||
'email',
|
||||
'impp',
|
||||
'tel',
|
||||
'key',
|
||||
]
|
||||
|
||||
|
||||
ORDER = [
|
||||
'fn',
|
||||
'gender',
|
||||
'bday',
|
||||
'adr',
|
||||
'email',
|
||||
'impp',
|
||||
'tel',
|
||||
'org',
|
||||
'title',
|
||||
'role',
|
||||
'url',
|
||||
'key',
|
||||
'note',
|
||||
]
|
||||
|
||||
|
||||
SEX_VALUES = {
|
||||
'M': _('Male'),
|
||||
'F': _('Female'),
|
||||
'O': Q_('?Gender:Other'),
|
||||
'N': Q_('?Gender:None'),
|
||||
'U': _('Unknown')
|
||||
}
|
||||
|
||||
|
||||
TYPE_VALUES = {
|
||||
'-': None,
|
||||
'home': _('Home'),
|
||||
'work': _('Work')
|
||||
}
|
||||
|
||||
|
||||
class VCardGrid(Gtk.Grid):
|
||||
def __init__(self, account):
|
||||
Gtk.Grid.__init__(self)
|
||||
|
||||
self._callbacks = {
|
||||
'fn': TextEntryProperty,
|
||||
'bday': DateProperty,
|
||||
'gender': GenderProperty,
|
||||
'adr': AdrProperty,
|
||||
'tel': TextEntryProperty,
|
||||
'email': TextEntryProperty,
|
||||
'impp': TextEntryProperty,
|
||||
'title': TextEntryProperty,
|
||||
'role': TextEntryProperty,
|
||||
'org': TextEntryProperty,
|
||||
'url': TextEntryProperty,
|
||||
'key': KeyProperty,
|
||||
'note': MultiLineProperty,
|
||||
}
|
||||
|
||||
self.set_column_spacing(12)
|
||||
self.set_row_spacing(12)
|
||||
self.set_no_show_all(True)
|
||||
self.set_visible(True)
|
||||
self.set_halign(Gtk.Align.CENTER)
|
||||
|
||||
self._account = account
|
||||
self._row_count = 0
|
||||
self._vcard = None
|
||||
self._props = []
|
||||
|
||||
def set_editable(self, enabled):
|
||||
for prop in self._props:
|
||||
prop.set_editable(enabled)
|
||||
|
||||
def set_vcard(self, vcard):
|
||||
self.clear()
|
||||
self._vcard = vcard
|
||||
|
||||
for entry in ORDER:
|
||||
for prop in vcard.get_properties():
|
||||
if entry != prop.name:
|
||||
continue
|
||||
|
||||
self.add_property(prop)
|
||||
|
||||
def get_vcard(self):
|
||||
return self._vcard
|
||||
|
||||
def validate(self):
|
||||
for prop in list(self._props):
|
||||
base_prop = prop.get_base_property()
|
||||
if base_prop.is_empty:
|
||||
self.remove_property(prop)
|
||||
|
||||
def add_new_property(self, name):
|
||||
kwargs = DEFAULT_KWARGS[name]
|
||||
prop = self._vcard.add_property(name, **kwargs)
|
||||
self.add_property(prop, editable=True)
|
||||
|
||||
def add_property(self, prop, editable=False):
|
||||
prop_class = self._callbacks.get(prop.name)
|
||||
if prop_class is None:
|
||||
return
|
||||
prop_obj = prop_class(prop, self._account)
|
||||
prop_obj.set_editable(editable)
|
||||
prop_obj.add_to_grid(self, self._row_count)
|
||||
|
||||
self._props.append(prop_obj)
|
||||
self._row_count += 1
|
||||
|
||||
def remove_property(self, prop):
|
||||
self.remove_row(prop.row_number)
|
||||
self._props.remove(prop)
|
||||
self._vcard.remove_property(prop.get_base_property())
|
||||
|
||||
def clear(self):
|
||||
self._vcard = None
|
||||
self._row_count = 0
|
||||
for prop in list(self._props):
|
||||
self.remove_row(prop.row_number)
|
||||
|
||||
self._props = []
|
||||
|
||||
def sort(self):
|
||||
self.set_vcard(self._vcard)
|
||||
|
||||
|
||||
class DescriptionLabel(Gtk.Label):
|
||||
def __init__(self, value):
|
||||
Gtk.Label.__init__(self, label=LABEL_DICT[value])
|
||||
if value == 'adr':
|
||||
self.set_valign(Gtk.Align.START)
|
||||
else:
|
||||
self.set_valign(Gtk.Align.CENTER)
|
||||
self.get_style_context().add_class('dim-label')
|
||||
self.get_style_context().add_class('margin-right18')
|
||||
self.set_visible(True)
|
||||
self.set_xalign(1)
|
||||
self.set_tooltip_text(FIELD_TOOLTIPS.get(value, ''))
|
||||
|
||||
|
||||
class ValueLabel(Gtk.Label):
|
||||
def __init__(self, prop, account):
|
||||
Gtk.Label.__init__(self)
|
||||
self._prop = prop
|
||||
self._uri = None
|
||||
self._account = account
|
||||
self.set_selectable(True)
|
||||
self.set_xalign(0)
|
||||
self.set_max_width_chars(50)
|
||||
self.set_valign(Gtk.Align.CENTER)
|
||||
self.set_halign(Gtk.Align.START)
|
||||
|
||||
self.connect('activate-link', self._on_activate_link)
|
||||
if prop.name == 'org':
|
||||
self.set_value(prop.values[0] if prop.values else '')
|
||||
else:
|
||||
self.set_value(prop.value)
|
||||
|
||||
def set_value(self, value):
|
||||
if self._prop.name == 'email':
|
||||
self._uri = URI(type=URIType.MAIL, data=value)
|
||||
self.set_markup(value)
|
||||
|
||||
elif self._prop.name in ('impp', 'tel'):
|
||||
self._uri = parse_uri(value)
|
||||
self.set_markup(value)
|
||||
|
||||
else:
|
||||
self.set_text(value)
|
||||
|
||||
def set_markup(self, text):
|
||||
if not text:
|
||||
self.set_text('')
|
||||
return
|
||||
super().set_markup('<a href="{}">{}</a>'.format(
|
||||
GLib.markup_escape_text(text),
|
||||
GLib.markup_escape_text(text)))
|
||||
|
||||
def _on_activate_link(self, _label, _value):
|
||||
open_uri(self._uri, self._account)
|
||||
return Gdk.EVENT_STOP
|
||||
|
||||
|
||||
class SexLabel(Gtk.Label):
|
||||
def __init__(self, prop):
|
||||
Gtk.Label.__init__(self)
|
||||
self._prop = prop
|
||||
|
||||
self.set_selectable(True)
|
||||
self.set_xalign(0)
|
||||
self.set_max_width_chars(50)
|
||||
self.set_valign(Gtk.Align.CENTER)
|
||||
self.set_halign(Gtk.Align.START)
|
||||
|
||||
self.set_text(prop.sex)
|
||||
|
||||
def set_text(self, value):
|
||||
if not value or value == '-':
|
||||
super().set_text('')
|
||||
else:
|
||||
super().set_text(SEX_VALUES[value])
|
||||
|
||||
|
||||
class IdentityLabel(Gtk.Label):
|
||||
def __init__(self, prop):
|
||||
Gtk.Label.__init__(self)
|
||||
self._prop = prop
|
||||
|
||||
self.set_selectable(True)
|
||||
self.set_xalign(0)
|
||||
self.set_max_width_chars(50)
|
||||
self.set_valign(Gtk.Align.CENTER)
|
||||
self.set_halign(Gtk.Align.START)
|
||||
|
||||
self.set_text(prop.identity)
|
||||
|
||||
def set_text(self, value):
|
||||
super().set_text('' if not value else value)
|
||||
|
||||
|
||||
class ValueEntry(Gtk.Entry):
|
||||
def __init__(self, prop):
|
||||
Gtk.Entry.__init__(self)
|
||||
self.set_valign(Gtk.Align.CENTER)
|
||||
self.set_max_width_chars(50)
|
||||
if prop.name == 'org':
|
||||
self.set_text(prop.values[0] if prop.values else '')
|
||||
else:
|
||||
self.set_text(prop.value)
|
||||
|
||||
|
||||
class AdrEntry(Gtk.Entry):
|
||||
def __init__(self, prop, type_):
|
||||
Gtk.Entry.__init__(self)
|
||||
self.set_valign(Gtk.Align.CENTER)
|
||||
self.set_max_width_chars(50)
|
||||
values = getattr(prop, type_)
|
||||
if not values:
|
||||
value = ''
|
||||
else:
|
||||
value = values[0]
|
||||
self.set_text(value)
|
||||
self.set_placeholder_text(ADR_PLACEHOLDER_TEXT.get(type_))
|
||||
|
||||
|
||||
class IdentityEntry(Gtk.Entry):
|
||||
def __init__(self, prop):
|
||||
Gtk.Entry.__init__(self)
|
||||
self.set_valign(Gtk.Align.CENTER)
|
||||
self.set_max_width_chars(50)
|
||||
self.set_text('' if not prop.identity else prop.identity)
|
||||
|
||||
|
||||
class AdrBox(Gtk.Box):
|
||||
|
||||
__gsignals__ = {
|
||||
'field-changed': (
|
||||
GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION,
|
||||
None, # return value
|
||||
(str, str) # arguments
|
||||
)}
|
||||
|
||||
def __init__(self, prop):
|
||||
Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL, spacing=6)
|
||||
|
||||
for field in ADR_FIELDS:
|
||||
entry = AdrEntry(prop, field)
|
||||
entry.connect('notify::text', self._on_text_changed, field)
|
||||
self.add(entry)
|
||||
|
||||
self.show_all()
|
||||
|
||||
def _on_text_changed(self, entry, _param, field):
|
||||
self.emit('field-changed', field, entry.get_text())
|
||||
|
||||
|
||||
class AdrLabel(Gtk.Label):
|
||||
def __init__(self, prop, type_):
|
||||
Gtk.Label.__init__(self)
|
||||
self.set_selectable(True)
|
||||
self.set_xalign(0)
|
||||
self.set_max_width_chars(50)
|
||||
self.set_valign(Gtk.Align.CENTER)
|
||||
self.set_halign(Gtk.Align.START)
|
||||
values = getattr(prop, type_)
|
||||
if not values:
|
||||
value = ''
|
||||
else:
|
||||
value = values[0]
|
||||
self.set_text(value)
|
||||
|
||||
def set_text(self, value):
|
||||
self.set_visible(bool(value))
|
||||
super().set_text(value)
|
||||
|
||||
|
||||
class AdrBoxReadOnly(Gtk.Box):
|
||||
def __init__(self, prop):
|
||||
Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL, spacing=6)
|
||||
|
||||
self._labels = {}
|
||||
|
||||
for field in ADR_FIELDS:
|
||||
label = AdrLabel(prop, field)
|
||||
self._labels[field] = label
|
||||
self.add(label)
|
||||
|
||||
def set_field(self, field, value):
|
||||
self._labels[field].set_text(value)
|
||||
|
||||
|
||||
class ValueTextView(Gtk.TextView):
|
||||
def __init__(self, prop):
|
||||
Gtk.TextView.__init__(self)
|
||||
self.props.right_margin = 8
|
||||
self.props.left_margin = 8
|
||||
self.props.top_margin = 8
|
||||
self.props.bottom_margin = 8
|
||||
|
||||
self.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
|
||||
self.set_hexpand(True)
|
||||
self.set_valign(Gtk.Align.FILL)
|
||||
|
||||
self._prop = prop
|
||||
self.get_buffer().set_text(prop.value)
|
||||
self.get_buffer().connect('notify::text', self._on_text_changed)
|
||||
|
||||
def get_text(self):
|
||||
start_iter, end_iter = self.get_buffer().get_bounds()
|
||||
return self.get_buffer().get_text(start_iter, end_iter, False)
|
||||
|
||||
def _on_text_changed(self, _buffer, _param):
|
||||
self._prop.value = self.get_text()
|
||||
|
||||
|
||||
class TypeComboBox(Gtk.ComboBoxText):
|
||||
def __init__(self, parameters):
|
||||
Gtk.ComboBoxText.__init__(self)
|
||||
self.set_valign(Gtk.Align.CENTER)
|
||||
self._parameters = parameters
|
||||
self.append('-', '-')
|
||||
self.append('home', _('Home'))
|
||||
self.append('work', _('Work'))
|
||||
|
||||
values = self._parameters.get_types()
|
||||
if 'home' in values:
|
||||
self.set_active_id('home')
|
||||
|
||||
elif 'work' in values:
|
||||
self.set_active_id('work')
|
||||
|
||||
else:
|
||||
self.set_active_id('-')
|
||||
|
||||
self.connect('notify::active-id', self._on_active_id_changed)
|
||||
|
||||
def _on_active_id_changed(self, _combobox, _param):
|
||||
type_ = self.get_active_id()
|
||||
if type_ == '-':
|
||||
self._parameters.remove_types(['work', 'home'])
|
||||
|
||||
elif type_ == 'work':
|
||||
self._parameters.add_types(['work'])
|
||||
self._parameters.remove_types(['home'])
|
||||
|
||||
elif type_ == 'home':
|
||||
self._parameters.add_types(['home'])
|
||||
self._parameters.remove_types(['work'])
|
||||
|
||||
def get_text(self):
|
||||
type_value = self.get_active_id()
|
||||
if type_value == '-':
|
||||
return ''
|
||||
return self.get_active_text()
|
||||
|
||||
|
||||
class GenderComboBox(Gtk.ComboBoxText):
|
||||
def __init__(self, prop):
|
||||
Gtk.ComboBoxText.__init__(self)
|
||||
self.set_valign(Gtk.Align.CENTER)
|
||||
self.set_halign(Gtk.Align.START)
|
||||
|
||||
self._prop = prop
|
||||
|
||||
self.append('-', '-')
|
||||
for key, value in SEX_VALUES.items():
|
||||
self.append(key, value)
|
||||
|
||||
if not prop.sex:
|
||||
self.set_active_id('-')
|
||||
else:
|
||||
self.set_active_id(prop.sex)
|
||||
|
||||
|
||||
class RemoveButton(Gtk.Button):
|
||||
def __init__(self):
|
||||
Gtk.Button.__init__(self)
|
||||
self.set_valign(Gtk.Align.CENTER)
|
||||
self.set_halign(Gtk.Align.START)
|
||||
image = Gtk.Image.new_from_icon_name('user-trash-symbolic',
|
||||
Gtk.IconSize.MENU)
|
||||
self.set_image(image)
|
||||
self.set_no_show_all(True)
|
||||
|
||||
|
||||
class VCardProperty:
|
||||
def __init__(self, prop):
|
||||
self._prop = prop
|
||||
|
||||
self._second_column = []
|
||||
self._third_column = []
|
||||
|
||||
self._desc_label = DescriptionLabel(prop.name)
|
||||
self._remove_button = RemoveButton()
|
||||
self._remove_button.connect('clicked', self._on_remove_clicked)
|
||||
|
||||
self._edit_widgets = [self._remove_button]
|
||||
self._read_widgets = []
|
||||
|
||||
if prop.name in PROPERTIES_WITH_TYPE:
|
||||
self._type_combobox = TypeComboBox(prop.parameters)
|
||||
self._type_combobox.connect('notify::active-id',
|
||||
self._on_type_changed)
|
||||
type_ = self._type_combobox.get_active_id()
|
||||
icon_name = self._get_icon_name(type_)
|
||||
self._type_image = Gtk.Image.new_from_icon_name(
|
||||
icon_name, Gtk.IconSize.MENU)
|
||||
self._type_image.set_tooltip_text(TYPE_VALUES[type_])
|
||||
|
||||
if prop.name == 'adr':
|
||||
self._type_image.set_valign(Gtk.Align.START)
|
||||
self._type_combobox.set_valign(Gtk.Align.START)
|
||||
|
||||
self._edit_widgets.append(self._type_combobox)
|
||||
self._read_widgets.append(self._type_image)
|
||||
self._second_column.extend([self._type_combobox, self._type_image])
|
||||
|
||||
@staticmethod
|
||||
def _get_icon_name(type_):
|
||||
if type_ == 'home':
|
||||
return 'feather-home'
|
||||
if type_ == 'work':
|
||||
return 'feather-briefcase'
|
||||
return None
|
||||
|
||||
def _on_type_changed(self, _combobox, _param):
|
||||
type_ = self._type_combobox.get_active_id()
|
||||
icon_name = self._get_icon_name(type_)
|
||||
self._type_image.set_from_icon_name(icon_name, Gtk.IconSize.MENU)
|
||||
self._type_image.set_tooltip_text(TYPE_VALUES[type_])
|
||||
|
||||
def _on_remove_clicked(self, button):
|
||||
button.get_parent().remove_property(self)
|
||||
|
||||
@property
|
||||
def row_number(self):
|
||||
grid = self._desc_label.get_parent()
|
||||
return grid.child_get_property(self._desc_label, 'top-attach')
|
||||
|
||||
def get_base_property(self):
|
||||
return self._prop
|
||||
|
||||
def set_editable(self, enabled):
|
||||
for widget in self._edit_widgets:
|
||||
widget.set_visible(enabled)
|
||||
|
||||
for widget in self._read_widgets:
|
||||
widget.set_visible(not enabled)
|
||||
|
||||
def add_to_grid(self, grid, row_number):
|
||||
# child, left, top, width, height
|
||||
grid.attach(self._desc_label, 0, row_number, 1, 1)
|
||||
|
||||
for widget in self._second_column:
|
||||
grid.attach(widget, 1, row_number, 1, 1)
|
||||
|
||||
for widget in self._third_column:
|
||||
grid.attach(widget, 2, row_number, 1, 1)
|
||||
|
||||
grid.attach(self._remove_button, 3, row_number, 1, 1)
|
||||
|
||||
|
||||
class TextEntryProperty(VCardProperty):
|
||||
def __init__(self, prop, account):
|
||||
VCardProperty.__init__(self, prop)
|
||||
|
||||
self._value_entry = ValueEntry(prop)
|
||||
self._value_entry.connect('notify::text', self._on_text_changed)
|
||||
|
||||
self._value_label = ValueLabel(prop, account)
|
||||
|
||||
self._edit_widgets.append(self._value_entry)
|
||||
self._read_widgets.append(self._value_label)
|
||||
|
||||
self._third_column = [self._value_entry, self._value_label]
|
||||
|
||||
def _on_text_changed(self, entry, _param):
|
||||
text = entry.get_text()
|
||||
if self._prop.name == 'org':
|
||||
self._prop.values = [text]
|
||||
else:
|
||||
self._prop.value = text
|
||||
self._value_label.set_value(text)
|
||||
|
||||
|
||||
class MultiLineProperty(VCardProperty):
|
||||
def __init__(self, prop, _account):
|
||||
VCardProperty.__init__(self, prop)
|
||||
|
||||
self._edit_text_view = ValueTextView(prop)
|
||||
self._edit_text_view.show()
|
||||
|
||||
self._edit_scrolled = Gtk.ScrolledWindow()
|
||||
self._edit_scrolled.set_policy(Gtk.PolicyType.NEVER,
|
||||
Gtk.PolicyType.AUTOMATIC)
|
||||
self._edit_scrolled.add(self._edit_text_view)
|
||||
self._edit_scrolled.set_valign(Gtk.Align.CENTER)
|
||||
self._edit_scrolled.set_size_request(350, 100)
|
||||
self._edit_scrolled.get_style_context().add_class('profile-scrolled')
|
||||
|
||||
self._read_text_view = ValueTextView(prop)
|
||||
self._read_text_view.set_sensitive(False)
|
||||
self._read_text_view.set_left_margin(0)
|
||||
self._read_text_view.show()
|
||||
|
||||
self._read_scrolled = Gtk.ScrolledWindow()
|
||||
self._read_scrolled.set_policy(Gtk.PolicyType.NEVER,
|
||||
Gtk.PolicyType.AUTOMATIC)
|
||||
self._read_scrolled.add(self._read_text_view)
|
||||
self._read_scrolled.set_valign(Gtk.Align.CENTER)
|
||||
self._read_scrolled.set_size_request(350, 100)
|
||||
self._read_scrolled.get_style_context().add_class(
|
||||
'profile-scrolled-read')
|
||||
|
||||
self._edit_widgets.append(self._edit_scrolled)
|
||||
self._read_widgets.append(self._read_scrolled)
|
||||
|
||||
self._third_column = [self._edit_scrolled, self._read_scrolled]
|
||||
|
||||
|
||||
class DateProperty(VCardProperty):
|
||||
def __init__(self, prop, account):
|
||||
VCardProperty.__init__(self, prop)
|
||||
|
||||
self._box = Gtk.Box(spacing=6)
|
||||
self._value_entry = ValueEntry(prop)
|
||||
self._value_entry.set_placeholder_text(_('YYYY-MM-DD'))
|
||||
self._value_entry.connect('notify::text', self._on_text_changed)
|
||||
|
||||
self._calendar_button = Gtk.MenuButton()
|
||||
image = Gtk.Image.new_from_icon_name(
|
||||
'x-office-calendar-symbolic', Gtk.IconSize.BUTTON)
|
||||
self._calendar_button.set_image(image)
|
||||
self._calendar_button.connect(
|
||||
'clicked', self._on_calendar_button_clicked)
|
||||
self._box.add(self._value_entry)
|
||||
self._box.add(self._calendar_button)
|
||||
self._box.show_all()
|
||||
|
||||
self.calendar = Gtk.Calendar(year=1980, month=5, day=15)
|
||||
self.calendar.set_visible(True)
|
||||
self.calendar.connect(
|
||||
'day-selected', self._on_calendar_day_selected)
|
||||
|
||||
popover = Gtk.Popover()
|
||||
popover.add(self.calendar)
|
||||
self._calendar_button.set_popover(popover)
|
||||
|
||||
self._value_label = ValueLabel(prop, account)
|
||||
|
||||
self._edit_widgets.append(self._box)
|
||||
self._read_widgets.append(self._value_label)
|
||||
|
||||
self._third_column = [self._box, self._value_label]
|
||||
|
||||
def _on_text_changed(self, entry, _param):
|
||||
text = entry.get_text()
|
||||
self._prop.value = text
|
||||
self._value_label.set_value(text)
|
||||
|
||||
def _on_calendar_button_clicked(self, _widget):
|
||||
birthday = self._value_entry.get_text()
|
||||
if not birthday:
|
||||
return
|
||||
try:
|
||||
date = datetime.datetime.strptime(birthday, '%Y-%m-%d')
|
||||
except ValueError:
|
||||
return
|
||||
month = gtk_month(date.month)
|
||||
self.calendar.select_month(month, date.year)
|
||||
self.calendar.select_day(date.day)
|
||||
|
||||
def _on_calendar_day_selected(self, _widget):
|
||||
year, month, day = self.calendar.get_date() # Integers
|
||||
month = python_month(month)
|
||||
date_str = datetime.date(year, month, day).strftime('%Y-%m-%d')
|
||||
self._value_entry.set_text(date_str)
|
||||
|
||||
|
||||
class KeyProperty(VCardProperty):
|
||||
def __init__(self, prop, _account):
|
||||
VCardProperty.__init__(self, prop)
|
||||
|
||||
self._value_text_view = ValueTextView(prop)
|
||||
self._value_text_view.show()
|
||||
|
||||
self._scrolled_window = Gtk.ScrolledWindow()
|
||||
self._scrolled_window.set_policy(Gtk.PolicyType.NEVER,
|
||||
Gtk.PolicyType.AUTOMATIC)
|
||||
self._scrolled_window.add(self._value_text_view)
|
||||
self._scrolled_window.set_valign(Gtk.Align.CENTER)
|
||||
self._scrolled_window.set_size_request(350, 200)
|
||||
self._scrolled_window.get_style_context().add_class('profile-scrolled')
|
||||
|
||||
self._copy_button = Gtk.Button.new_from_icon_name('edit-copy-symbolic',
|
||||
Gtk.IconSize.MENU)
|
||||
self._copy_button.connect('clicked', self._on_copy_clicked)
|
||||
self._copy_button.set_halign(Gtk.Align.START)
|
||||
self._copy_button.set_valign(Gtk.Align.CENTER)
|
||||
|
||||
self._edit_widgets.append(self._scrolled_window)
|
||||
self._read_widgets.append(self._copy_button)
|
||||
|
||||
self._third_column = [self._scrolled_window, self._copy_button]
|
||||
|
||||
def _on_copy_clicked(self, _button):
|
||||
clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
|
||||
clipboard.set_text(self._value_text_view.get_text(), -1)
|
||||
|
||||
|
||||
class GenderProperty(VCardProperty):
|
||||
def __init__(self, prop, _account):
|
||||
VCardProperty.__init__(self, prop)
|
||||
|
||||
value_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=12)
|
||||
self._value_combobox = GenderComboBox(prop)
|
||||
self._value_combobox.connect('notify::active-id',
|
||||
self._on_active_id_changed)
|
||||
self._value_combobox.show()
|
||||
|
||||
self._value_entry = IdentityEntry(prop)
|
||||
self._value_entry.show()
|
||||
self._value_entry.connect('notify::text', self._on_text_changed)
|
||||
|
||||
value_box.add(self._value_combobox)
|
||||
value_box.add(self._value_entry)
|
||||
|
||||
label_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=12)
|
||||
self._identity_label = IdentityLabel(prop)
|
||||
self._identity_label.show()
|
||||
self._sex_label = SexLabel(prop)
|
||||
self._sex_label.show()
|
||||
|
||||
label_box.add(self._sex_label)
|
||||
label_box.add(self._identity_label)
|
||||
|
||||
self._edit_widgets.append(value_box)
|
||||
self._read_widgets.append(label_box)
|
||||
|
||||
self._third_column = [value_box, label_box]
|
||||
|
||||
def _on_text_changed(self, entry, _param):
|
||||
text = entry.get_text()
|
||||
self._prop.identity = text
|
||||
self._identity_label.set_text(text)
|
||||
|
||||
def _on_active_id_changed(self, combobox, _param):
|
||||
sex = combobox.get_active_id()
|
||||
self._prop.sex = None if sex == '-' else sex
|
||||
self._sex_label.set_text(sex)
|
||||
|
||||
|
||||
class AdrProperty(VCardProperty):
|
||||
def __init__(self, prop, _account):
|
||||
VCardProperty.__init__(self, prop)
|
||||
|
||||
self._entry_box = AdrBox(prop)
|
||||
self._entry_box.connect('field-changed', self._on_field_changed)
|
||||
|
||||
self._read_box = AdrBoxReadOnly(prop)
|
||||
|
||||
self._edit_widgets.append(self._entry_box)
|
||||
self._read_widgets.append(self._read_box)
|
||||
|
||||
self._third_column = [self._entry_box, self._read_box]
|
||||
|
||||
def _on_field_changed(self, _box, field, value):
|
||||
setattr(self._prop, field, [value])
|
||||
self._read_box.set_field(field, value)
|
||||
Loading…
Add table
Add a link
Reference in a new issue