gajim.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2026
October
September
August
July
June
May
April
March
February
January
2025
December
November
October
September
August
July
June
May
April
March
February
January
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
List overview
Download
Commits
November 2021
----- 2026 -----
October 2026
September 2026
August 2026
July 2026
June 2026
May 2026
April 2026
March 2026
February 2026
January 2026
----- 2025 -----
December 2025
November 2025
October 2025
September 2025
August 2025
July 2025
June 2025
May 2025
April 2025
March 2025
February 2025
January 2025
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
commits@gajim.org
1 participants
101 discussions
Start a n
N
ew thread
[Git][gajim/gajim][master] 2 commits: HistoryManager: Fix #10682
by Daniel Brötzmann (@wurstsalat)
24 Nov '21
24 Nov '21
Daniel Brötzmann pushed to branch master at gajim / gajim Commits: 6015434b by wurstsalat at 2021-11-24T22:23:46+01:00 HistoryManager: Fix #10682 - - - - - 868a9f21 by wurstsalat at 2021-11-24T22:45:15+01:00 HistoryManager: Typing, Linting - - - - - 1 changed file: - gajim/history_manager.py Changes: ===================================== gajim/history_manager.py ===================================== @@ -25,6 +25,8 @@ # that abstracts db connections and helpers on it # the same can be said for history.py +from typing import List + import os import sys import time @@ -57,7 +59,7 @@ from gajim.common.const import ShowConstant -def is_standalone(): +def is_standalone() -> bool: # Determine if we are in standalone mode if Gio.Application.get_default() is None: return True @@ -66,7 +68,7 @@ def is_standalone(): return False -def init_gtk(): +def init_gtk() -> None: gajim.gui.init('gtk') from gajim.gui import exception exception.init() @@ -92,7 +94,8 @@ def init_gtk(): _('Options:') + \ '\n -h, --help ' + \ _('Show this help message and exit') + \ - '\n -c, --config-path ' + _('Choose folder for logfile') + '\n') + '\n -c, --config-path ' + _('Choose folder for logfile') + \ + '\n') sys.exit() elif o in ('-c', '--config-path'): configpaths.set_config_root(a) @@ -123,7 +126,7 @@ class Column(IntEnum): class HistoryManager: - def __init__(self): + def __init__(self) -> None: log_db_path = configpaths.get('LOG_DB') if not log_db_path.exists(): ErrorDialog(_('Cannot find history logs database'), @@ -134,7 +137,8 @@ def __init__(self): Gtk.Window.set_default_icon_list(get_app_icon_list( self._ui.history_manager_window)) - self.jids_already_in = [] # holds jids that we already have in DB + # holds jids that we already have in DB + self.jids_already_in: List[str] = [] self.AT_LEAST_ONE_DELETION_DONE = False self.con = sqlite3.connect( @@ -154,10 +158,11 @@ def __init__(self): self._ui.connect_signals(self) - def _init_jids_listview(self): + def _init_jids_listview(self) -> None: self.jids_liststore = Gtk.ListStore(str, str) # jid, jid_id self._ui.jids_listview.set_model(self.jids_liststore) - self._ui.jids_listview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) + self._ui.jids_listview.get_selection().set_mode( + Gtk.SelectionMode.MULTIPLE) renderer_text = Gtk.CellRendererText() # holds jid col = Gtk.TreeViewColumn(_('XMPP Address'), renderer_text, text=0) @@ -166,21 +171,24 @@ def _init_jids_listview(self): self._ui.jids_listview.get_selection().connect('changed', self.on_jids_listview_selection_changed) - def _init_logs_listview(self): + def _init_logs_listview(self) -> None: # log_line_id(HIDDEN), jid_id(HIDDEN), time, message, subject, nickname self.logs_liststore = Gtk.ListStore(str, str, str, str, str, str) self._ui.logs_listview.set_model(self.logs_liststore) - self._ui.logs_listview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) + self._ui.logs_listview.get_selection().set_mode( + Gtk.SelectionMode.MULTIPLE) renderer_text = Gtk.CellRendererText() # holds time - col = Gtk.TreeViewColumn(_('Date'), renderer_text, text=Column.UNIXTIME) + col = Gtk.TreeViewColumn( + _('Date'), renderer_text, text=Column.UNIXTIME) # user can click this header and sort col.set_sort_column_id(Column.UNIXTIME) col.set_resizable(True) self._ui.logs_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds nickname - col = Gtk.TreeViewColumn(_('Nickname'), renderer_text, text=Column.NICKNAME) + col = Gtk.TreeViewColumn( + _('Nickname'), renderer_text, text=Column.NICKNAME) # user can click this header and sort col.set_sort_column_id(Column.NICKNAME) col.set_resizable(True) @@ -191,7 +199,8 @@ def _init_logs_listview(self): renderer_text = Gtk.CellRendererText() # holds message renderer_text.set_property('width_chars', 60) renderer_text.set_property('ellipsize', Pango.EllipsizeMode.END) - col = Gtk.TreeViewColumn(_('Message'), renderer_text, markup=Column.MESSAGE) + col = Gtk.TreeViewColumn( + _('Message'), renderer_text, markup=Column.MESSAGE) # user can click this header and sort col.set_sort_column_id(Column.MESSAGE) col.set_resizable(True) @@ -199,7 +208,8 @@ def _init_logs_listview(self): self._ui.logs_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds subject - col = Gtk.TreeViewColumn(_('Subject'), renderer_text, text=Column.SUBJECT) + col = Gtk.TreeViewColumn( + _('Subject'), renderer_text, text=Column.SUBJECT) # user can click this header and sort col.set_sort_column_id(Column.SUBJECT) col.set_resizable(True) @@ -207,11 +217,12 @@ def _init_logs_listview(self): self.subject_col_for_logs = col self._ui.logs_listview.append_column(col) - def _init_search_results_listview(self): + def _init_search_results_listview(self) -> None: # log_line_id (HIDDEN), jid, time, message, subject, nickname - self.search_results_liststore = Gtk.ListStore(int, str, str, str, str, - str) - self._ui.search_results_listview.set_model(self.search_results_liststore) + self.search_results_liststore = Gtk.ListStore( + int, str, str, str, str, str) + self._ui.search_results_listview.set_model( + self.search_results_liststore) renderer_text = Gtk.CellRendererText() # holds JID (who said this) col = Gtk.TreeViewColumn(_('XMPP Address'), renderer_text, text=1) @@ -221,7 +232,8 @@ def _init_search_results_listview(self): self._ui.search_results_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds time - col = Gtk.TreeViewColumn(_('Date'), renderer_text, text=Column.UNIXTIME) + col = Gtk.TreeViewColumn( + _('Date'), renderer_text, text=Column.UNIXTIME) # user can click this header and sort col.set_sort_column_id(Column.UNIXTIME) col.set_resizable(True) @@ -230,27 +242,30 @@ def _init_search_results_listview(self): renderer_text = Gtk.CellRendererText() # holds message renderer_text.set_property('width_chars', 60) renderer_text.set_property('ellipsize', Pango.EllipsizeMode.END) - col = Gtk.TreeViewColumn(_('Message'), renderer_text, text=Column.MESSAGE) + col = Gtk.TreeViewColumn( + _('Message'), renderer_text, text=Column.MESSAGE) # user can click this header and sort col.set_sort_column_id(Column.MESSAGE) col.set_resizable(True) self._ui.search_results_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds subject - col = Gtk.TreeViewColumn(_('Subject'), renderer_text, text=Column.SUBJECT) + col = Gtk.TreeViewColumn( + _('Subject'), renderer_text, text=Column.SUBJECT) # user can click this header and sort col.set_sort_column_id(Column.SUBJECT) col.set_resizable(True) self._ui.search_results_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds nickname - col = Gtk.TreeViewColumn(_('Nickname'), renderer_text, text=Column.NICKNAME) + col = Gtk.TreeViewColumn( + _('Nickname'), renderer_text, text=Column.NICKNAME) # user can click this header and sort col.set_sort_column_id(Column.NICKNAME) col.set_resizable(True) self._ui.search_results_listview.append_column(col) - def on_history_manager_window_delete_event(self, widget, event): + def on_history_manager_window_delete_event(self, _widget, _event): if not self.AT_LEAST_ONE_DELETION_DONE: if is_standalone(): Gtk.main_quit() @@ -278,7 +293,7 @@ def _on_no(): text=_('_Cleanup'), callback=_on_yes)]).show() - def _fill_jids_listview(self): + def _fill_jids_listview(self) -> None: # get those jids that have at least one entry in logs self.cur.execute('SELECT jid, jid_id FROM jids WHERE jid_id IN (' 'SELECT distinct logs.jid_id FROM logs) ORDER BY jid') @@ -288,9 +303,9 @@ def _fill_jids_listview(self): self.jids_already_in.append(row[0]) # jid self.jids_liststore.append([row[0], str(row[1])]) # jid, jid_id - def on_jids_listview_selection_changed(self, widget, data=None): - liststore, list_of_paths = self._ui.jids_listview.get_selection()\ - .get_selected_rows() + def on_jids_listview_selection_changed(self, _widget): + selection = self._ui.jids_listview.get_selection() + liststore, list_of_paths = selection.get_selected_rows() self.logs_liststore.clear() if not list_of_paths: @@ -311,7 +326,7 @@ def on_jids_listview_selection_changed(self, widget, data=None): jid = liststore[path][0] # jid self._fill_logs_listview(jid) - def _get_jid_id(self, jid): + def _get_jid_id(self, jid: str) -> str: """ jids table has jid and jid_id logs table has log_id, jid_id, contact_name, time, kind, show, message @@ -327,7 +342,7 @@ def _get_jid_id(self, jid): jid_id = self.cur.fetchone()[0] return str(jid_id) - def _get_jid_from_jid_id(self, jid_id): + def _get_jid_from_jid_id(self, jid_id: str) -> str: """ jids table has jid and jid_id @@ -337,7 +352,7 @@ def _get_jid_from_jid_id(self, jid_id): jid = self.cur.fetchone()[0] return jid - def _jid_is_from_pm(self, jid): + def _jid_is_from_pm(self, jid: str) -> bool: """ If jid is gajim@conf/nkour it's likely a pm one, how we know gajim@conf is not a normal guy and nkour is not his resource? We ask if gajim@conf @@ -355,7 +370,7 @@ def _jid_is_from_pm(self, jid): return False return True - def _jid_is_room_type(self, jid): + def _jid_is_room_type(self, jid: str) -> bool: """ Return True/False if given id is room type or not eg. if it is room """ @@ -363,7 +378,7 @@ def _jid_is_room_type(self, jid): row = self.cur.fetchone() return row[0] == JIDConstant.ROOM_TYPE - def _fill_logs_listview(self, jid): + def _fill_logs_listview(self, jid: str) -> None: """ Fill the listview with all messages that user sent to or received from JID @@ -424,13 +439,13 @@ def _fill_logs_listview(self, jid): message_ = '<span' if color: - message_ += ' foreground="%s"' % convert_rgb_to_hex(color) - message_ += '>%s</span>' % GLib.markup_escape_text(message) + message_ += f' foreground="{convert_rgb_to_hex(color)}"' + message_ += f'>{GLib.markup_escape_text(message)}</span>' self.logs_liststore.append( (str(log_line_id), str(jid_id), time_, message_, subject, nickname)) - def _fill_search_results_listview(self, text): + def _fill_search_results_listview(self, text: str) -> None: """ Ask db and fill listview with results that match text """ @@ -461,7 +476,7 @@ def _fill_search_results_listview(self, text): self.search_results_liststore.append((log_line_id, jid, time_, message, subject, nickname)) - def on_logs_listview_key_press_event(self, widget, event): + def on_logs_listview_key_press_event(self, _widget, event): liststore, list_of_paths = self._ui.logs_listview.get_selection()\ .get_selected_rows() if event.keyval == Gdk.KEY_Delete: @@ -480,17 +495,17 @@ def on_listview_button_press_event(self, widget, event): event.button, event.time) return True - def on_export_menuitem_activate(self, widget): + def on_export_menuitem_activate(self, _widget): FileSaveDialog(self._on_export, transient_for=self._ui.history_manager_window, modal=True) - def _on_export(self, filename): - liststore, list_of_paths = self._ui.jids_listview.get_selection()\ - .get_selected_rows() + def _on_export(self, filename: str) -> None: + selection = self._ui.jids_listview.get_selection() + liststore, list_of_paths = selection.get_selected_rows() self._export_jids_logs_to_file(liststore, list_of_paths, filename) - def on_delete_menuitem_activate(self, widget, listview): + def on_delete_menuitem_activate(self, _widget, listview): widget_name = Gtk.Buildable.get_name(listview) liststore, list_of_paths = listview.get_selection().get_selected_rows() if widget_name == 'jids_listview': @@ -500,7 +515,7 @@ def on_delete_menuitem_activate(self, widget, listview): else: # Huh ? We don't know this widget return - def on_jids_listview_key_press_event(self, widget, event): + def on_jids_listview_key_press_event(self, _widget, event): liststore, list_of_paths = self._ui.jids_listview.get_selection()\ .get_selected_rows() if event.keyval == Gdk.KEY_Delete: @@ -530,30 +545,31 @@ def _export_jids_logs_to_file(self, liststore, list_of_paths, path_to_file): # AT THIS TIME FIRST EXECUTE IS LOST! WTH!!!!! results = self.cur.fetchall() #print results[0] - file_ = open(path_to_file, 'w', encoding='utf-8') - for row in results: - # in store: time, kind, message, contact_name FROM logs - # in text: JID or You or nickname (if it's gc_msg), time, message - time_, kind, message, nickname = row - if kind in (KindConstant.SINGLE_MSG_RECV, - KindConstant.CHAT_MSG_RECV): - who = self._get_jid_from_jid_id(jid_id) - elif kind in (KindConstant.SINGLE_MSG_SENT, - KindConstant.CHAT_MSG_SENT): - who = _('You') - elif kind == KindConstant.GC_MSG: - who = nickname - else: # status or gc_status. do not save - #print kind - continue + with open(path_to_file, 'w', encoding='utf-8') as file_: + for row in results: + # in store: time, kind, message, contact_name FROM logs + # in text: JID or You or nickname (if it's gc_msg), time, + # message + time_, kind, message, nickname = row + if kind in (KindConstant.SINGLE_MSG_RECV, + KindConstant.CHAT_MSG_RECV): + who = self._get_jid_from_jid_id(jid_id) + elif kind in (KindConstant.SINGLE_MSG_SENT, + KindConstant.CHAT_MSG_SENT): + who = _('You') + elif kind == KindConstant.GC_MSG: + who = nickname + else: # status or gc_status. do not save + #print kind + continue - try: - time_ = time.strftime('%c', time.localtime(float(time_))) - except ValueError: - pass + try: + time_ = time.strftime('%c', time.localtime(float(time_))) + except ValueError: + pass - file_.write(_('%(who)s on %(time)s said: %(message)s\n') % { - 'who': who, 'time': time_, 'message': message}) + file_.write(_('%(who)s on %(time)s said: %(message)s\n') % { + 'who': who, 'time': time_, 'message': message}) def _delete_jid_logs(self, liststore, list_of_paths): paths_len = len(list_of_paths) @@ -564,7 +580,8 @@ def on_ok(): # delete all rows from db that match jid_id list_of_rowrefs = [] for path in list_of_paths: # make them treerowrefs (it's needed) - list_of_rowrefs.append(Gtk.TreeRowReference.new(liststore, path)) + list_of_rowrefs.append(Gtk.TreeRowReference.new( + liststore, path)) for rowref in list_of_rowrefs: path = rowref.get_path() @@ -609,7 +626,8 @@ def on_ok(): # delete rows from db that match log_line_id list_of_rowrefs = [] for path in list_of_paths: # make them treerowrefs (it's needed) - list_of_rowrefs.append(Gtk.TreeRowReference.new(liststore, path)) + list_of_rowrefs.append(Gtk.TreeRowReference.new( + liststore, path)) for rowref in list_of_rowrefs: path = rowref.get_path() @@ -638,7 +656,7 @@ def on_ok(): callback=on_ok)], transient_for=self._ui.history_manager_window).show() - def on_search_db_button_clicked(self, widget): + def on_search_db_button_clicked(self, _widget): text = self._ui.search_entry.get_text() if not text: return @@ -649,7 +667,7 @@ def on_search_db_button_clicked(self, widget): self._fill_search_results_listview(text) - def on_search_results_listview_row_activated(self, widget, path, column): + def on_search_results_listview_row_activated(self, _widget, path, _column): # get log_line_id, jid_id from row we double clicked log_line_id = str(self.search_results_liststore[path][0]) jid = self.search_results_liststore[path][1] @@ -677,12 +695,15 @@ def on_search_results_listview_row_activated(self, widget, path, column): break iter_ = self.logs_liststore.iter_next(iter_) + if iter_ is None: + return + path = self.logs_liststore.get_path(iter_) self._ui.logs_listview.scroll_to_cell(path) self._ui.logs_listview.get_selection().select_path(path) -def main(): +def main() -> None: if sys.platform != 'win32': if os.geteuid() == 0: sys.exit("You must not launch gajim as root, it is insecure.") View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/compare/f9eedc129c93d07ba5d2e7de827e61c…
-- View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/compare/f9eedc129c93d07ba5d2e7de827e61c…
You're receiving this email because of your account on
dev.gajim.org
.
1
0
0
0
[Git][gajim/gajim][mainwindow] 4 commits: CodeWidget: Fix missing imports
by Daniel Brötzmann (@wurstsalat)
24 Nov '21
24 Nov '21
Daniel Brötzmann pushed to branch mainwindow at gajim / gajim Commits: 530a4902 by wurstsalat at 2021-11-24T21:51:41+01:00 CodeWidget: Fix missing imports - - - - - c15e3e8a by wurstsalat at 2021-11-24T22:11:02+01:00 Types: Prevent circular imports - - - - - bbf649fc by wurstsalat at 2021-11-24T22:11:02+01:00 MessageRow: Fix unknown type - - - - - 813ba5a8 by wurstsalat at 2021-11-24T22:14:40+01:00 QuoteWidget: Remove typing - - - - - 4 changed files: - gajim/gtk/conversation/code_widget.py - gajim/gtk/conversation/quote_widget.py - gajim/gtk/conversation/rows/message.py - gajim/gtk/types.py Changes: ===================================== gajim/gtk/conversation/code_widget.py ===================================== @@ -12,11 +12,13 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see <
http://www.gnu.org/licenses/
>. +from typing import Tuple +from typing import Optional + import logging import gi gi.require_version('GtkSource', '4') -from gi.repository import GObject from gi.repository import Gdk from gi.repository import Gtk from gi.repository import GtkSource @@ -76,7 +78,7 @@ def add_content(self, block): self._textview.print_code(code) @staticmethod - def _prepare_code(text: str) -> Tuple[str, str]: + def _prepare_code(text: str) -> Tuple[str, Optional[str]]: code_start = text.partition('\n')[0] lang = None if len(code_start) > 3: ===================================== gajim/gtk/conversation/quote_widget.py ===================================== @@ -12,12 +12,8 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see <
http://www.gnu.org/licenses/
>. -from typing import Optional - from gi.repository import Gtk -from .message_widget import MessageWidget - class QuoteWidget(Gtk.Box): def __init__(self, account: str) -> None: @@ -32,9 +28,9 @@ def __init__(self, account: str) -> None: self._account = account - self._message_widget: Optional[MessageWidget] = None + self._message_widget = None - def attach_message_widget(self, message_widget: MessageWidget) -> None: + def attach_message_widget(self, message_widget): # Purpose of this method is to prevent circular imports if self._message_widget is not None: raise ValueError( ===================================== gajim/gtk/conversation/rows/message.py ===================================== @@ -247,10 +247,10 @@ def _on_avatar_clicked(self, _widget, event, name): def _on_realize(event_box): event_box.get_window().set_cursor(get_cursor('pointer')) - def is_same_sender(self, message: MessageRow) -> bool: + def is_same_sender(self, message): return message.name == self.name - def is_same_encryption(self, message: MessageRow) -> bool: + def is_same_encryption(self, message): message_details = self._get_encryption_details(message.additional_data) own_details = self._get_encryption_details(self.additional_data) if message_details is None and own_details is None: ===================================== gajim/gtk/types.py ===================================== @@ -15,41 +15,43 @@ # Types for typechecking from typing import Union +from typing import TYPE_CHECKING -from .controls.chat import ChatControl -from .controls.private import PrivateChatControl -from .controls.groupchat import GroupchatControl -from .conversation.rows.call import CallRow -from .conversation.rows.command_output import CommandOutputRow -from .conversation.rows.date import DateRow -from .conversation.rows.file_transfer_jingle import FileTransferJingleRow -from .conversation.rows.file_transfer import FileTransferRow -from .conversation.rows.info import InfoMessage -from .conversation.rows.message import MessageRow -from .conversation.rows.muc_join_left import MUCJoinLeft -from .conversation.rows.muc_subject import MUCSubject -from .conversation.rows.muc_user_status import MUCUserStatus -from .conversation.rows.read_marker import ReadMarkerRow -from .conversation.rows.scroll_hint import ScrollHintRow +if TYPE_CHECKING: + from .controls.chat import ChatControl + from .controls.private import PrivateChatControl + from .controls.groupchat import GroupchatControl + from .conversation.rows.call import CallRow + from .conversation.rows.command_output import CommandOutputRow + from .conversation.rows.date import DateRow + from .conversation.rows.file_transfer_jingle import FileTransferJingleRow + from .conversation.rows.file_transfer import FileTransferRow + from .conversation.rows.info import InfoMessage + from .conversation.rows.message import MessageRow + from .conversation.rows.muc_join_left import MUCJoinLeft + from .conversation.rows.muc_subject import MUCSubject + from .conversation.rows.muc_user_status import MUCUserStatus + from .conversation.rows.read_marker import ReadMarkerRow + from .conversation.rows.scroll_hint import ScrollHintRow ConversationRowType = Union[ - CallRow, - CommandOutputRow, - DateRow, - FileTransferJingleRow, - FileTransferRow, - InfoMessage, - MessageRow, - MUCJoinLeft, - MUCSubject, - MUCUserStatus, - ReadMarkerRow, - ScrollHintRow + 'CallRow', + 'CommandOutputRow', + 'DateRow', + 'FileTransferJingleRow', + 'FileTransferRow', + 'InfoMessage', + 'MessageRow', + 'MUCJoinLeft', + 'MUCSubject', + 'MUCUserStatus', + 'ReadMarkerRow', + 'ScrollHintRow' ] ControlType = Union [ - ChatControl, - PrivateChatControl, - GroupchatControl + 'ChatControl', + 'PrivateChatControl', + 'GroupchatControl' ] View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/compare/1cd0e8ab9e064928f151efca79651a5…
-- View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/compare/1cd0e8ab9e064928f151efca79651a5…
You're receiving this email because of your account on
dev.gajim.org
.
1
0
0
0
[Git][gajim/gajim][mainwindow] Helpers: Fix missing import + linting
by Daniel Brötzmann (@wurstsalat)
24 Nov '21
24 Nov '21
Daniel Brötzmann pushed to branch mainwindow at gajim / gajim Commits: 1cd0e8ab by wurstsalat at 2021-11-24T21:46:04+01:00 Helpers: Fix missing import + linting - - - - - 1 changed file: - gajim/common/helpers.py Changes: ===================================== gajim/common/helpers.py ===================================== @@ -67,7 +67,7 @@ from nbxmpp.const import ConnectionProtocol from nbxmpp.const import ConnectionType from nbxmpp.const import Affiliation -from nbxmpp.const import Role +from nbxmpp.errors import StanzaError from nbxmpp.structs import ProxyData from nbxmpp.protocol import JID from nbxmpp.protocol import InvalidJid @@ -376,7 +376,7 @@ def exec_command(command, use_shell=False, posix=True): is executed. """ if use_shell: - subprocess.Popen('%s &' % command, shell=True).wait() + subprocess.Popen(f'{command} &', shell=True).wait() else: args = shlex.split(command, posix=posix) process = subprocess.Popen(args) @@ -386,7 +386,7 @@ def build_command(executable, parameter): # we add to the parameter (can hold path with spaces) # "" so we have good parsing from shell parameter = parameter.replace('"', '\\"') # but first escape " - command = '%s "%s"' % (executable, parameter) + command = f'{executable} "{parameter}"' return command def get_file_path_from_dnd_dropped_uri(uri): @@ -630,8 +630,8 @@ def get_auth_sha(sid, initiator, target): """ Return sha of sid + initiator + target used for proxy auth """ - return hashlib.sha1(("%s%s%s" % (sid, initiator, target)).encode('utf-8')).\ - hexdigest() + return hashlib.sha1( + (f'{sid}{initiator}{target}').encode('utf-8')).hexdigest() def remove_invalid_xml_chars(string_): if string_: @@ -744,8 +744,9 @@ def get_subscription_request_msg(account: Optional[str] = None) -> str: message = _('I would like to add you to my contact list.') if account is None: return message - - message = app.settings.get_account_setting(account, 'subscription_request_msg') + + message = app.settings.get_account_setting( + account, 'subscription_request_msg') if message: return message @@ -928,7 +929,7 @@ def func_wrapper(self, event, *args, **kwargs): if getattr(event, attr1) != getattr(self, attr2): return None except AttributeError: - if getattr(event, attr1) != getattr(self, '_%s' % attr2): + if getattr(event, attr1) != getattr(self, f'_{attr2}'): return None return func(self, event, *args, **kwargs) @@ -1167,7 +1168,7 @@ def to_user_string(error: StanzaError) -> str: condition = error.condition if error.app_condition is not None: - return '%s (%s)' % (condition, error.app_condition) + return f'{condition} ({error.app_condition})' return condition View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/commit/1cd0e8ab9e064928f151efca79651a52…
-- View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/commit/1cd0e8ab9e064928f151efca79651a52…
You're receiving this email because of your account on
dev.gajim.org
.
1
0
0
0
[Git][gajim/gajim][mainwindow] 8 commits: ScrolledView: Typing
by Daniel Brötzmann (@wurstsalat)
23 Nov '21
23 Nov '21
Daniel Brötzmann pushed to branch mainwindow at gajim / gajim Commits: fcd3a2e9 by wurstsalat at 2021-11-23T20:05:24+01:00 ScrolledView: Typing - - - - - c3c40271 by wurstsalat at 2021-11-23T21:24:26+01:00 Types: Add ConversationRowType - - - - - 1f3948db by wurstsalat at 2021-11-23T22:50:42+01:00 Conversation Rows: Typing - - - - - 5e95fe18 by wurstsalat at 2021-11-23T22:50:45+01:00 ConversationView: Typing - - - - - f0d73b49 by wurstsalat at 2021-11-23T22:50:45+01:00 Conversation Widgets: Typing - - - - - def5a560 by wurstsalat at 2021-11-23T22:58:20+01:00 Chat Controls: Use ControlType for typing - - - - - e38d1fde by wurstsalat at 2021-11-23T23:04:15+01:00 AccountPage: Typing - - - - - a75088ca by wurstsalat at 2021-11-23T23:04:28+01:00 AccountSideBar: Typing - - - - - 25 changed files: - gajim/common/helpers.py - gajim/gtk/account_page.py - gajim/gtk/account_side_bar.py - gajim/gtk/chat_page.py - gajim/gtk/chat_stack.py - gajim/gtk/conversation/code_widget.py - gajim/gtk/conversation/message_widget.py - gajim/gtk/conversation/quote_widget.py - gajim/gtk/conversation/rows/base.py - gajim/gtk/conversation/rows/call.py - gajim/gtk/conversation/rows/command_output.py - gajim/gtk/conversation/rows/date.py - gajim/gtk/conversation/rows/file_transfer.py - gajim/gtk/conversation/rows/file_transfer_jingle.py - gajim/gtk/conversation/rows/info.py - gajim/gtk/conversation/rows/message.py - gajim/gtk/conversation/rows/muc_join_left.py - gajim/gtk/conversation/rows/muc_subject.py - gajim/gtk/conversation/rows/muc_user_status.py - gajim/gtk/conversation/rows/read_marker.py - gajim/gtk/conversation/rows/scroll_hint.py - gajim/gtk/conversation/scrolled.py - gajim/gtk/conversation/view.py - gajim/gtk/main.py - gajim/gtk/types.py Changes: ===================================== gajim/common/helpers.py ===================================== @@ -1160,7 +1160,7 @@ def validate_jid(jid, type_=None): raise ValueError('Not a %s JID' % type_) -def to_user_string(error): +def to_user_string(error: StanzaError) -> str: text = error.get_text(get_rfc5646_lang()) if text: return text @@ -1420,7 +1420,7 @@ def get_muc_context(jid): return 'public' -def get_start_of_day(date_time): +def get_start_of_day(date_time: datetime) -> datetime: return date_time.replace(hour=0, minute=0, second=0, ===================================== gajim/gtk/account_page.py ===================================== @@ -35,7 +35,7 @@ class AccountPage(Gtk.Box, EventHelper): - def __init__(self, account): + def __init__(self, account: str) -> None: Gtk.Box.__init__(self) EventHelper.__init__(self) @@ -101,10 +101,10 @@ def _on_button_release(paned, event): position = paned.get_position() app.settings.set('chat_handle_position', position) - def get_roster(self): + def get_roster(self) -> Roster: return self._roster - def update(self): + def update(self) -> None: account_label = app.settings.get_account_setting( self._account, 'account_label') self._ui.account_label.set_text(account_label) ===================================== gajim/gtk/account_side_bar.py ===================================== @@ -12,6 +12,9 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see <
http://www.gnu.org/licenses/
>. +from typing import List +from typing import Optional + from gi.repository import Gtk from gajim.common.const import AvatarSize @@ -20,7 +23,7 @@ class AccountSideBar(Gtk.ListBox): - def __init__(self): + def __init__(self) -> None: Gtk.ListBox.__init__(self) self.set_vexpand(True) self.set_valign(Gtk.Align.END) @@ -28,14 +31,14 @@ def __init__(self): self.get_style_context().add_class('account-sidebar') self.connect('row-activated', self._on_row_activated) - self._accounts = list(app.connections.keys()) + self._accounts: List[str] = list(app.connections.keys()) for account in self._accounts: self.add_account(account) - def add_account(self, account): + def add_account(self, account: str) -> None: self.add(Account(account)) - def remove_account(self, account): + def remove_account(self, account: str) -> None: for row in self.get_children(): if row.account == account: row.destroy() @@ -45,7 +48,7 @@ def remove_account(self, account): def _on_row_activated(_listbox, row): app.window.show_account_page(row.account) - def activate_account_page(self, account): + def activate_account_page(self, account: str) -> None: row = self.get_selected_row() if row is not None and row.account == account: return @@ -54,12 +57,12 @@ def activate_account_page(self, account): class Account(Gtk.ListBoxRow): - def __init__(self, account): + def __init__(self, account: str) -> None: Gtk.ListBoxRow.__init__(self) self.get_style_context().add_class('account-sidebar-item') self.account = account - self._account_class = None + self._account_class: Optional[str] = None selection_bar = Gtk.Box() selection_bar.set_size_request(6, -1) @@ -83,7 +86,7 @@ def __init__(self, account): self.add(account_box) self.show_all() - def _update_account_color(self): + def _update_account_color(self) -> None: context = self._account_color_bar.get_style_context() if self._account_class is not None: context.remove_class(self._account_class) @@ -91,12 +94,12 @@ def _update_account_color(self): self._account_class = app.css_config.get_dynamic_class(self.account) context.add_class(self._account_class) - def update(self): + def update(self) -> None: self._update_account_color() class AccountAvatar(Gtk.Image): - def __init__(self, account): + def __init__(self, account: str) -> None: Gtk.Image.__init__(self) self._account = account @@ -115,7 +118,7 @@ def _on_presence_update(self, _contact, _signal_name): def _on_avatar_update(self, _contact, _signal_name): self._update_image() - def _update_image(self): + def _update_image(self) -> None: surface = self._contact.get_avatar(AvatarSize.ACCOUNT_SIDE_BAR, self.get_scale_factor(), style='round-corners') ===================================== gajim/gtk/chat_page.py ===================================== @@ -24,13 +24,13 @@ from gajim.common import app -from .controls.base import BaseControl from .util import get_builder from .chat_filter import ChatFilter from .chat_list import ChatList from .chat_list_stack import ChatListStack from .chat_stack import ChatStack from .search_view import SearchView +from .types import ControlType class ChatPage(Gtk.Box): @@ -82,7 +82,7 @@ def __init__(self): self._ui.paned.set_position(app.settings.get('chat_handle_position')) self._ui.paned.connect('button-release-event', self._on_button_release) - self._currently_loaded_control: Optional[BaseControl] = None + self._currently_loaded_control: Optional[ControlType] = None self._startup_finished: bool = False self._add_actions() @@ -275,20 +275,20 @@ def remove_chats_for_account(self, account: str) -> None: self._chat_list_stack.remove_chats_for_account(account) self._chat_stack.remove_chats_for_account(account) - def get_control(self, account: str, jid: JID) -> Optional[BaseControl]: + def get_control(self, account: str, jid: JID) -> Optional[ControlType]: return self._chat_stack.get_control(account, jid) - def get_active_control(self) -> Optional[BaseControl]: + def get_active_control(self) -> Optional[ControlType]: chat = self._chat_list_stack.get_selected_chat() if chat is None: return None return self.get_control(chat.account, chat.jid) - def get_currently_loaded_control(self) -> Optional[BaseControl]: + def get_currently_loaded_control(self) -> Optional[ControlType]: return self._currently_loaded_control def get_controls(self, account: Optional[str] - ) -> Generator[BaseControl, None, None]: + ) -> Generator[ControlType, None, None]: return self._chat_stack.get_controls(account) def hide_search(self) -> bool: ===================================== gajim/gtk/chat_stack.py ===================================== @@ -27,11 +27,11 @@ from gajim.common import ged from gajim.common.i18n import _ -from .controls.base import BaseControl from .controls.chat import ChatControl from .controls.groupchat import GroupchatControl from .controls.private import PrivateChatControl +from .types import ControlType from .util import EventHelper log = logging.getLogger('gajim.gui.chatstack') @@ -53,17 +53,17 @@ def __init__(self): ]) self.show_all() - self._controls: Dict[Tuple[str, JID], BaseControl] = {} - self._active_control: Optional[BaseControl] = None + self._controls: Dict[Tuple[str, JID], ControlType] = {} + self._active_control: Optional[ControlType] = None - def get_control(self, account: str, jid: JID) -> Optional[BaseControl]: + def get_control(self, account: str, jid: JID) -> Optional[ControlType]: try: return self._controls[(account, jid)] except KeyError: return None def get_controls(self, account: Optional[str] - ) -> Generator[BaseControl, None, None]: + ) -> Generator[ControlType, None, None]: if account is None: for control in self._controls.values(): yield control ===================================== gajim/gtk/conversation/code_widget.py ===================================== @@ -28,7 +28,7 @@ class CodeWidget(Gtk.Box): - def __init__(self, account): + def __init__(self, account: str) -> None: Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL) self.set_vexpand(True) self.get_style_context().add_class('code-widget') @@ -76,7 +76,7 @@ def add_content(self, block): self._textview.print_code(code) @staticmethod - def _prepare_code(text): + def _prepare_code(text: str) -> Tuple[str, str]: code_start = text.partition('\n')[0] lang = None if len(code_start) > 3: @@ -87,7 +87,7 @@ def _prepare_code(text): class CodeTextview(GtkSource.View): - def __init__(self): + def __init__(self) -> None: GtkSource.View.__init__(self) self.set_editable(False) self.set_cursor_visible(False) @@ -107,7 +107,7 @@ def __init__(self): if style_scheme is not None: self.get_buffer().set_style_scheme(style_scheme) - def set_language(self, language_string): + def set_language(self, language_string: Optional[str]) -> None: if language_string is None: lang = self._source_manager.get_language('python3') else: @@ -116,12 +116,12 @@ def set_language(self, language_string): self.get_buffer().set_language(lang) return lang.get_name() - def get_code(self): + def get_code(self) -> str: buffer_ = self.get_buffer() start, end = buffer_.get_bounds() return buffer_.get_text(start, end, False) - def print_code(self, code): + def print_code(self, code: str) -> None: self.set_show_line_numbers(True) buffer_ = self.get_buffer() buffer_.insert(buffer_.get_start_iter(), code) ===================================== gajim/gtk/conversation/message_widget.py ===================================== @@ -20,7 +20,7 @@ class MessageWidget(Gtk.Box): - def __init__(self, account, selectable=True): + def __init__(self, account: str, selectable: bool = True) -> None: Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL) self._account = account self._selectable = selectable @@ -59,7 +59,7 @@ def add_content(self, content): self.show_all() - def clear(self): + def clear(self) -> None: self.foreach(self.remove) def update_text_tags(self, *args): ===================================== gajim/gtk/conversation/quote_widget.py ===================================== @@ -12,12 +12,15 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see <
http://www.gnu.org/licenses/
>. +from typing import Optional from gi.repository import Gtk +from .message_widget import MessageWidget + class QuoteWidget(Gtk.Box): - def __init__(self, account): + def __init__(self, account: str) -> None: Gtk.Box.__init__(self) self.set_vexpand(True) self.get_style_context().add_class('conversation-quote') @@ -29,11 +32,12 @@ def __init__(self, account): self._account = account - self._message_widget = None + self._message_widget: Optional[MessageWidget] = None - def attach_message_widget(self, message_widget): + def attach_message_widget(self, message_widget: MessageWidget) -> None: # Purpose of this method is to prevent circular imports if self._message_widget is not None: - raise ValueError('QuoteWidget already has a MessageWidget attached') + raise ValueError( + 'QuoteWidget already has a MessageWidget attached') self._message_widget = message_widget self.add(message_widget) ===================================== gajim/gtk/conversation/rows/base.py ===================================== @@ -12,6 +12,8 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see <
http://www.gnu.org/licenses/
>. +from typing import Optional + from datetime import datetime from gi.repository import GLib @@ -27,18 +29,18 @@ class BaseRow(Gtk.ListBoxRow): - def __init__(self, account, widget=None): + def __init__(self, account: str, widget: Optional[str] = None) -> None: Gtk.ListBoxRow.__init__(self) self._account = account self._client = app.get_client(account) - self.type = '' - self.timestamp = None - self.kind = None - self.name = None - self.message_id = None - self.log_line_id = None - self.text = '' - self._merged = False + self.type: str = '' + self.timestamp: datetime = datetime.fromtimestamp(0) + self.kind: Optional[str] = None + self.name: Optional[str] = None + self.message_id: Optional[str] = None + self.log_line_id: Optional[str] = None + self.text: str = '' + self._merged: bool = False self.get_style_context().add_class('conversation-row') @@ -53,10 +55,10 @@ def __init__(self, account, widget=None): self.label.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR) @property - def is_merged(self): + def is_merged(self) -> bool: return self._merged - def update_text_tags(self): + def update_text_tags(self) -> None: pass @staticmethod ===================================== gajim/gtk/conversation/rows/call.py ===================================== @@ -12,6 +12,8 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see <
http://www.gnu.org/licenses/
>. +from typing import Optional + import time from datetime import datetime @@ -21,6 +23,7 @@ from gajim.common.const import AvatarSize from gajim.common.const import KindConstant from gajim.common.i18n import _ +from gajim.common.jingle_session import JingleSession from .widgets import SimpleLabel from .base import BaseRow @@ -46,7 +49,8 @@ def __init__(self, account, contact, event=None, db_message=None): self._contact = contact self._event = event self._db_message = db_message - self._session = None + + self._session: Optional[JingleSession] = None if is_from_db: sid = db_message.additional_data.get_value('gajim', 'sid') @@ -70,7 +74,7 @@ def __init__(self, account, contact, event=None, db_message=None): self.show_all() - def update(self): + def update(self) -> None: if self._event is None and self._session is None: return @@ -90,7 +94,7 @@ def _on_accept(self, button): else: self.get_parent().accept_call(self._session) - def _on_decline(self, button): + def _on_decline(self, _button): if self._event is not None: session = self._client.get_module('Jingle').get_jingle_session( self._event.fjid, self._event.sid) @@ -99,7 +103,7 @@ def _on_decline(self, button): self.get_parent().decline_call(self._session) self._session = None - def _add_history_call_widget(self): + def _add_history_call_widget(self) -> None: if self._db_message is not None: if self._db_message.kind == KindConstant.CALL_INCOMING: contact = self._contact @@ -141,7 +145,7 @@ def _add_history_call_widget(self): self.grid.attach(content_box, 1, 1, 1, 1) self.show_all() - def _add_incoming_call_widget(self): + def _add_incoming_call_widget(self) -> None: self._call_box = Gtk.Box( orientation=Gtk.Orientation.VERTICAL, spacing=6) self._call_box.set_size_request(350, -1) ===================================== gajim/gtk/conversation/rows/command_output.py ===================================== @@ -25,7 +25,7 @@ class CommandOutputRow(BaseRow): - def __init__(self, account, text, is_error): + def __init__(self, account: str, text: str, is_error: bool) -> None: BaseRow.__init__(self, account) self.type = 'command_output' ===================================== gajim/gtk/conversation/rows/date.py ===================================== @@ -12,6 +12,7 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see <
http://www.gnu.org/licenses/
>. +from datetime import datetime from gi.repository import Gtk @@ -19,7 +20,7 @@ class DateRow(BaseRow): - def __init__(self, account, timestamp): + def __init__(self, account: str, timestamp: datetime) -> None: BaseRow.__init__(self, account, widget='label') self.set_selectable(False) ===================================== gajim/gtk/conversation/rows/file_transfer.py ===================================== @@ -21,6 +21,7 @@ from gajim.common import app from gajim.common.const import AvatarSize from gajim.common.i18n import _ +from gajim.common.modules.httpupload import HTTPFileTransfer from .base import BaseRow @@ -31,7 +32,7 @@ class FileTransferRow(BaseRow, EventHelper): - def __init__(self, account, transfer): + def __init__(self, account: str, transfer: HTTPFileTransfer) -> None: BaseRow.__init__(self, account) EventHelper.__init__(self) @@ -40,7 +41,7 @@ def __init__(self, account, transfer): self.timestamp = datetime.fromtimestamp(timestamp) self.db_timestamp = timestamp - self._destroyed = False + self._destroyed: bool = False if app.settings.get('use_kib_mib'): self._units = GLib.FormatSizeFlags.IEC_UNITS ===================================== gajim/gtk/conversation/rows/file_transfer_jingle.py ===================================== @@ -24,6 +24,7 @@ from gajim.common import ged from gajim.common.const import AvatarSize from gajim.common.const import KindConstant +from gajim.common.file_props import FileProp from gajim.common.file_props import FilesProp from gajim.common.helpers import open_file from gajim.common.i18n import _ @@ -130,7 +131,7 @@ def __init__(self, account, contact, event=None, db_message=None): app.ged.register_event_handler('jingle-ft-cancelled-received', ged.GUI1, self.process_event) # pylint: enable=line-too-long - def _reconstruct_transfer(self): + def _reconstruct_transfer(self) -> None: self._show_file_infos() if self._file_props is None: self._ui.transfer_action.set_text(_('File Transfer')) @@ -154,7 +155,7 @@ def _reconstruct_transfer(self): self._ui.transfer_action.set_text(_('File Offered…')) - def _display_transfer_info(self, event_name): + def _display_transfer_info(self, event_name: str) -> None: if event_name == 'file-request-sent': self._ui.action_stack.set_visible_child_name('progress') self._ui.progress_label.set_text(_('Waiting…')) @@ -162,7 +163,7 @@ def _display_transfer_info(self, event_name): self._ui.transfer_action.set_text(_('File Offered…')) self._show_file_infos() - def _show_file_infos(self): + def _show_file_infos(self) -> None: if self._file_props is None: self._ui.file_name.hide() self._ui.file_description.hide() @@ -227,7 +228,7 @@ def process_event(self, event): elif event.name == 'file-progress': self._update_progress(event.file_props) - def _update_progress(self, file_props): + def _update_progress(self, file_props: FileProp) -> None: self._ui.action_stack.set_visible_child_name('progress') self._ui.transfer_action.set_text(_('Transferring File…')) @@ -267,7 +268,7 @@ def _update_progress(self, file_props): self._ui.progress_bar.set_fraction(progress) - def _show_error(self, file_props): + def _show_error(self, file_props: FileProp) -> None: self._ui.action_stack.set_visible_child_name('error') self._ui.transfer_action.set_text(_('File Transfer Stopped')) if file_props.error == -1: @@ -280,7 +281,7 @@ def _show_error(self, file_props): else: self._ui.error_label.set_text(_('An error occurred')) - def _show_completed(self): + def _show_completed(self) -> None: self._ui.action_stack.set_visible_child_name('complete') self._ui.transfer_action.set_text(_('File Transfer Completed')) ===================================== gajim/gtk/conversation/rows/info.py ===================================== @@ -25,7 +25,7 @@ class InfoMessage(BaseRow): - def __init__(self, account, text): + def __init__(self, account: str, text: str) -> None: BaseRow.__init__(self, account) self.type = 'info' ===================================== gajim/gtk/conversation/rows/message.py ===================================== @@ -12,6 +12,9 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see <
http://www.gnu.org/licenses/
>. +from typing import Optional +from typing import Union + from datetime import datetime from datetime import timedelta @@ -19,15 +22,25 @@ from gi.repository import GLib from gi.repository import Gtk +import cairo + +from nbxmpp.errors import StanzaError +from nbxmpp.modules.security_labels import Displaymarking + from gajim.common import app from gajim.common.const import AvatarSize from gajim.common.const import TRUST_SYMBOL_DATA +from gajim.common.helpers import AdditionalDataDict from gajim.common.helpers import get_group_chat_nick from gajim.common.helpers import get_muc_context from gajim.common.helpers import message_needs_highlight from gajim.common.helpers import reduce_chars_newlines from gajim.common.helpers import to_user_string +from gajim.common.modules.contacts import BareContact +from gajim.common.modules.contacts import GroupchatContact +from gajim.common.modules.contacts import GroupchatParticipant from gajim.common.styling import process +from gajim.common.styling import ParsingResult from gajim.common.i18n import _ from gajim.common.i18n import Q_ @@ -37,28 +50,32 @@ from ...dialogs import InputDialog from ...dialogs import DialogButton from ...preview import PreviewWidget +from ...types import ConversationRowType from ...util import format_fingerprint from ...util import get_cursor MERGE_TIMEFRAME = timedelta(seconds=120) +# TODO: +ContactType = Union[BareContact, GroupchatContact, GroupchatParticipant] + class MessageRow(BaseRow): def __init__(self, - account, - contact, - message_id, - stanza_id, - timestamp, - kind, - name, - text, - additional_data=None, - display_marking=None, - marker=None, - error=None, - encryption_enabled=False, - log_line_id=None): + account: str, + contact: ContactType, + message_id: Optional[str], + stanza_id: Optional[str], + timestamp: float, + kind: str, + name: str, + text: str, + additional_data: Optional[AdditionalDataDict] = None, + display_marking: Optional[Displaymarking] = None, + marker: Optional[str] = None, + error: Optional[StanzaError] = None, + encryption_enabled: bool =False, + log_line_id: Optional[str] = None) -> None: BaseRow.__init__(self, account) self.type = 'chat' @@ -73,12 +90,13 @@ def __init__(self, self.additional_data = additional_data self._contact = contact - self._is_groupchat = False + + self._is_groupchat: bool = False if contact is not None and contact.is_groupchat: self._is_groupchat = True - self._has_receipt = marker == 'received' - self._has_displayed = marker == 'displayed' + self._has_receipt: bool = marker == 'received' + self._has_displayed: bool = marker == 'displayed' # Keep original text for message correction self._original_text: str = text @@ -192,10 +210,10 @@ def __init__(self, self.show_all() - def update_text_tags(self): + def update_text_tags(self) -> None: self._message_widget.update_text_tags() - def _check_for_highlight(self, content): + def _check_for_highlight(self, content: ParsingResult) -> None: needs_highlight = message_needs_highlight( content.text, self._contact.nickname, @@ -204,7 +222,7 @@ def _check_for_highlight(self, content): self.get_style_context().add_class( 'gajim-mention-highlight') - def _get_avatar(self, kind, name): + def _get_avatar(self, kind: str, name: str) -> Optional[cairo.Surface]: if self._contact is None: return None @@ -229,10 +247,10 @@ def _on_avatar_clicked(self, _widget, event, name): def _on_realize(event_box): event_box.get_window().set_cursor(get_cursor('pointer')) - def is_same_sender(self, message): + def is_same_sender(self, message: MessageRow) -> bool: return message.name == self.name - def is_same_encryption(self, message): + def is_same_encryption(self, message: MessageRow) -> bool: message_details = self._get_encryption_details(message.additional_data) own_details = self._get_encryption_details(self.additional_data) if message_details is None and own_details is None: @@ -245,7 +263,7 @@ def is_same_encryption(self, message): return True return False - def is_mergeable(self, message): + def is_mergeable(self, message: ConversationRowType) -> bool: if message.type != self.type: return False if not self.is_same_sender(message): ===================================== gajim/gtk/conversation/rows/muc_join_left.py ===================================== @@ -12,6 +12,8 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see <
http://www.gnu.org/licenses/
>. +from typing import Optional + import time from datetime import datetime @@ -25,7 +27,9 @@ class MUCJoinLeft(BaseRow): - def __init__(self, type_, account, nick, reason=None, error=False): + def __init__(self, type_: str, account: str, nick: str, + reason: Optional[str] = None, + error: bool = False): BaseRow.__init__(self, account) self.type = type_ @@ -64,8 +68,9 @@ def __init__(self, type_, account, nick, reason=None, error=False): self.show_all() @staticmethod - def _make_left_message(nick, reason, error): - reason = '' if reason is None else ': {reason}'.format(reason=reason) + def _make_left_message(nick: str, reason: Optional[str], + error: bool) -> str: + reason = '' if reason is None else f': {reason}' if error: # Group Chat: User was kicked because of an server error: reason @@ -78,5 +83,5 @@ def _make_left_message(nick, reason, error): return message @staticmethod - def _make_join_message(nick): + def _make_join_message(nick: str) -> str: return _('%s has joined') % nick ===================================== gajim/gtk/conversation/rows/muc_subject.py ===================================== @@ -15,7 +15,6 @@ import time from datetime import datetime -from gi.repository import GLib from gi.repository import Gtk from gajim.common.const import AvatarSize @@ -30,7 +29,7 @@ class MUCSubject(BaseRow): type = 'muc-subject' - def __init__(self, account, text, nick, date): + def __init__(self, account: str, text: str, nick: str, date: str) -> None: BaseRow.__init__(self, account) timestamp = time.time() ===================================== gajim/gtk/conversation/rows/muc_user_status.py ===================================== @@ -17,9 +17,10 @@ from gi.repository import Gtk +from gajim.common.modules.contacts import GroupchatParticipant from gajim.common.i18n import _ from gajim.common.const import AvatarSize -from gajim.common import helpers +from gajim.common.helpers import get_uf_show from gajim.common.styling import process from .widgets import SimpleLabel @@ -31,7 +32,8 @@ class MUCUserStatus(BaseRow): - def __init__(self, account, user_contact, is_self): + def __init__(self, account: str, user_contact: GroupchatParticipant, + is_self: bool) -> None: BaseRow.__init__(self, account) self.type = 'muc-user-status' @@ -73,9 +75,10 @@ def __init__(self, account, user_contact, is_self): self.show_all() @staticmethod - def _make_show_text(user_contact, is_self): + def _make_show_text(user_contact: GroupchatParticipant, + is_self: bool) -> str: nick = user_contact.name - show = helpers.get_uf_show(user_contact.show.value) + show = get_uf_show(user_contact.show.value) if is_self: message = _('You are now {show}').format(show=show) ===================================== gajim/gtk/conversation/rows/read_marker.py ===================================== @@ -43,7 +43,7 @@ def _on_nickname_update(self, contact, _signal_name): text = _('%s has read up to this point') % contact.name self.label.set_text(text) - def set_timestamp(self, timestamp): + def set_timestamp(self, timestamp: datetime) -> None: if timestamp < self._last_incoming_timestamp: return @@ -53,6 +53,6 @@ def set_timestamp(self, timestamp): self.set_no_show_all(False) self.show_all() - def set_last_incoming_timestamp(self, timestamp): + def set_last_incoming_timestamp(self, timestamp: datetime) -> None: if timestamp > self._last_incoming_timestamp: self._last_incoming_timestamp = timestamp ===================================== gajim/gtk/conversation/rows/scroll_hint.py ===================================== @@ -22,7 +22,7 @@ class ScrollHintRow(BaseRow): - def __init__(self, account): + def __init__(self, account: str) -> None: BaseRow.__init__(self, account, widget='label') self.set_selectable(False) self.set_activatable(False) @@ -40,7 +40,7 @@ def __init__(self, account): self.set_history_complete(False) - def set_history_complete(self, complete): + def set_history_complete(self, complete: bool) -> None: if complete: self.label.set_text(_('There is no more history')) else: ===================================== gajim/gtk/conversation/scrolled.py ===================================== @@ -12,9 +12,13 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see <
http://www.gnu.org/licenses/
>. +from typing import Optional + from gi.repository import Gtk from gi.repository import GObject +from .view import ConversationView + class ScrolledView(Gtk.ScrolledWindow): @@ -52,24 +56,24 @@ def __init__(self, *args, **kwargs): # horizontally under certain conditions (applies to GroupchatControl) self.get_hscrollbar().hide() - self._current_upper = 0 - self._autoscroll = True - self._request_history_at_upper = None - self._upper_complete = False - self._lower_complete = False - self._requesting = None + self._current_upper: int = 0 + self._autoscroll: bool = True + self._request_history_at_upper: Optional[float] = None + self._upper_complete: bool = False + self._lower_complete: bool = False + self._requesting: Optional[str] = None vadjustment = self.get_vadjustment() vadjustment.connect('notify::upper', self._on_adj_upper_changed) vadjustment.connect('notify::value', self._on_adj_value_changed) - def get_autoscroll(self): + def get_autoscroll(self) -> bool: return self._autoscroll - def get_view(self): + def get_view(self) -> ConversationView: return self.get_child().get_child() - def reset(self): + def reset(self) -> None: self._current_upper = 0 self._request_history_at_upper = None self._upper_complete = False @@ -77,14 +81,14 @@ def reset(self): self._requesting = None self.set_history_complete(True, False) - def set_history_complete(self, before, complete): + def set_history_complete(self, before: bool, complete: bool) -> None: if before: self._upper_complete = complete self.get_view().set_history_complete(complete) else: self._lower_complete = complete - def get_lower_complete(self): + def get_lower_complete(self) -> bool: return self._lower_complete def _on_adj_upper_changed(self, adj, *args): ===================================== gajim/gtk/conversation/view.py ===================================== @@ -12,20 +12,31 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see <
http://www.gnu.org/licenses/
>. +from typing import Dict +from typing import Set from typing import Optional +from typing import Generator import logging import time +from datetime import datetime from datetime import timedelta from gi.repository import GLib from gi.repository import GObject from gi.repository import Gtk +from nbxmpp.errors import StanzaError +from nbxmpp.modules.security_labels import Displaymarking + from gajim.common import app +from gajim.common.client import Client +from gajim.common.helpers import AdditionalDataDict from gajim.common.helpers import to_user_string from gajim.common.helpers import get_start_of_day +from gajim.common.modules.contacts import GroupchatParticipant +from gajim.common.modules.httpupload import HTTPFileTransfer from .rows.read_marker import ReadMarkerRow from .rows.scroll_hint import ScrollHintRow @@ -39,6 +50,8 @@ from .rows.muc_subject import MUCSubject from .rows.muc_join_left import MUCJoinLeft from .rows.muc_user_status import MUCUserStatus + +from ..types import ConversationRowType from ..util import scroll_to_end log = logging.getLogger('gajim.gui.conversation_view') @@ -75,24 +88,24 @@ def __init__(self, account, contact): self.set_sort_func(self._sort_func) self.set_filter_func(self._filter_func) self._account = account - self._client = None + self._client: Optional[Client] = None if account is not None: self._client = app.get_client(account) self._contact = contact - self.encryption_enabled = False - self.autoscroll = True - self.locked = False + self.encryption_enabled: bool = False + self.autoscroll: bool = True + self.locked: bool = False # Keeps track of the number of rows shown in ConversationView - self._row_count = 0 - self._max_row_count = 100 + self._row_count: int = 0 + self._max_row_count: int = 100 # Keeps track of date rows we have added to the list - self._active_date_rows = set() + self._active_date_rows: Set[datetime] = set() # message_id -> row mapping - self._message_id_row_map = {} + self._message_id_row_map: Dict[str, MessageRow] = {} app.settings.connect_signal('print_join_left', self._on_contact_setting_changed, @@ -111,31 +124,31 @@ def __init__(self, account, contact): self._scroll_hint_row = ScrollHintRow(self._account) self.add(self._scroll_hint_row) - def lock(self): + def lock(self) -> None: self.locked = True - def unlock(self): + def unlock(self) -> None: self.locked = False - def clear(self): + def clear(self) -> None: for row in self.get_children()[2:]: if row.type == 'read_marker': continue self.remove(row) self._reset_conversation_view() - def _reset_conversation_view(self): + def _reset_conversation_view(self) -> None: self._row_count = 0 self._active_date_rows = set() self._message_id_row_map = {} - def get_first_message_row(self): + def get_first_message_row(self) -> Optional[MessageRow]: for row in self.get_children(): if isinstance(row, MessageRow): return row return None - def get_last_message_row(self): + def get_last_message_row(self) -> Optional[MessageRow]: children = self.get_children() children.reverse() for row in children: @@ -143,7 +156,7 @@ def get_last_message_row(self): return row return None - def set_history_complete(self, complete): + def set_history_complete(self, complete: bool) -> None: self._scroll_hint_row.set_history_complete(complete) @staticmethod @@ -160,11 +173,12 @@ def _filter_func(self, row): return True - def add_muc_subject(self, text, nick, date): + def add_muc_subject(self, text: str, nick: str, date: str) -> None: subject = MUCSubject(self._account, text, nick, date) self._insert_message(subject) - def add_muc_user_left(self, nick, reason, error=False): + def add_muc_user_left(self, nick: str, reason: str, + error: bool = False) -> None: join_left = MUCJoinLeft('muc-user-left', self._account, nick, @@ -172,21 +186,22 @@ def add_muc_user_left(self, nick, reason, error=False): error=error) self._insert_message(join_left) - def add_muc_user_joined(self, nick): + def add_muc_user_joined(self, nick: str) -> None: join_left = MUCJoinLeft('muc-user-joined', self._account, nick) self._insert_message(join_left) - def add_muc_user_status(self, user_contact, is_self): + def add_muc_user_status(self, user_contact: GroupchatParticipant, + is_self: bool) -> None: user_status = MUCUserStatus(self._account, user_contact, is_self) self._insert_message(user_status) - def add_info_message(self, text): + def add_info_message(self, text: str) -> None: message = InfoMessage(self._account, text) self._insert_message(message) - def add_file_transfer(self, transfer): + def add_file_transfer(self, transfer: HTTPFileTransfer) -> None: transfer_row = FileTransferRow(self._account, transfer) self._insert_message(transfer_row) @@ -200,22 +215,22 @@ def add_call_message(self, event=None, db_message=None): self._account, self._contact, event=event, db_message=db_message) self._insert_message(call_row) - def add_command_output(self, text, is_error): + def add_command_output(self, text: str, is_error: bool) -> None: command_output_row = CommandOutputRow(self._account, text, is_error) self._insert_message(command_output_row) def add_message(self, - text, - kind, - name, - timestamp, - log_line_id=None, - message_id=None, - stanza_id=None, - display_marking=None, - additional_data=None, - marker=None, - error=None): + text: str, + kind: str, + name: str, + timestamp: float, + log_line_id: Optional[str] = None, + message_id: Optional[str] = None, + stanza_id: Optional[str] = None, + display_marking: Optional[Displaymarking] = None, + additional_data: Optional[AdditionalDataDict] = None, + marker: Optional[str] = None, + error: Optional[StanzaError] = None) -> None: if not timestamp: timestamp = time.time() @@ -237,17 +252,19 @@ def add_message(self, log_line_id=log_line_id) if message.type == 'chat': - self._message_id_row_map[message_id] = message + if message_id is not None: + self._message_id_row_map[message_id] = message if kind == 'incoming': self._read_marker_row.set_last_incoming_timestamp( message.timestamp) - if marker is not None and marker == 'displayed': + if (marker is not None and marker == 'displayed' + and message_id is not None): self.set_read_marker(message_id) self._insert_message(message) - def _insert_message(self, message): + def _insert_message(self, message: MessageRow) -> None: self.add(message) self._add_date_row(message.timestamp) self._check_for_merge(message) @@ -258,7 +275,7 @@ def _insert_message(self, message): GLib.idle_add(message.queue_resize) - def _add_date_row(self, timestamp): + def _add_date_row(self, timestamp: datetime) -> None: start_of_day = get_start_of_day(timestamp) if start_of_day in self._active_date_rows: return @@ -276,7 +293,7 @@ def _add_date_row(self, timestamp): row.set_merged(False) - def _check_for_merge(self, message): + def _check_for_merge(self, message: ConversationRowType) -> None: if message.type != 'chat': return @@ -290,7 +307,7 @@ def _check_for_merge(self, message): if message.is_mergeable(ancestor): message.set_merged(True) - def _find_ancestor(self, message): + def _find_ancestor(self, message: MessageRow) -> Optional[MessageRow]: index = message.get_index() while index != 0: index -= 1 @@ -311,7 +328,7 @@ def _find_ancestor(self, message): return row return None - def _update_descendants(self, message): + def _update_descendants(self, message: MessageRow) -> None: index = message.get_index() while True: index += 1 @@ -334,7 +351,7 @@ def _update_descendants(self, message): self._update_descendants(row) return - def reduce_message_count(self, before): + def reduce_message_count(self, before: bool) -> bool: success = False row_count = len(self.get_children()) while row_count > self._max_row_count: @@ -349,7 +366,7 @@ def reduce_message_count(self, before): return success - def _reduce_messages_before(self): + def _reduce_messages_before(self) -> bool: success = False # We want to keep relevant DateRows when removing rows @@ -375,11 +392,11 @@ def _reduce_messages_before(self): return success - def _reduce_messages_after(self): + def _reduce_messages_after(self) -> None: row = self.get_row_at_index(len(self.get_children()) - 1) self.remove(row) - def scroll_to_message_and_highlight(self, log_line_id): + def scroll_to_message_and_highlight(self, log_line_id: str) -> None: highlight_row = None for row in self.get_children(): row.get_style_context().remove_class( @@ -393,10 +410,10 @@ def scroll_to_message_and_highlight(self, log_line_id): # This scrolls the ListBox to the highlighted row highlight_row.grab_focus() - def _get_row_by_message_id(self, id_): + def _get_row_by_message_id(self, id_: str) -> Optional[MessageRow]: return self._message_id_row_map.get(id_) - def get_row_by_log_line_id(self, log_line_id): + def get_row_by_log_line_id(self, log_line_id: str) -> Optional[MessageRow]: for row in self.get_children(): if row.log_line_id == log_line_id: return row @@ -410,16 +427,16 @@ def get_row_by_stanza_id(self, stanza_id: str) -> Optional[MessageRow]: return row return None - def iter_rows(self): + def iter_rows(self) -> Generator[ConversationRowType, None, None]: for row in self.get_children(): yield row - def update_call_rows(self): + def update_call_rows(self) -> None: for row in self.get_children(): if row.type == 'call': row.update() - def set_read_marker(self, id_): + def set_read_marker(self, id_: str) -> None: if id_ is None: return @@ -435,16 +452,16 @@ def set_read_marker(self, id_): self._read_marker_row.set_timestamp(timestamp) - def update_avatars(self): + def update_avatars(self) -> None: for row in self.get_children(): if row.type == 'chat': row.update_avatar() - def update_text_tags(self): + def update_text_tags(self) -> None: for row in self.get_children(): row.update_text_tags() - def scroll_to_end(self, force=False): + def scroll_to_end(self, force: bool = False) -> None: if self.autoscroll or force: GLib.idle_add(scroll_to_end, self.get_parent().get_parent()) @@ -459,21 +476,21 @@ def show_message_retraction(self, stanza_id: str, text: str) -> None: if message_row is not None: message_row.set_retracted(text) - def show_receipt(self, id_): + def show_receipt(self, id_: str) -> None: message_row = self._get_row_by_message_id(id_) if message_row is not None: message_row.set_receipt() - def show_error(self, id_, error): + def show_error(self, id_: str, error: StanzaError) -> None: message_row = self._get_row_by_message_id(id_) if message_row is not None: message_row.set_error(to_user_string(error)) message_row.set_merged(False) - def on_quote(self, text): + def on_quote(self, text: str) -> None: self.emit('quote', text) - def on_mention(self, name): + def on_mention(self, name: str) -> None: self.emit('mention', name) def accept_call(self, event): ===================================== gajim/gtk/main.py ===================================== @@ -19,7 +19,6 @@ from gajim.common.nec import EventHelper from gajim.common.modules.bytestream import is_transfer_active -from .controls.base import BaseControl from .adhoc import AdHocCommand from .account_side_bar import AccountSideBar from .app_side_bar import AppSideBar @@ -30,6 +29,7 @@ from .dialogs import DialogButton from .dialogs import ConfirmationDialog from .dialogs import ConfirmationCheckDialog +from .types import ControlType from .util import get_builder from .util import resize_window from .util import restore_main_window_position @@ -470,17 +470,17 @@ def add_app_message(self, category: str, message: Optional[str] = None) -> None: self._app_page.add_app_message(category, message) - def get_control(self, account: str, jid: JID) -> Optional[BaseControl]: + def get_control(self, account: str, jid: JID) -> Optional[ControlType]: return self._chat_page.get_control(account, jid) def get_controls(self, account: Optional[str] = None - ) -> Generator[BaseControl, None, None]: + ) -> Generator[ControlType, None, None]: return self._chat_page.get_controls(account) - def get_active_control(self) -> Optional[BaseControl]: + def get_active_control(self) -> Optional[ControlType]: return self._chat_page.get_active_control() - def get_currently_loaded_control(self) -> Optional[BaseControl]: + def get_currently_loaded_control(self) -> Optional[ControlType]: return self._chat_page.get_currently_loaded_control() def chat_exists(self, account: str, jid: JID) -> bool: ===================================== gajim/gtk/types.py ===================================== @@ -13,3 +13,43 @@ # along with Gajim. If not, see <
http://www.gnu.org/licenses/
>. # Types for typechecking + +from typing import Union + +from .controls.chat import ChatControl +from .controls.private import PrivateChatControl +from .controls.groupchat import GroupchatControl +from .conversation.rows.call import CallRow +from .conversation.rows.command_output import CommandOutputRow +from .conversation.rows.date import DateRow +from .conversation.rows.file_transfer_jingle import FileTransferJingleRow +from .conversation.rows.file_transfer import FileTransferRow +from .conversation.rows.info import InfoMessage +from .conversation.rows.message import MessageRow +from .conversation.rows.muc_join_left import MUCJoinLeft +from .conversation.rows.muc_subject import MUCSubject +from .conversation.rows.muc_user_status import MUCUserStatus +from .conversation.rows.read_marker import ReadMarkerRow +from .conversation.rows.scroll_hint import ScrollHintRow + + +ConversationRowType = Union[ + CallRow, + CommandOutputRow, + DateRow, + FileTransferJingleRow, + FileTransferRow, + InfoMessage, + MessageRow, + MUCJoinLeft, + MUCSubject, + MUCUserStatus, + ReadMarkerRow, + ScrollHintRow +] + +ControlType = Union [ + ChatControl, + PrivateChatControl, + GroupchatControl +] View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/compare/14fa1c30663200665f5b3487add1b31…
-- View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/compare/14fa1c30663200665f5b3487add1b31…
You're receiving this email because of your account on
dev.gajim.org
.
1
0
0
0
[Git][gajim/gajim][master] 2 commits: GroupChatControl: Add management page
by Daniel Brötzmann (@wurstsalat)
22 Nov '21
22 Nov '21
Daniel Brötzmann pushed to branch master at gajim / gajim Commits: dac7c137 by Daniel Brötzmann at 2021-11-22T22:30:28+01:00 GroupChatControl: Add management page - - - - - f9eedc12 by Daniel Brötzmann at 2021-11-22T22:38:28+01:00 GroupChatControl: Add avatar selector page - - - - - 3 changed files: - gajim/data/gui/groupchat_control.ui - gajim/groupchat_control.py - gajim/gui_menu_builder.py Changes: ===================================== gajim/data/gui/groupchat_control.ui ===================================== @@ -123,6 +123,91 @@ </object> </child> </object> + <object class="GtkPopover" id="manage_popover"> + <property name="can_focus">False</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkButton" id="manage_change_subject_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="_on_change_subject" swapped="no"/> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">start</property> + <property name="label" translatable="yes">Change Subject…</property> + </object> + </child> + <style> + <class name="flat"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="manage_advanced_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="_on_configure_room" swapped="no"/> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">start</property> + <property name="label" translatable="yes">Advanced Settings…</property> + </object> + </child> + <style> + <class name="flat"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="manage_destroy_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="_on_destroy_room" swapped="no"/> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">start</property> + <property name="label" translatable="yes">Destroy…</property> + </object> + </child> + <style> + <class name="flat"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <style> + <class name="padding-6"/> + </style> + </object> + </child> + </object> <object class="GtkBox" id="groupchat_control_hbox"> <property name="can_focus">True</property> <child> @@ -2082,6 +2167,327 @@ <property name="position">14</property> </packing> </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="orientation">vertical</property> + <property name="spacing">18</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_bottom">12</property> + <property name="label" translatable="yes">Manage This Chat</property> + <style> + <class name="bold16"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkOverlay"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <child> + <object class="GtkImage" id="avatar_button_image"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_end">6</property> + <property name="margin_bottom">6</property> + <property name="pixel_size">100</property> + <property name="icon_size">6</property> + </object> + <packing> + <property name="index">-1</property> + </packing> + </child> + <child type="overlay"> + <object class="GtkButton" id="avatar_select_button"> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="no_show_all">True</property> + <property name="halign">end</property> + <property name="valign">end</property> + <signal name="clicked" handler="_on_change_avatar" swapped="no"/> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">document-edit-symbolic</property> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="row_spacing">6</property> + <property name="column_spacing">12</property> + <child> + <object class="GtkEntry" id="muc_description_entry"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="muc_name_entry"> + <property name="width_request">250</property> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">end</property> + <property name="label" translatable="yes">Name</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"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">end</property> + <property name="label" translatable="yes">Description</property> + <style> + <class name="dim-label"/> + </style> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkMenuButton"> + <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">center</property> + <property name="margin_top">12</property> + <property name="direction">up</property> + <property name="popover">manage_popover</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">More…</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">18</property> + <child> + <object class="GtkButton"> + <property name="label" translatable="yes">_Close</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="_on_page_cancel_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="manage_save_button"> + <property name="label" translatable="yes">Save</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="receives_default">True</property> + <property name="sensitive">False</property> + <signal name="clicked" handler="_on_manage_save_clicked" swapped="no"/> + <style> + <class name="suggested-action"/> + </style> + </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="expand">False</property> + <property name="fill">True</property> + <property name="position">5</property> + </packing> + </child> + <style> + <class name="padding-18"/> + </style> + </object> + <packing> + <property name="name">muc-manage</property> + <property name="position">15</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkGrid" id="avatar_selector_grid"> + <property name="name">settings_grid</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="border_width">18</property> + <property name="row_spacing">6</property> + <property name="column_spacing">12</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="margin_top">6</property> + <property name="spacing">12</property> + <child type="center"> + <object class="GtkButton" id="avatar_update_button"> + <property name="label" translatable="yes">Update</property> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="_on_avatar_update_clicked" swapped="no"/> + <style> + <class name="suggested-action"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkButton"> + <property name="label" translatable="yes">_Close</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="_on_page_cancel_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton"> + <property name="label" translatable="yes">Select File…</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <signal name="clicked" handler="_on_avatar_select_file_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Update Avatar</property> + <style> + <class name="bold16"/> + </style> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="name">avatar-selector</property> + <property name="position">16</property> + </packing> + </child> </object> <packing> <property name="index">-1</property> ===================================== gajim/groupchat_control.py ===================================== @@ -69,6 +69,7 @@ from gajim.gui.filechoosers import AvatarChooserDialog from gajim.gui.groupchat_config import GroupchatConfig from gajim.gui.adhoc import AdHocCommand +from gajim.gui.avatar_selector import AvatarSelector from gajim.gui.dataform import DataFormWidget from gajim.gui.groupchat_info import GroupChatInfoScrolled from gajim.gui.groupchat_invite import GroupChatInvite @@ -179,6 +180,10 @@ def __init__(self, parent_win, contact, muc_data, acct): # Groupchat settings self._groupchat_settings_box = None + # Holds the room’s config form, which is requested when managing + # the room + self._room_config_form = None + # Groupchat invite self.xml.quick_invite_button.set_action_name( 'win.invite-%s' % self.control_id) @@ -187,6 +192,11 @@ def __init__(self, parent_win, contact, muc_data, acct): self.xml.invite_grid.attach(self._invite_box, 0, 0, 1, 1) self._invite_box.connect('listbox-changed', self._on_invite_ready) + # Avatar selector + self._avatar_selector = AvatarSelector() + self._avatar_selector.set_size_request(400, 400) + self.xml.avatar_selector_grid.attach(self._avatar_selector, 0, 1, 1, 1) + self.control_menu = gui_menu_builder.get_groupchat_menu(self.control_id, self.account, self.room_jid) @@ -275,14 +285,11 @@ def add_actions(self): super().add_actions() actions = [ ('groupchat-settings-', None, self._on_groupchat_settings), + ('groupchat-manage-', None, self._on_groupchat_manage), ('rename-groupchat-', None, self._on_rename_groupchat), - ('change-subject-', None, self._on_change_subject), ('change-nickname-', None, self._on_change_nick), ('disconnect-', None, self._on_disconnect), - ('destroy-', None, self._on_destroy_room), - ('configure-', None, self._on_configure_room), ('request-voice-', None, self._on_request_voice), - ('upload-avatar-', None, self._on_upload_avatar), ('information-', None, self._on_information), ('invite-', None, self._on_invite), ('contact-information-', 's', self._on_contact_information), @@ -309,22 +316,8 @@ def update_actions(self, *args): self.account, self.room_jid, self.nick) con = app.connections[self.account] - # Destroy Room - self._get_action('destroy-').set_enabled(self.is_connected and - contact.affiliation.is_owner) - - # Configure Room - self._get_action('configure-').set_enabled( - self.is_connected and contact.affiliation in (Affiliation.ADMIN, - Affiliation.OWNER)) - - self._get_action('request-voice-').set_enabled(self.is_connected and - contact.role.is_visitor) - - # Change Subject - subject_change = self._is_subject_change_allowed() - self._get_action('change-subject-').set_enabled(self.is_connected and - subject_change) + self._get_action('request-voice-').set_enabled( + self.is_connected and contact.role.is_visitor) # Change Nick self._get_action('change-nickname-').set_enabled(self.is_connected) @@ -354,14 +347,31 @@ def update_actions(self, *args): tooltip_text = _('No File Transfer available') self.xml.sendfile_button.set_tooltip_text(tooltip_text) - # Upload Avatar + # Manage chat + self._get_action('groupchat-manage-').set_enabled( + self.is_connected and contact.affiliation in (Affiliation.ADMIN, + Affiliation.OWNER)) + vcard_support = False if self.disco_info is not None: vcard_support = self.disco_info.supports(Namespace.VCARD) - self._get_action('upload-avatar-').set_enabled( - self.is_connected and - vcard_support and - contact.affiliation.is_owner) + self.xml.muc_name_entry.set_text(self.disco_info.muc_name or '') + self.xml.muc_description_entry.set_text( + self.disco_info.muc_description or '') + + if (self.is_connected and vcard_support and + contact.affiliation.is_owner): + self.xml.avatar_select_button.show() + + self.xml.manage_change_subject_button.set_sensitive( + self.is_connected and self._is_subject_change_allowed()) + + self.xml.manage_advanced_button.set_sensitive( + self.is_connected and contact.affiliation in (Affiliation.ADMIN, + Affiliation.OWNER)) + + self.xml.manage_destroy_button.set_sensitive( + self.is_connected and contact.affiliation.is_owner) self._get_action('contact-information-').set_enabled(self.is_connected) @@ -375,14 +385,11 @@ def remove_actions(self): super().remove_actions() actions = [ 'groupchat-settings-', + 'groupchat-manage-', 'rename-groupchat-', - 'change-subject-', 'change-nickname-', 'disconnect-', - 'destroy-', - 'configure-', 'request-voice-', - 'upload-avatar-', 'information-', 'invite-', 'contact-information-', @@ -477,6 +484,36 @@ def _on_groupchat_settings(self, _action, _param): self.xml.settings_scrolled_box.add(self._groupchat_settings_box) self._show_page('muc-settings') + def _on_groupchat_manage(self, _action, _param): + surface = app.interface.avatar_storage.get_muc_surface( + self.account, + self.contact.jid, + AvatarSize.GROUP_INFO, + self.scale_factor) + self.xml.avatar_button_image.set_from_surface(surface) + + self._show_page('muc-manage') + self.xml.manage_save_button.grab_default() + + contact = app.contacts.get_gc_contact( + self.account, self.room_jid, self.nick) + if contact.affiliation.is_owner: + con = app.connections[self.account] + con.get_module('MUC').request_config( + self.room_jid, callback=self._on_manage_form_received) + + def _on_manage_form_received(self, task): + try: + result = task.finish() + except StanzaError as error: + log.info(error) + return + + self.xml.muc_name_entry.set_sensitive(True) + self.xml.muc_description_entry.set_sensitive(True) + self.xml.manage_save_button.set_sensitive(True) + self._room_config_form = result.form + def _on_invite(self, _action, _param): self._invite_box.load_contacts() self._show_page('invite') @@ -497,7 +534,7 @@ def invite(self, contact_jid): _('%s has been invited to this group chat') % contact_jid, message_id=message_id) - def _on_destroy_room(self, _action, _param): + def _on_destroy_room(self, _button): self.xml.destroy_reason_entry.grab_focus() self.xml.destroy_button.grab_default() self._show_page('destroy') @@ -528,7 +565,9 @@ def _on_destroy_confirm(self, _button): con.get_module('MUC').destroy(self.room_jid, reason, jid) self._show_page('groupchat') - def _on_configure_room(self, _action, _param): + def _on_configure_room(self, _button): + self.xml.manage_popover.popdown() + win = get_app_window('GroupchatConfig', self.account, self.room_jid) if win is not None: win.present() @@ -567,22 +606,23 @@ def _on_execute_command(self, _action, param): jid += '/' + nick AdHocCommand(self.account, jid) - def _on_upload_avatar(self, _action, _param): - def _on_accept(filename): - data, sha = app.interface.avatar_storage.prepare_for_publish( - filename) - if sha is None: - self.add_info_message(_('Loading avatar failed')) - return + def _on_change_avatar(self, _button): + def _on_accept(path): + self._avatar_selector.prepare_crop_area(path) + self.xml.avatar_update_button.set_sensitive( + self._avatar_selector.get_prepared()) + self._show_page('avatar-selector') + self.xml.avatar_update_button.grab_default() - vcard = VCard() - vcard.set_avatar(data, 'image/png') + AvatarChooserDialog(_on_accept, + transient_for=self.parent_win.window, + modal=True) - con = app.connections[self.account] - con.get_module('VCardTemp').set_vcard( - vcard, - jid=self.room_jid, - callback=self._on_upload_avatar_result) + def _on_avatar_select_file_clicked(self, _button): + def _on_accept(path): + self._avatar_selector.prepare_crop_area(path) + self.xml.avatar_update_button.set_sensitive( + self._avatar_selector.get_prepared()) AvatarChooserDialog(_on_accept, transient_for=self.parent_win.window, @@ -597,6 +637,27 @@ def _on_upload_avatar_result(self, task): else: self.add_info_message(_('Avatar upload successful')) + def _on_avatar_update_clicked(self, _button): + success, data, _, _ = self._avatar_selector.get_avatar_bytes() + if not success: + self.add_info_message(_('Loading avatar failed')) + return + + sha = app.interface.avatar_storage.save_avatar(data) + if sha is None: + self.add_info_message(_('Loading avatar failed')) + return + + vcard = VCard() + vcard.set_avatar(data, 'image/png') + + client = app.get_client(self.account) + client.get_module('VCardTemp').set_vcard( + vcard, + jid=self.room_jid, + callback=self._on_upload_avatar_result) + self._show_page('groupchat') + def _on_contact_information(self, _action, param): nick = param.get_string() gc_contact = app.contacts.get_gc_contact(self.account, @@ -744,7 +805,6 @@ def _update_avatar(self): self.contact.jid, AvatarSize.CHAT, self.scale_factor) - self.xml.avatar_image.set_from_surface(surface) def draw_banner_text(self): @@ -755,7 +815,7 @@ def draw_banner_text(self): self.xml.banner_name_label.set_text(self.room_name) @event_filter(['jid=room_jid']) - def _on_update_room_avatar(self, event): + def _on_update_room_avatar(self, _event): self._update_avatar() @event_filter(['account']) @@ -2004,8 +2064,27 @@ def _on_rename_clicked(self, _button): self.room_jid, name=new_name) self._show_page('groupchat') - def _on_change_subject(self, _action, _param): - if self._get_current_page() != 'groupchat': + def _on_manage_save_clicked(self, _button): + if self._room_config_form is not None: + name = self.xml.muc_name_entry.get_text() + desc = self.xml.muc_description_entry.get_text() + try: + name_field = self._room_config_form['muc#roomconfig_roomname'] + desc_field = self._room_config_form['muc#roomconfig_roomdesc'] + except KeyError: + pass + else: + name_field.value = name + desc_field.value = desc + + con = app.connections[self.account] + con.get_module('MUC').set_config( + self.room_jid, self._room_config_form) + + self._show_page('groupchat') + + def _on_change_subject(self, _button): + if self._get_current_page() not in ('groupchat', 'muc-manage'): return self.xml.subject_textview.get_buffer().set_text(self.subject) self.xml.subject_textview.grab_focus() ===================================== gajim/gui_menu_builder.py ===================================== @@ -575,13 +575,8 @@ def get_groupchat_menu(control_id, account, jid): groupchat_menu = [ ('win.information-', _('Information')), ('win.groupchat-settings-', _('Settings…')), - (_('Manage Group Chat'), [ - ('win.rename-groupchat-', _('Rename…')), - ('win.change-subject-', _('Change Subject…')), - ('win.upload-avatar-', _('Upload Avatar…')), - ('win.configure-', _('Configure…')), - ('win.destroy-', _('Destroy…')), - ]), + ('win.groupchat-manage-', _('Manage…')), + ('win.rename-groupchat-', _('Rename Chat…')), ('win.change-nickname-', _('Change Nickname…')), ('win.request-voice-', _('Request Voice')), ('win.execute-command-', _('Execute Command…')), View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/compare/73decf08d20d08e4f8de0b82ef939d3…
-- View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/compare/73decf08d20d08e4f8de0b82ef939d3…
You're receiving this email because of your account on
dev.gajim.org
.
1
0
0
0
[Git][gajim/gajim][master] AccountWizard: Improve badge preview
by Daniel Brötzmann (@wurstsalat)
22 Nov '21
22 Nov '21
Daniel Brötzmann pushed to branch master at gajim / gajim Commits: 73decf08 by wurstsalat at 2021-11-22T21:34:01+01:00 AccountWizard: Improve badge preview - - - - - 2 changed files: - gajim/data/gui/account_wizard.ui - gajim/gtk/account_wizard.py Changes: ===================================== gajim/data/gui/account_wizard.ui ===================================== @@ -1,20 +1,20 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.36.0 --> +<!-- Generated with glade 3.38.2 --> <interface> <requires lib="gtk+" version="3.22"/> <object class="GtkBox" id="account_label_box"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="halign">center</property> <property name="orientation">vertical</property> <property name="spacing">12</property> <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Optional: Add a name and color for your account</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes">Add a name and color for your account</property> <property name="wrap">True</property> - <property name="max_width_chars">50</property> + <property name="max-width-chars">50</property> <style> <class name="dim-label"/> </style> @@ -28,16 +28,13 @@ <child> <object class="GtkBox"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="halign">center</property> - <style> - <class name="linked"/> - </style> <child> <object class="GtkEntry" id="account_name_entry"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="placeholder_text" translatable="yes">Account Name...</property> + <property name="can-focus">True</property> + <property name="placeholder-text" translatable="yes">Account Name...</property> </object> <packing> <property name="expand">False</property> @@ -48,8 +45,8 @@ <child> <object class="GtkColorButton" id="account_color_button"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> </object> <packing> <property name="expand">False</property> @@ -57,6 +54,9 @@ <property name="position">1</property> </packing> </child> + <style> + <class name="linked"/> + </style> </object> <packing> <property name="expand">False</property> @@ -67,8 +67,8 @@ <child> <object class="GtkImage"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="icon_name">go-down-symbolic</property> + <property name="can-focus">False</property> + <property name="icon-name">go-down-symbolic</property> </object> <packing> <property name="expand">False</property> @@ -79,8 +79,11 @@ <child> <object class="GtkLabel" id="badge_preview"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="halign">center</property> + <property name="ellipsize">end</property> + <property name="single-line-mode">True</property> + <property name="max-width-chars">42</property> <style> <class name="badge"/> </style> @@ -92,94 +95,95 @@ </packing> </child> </object> + <!-- n-columns=3 n-rows=5 --> <object class="GtkGrid" id="advanced_grid"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="halign">center</property> - <property name="row_spacing">6</property> - <property name="column_spacing">12</property> + <property name="row-spacing">6</property> + <property name="column-spacing">12</property> <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="halign">end</property> <property name="label" translatable="yes">_Port</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">custom_port_entry</property> + <property name="use-underline">True</property> + <property name="mnemonic-widget">custom_port_entry</property> <style> <class name="dim-label"/> </style> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">3</property> + <property name="left-attach">0</property> + <property name="top-attach">3</property> </packing> </child> <child> <object class="GtkEntry" id="custom_port_entry"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="width_chars">6</property> - <property name="placeholder_text">5222</property> - <property name="input_purpose">number</property> + <property name="can-focus">True</property> + <property name="width-chars">6</property> + <property name="placeholder-text">5222</property> + <property name="input-purpose">number</property> </object> <packing> - <property name="left_attach">1</property> - <property name="top_attach">3</property> + <property name="left-attach">1</property> + <property name="top-attach">3</property> </packing> </child> <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="halign">end</property> <property name="label" translatable="yes">_Hostname</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">custom_host_entry</property> + <property name="use-underline">True</property> + <property name="mnemonic-widget">custom_host_entry</property> <style> <class name="dim-label"/> </style> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">2</property> + <property name="left-attach">0</property> + <property name="top-attach">2</property> </packing> </child> <child> <object class="GtkEntry" id="custom_host_entry"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="placeholder_text" translatable="yes">
example.org
</property> + <property name="can-focus">True</property> + <property name="placeholder-text" translatable="yes">
example.org
</property> </object> <packing> - <property name="left_attach">1</property> - <property name="top_attach">2</property> + <property name="left-attach">1</property> + <property name="top-attach">2</property> </packing> </child> <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="halign">end</property> - <property name="margin_bottom">18</property> + <property name="margin-bottom">18</property> <property name="label" translatable="yes">Prox_y</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">proxies_combobox</property> + <property name="use-underline">True</property> + <property name="mnemonic-widget">proxies_combobox</property> <style> <class name="dim-label"/> </style> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">1</property> + <property name="left-attach">0</property> + <property name="top-attach">1</property> </packing> </child> <child> <object class="GtkComboBox" id="proxies_combobox"> - <property name="width_request">250</property> + <property name="width-request">250</property> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="margin_bottom">18</property> + <property name="can-focus">False</property> + <property name="margin-bottom">18</property> <child> <object class="GtkCellRendererText"/> <attributes> @@ -188,51 +192,51 @@ </child> </object> <packing> - <property name="left_attach">1</property> - <property name="top_attach">1</property> + <property name="left-attach">1</property> + <property name="top-attach">1</property> </packing> </child> <child> <object class="GtkButton" id="manage_proxies_button"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="tooltip_text" translatable="yes">Manage Proxies...</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="tooltip-text" translatable="yes">Manage Proxies...</property> <property name="halign">start</property> <property name="valign">start</property> <child> <object class="GtkImage"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="icon_name">preferences-system-symbolic</property> + <property name="can-focus">False</property> + <property name="icon-name">preferences-system-symbolic</property> </object> </child> </object> <packing> - <property name="left_attach">2</property> - <property name="top_attach">1</property> + <property name="left-attach">2</property> + <property name="top-attach">1</property> </packing> </child> <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="margin_bottom">12</property> + <property name="can-focus">False</property> + <property name="margin-bottom">12</property> <property name="label" translatable="yes">Advanced Settings</property> <style> <class name="large-header"/> </style> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">0</property> + <property name="left-attach">0</property> + <property name="top-attach">0</property> <property name="width">3</property> </packing> </child> <child> <object class="GtkComboBoxText" id="con_type_combo"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="active">0</property> <items> <item>START TLS</item> @@ -241,25 +245,25 @@ </items> </object> <packing> - <property name="left_attach">1</property> - <property name="top_attach">4</property> + <property name="left-attach">1</property> + <property name="top-attach">4</property> </packing> </child> <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="halign">end</property> <property name="label" translatable="yes">_Type</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">con_type_combo</property> + <property name="use-underline">True</property> + <property name="mnemonic-widget">con_type_combo</property> <style> <class name="dim-label"/> </style> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">4</property> + <property name="left-attach">0</property> + <property name="top-attach">4</property> </packing> </child> <child> @@ -273,14 +277,14 @@ </child> </object> <object class="GtkEntryCompletion" id="entrycompletion1"> - <property name="text_column">0</property> - <property name="inline_completion">True</property> - <property name="popup_completion">False</property> - <property name="popup_single_match">False</property> + <property name="text-column">0</property> + <property name="inline-completion">True</property> + <property name="popup-completion">False</property> + <property name="popup-single-match">False</property> </object> <object class="GtkBox" id="login_box"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="halign">center</property> <property name="valign">center</property> <property name="orientation">vertical</property> @@ -288,8 +292,8 @@ <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="margin_bottom">12</property> + <property name="can-focus">False</property> + <property name="margin-bottom">12</property> <property name="label" translatable="yes">Welcome</property> <style> <class name="large-header"/> @@ -304,11 +308,11 @@ <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="halign">center</property> <property name="label" translatable="yes">Please enter your credentials or Sign Up</property> <property name="wrap">True</property> - <property name="max_width_chars">40</property> + <property name="max-width-chars">40</property> <style> <class name="dim-label"/> </style> @@ -321,12 +325,12 @@ </child> <child> <object class="GtkEntry" id="log_in_address_entry"> - <property name="width_request">300</property> + <property name="width-request">300</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="tooltip_text" translatable="yes">Your XMPP address (e.g. user(a)example.org)</property> - <property name="activates_default">True</property> - <property name="placeholder_text" translatable="yes">user(a)example.org</property> + <property name="can-focus">True</property> + <property name="tooltip-text" translatable="yes">Your XMPP address (e.g. user(a)example.org)</property> + <property name="activates-default">True</property> + <property name="placeholder-text" translatable="yes">user(a)example.org</property> <property name="completion">entrycompletion1</property> </object> <packing> @@ -338,12 +342,12 @@ <child> <object class="GtkEntry" id="log_in_password_entry"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="tooltip_text" translatable="yes">Your password</property> + <property name="can-focus">True</property> + <property name="tooltip-text" translatable="yes">Your password</property> <property name="visibility">False</property> - <property name="activates_default">True</property> - <property name="placeholder_text" translatable="yes">Password</property> - <property name="input_purpose">password</property> + <property name="activates-default">True</property> + <property name="placeholder-text" translatable="yes">Password</property> + <property name="input-purpose">password</property> </object> <packing> <property name="expand">False</property> @@ -355,12 +359,12 @@ <object class="GtkCheckButton" id="login_advanced_checkbutton"> <property name="label" translatable="yes">_Advanced Settings</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="tooltip_text" translatable="yes">Proxy, custom hostname and port</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="tooltip-text" translatable="yes">Proxy, custom hostname and port</property> <property name="halign">start</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> </object> <packing> <property name="expand">False</property> @@ -373,10 +377,10 @@ <property name="label" translatable="yes">_Log In</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="tooltip_text" translatable="yes">Log in with your credentials</property> - <property name="use_underline">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="tooltip-text" translatable="yes">Log in with your credentials</property> + <property name="use-underline">True</property> <style> <class name="suggested-action"/> </style> @@ -390,7 +394,7 @@ <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="label" translatable="yes">or</property> </object> <packing> @@ -403,10 +407,10 @@ <object class="GtkButton" id="sign_up_button"> <property name="label" translatable="yes">_Sign Up</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_text" translatable="yes">Sign up for a new account on a server of your choice</property> - <property name="use_underline">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="tooltip-text" translatable="yes">Sign up for a new account on a server of your choice</property> + <property name="use-underline">True</property> </object> <packing> <property name="expand">False</property> @@ -416,22 +420,22 @@ </child> </object> <object class="GtkEntryCompletion" id="entrycompletion2"> - <property name="text_column">0</property> - <property name="inline_completion">True</property> - <property name="popup_completion">False</property> - <property name="popup_single_match">False</property> + <property name="text-column">0</property> + <property name="inline-completion">True</property> + <property name="popup-completion">False</property> + <property name="popup-single-match">False</property> </object> <object class="GtkBox" id="redirect_box"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="orientation">vertical</property> <property name="spacing">18</property> <child> <object class="GtkImage"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="halign">center</property> - <property name="icon_name">applications-internet-symbolic</property> + <property name="icon-name">applications-internet-symbolic</property> <property name="icon_size">6</property> </object> <packing> @@ -443,10 +447,10 @@ <child> <object class="GtkLabel" id="instructions"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="halign">center</property> <property name="wrap">True</property> - <property name="max_width_chars">42</property> + <property name="max-width-chars">42</property> </object> <packing> <property name="expand">False</property> @@ -458,10 +462,10 @@ <object class="GtkButton" id="link_button"> <property name="label" translatable="yes">Visit Website</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> <property name="halign">center</property> - <property name="use_underline">True</property> + <property name="use-underline">True</property> <style> <class name="suggested-action"/> </style> @@ -475,15 +479,15 @@ </object> <object class="GtkBox" id="security_warning_box"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="orientation">vertical</property> <property name="spacing">18</property> <child> <object class="GtkImage"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="halign">center</property> - <property name="icon_name">application-certificate-symbolic</property> + <property name="icon-name">application-certificate-symbolic</property> <property name="icon_size">6</property> </object> <packing> @@ -495,7 +499,7 @@ <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="halign">center</property> <property name="label" translatable="yes">Certificate Verification Failed</property> <property name="wrap">True</property> @@ -513,11 +517,11 @@ <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="halign">center</property> <property name="label" translatable="yes">The following warnings came up while trying to verify the server's certificate</property> <property name="wrap">True</property> - <property name="max_width_chars">42</property> + <property name="max-width-chars">42</property> </object> <packing> <property name="expand">False</property> @@ -527,11 +531,11 @@ </child> <child> <object class="GtkListBox" id="error_list"> - <property name="width_request">300</property> + <property name="width-request">300</property> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="halign">center</property> - <property name="selection_mode">none</property> + <property name="selection-mode">none</property> <style> <class name="tls-error-list"/> </style> @@ -546,10 +550,10 @@ <object class="GtkButton" id="view_cert_button"> <property name="label" translatable="yes">_Show Certificate</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> <property name="halign">center</property> - <property name="use_underline">True</property> + <property name="use-underline">True</property> </object> <packing> <property name="expand">False</property> @@ -560,12 +564,12 @@ <child> <object class="GtkCheckButton" id="trust_cert_checkbutton"> <property name="label" translatable="yes">_Add to Trusted Certificates</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="no_show_all">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="no-show-all">True</property> <property name="halign">center</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> </object> <packing> <property name="expand">False</property> @@ -575,19 +579,19 @@ </child> </object> <object class="GtkPopover" id="server_recommendations"> - <property name="width_request">350</property> - <property name="can_focus">False</property> + <property name="width-request">350</property> + <property name="can-focus">False</property> <child> <object class="GtkBox"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="border_width">12</property> + <property name="can-focus">False</property> + <property name="border-width">12</property> <property name="orientation">vertical</property> <property name="spacing">6</property> <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="label" translatable="yes">Which server should I choose?</property> <style> <class name="bold"/> @@ -602,11 +606,11 @@ <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="label" translatable="yes">There are plenty of servers to choose from. Creating an account on one server allows you to communicate with contacts from other servers as well.</property> <property name="wrap">True</property> - <property name="max_width_chars">40</property> + <property name="max-width-chars">40</property> <property name="xalign">0</property> </object> <packing> @@ -618,9 +622,9 @@ Creating an account on one server allows you to communicate with contacts from o <child> <object class="GtkButton" id="visit_server_button"> <property name="label" translatable="yes">Visit Server's Website</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="no_show_all">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="no-show-all">True</property> <property name="halign">center</property> <style> <class name="suggested-action"/> @@ -635,11 +639,11 @@ Creating an account on one server allows you to communicate with contacts from o <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="margin_top">3</property> + <property name="can-focus">False</property> + <property name="margin-top">3</property> <property name="label" translatable="yes">Listing of Servers</property> <property name="wrap">True</property> - <property name="max_width_chars">40</property> + <property name="max-width-chars">40</property> <property name="xalign">0</property> <style> <class name="bold"/> @@ -654,12 +658,12 @@ Creating an account on one server allows you to communicate with contacts from o <child> <object class="GtkLabel" id="recommendation_link1"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="label" translatable="yes"><a href='
https://xmpp.org/getting-started/
'>xmpp.org/getting-started</a></property> - <property name="use_markup">True</property> + <property name="use-markup">True</property> <property name="wrap">True</property> - <property name="wrap_mode">word-char</property> - <property name="max_width_chars">40</property> + <property name="wrap-mode">word-char</property> + <property name="max-width-chars">40</property> <property name="xalign">0</property> </object> <packing> @@ -671,11 +675,11 @@ Creating an account on one server allows you to communicate with contacts from o <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="margin_top">3</property> + <property name="can-focus">False</property> + <property name="margin-top">3</property> <property name="label" translatable="yes">A Feature Comparison of Various Servers</property> <property name="wrap">True</property> - <property name="max_width_chars">40</property> + <property name="max-width-chars">40</property> <property name="xalign">0</property> <style> <class name="bold"/> @@ -690,12 +694,12 @@ Creating an account on one server allows you to communicate with contacts from o <child> <object class="GtkLabel" id="recommendation_link2"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="label" translatable="yes"><a href='
https://conversations.im/compliance/
'>conversations.im/compliance</a></property> - <property name="use_markup">True</property> + <property name="use-markup">True</property> <property name="wrap">True</property> - <property name="wrap_mode">word-char</property> - <property name="max_width_chars">40</property> + <property name="wrap-mode">word-char</property> + <property name="max-width-chars">40</property> <property name="xalign">0</property> </object> <packing> @@ -707,100 +711,101 @@ Creating an account on one server allows you to communicate with contacts from o </object> </child> </object> + <!-- n-columns=3 n-rows=5 --> <object class="GtkGrid" id="signup_grid"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="halign">center</property> - <property name="row_spacing">6</property> - <property name="column_spacing">12</property> + <property name="row-spacing">6</property> + <property name="column-spacing">12</property> <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="margin_bottom">12</property> + <property name="can-focus">False</property> + <property name="margin-bottom">12</property> <property name="label" translatable="yes">Sign Up</property> <style> <class name="large-header"/> </style> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">0</property> + <property name="left-attach">0</property> + <property name="top-attach">0</property> <property name="width">2</property> </packing> </child> <child> <object class="GtkLabel"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="label" translatable="yes">_Please choose a server</property> - <property name="use_markup">True</property> - <property name="use_underline">True</property> + <property name="use-markup">True</property> + <property name="use-underline">True</property> <style> <class name="dim-label"/> </style> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">1</property> + <property name="left-attach">0</property> + <property name="top-attach">1</property> <property name="width">2</property> </packing> </child> <child> <object class="GtkMenuButton"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_text" translatable="yes">Which server should I choose?</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="tooltip-text" translatable="yes">Which server should I choose?</property> <property name="popover">server_recommendations</property> <child> <object class="GtkImage"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="icon_name">dialog-information-symbolic</property> + <property name="can-focus">False</property> + <property name="icon-name">dialog-information-symbolic</property> </object> </child> </object> <packing> - <property name="left_attach">1</property> - <property name="top_attach">2</property> + <property name="left-attach">1</property> + <property name="top-attach">2</property> </packing> </child> <child> <object class="GtkComboBoxText" id="server_comboboxtext_sign_up"> - <property name="width_request">300</property> + <property name="width-request">300</property> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="has_entry">True</property> + <property name="can-focus">False</property> + <property name="has-entry">True</property> <child internal-child="entry"> <object class="GtkEntry" id="server_comboboxtext_sign_up_entry"> - <property name="can_focus">True</property> - <property name="activates_default">True</property> - <property name="placeholder_text" translatable="yes">
example.org
</property> + <property name="can-focus">True</property> + <property name="activates-default">True</property> + <property name="placeholder-text" translatable="yes">
example.org
</property> <property name="completion">entrycompletion2</property> - <property name="input_purpose">url</property> + <property name="input-purpose">url</property> </object> </child> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">2</property> + <property name="left-attach">0</property> + <property name="top-attach">2</property> </packing> </child> <child> <object class="GtkCheckButton" id="sign_up_anonymously"> <property name="label" translatable="yes">Sign up Anonymously</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="tooltip_text" translatable="yes">Note: Anonymous accounts are not possible on all servers</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="tooltip-text" translatable="yes">Note: Anonymous accounts are not possible on all servers</property> <property name="halign">start</property> <property name="valign">start</property> - <property name="draw_indicator">True</property> + <property name="draw-indicator">True</property> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">3</property> + <property name="left-attach">0</property> + <property name="top-attach">3</property> <property name="width">2</property> </packing> </child> @@ -808,18 +813,33 @@ Creating an account on one server allows you to communicate with contacts from o <object class="GtkCheckButton" id="sign_up_advanced_checkbutton"> <property name="label" translatable="yes">_Advanced Settings</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="tooltip_text" translatable="yes">Proxy, custom hostname and port</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="tooltip-text" translatable="yes">Proxy, custom hostname and port</property> <property name="halign">start</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">4</property> + <property name="left-attach">0</property> + <property name="top-attach">4</property> <property name="width">2</property> </packing> </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> </object> </interface> ===================================== gajim/gtk/account_wizard.py ===================================== @@ -1017,7 +1017,7 @@ def _on_color_set(self, button): self._save_config() def _set_badge_color(self, color): - css = '.badge { background-color: %s }' % color + css = '.badge { background-color: %s; font-size: 100%%; }' % color self._provider.load_from_data(bytes(css.encode())) def _save_config(self): View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/commit/73decf08d20d08e4f8de0b82ef939d34…
-- View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/commit/73decf08d20d08e4f8de0b82ef939d34…
You're receiving this email because of your account on
dev.gajim.org
.
1
0
0
0
[Git][gajim/gajim][mainwindow] StatusIcon: Make use of libappindicator configurable
by Daniel Brötzmann (@wurstsalat)
22 Nov '21
22 Nov '21
Daniel Brötzmann pushed to branch mainwindow at gajim / gajim Commits: 14fa1c30 by wurstsalat at 2021-11-22T21:14:39+01:00 StatusIcon: Make use of libappindicator configurable - - - - - 2 changed files: - gajim/common/setting_values.py - gajim/gtk/status_icon.py Changes: ===================================== gajim/common/setting_values.py ===================================== @@ -124,6 +124,7 @@ class _ACCOUNT_DEFAULT: 'groupchat_roster_width': 210, 'dev_force_bookmark_2': False, 'developer_modus': False, + 'use_libappindicator': False, 'show_help_start_chat': True, 'gc_notify_on_all_messages_private_default': True, 'gc_notify_on_all_messages_public_default': False, @@ -398,6 +399,7 @@ class _ACCOUNT_DEFAULT: 'gc_notify_on_all_messages_public_default': '', 'metacontacts_enabled': '', 'developer_modus': '', + 'use_libappindicator': _('Enables libappindicator, an alternative tray icon provider'), }, } ===================================== gajim/gtk/status_icon.py ===================================== @@ -60,6 +60,7 @@ def __init__(self): self._popup_menus = [] self._hide_menuitem_added = False self._status_icon = None + self._use_libappindicator = app.settings.get('use_libappindicator') self._ui.sounds_mute_menuitem.set_active( not app.settings.get('sounds_on')) @@ -86,7 +87,7 @@ def _on_account_state(self, _event): def show_icon(self): if not self._status_icon: - if HAS_INDICATOR: + if HAS_INDICATOR and self._use_libappindicator: self._status_icon = appindicator.Indicator.new( 'Gajim', 'dcraven-online', @@ -112,7 +113,7 @@ def show_icon(self): self.update_icon() def hide_icon(self): - if HAS_INDICATOR: + if HAS_INDICATOR and self._use_libappindicator: self._status_icon.set_status(appindicator.IndicatorStatus.PASSIVE) else: self._status_icon.set_visible(False) @@ -126,14 +127,14 @@ def update_icon(self, *args, count=0): if not app.interface.systray_enabled: return if app.settings.get('trayicon') == 'always': - if HAS_INDICATOR: + if HAS_INDICATOR and self._use_libappindicator: self._status_icon.set_status( appindicator.IndicatorStatus.ACTIVE) else: self._status_icon.set_visible(True) if count > 0: icon_name = 'dcraven-message-new' - if HAS_INDICATOR: + if HAS_INDICATOR and self._use_libappindicator: self._status_icon.set_icon_full(icon_name, _('Pending Event')) else: self._status_icon.set_visible(True) @@ -141,7 +142,7 @@ def update_icon(self, *args, count=0): return if app.settings.get('trayicon') == 'on_event': - if HAS_INDICATOR: + if HAS_INDICATOR and self._use_libappindicator: self._status_icon.set_status( appindicator.IndicatorStatus.PASSIVE) else: @@ -149,7 +150,7 @@ def update_icon(self, *args, count=0): show = get_global_show() icon_name = get_icon_name(show) - if HAS_INDICATOR: + if HAS_INDICATOR and self._use_libappindicator: self._status_icon.set_icon_full(icon_name, show) self._status_icon.set_status(appindicator.IndicatorStatus.ACTIVE) else: View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/commit/14fa1c30663200665f5b3487add1b311…
-- View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/commit/14fa1c30663200665f5b3487add1b311…
You're receiving this email because of your account on
dev.gajim.org
.
1
0
0
0
[Git][gajim/gajim][mainwindow] 2 commits: Remote: Add TODO
by Daniel Brötzmann (@wurstsalat)
22 Nov '21
22 Nov '21
Daniel Brötzmann pushed to branch mainwindow at gajim / gajim Commits: d249841a by wurstsalat at 2021-11-22T20:50:35+01:00 Remote: Add TODO - - - - - 9891ff3d by wurstsalat at 2021-11-22T20:54:23+01:00 Store message corrections in database Original text is preserved in additional_data, message text is overwritten with corrected text. - - - - - 10 changed files: - gajim/common/modules/mam.py - gajim/common/modules/message.py - gajim/common/storage/archive.py - gajim/gtk/chat_list.py - gajim/gtk/controls/base.py - gajim/gtk/controls/chat.py - gajim/gtk/controls/groupchat.py - gajim/gtk/conversation/rows/message.py - gajim/gtk/conversation/view.py - gajim/remote_control.py Changes: ===================================== gajim/common/modules/mam.py ===================================== @@ -257,6 +257,33 @@ def _mam_message_received(self, _con, stanza, properties): return stanza_id = message_id + event_attr = { + 'account': self._account, + 'jid': str(properties.jid.bare), + 'msgtxt': properties.body, + 'properties': properties, + 'additional_data': additional_data, + 'unique_id': properties.id, + 'stanza_id': stanza_id, + 'archive_jid': properties.mam.archive, + 'kind': kind, + } + + correct_id = parse_correction(properties) + if correct_id is not None: + event_attr.update({ + 'correct_id': correct_id, + }) + app.nec.push_incoming_event( + NetworkEvent('message-updated', **event_attr)) + app.storage.archive.store_message_correction( + self._account, + properties.jid.bare, + correct_id, + properties.body, + properties.type.is_groupchat) + return + app.storage.archive.insert_into_logs( self._account, with_, @@ -269,18 +296,7 @@ def _mam_message_received(self, _con, stanza, properties): message_id=properties.id) app.nec.push_incoming_event( - NetworkEvent('mam-message-received', - account=self._account, - additional_data=additional_data, - correct_id=parse_correction(properties), - stanza_id=stanza_id, - archive_jid=properties.mam.archive, - msgtxt=properties.body, - properties=properties, - kind=kind, - jid=str(properties.jid.bare) - ) - ) + NetworkEvent('mam-message-received', **event_attr)) def _is_valid_request(self, properties): valid_id = self._mam_query_ids.get(properties.mam.archive, None) ===================================== gajim/common/modules/message.py ===================================== @@ -180,17 +180,30 @@ def _message_received(self, _con, stanza, properties): 'resource': resource, 'stanza_id': stanza_id, 'unique_id': stanza_id or message_id, - 'correct_id': parse_correction(properties), 'msgtxt': msgtxt, 'session': session, 'delayed': properties.user_timestamp is not None, - 'gc_control': None, - 'popup': False, 'msg_log_id': None, 'displaymarking': displaymarking, 'properties': properties, } + correct_id = parse_correction(properties) + if correct_id is not None: + event_attr.update({ + 'correct_id': correct_id, + }) + event = NetworkEvent('message-updated', **event_attr) + if should_log(self._account, jid): + app.storage.archive.store_message_correction( + self._account, + jid, + correct_id, + msgtxt, + properties.type.is_groupchat) + app.nec.push_incoming_event(event) + return + if type_.is_groupchat: if not msgtxt: return @@ -381,6 +394,15 @@ def log_message(self, message): if message.message is None: return + if message.correct_id is not None: + app.storage.archive.store_message_correction( + self._account, + message.jid, + message.correct_id, + message.message, + message.is_groupchat) + return + app.storage.archive.insert_into_logs( self._account, message.jid, ===================================== gajim/common/storage/archive.py ===================================== @@ -29,6 +29,7 @@ import sqlite3 as sqlite from collections import namedtuple +from nbxmpp import JID from nbxmpp.structs import MessageProperties from gajim.common import app @@ -431,7 +432,7 @@ def get_last_conversation_line(self, account, jid): KindConstant.ERROR]) sql = ''' - SELECT contact_name, time, kind, message, stanza_id, + SELECT contact_name, time, kind, message, stanza_id, message_id, additional_data FROM logs NATURAL JOIN jids WHERE jid IN ({jids}) AND account_id = {account_id} @@ -923,6 +924,51 @@ def find_stanza_id(self, account, archive_jid, stanza_id, origin_id=None, return True return False + @timeit + def store_message_correction(self, + account: str, + jid: JID, + correct_id: str, + corrected_text: str, + is_groupchat: bool) -> None: + type_ = JIDConstant.NORMAL_TYPE + if is_groupchat: + type_ = JIDConstant.ROOM_TYPE + + jid_id = self.get_jid_id(str(jid), type_=type_) + account_id = self.get_account_id(account) + sql = ''' + SELECT log_line_id, message, additional_data + FROM logs + WHERE +jid_id = ? + AND account_id = ? + AND message_id = ? + ''' + row = self._con.execute( + sql, (jid_id, account_id, correct_id)).fetchone() + if row is None: + return + + if row.additional_data is None: + additional_data = AdditionalDataDict() + else: + additional_data = row.additional_data + + original_text = additional_data.get_value( + 'corrected', 'original_text') + if original_text is None: + # Only set original_text for the first correction + additional_data.set_value( + 'corrected', 'original_text', row.message) + serialized_dict = json.dumps(additional_data.data) + + sql = ''' + UPDATE logs SET message = ?, additional_data = ? + WHERE log_line_id = ? + ''' + self._con.execute( + sql, (corrected_text, serialized_dict, row.log_line_id)) + @timeit def update_additional_data(self, account: str, ===================================== gajim/gtk/chat_list.py ===================================== @@ -358,6 +358,7 @@ def _on_message_received(self, event): if event.properties.stanza_id: stanza_id = event.properties.stanza_id.id row.set_stanza_id(stanza_id) + row.set_message_id(event.unique_id) row.set_message_text( event.msgtxt, additional_data=event.additional_data) @@ -369,6 +370,10 @@ def _on_message_updated(self, event): if row is None: return + if hasattr(event, 'correct_id'): + if event.correct_id == row.message_id: + row.set_message_text(event.msgtxt) + if event.properties.is_moderation: if event.properties.moderation.stanza_id == row.stanza_id: text = get_retraction_text( @@ -483,6 +488,7 @@ def __init__(self, workspace_id: str, account: str, jid: JID, type_: str, self.contact_name: str = self.contact.name self.timestamp: int = 0 self.stanza_id: Optional[str] = None + self.message_id: Optional[str] = None self._unread_count: int = 0 self._pinned: bool = pinned @@ -542,6 +548,7 @@ def __init__(self, workspace_id: str, account: str, jid: JID, type_: str, self._ui.timestamp_label.set_text(uf_timestamp) self.stanza_id = line.stanza_id + self.message_id = line.message_id if line.kind in (KindConstant.FILE_TRANSFER_INCOMING, KindConstant.FILE_TRANSFER_OUTGOING): @@ -685,6 +692,9 @@ def set_timestamp(self, timestamp: int) -> None: def set_stanza_id(self, stanza_id: str) -> None: self.stanza_id = stanza_id + def set_message_id(self, message_id: str) -> None: + self.message_id = message_id + def update_time(self) -> None: if self.timestamp == 0: return ===================================== gajim/gtk/controls/base.py ===================================== @@ -296,6 +296,11 @@ def process_event(self, event): getattr(self, method_name)(event) def _on_message_updated(self, event): + if hasattr(event, 'correct_id'): + self.conversation_view.correct_message( + event.correct_id, event.msgtxt) + return + if event.properties.is_moderation: text = get_retraction_text( self.account, @@ -1122,7 +1127,6 @@ def add_message(self, msg_log_id=None, message_id=None, stanza_id=None, - correct_id=None, additional_data=None): if additional_data is None: @@ -1139,7 +1143,6 @@ def add_message(self, display_marking=displaymarking, message_id=message_id, stanza_id=stanza_id, - correct_id=correct_id, log_line_id=msg_log_id, additional_data=additional_data) ===================================== gajim/gtk/controls/chat.py ===================================== @@ -412,7 +412,6 @@ def _on_mam_message_received(self, event): self.add_message(event.msgtxt, kind, tim=event.properties.mam.timestamp, - correct_id=event.correct_id, message_id=event.properties.id, stanza_id=event.stanza_id, additional_data=event.additional_data, @@ -433,7 +432,6 @@ def _on_message_received(self, event): msg_log_id=event.msg_log_id, message_id=event.properties.id, stanza_id=event.stanza_id, - correct_id=event.correct_id, additional_data=event.additional_data) if kind == 'outgoing': @@ -460,12 +458,16 @@ def _on_message_sent(self, event): self.msg_textview.get_style_context().remove_class( 'gajim-msg-correcting') + if event.correct_id: + self.conversation_view.correct_message( + event.correct_id, event.message) + return + self.add_message(event.message, 'outgoing', tim=event.timestamp, displaymarking=displaymarking, message_id=message_id, - correct_id=event.correct_id, additional_data=event.additional_data) def _on_receipt_received(self, event): @@ -606,7 +608,6 @@ def add_message(self, displaymarking=None, msg_log_id=None, stanza_id=None, - correct_id=None, message_id=None, additional_data=None, notify=True): @@ -629,7 +630,6 @@ def add_message(self, msg_log_id=msg_log_id, message_id=message_id, stanza_id=stanza_id, - correct_id=correct_id, additional_data=additional_data) def shutdown(self): ===================================== gajim/gtk/controls/groupchat.py ===================================== @@ -671,7 +671,6 @@ def _on_mam_message_received(self, event): self.add_message(event.msgtxt, contact=event.properties.muc_nickname, tim=event.properties.mam.timestamp, - correct_id=event.correct_id, message_id=event.properties.id, stanza_id=event.stanza_id, additional_data=event.additional_data, @@ -694,7 +693,6 @@ def _on_gc_message_received(self, event): contact=event.properties.muc_nickname, tim=event.properties.timestamp, displaymarking=event.displaymarking, - correct_id=event.correct_id, message_id=event.properties.id, stanza_id=stanza_id, additional_data=event.additional_data) @@ -708,7 +706,6 @@ def add_message(self, contact='', tim=None, displaymarking=None, - correct_id=None, message_id=None, stanza_id=None, additional_data=None, @@ -733,7 +730,6 @@ def add_message(self, tim, notify, displaymarking=displaymarking, - correct_id=correct_id, message_id=message_id, stanza_id=stanza_id, additional_data=additional_data) ===================================== gajim/gtk/conversation/rows/message.py ===================================== @@ -70,7 +70,6 @@ def __init__(self, self.kind = kind self.name = name or '' self.text = text - self.additional_data = additional_data self._contact = contact @@ -78,13 +77,11 @@ def __init__(self, if contact is not None and contact.is_groupchat: self._is_groupchat = True - self._corrections = [] self._has_receipt = marker == 'received' self._has_displayed = marker == 'displayed' - if additional_data is not None: - if additional_data.get_value('retracted', 'by') is not None: - self.get_style_context().add_class('retracted-message') + # Keep original text for message correction + self._original_text: str = text is_previewable = app.interface.preview_manager.is_previewable( text, additional_data) @@ -144,6 +141,21 @@ def __init__(self, self._message_icons = MessageIcons() + if additional_data is not None: + if additional_data.get_value('retracted', 'by') is not None: + self.get_style_context().add_class('retracted-message') + + correction_original = additional_data.get_value( + 'corrected', 'original_text') + if correction_original is not None: + self._original_text = correction_original + self._message_icons.set_correction_icon_visible(True) + original_text = reduce_chars_newlines( + correction_original, max_chars=150, max_lines=10) + self._message_icons.set_correction_tooltip( + _('Message corrected. Original message:' + '\n%s') % original_text) + if error is not None: self.set_error(to_user_string(error)) @@ -326,7 +338,6 @@ def set_retracted(self, text: str) -> None: self.get_style_context().add_class('retracted-message') def set_correction(self, text: str) -> None: - self._corrections.append(self._message_widget.get_text()) result = process(text) self._message_widget.add_content(result) @@ -334,11 +345,10 @@ def set_correction(self, text: str) -> None: self._message_icons.set_receipt_icon_visible(False) self._message_icons.set_correction_icon_visible(True) - corrections = '\n'.join(line for line in self._corrections) - corrections = reduce_chars_newlines( - corrections, max_chars=150, max_lines=10) + original_text = reduce_chars_newlines( + self._original_text, max_chars=150, max_lines=10) self._message_icons.set_correction_tooltip( - _('Message corrected. Original message:\n%s') % corrections) + _('Message corrected. Original message:\n%s') % original_text) def set_error(self, tooltip): self._message_icons.set_error_icon_visible(True) ===================================== gajim/gtk/conversation/view.py ===================================== @@ -212,7 +212,6 @@ def add_message(self, log_line_id=None, message_id=None, stanza_id=None, - correct_id=None, display_marking=None, additional_data=None, marker=None, @@ -221,10 +220,6 @@ def add_message(self, if not timestamp: timestamp = time.time() - if correct_id is not None: - self.correct_message(correct_id, text) - return - message = MessageRow( self._account, self._contact, ===================================== gajim/remote_control.py ===================================== @@ -348,6 +348,7 @@ def on_unsubscribed_presence_received(self, obj): def on_gc_message_received(self, obj): if not hasattr(obj, 'needs_highlight'): + # TODO: # event has not been handled at GUI level return self.raise_signal('GCMessage', (obj.conn.name, [obj.fjid, obj.msgtxt, View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/compare/4dc79ca45426e17f247a11e0aeb404d…
-- View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/compare/4dc79ca45426e17f247a11e0aeb404d…
You're receiving this email because of your account on
dev.gajim.org
.
1
0
0
0
[Git][gajim/gajim][master] Generate local version identifier only during development
by Philipp Hörist (@lovetox)
22 Nov '21
22 Nov '21
Philipp Hörist pushed to branch master at gajim / gajim Commits: 0138c5c9 by André Apitzsch at 2021-11-22T19:27:35+01:00 Generate local version identifier only during development Fixes #10678. - - - - - 2 changed files: - gajim/__init__.py - launch.py Changes: ===================================== gajim/__init__.py ===================================== @@ -1,4 +1,3 @@ -import subprocess import sys from pathlib import Path @@ -8,12 +7,3 @@ portable_path = Path(sys.executable).parent / 'is_portable' IS_PORTABLE = portable_path.exists() - -try: - p = subprocess.Popen('git rev-parse --short=12 HEAD', shell=True, - stdout=subprocess.PIPE, stderr=subprocess.DEVNULL) - node = p.communicate()[0] - if node: - __version__ += '+' + node.decode('utf-8').strip() -except Exception: - pass ===================================== launch.py ===================================== @@ -1,4 +1,16 @@ #!/usr/bin/env python3 +import subprocess from gajim import gajim + +try: + p = subprocess.Popen('git rev-parse --short=12 HEAD', shell=True, + stdout=subprocess.PIPE, stderr=subprocess.DEVNULL) + node = p.communicate()[0] + if node: + import gajim as g + g.__version__ += '+' + node.decode('utf-8').strip() +except Exception: + pass + gajim.main() View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/commit/0138c5c924296ae0e3f652c4542b6b94…
-- View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/commit/0138c5c924296ae0e3f652c4542b6b94…
You're receiving this email because of your account on
dev.gajim.org
.
1
0
0
0
[Git][gajim/gajim][master] 2 commits: Settings: Bind signals for ColorSetting and EntrySetting
by Daniel Brötzmann (@wurstsalat)
22 Nov '21
22 Nov '21
Daniel Brötzmann pushed to branch master at gajim / gajim Commits: 6b5e38dd by Daniel Brötzmann at 2021-11-22T09:19:35+00:00 Settings: Bind signals for ColorSetting and EntrySetting - - - - - 616211c5 by Daniel Brötzmann at 2021-11-22T09:19:35+00:00 AccountWizard: Add account badge preview - - - - - 3 changed files: - gajim/data/gui/account_wizard.ui - gajim/gtk/account_wizard.py - gajim/gtk/settings.py Changes: ===================================== gajim/data/gui/account_wizard.ui ===================================== @@ -1,7 +1,97 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.22.1 --> +<!-- Generated with glade 3.36.0 --> <interface> - <requires lib="gtk+" version="3.20"/> + <requires lib="gtk+" version="3.22"/> + <object class="GtkBox" id="account_label_box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="orientation">vertical</property> + <property name="spacing">12</property> + <child> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Optional: Add a name and color for your account</property> + <property name="wrap">True</property> + <property name="max_width_chars">50</property> + <style> + <class name="dim-label"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <style> + <class name="linked"/> + </style> + <child> + <object class="GtkEntry" id="account_name_entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="placeholder_text" translatable="yes">Account Name...</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkColorButton" id="account_color_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </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">1</property> + </packing> + </child> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">go-down-symbolic</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="badge_preview"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <style> + <class name="badge"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + </object> <object class="GtkGrid" id="advanced_grid"> <property name="visible">True</property> <property name="can_focus">False</property> ===================================== gajim/gtk/account_wizard.py ===================================== @@ -49,6 +49,8 @@ from .dataform import DataFormWidget from .util import get_builder from .util import open_window +from .util import get_color_for_account +from .util import get_app_window log = logging.getLogger('gajim.gui.account_wizard') @@ -969,14 +971,66 @@ def __init__(self): self.set_heading(_('Account has been added successfully')) self._account = None + self._our_jid = None + self._label = None + self._color = None + + self._ui = get_builder('account_wizard.ui') + self.pack_start(self._ui.account_label_box, True, True, 0) + + self._provider = self._add_css_provider() + + self._ui.account_name_entry.connect('changed', self._on_name_changed) + self._ui.account_color_button.connect('color-set', self._on_color_set) + + self.show_all() def set_account(self, account): self._account = account + self._our_jid = app.get_jid_from_account(account) + self._ui.badge_preview.set_text(self._our_jid) + rgba = Gdk.RGBA() + rgba.parse(get_color_for_account(self._our_jid)) + self._ui.account_color_button.set_rgba(rgba) + self._color = rgba.to_string() + self._set_badge_color(self._color) @property def account(self): return self._account + def _add_css_provider(self): + context = self._ui.badge_preview.get_style_context() + provider = Gtk.CssProvider() + context.add_provider(provider, Gtk.STYLE_PROVIDER_PRIORITY_USER) + return provider + + def _on_name_changed(self, entry): + self._label = entry.get_text() + self._ui.badge_preview.set_text(self._label or self._our_jid) + self._save_config() + + def _on_color_set(self, button): + rgba = button.get_rgba() + self._color = rgba.to_string() + self._set_badge_color(self._color) + self._save_config() + + def _set_badge_color(self, color): + css = '.badge { background-color: %s }' % color + self._provider.load_from_data(bytes(css.encode())) + + def _save_config(self): + app.settings.set_account_setting( + self._account, 'account_color', self._color) + if self._label: + app.settings.set_account_setting( + self._account, 'account_label', self._label) + app.css_config.refresh() + window = get_app_window('AccountsWindow') + if window is not None: + window.update_account_label(self._account) + def get_visible_buttons(self): return ['connect'] ===================================== gajim/gtk/settings.py ===================================== @@ -417,8 +417,21 @@ def __init__(self, *args): self.setting_box.pack_end(self.entry, True, True, 0) + app.settings.connect_signal(self.value, + self._on_setting_changed, + account=self.account, + jid=self.jid) + + self.connect('destroy', self._on_destroy) + self.show_all() + def _on_setting_changed(self, value, *args): + self.entry.set_text(value) + + def _on_destroy(self, *args): + app.settings.disconnect_signals(self) + def on_text_change(self, *args): text = self.entry.get_text() self.set_value(text) @@ -441,8 +454,23 @@ def __init__(self, *args): self.setting_box.pack_end(self.color_button, True, True, 0) + app.settings.connect_signal(self.value, + self._on_setting_changed, + account=self.account, + jid=self.jid) + + self.connect('destroy', self._on_destroy) + self.show_all() + def _on_setting_changed(self, value, *args): + rgba = Gdk.RGBA() + rgba.parse(value) + self.color_button.set_rgba(rgba) + + def _on_destroy(self, *args): + app.settings.disconnect_signals(self) + def on_color_set(self, button): rgba = button.get_rgba() self.set_value(rgba.to_string()) View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/compare/c5dec94fe05439a45c41c972f026762…
-- View it on GitLab:
https://dev.gajim.org/gajim/gajim/-/compare/c5dec94fe05439a45c41c972f026762…
You're receiving this email because of your account on
dev.gajim.org
.
1
0
0
0
← Newer
1
2
3
4
5
6
...
11
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
Results per page:
10
25
50
100
200