From 3f38ccc3a57d4fa783d314be7751771954f5eeb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20H=C3=B6rist?= Date: Mon, 6 Mar 2017 02:41:33 +0100 Subject: [PATCH 1/3] Simplify import and move to the top --- src/chat_control.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/chat_control.py b/src/chat_control.py index 2fe95cf79..0739adf0d 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -39,6 +39,7 @@ import gui_menu_builder import message_control import dialogs +from common import logger from common import gajim from common import helpers from common import exceptions @@ -1626,10 +1627,9 @@ class ChatControl(ChatControlBase): rows = gajim.logger.get_last_conversation_lines(jid, restore_how_many, pending_how_many, timeout, self.account) except exceptions.DatabaseMalformed: - import common.logger dialogs.ErrorDialog(_('Database Error'), _('The database file (%s) cannot be read. Try to repair it or ' - 'remove it (all history will be lost).') % common.logger.LOG_DB_PATH) + 'remove it (all history will be lost).') % logger.LOG_DB_PATH) rows = [] local_old_kind = None self.conv_textview.just_cleared = True From 1e06db9fa6b6fa67ec745e883e53b5f999db0a59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20H=C3=B6rist?= Date: Mon, 6 Mar 2017 14:46:51 +0100 Subject: [PATCH 2/3] Remove smooth scrolling GTK3+ does smooth scrolling in ScrolledWindows on its own --- src/chat_control_base.py | 5 --- src/common/config.py | 1 - src/conversation_textview.py | 72 ++---------------------------------- 3 files changed, 3 insertions(+), 75 deletions(-) diff --git a/src/chat_control_base.py b/src/chat_control_base.py index d4be021b2..d474cbe48 100644 --- a/src/chat_control_base.py +++ b/src/chat_control_base.py @@ -1068,15 +1068,10 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): if self.conv_textview.at_the_end(): # we are at the end self.conv_textview.bring_scroll_to_end(-18) - else: - self.conv_textview.bring_scroll_to_end(-18, use_smooth=False) self.was_at_the_end = (adjustment.get_upper() - adjustment.get_value()\ - adjustment.get_page_size()) < 18 def on_conversation_vadjustment_value_changed(self, adjustment): - # stop automatic scroll when we manually scroll - if not self.conv_textview.auto_scrolling: - self.conv_textview.stop_scrolling() self.was_at_the_end = (adjustment.get_upper() - adjustment.get_value() \ - adjustment.get_page_size()) < 18 if self.resource: diff --git a/src/common/config.py b/src/common/config.py index f627a4c11..fdeae2ea1 100644 --- a/src/common/config.py +++ b/src/common/config.py @@ -279,7 +279,6 @@ class Config: 'hide_groupchat_occupants_list': [opt_bool, False, _('Hides the group chat occupants list in group chat window.')], 'chat_merge_consecutive_nickname': [opt_bool, False, _('In a chat, show the nickname at the beginning of a line only when it\'s not the same person talking than in previous message.')], 'chat_merge_consecutive_nickname_indent': [opt_str, ' ', _('Indentation when using merge consecutive nickname.')], - 'use_smooth_scrolling': [opt_bool, True, _('Smooth scroll message in conversation window')], 'gc_nicknames_colors': [ opt_str, '#4e9a06:#f57900:#ce5c00:#3465a4:#204a87:#75507b:#5c3566:#c17d11:#8f5902:#ef2929:#cc0000:#a40000', _('List of colors, separated by ":", that will be used to color nicknames in group chats.'), True ], 'ctrl_tab_go_to_next_composing': [opt_bool, True, _('Ctrl-Tab go to next composing tab when none is unread.')], 'confirm_metacontacts': [ opt_str, '', _('Should we show the confirm metacontacts creation dialog or not? Empty string means we never show the dialog.')], diff --git a/src/conversation_textview.py b/src/conversation_textview.py index 0429743c0..0a7c925ac 100644 --- a/src/conversation_textview.py +++ b/src/conversation_textview.py @@ -216,9 +216,6 @@ class ConversationTextview(GObject.GObject): # last_received_message_id[name] = (msg_stanza_id, line_start_mark) self.last_received_message_id = {} - # It's True when we scroll in the code, so we can detect scroll from user - self.auto_scrolling = False - # connect signals id_ = self.tv.connect('populate_popup', self.on_textview_populate_popup) self.handlers[id_] = self.tv @@ -325,7 +322,6 @@ class ConversationTextview(GObject.GObject): # holds a mark at the end of --- line self.focus_out_end_mark = None - self.smooth_id = None self.just_cleared = False def query_tooltip(self, widget, x_pos, y_pos, keyboard_mode, tooltip): @@ -406,79 +402,26 @@ class ConversationTextview(GObject.GObject): return True return False - # Smooth scrolling inspired by Pidgin code - def smooth_scroll(self): - parent = self.tv.get_parent() - if not parent: - return False - vadj = parent.get_vadjustment() - max_val = vadj.get_upper() - vadj.get_page_size() + 1 - cur_val = vadj.get_value() - # scroll by 1/3rd of remaining distance - onethird = cur_val + ((max_val - cur_val) / 3.0) - self.auto_scrolling = True - vadj.set_value(onethird) - self.auto_scrolling = False - if max_val - onethird < 0.01: - self.smooth_id = None - self.smooth_scroll_timer.cancel() - return False - return True - - def smooth_scroll_timeout(self): - GLib.idle_add(self.do_smooth_scroll_timeout) - return - - def do_smooth_scroll_timeout(self): - if not self.smooth_id: - # we finished scrolling - return - GLib.source_remove(self.smooth_id) - self.smooth_id = None - parent = self.tv.get_parent() - if parent: - vadj = parent.get_vadjustment() - self.auto_scrolling = True - vadj.set_value(vadj.get_upper() - vadj.get_page_size() + 1) - self.auto_scrolling = False - - def smooth_scroll_to_end(self): - if self.smooth_id is not None: # already scrolling - return False - self.smooth_id = GLib.timeout_add(self.SCROLL_DELAY, - self.smooth_scroll) - self.smooth_scroll_timer = Timer(self.MAX_SCROLL_TIME, - self.smooth_scroll_timeout) - self.smooth_scroll_timer.start() - return False - def scroll_to_end(self): parent = self.tv.get_parent() buffer_ = self.tv.get_buffer() end_mark = buffer_.get_mark('end') if not end_mark: return False - self.auto_scrolling = True self.tv.scroll_to_mark(end_mark, 0, True, 0, 1) adjustment = parent.get_hadjustment() adjustment.set_value(0) - self.auto_scrolling = False return False # when called in an idle_add, just do it once - def bring_scroll_to_end(self, diff_y=0, use_smooth=None): + def bring_scroll_to_end(self, diff_y=0): ''' scrolls to the end of textview if end is not visible ''' - if use_smooth is None: - use_smooth = gajim.config.get('use_smooth_scrolling') buffer_ = self.tv.get_buffer() end_iter = buffer_.get_end_iter() end_rect = self.tv.get_iter_location(end_iter) visible_rect = self.tv.get_visible_rect() # scroll only if expected end is not visible if end_rect.y >= (visible_rect.y + visible_rect.height + diff_y): - if use_smooth: - GLib.idle_add(self.smooth_scroll_to_end) - else: - GLib.idle_add(self.scroll_to_end_iter) + GLib.idle_add(self.scroll_to_end_iter) def scroll_to_end_iter(self): buffer_ = self.tv.get_buffer() @@ -488,12 +431,6 @@ class ConversationTextview(GObject.GObject): self.tv.scroll_to_iter(end_iter, 0, False, 1, 1) return False # when called in an idle_add, just do it once - def stop_scrolling(self): - if self.smooth_id: - GLib.source_remove(self.smooth_id) - self.smooth_id = None - self.smooth_scroll_timer.cancel() - def correct_message(self, correct_id, kind, name): allowed = True if kind == 'incoming': @@ -1372,10 +1309,7 @@ class ConversationTextview(GObject.GObject): if at_the_end or kind == 'outgoing': # we are at the end or we are sending something # scroll to the end (via idle in case the scrollbar has appeared) - if gajim.config.get('use_smooth_scrolling'): - GLib.idle_add(self.smooth_scroll_to_end) - else: - GLib.idle_add(self.scroll_to_end) + GLib.idle_add(self.scroll_to_end) self.just_cleared = False buffer_.end_user_action() From 8547d2b4f9818868a40ea719b62488b6a133624d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20H=C3=B6rist?= Date: Mon, 6 Mar 2017 16:27:50 +0100 Subject: [PATCH 3/3] Simplify scrolling in conversation textview --- src/chat_control_base.py | 28 +++----------------------- src/conversation_textview.py | 38 ++++-------------------------------- src/gui_interface.py | 2 +- 3 files changed, 8 insertions(+), 60 deletions(-) diff --git a/src/chat_control_base.py b/src/chat_control_base.py index d474cbe48..bc321ad4b 100644 --- a/src/chat_control_base.py +++ b/src/chat_control_base.py @@ -323,7 +323,6 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): id_ = widget.connect('changed', self.on_conversation_vadjustment_changed) self.handlers[id_] = widget - self.scroll_to_end_id = None self.was_at_the_end = True self.correcting = False self.last_sent_msg = None @@ -984,27 +983,8 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): # There were events to remove self.redraw_after_event_removed(jid) - def bring_scroll_to_end(self, textview, diff_y=0): - """ - Scroll to the end of textview if end is not visible - """ - if self.scroll_to_end_id: - # a scroll is already planned - return - buffer_ = textview.get_buffer() - end_iter = buffer_.get_end_iter() - end_rect = textview.get_iter_location(end_iter) - visible_rect = textview.get_visible_rect() - # scroll only if expected end is not visible - if end_rect.y >= (visible_rect.y + visible_rect.height + diff_y): - self.scroll_to_end_id = GLib.idle_add(self.scroll_to_end_iter, - textview) - - def scroll_to_end_iter(self, textview): - buffer_ = textview.get_buffer() - end_iter = buffer_.get_end_iter() - textview.scroll_to_iter(end_iter, 0, False, 1, 1) - self.scroll_to_end_id = None + def scroll_to_end_iter(self): + self.conv_textview.scroll_to_end_iter() return False def on_configure_event(self, msg_textview, event): @@ -1065,9 +1045,7 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): # used to stay at the end of the textview when we shrink conversation # textview. if self.was_at_the_end: - if self.conv_textview.at_the_end(): - # we are at the end - self.conv_textview.bring_scroll_to_end(-18) + self.scroll_to_end_iter() self.was_at_the_end = (adjustment.get_upper() - adjustment.get_value()\ - adjustment.get_page_size()) < 18 diff --git a/src/conversation_textview.py b/src/conversation_textview.py index 0a7c925ac..1b11e2c46 100644 --- a/src/conversation_textview.py +++ b/src/conversation_textview.py @@ -394,34 +394,7 @@ class ConversationTextview(GObject.GObject): self.tv.tagSthAtSth.set_property('foreground', color) def at_the_end(self): - buffer_ = self.tv.get_buffer() - end_iter = buffer_.get_end_iter() - end_rect = self.tv.get_iter_location(end_iter) - visible_rect = self.tv.get_visible_rect() - if end_rect.y <= (visible_rect.y + visible_rect.height): - return True - return False - - def scroll_to_end(self): - parent = self.tv.get_parent() - buffer_ = self.tv.get_buffer() - end_mark = buffer_.get_mark('end') - if not end_mark: - return False - self.tv.scroll_to_mark(end_mark, 0, True, 0, 1) - adjustment = parent.get_hadjustment() - adjustment.set_value(0) - return False # when called in an idle_add, just do it once - - def bring_scroll_to_end(self, diff_y=0): - ''' scrolls to the end of textview if end is not visible ''' - buffer_ = self.tv.get_buffer() - end_iter = buffer_.get_end_iter() - end_rect = self.tv.get_iter_location(end_iter) - visible_rect = self.tv.get_visible_rect() - # scroll only if expected end is not visible - if end_rect.y >= (visible_rect.y + visible_rect.height + diff_y): - GLib.idle_add(self.scroll_to_end_iter) + return gtkgui_helpers.at_the_end(self.tv.get_parent()) def scroll_to_end_iter(self): buffer_ = self.tv.get_buffer() @@ -586,7 +559,7 @@ class ConversationTextview(GObject.GObject): if scroll: # scroll to the end (via idle in case the scrollbar has # appeared) - GLib.idle_add(self.scroll_to_end) + GLib.idle_add(self.scroll_to_end_iter) def on_textview_draw(self, widget, ctx): return @@ -1220,8 +1193,6 @@ class ConversationTextview(GObject.GObject): # even if we insert directly at the mark iter temp_mark = buffer_.create_mark('temp', iter_, left_gravity=True) - at_the_end = self.at_the_end() - if text.startswith('/me '): direction_mark = i18n.paragraph_direction_mark(str(text[3:])) else: @@ -1306,10 +1277,9 @@ class ConversationTextview(GObject.GObject): self.last_sent_message_id = (msg_stanza_id, new_mark) if not insert_mark: - if at_the_end or kind == 'outgoing': + if self.at_the_end() or kind == 'outgoing': # we are at the end or we are sending something - # scroll to the end (via idle in case the scrollbar has appeared) - GLib.idle_add(self.scroll_to_end) + GLib.idle_add(self.scroll_to_end_iter) self.just_cleared = False buffer_.end_user_action() diff --git a/src/gui_interface.py b/src/gui_interface.py index 20dc64f14..3226674c4 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -1831,7 +1831,7 @@ class Interface: # Using isinstance here because we want to catch all derived types if isinstance(ctrl, ChatControlBase): tv = ctrl.conv_textview - tv.scroll_to_end() + tv.scroll_to_end_iter() ################################################################################ ### Methods dealing with emoticons