Merge branch 'history-highlighting' into 'master'
Highlight all paragraphs of a message in the history window See merge request !46
This commit is contained in:
		
						commit
						1b975172d6
					
				
					 3 changed files with 72 additions and 73 deletions
				
			
		| 
						 | 
				
			
			@ -628,7 +628,7 @@ class Logger:
 | 
			
		|||
 | 
			
		||||
    def get_conversation_for_date(self, jid, year, month, day, account):
 | 
			
		||||
        """
 | 
			
		||||
        Return contact_name, time, kind, show, message, subject
 | 
			
		||||
        Return contact_name, time, kind, show, message, subject, additional_data, log_line_id
 | 
			
		||||
 | 
			
		||||
        For each row in a list of tupples, returns list with empty tupple if we
 | 
			
		||||
        found nothing to meet our demands
 | 
			
		||||
| 
						 | 
				
			
			@ -645,7 +645,9 @@ class Logger:
 | 
			
		|||
        last_second_of_day = start_of_day + seconds_in_a_day - 1
 | 
			
		||||
 | 
			
		||||
        self.cur.execute('''
 | 
			
		||||
            SELECT contact_name, time, kind, show, message, subject, additional_data FROM logs
 | 
			
		||||
            SELECT contact_name, time, kind, show, message, subject,
 | 
			
		||||
                   additional_data, log_line_id
 | 
			
		||||
            FROM logs
 | 
			
		||||
            WHERE (%s)
 | 
			
		||||
            AND time BETWEEN %d AND %d
 | 
			
		||||
            ORDER BY time
 | 
			
		||||
| 
						 | 
				
			
			@ -660,7 +662,7 @@ class Logger:
 | 
			
		|||
    def get_search_results_for_query(self, jid, query, account, year=False,
 | 
			
		||||
        month=False, day=False):
 | 
			
		||||
        """
 | 
			
		||||
        Returns contact_name, time, kind, show, message
 | 
			
		||||
        Returns contact_name, time, kind, show, message, subject, log_line_id
 | 
			
		||||
 | 
			
		||||
        For each row in a list of tupples, returns list with empty tupple if we
 | 
			
		||||
        found nothing to meet our demands
 | 
			
		||||
| 
						 | 
				
			
			@ -671,33 +673,25 @@ class Logger:
 | 
			
		|||
            # Error trying to create a new jid_id. This means there is no log
 | 
			
		||||
            return []
 | 
			
		||||
 | 
			
		||||
        if False: # query.startswith('SELECT '): # it's SQL query (FIXME)
 | 
			
		||||
            try:
 | 
			
		||||
                self.cur.execute(query)
 | 
			
		||||
            except sqlite.OperationalError as e:
 | 
			
		||||
                results = [('', '', '', '', str(e))]
 | 
			
		||||
                return results
 | 
			
		||||
 | 
			
		||||
        else: # user just typed something, we search in message column
 | 
			
		||||
            where_sql, jid_tuple = self._build_contact_where(account, jid)
 | 
			
		||||
            like_sql = '%' + query.replace("'", "''") + '%'
 | 
			
		||||
            if year:
 | 
			
		||||
                start_of_day = self.get_unix_time_from_date(year, month, day)
 | 
			
		||||
                seconds_in_a_day = 86400 # 60 * 60 * 24
 | 
			
		||||
                last_second_of_day = start_of_day + seconds_in_a_day - 1
 | 
			
		||||
                self.cur.execute('''
 | 
			
		||||
                SELECT contact_name, time, kind, show, message, subject FROM logs
 | 
			
		||||
                WHERE (%s) AND message LIKE '%s'
 | 
			
		||||
                AND time BETWEEN %d AND %d
 | 
			
		||||
                ORDER BY time
 | 
			
		||||
                ''' % (where_sql, like_sql, start_of_day, last_second_of_day),
 | 
			
		||||
                    jid_tuple)
 | 
			
		||||
            else:
 | 
			
		||||
                self.cur.execute('''
 | 
			
		||||
                SELECT contact_name, time, kind, show, message, subject FROM logs
 | 
			
		||||
                WHERE (%s) AND message LIKE '%s'
 | 
			
		||||
                ORDER BY time
 | 
			
		||||
                ''' % (where_sql, like_sql), jid_tuple)
 | 
			
		||||
        where_sql, jid_tuple = self._build_contact_where(account, jid)
 | 
			
		||||
        like_sql = '%' + query.replace("'", "''") + '%'
 | 
			
		||||
        if year:
 | 
			
		||||
            start_of_day = self.get_unix_time_from_date(year, month, day)
 | 
			
		||||
            seconds_in_a_day = 86400 # 60 * 60 * 24
 | 
			
		||||
            last_second_of_day = start_of_day + seconds_in_a_day - 1
 | 
			
		||||
            self.cur.execute('''
 | 
			
		||||
            SELECT contact_name, time, kind, show, message, subject, log_line_id FROM logs
 | 
			
		||||
            WHERE (%s) AND message LIKE '%s'
 | 
			
		||||
            AND time BETWEEN %d AND %d
 | 
			
		||||
            ORDER BY time
 | 
			
		||||
            ''' % (where_sql, like_sql, start_of_day, last_second_of_day),
 | 
			
		||||
                jid_tuple)
 | 
			
		||||
        else:
 | 
			
		||||
            self.cur.execute('''
 | 
			
		||||
            SELECT contact_name, time, kind, show, message, subject, log_line_id FROM logs
 | 
			
		||||
            WHERE (%s) AND message LIKE '%s'
 | 
			
		||||
            ORDER BY time
 | 
			
		||||
            ''' % (where_sql, like_sql), jid_tuple)
 | 
			
		||||
 | 
			
		||||
        results = self.cur.fetchall()
 | 
			
		||||
        return results
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,6 +56,7 @@ class Column(IntEnum):
 | 
			
		|||
    UNIXTIME = 2
 | 
			
		||||
    MESSAGE = 3
 | 
			
		||||
    TIME = 4
 | 
			
		||||
    LOG_LINE_ID = 5
 | 
			
		||||
 | 
			
		||||
class HistoryWindow:
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			@ -85,8 +86,8 @@ class HistoryWindow:
 | 
			
		|||
        self.results_window = xml.get_object('results_scrolledwindow')
 | 
			
		||||
        self.search_in_date = xml.get_object('search_in_date')
 | 
			
		||||
 | 
			
		||||
        # contact_name, date, message, time
 | 
			
		||||
        model = Gtk.ListStore(str, str, str, str, str)
 | 
			
		||||
        # jid, contact_name, date, message, time, log_line_id
 | 
			
		||||
        model = Gtk.ListStore(str, str, str, str, str, int)
 | 
			
		||||
        self.results_treeview.set_model(model)
 | 
			
		||||
        col = Gtk.TreeViewColumn(_('Name'))
 | 
			
		||||
        self.results_treeview.append_column(col)
 | 
			
		||||
| 
						 | 
				
			
			@ -393,28 +394,31 @@ class HistoryWindow:
 | 
			
		|||
        show_status = self.show_status_checkbutton.get_active()
 | 
			
		||||
 | 
			
		||||
        lines = gajim.logger.get_conversation_for_date(self.jid, year, month, day, self.account)
 | 
			
		||||
        # lines holds list with tupples that have:
 | 
			
		||||
        # contact_name, time, kind, show, message
 | 
			
		||||
        for line in lines:
 | 
			
		||||
            # line[0] is contact_name, line[1] is time of message
 | 
			
		||||
            # line[2] is kind, line[3] is show, line[4] is message, line[5] is subject
 | 
			
		||||
            # line[6] is additional_data
 | 
			
		||||
            # line[6] is additional_data, line[7] is log_line_id
 | 
			
		||||
            if not show_status and line[2] in (KindConstant.GCSTATUS,
 | 
			
		||||
            KindConstant.STATUS):
 | 
			
		||||
                continue
 | 
			
		||||
            self._add_new_line(line[0], line[1], line[2], line[3], line[4],
 | 
			
		||||
                    line[5], line[6])
 | 
			
		||||
                    line[5], line[6], line[7])
 | 
			
		||||
 | 
			
		||||
    def _add_new_line(self, contact_name, tim, kind, show, message, subject, additional_data):
 | 
			
		||||
    def _add_new_line(self, contact_name, tim, kind, show, message, subject,
 | 
			
		||||
                      additional_data, log_line_id):
 | 
			
		||||
        """
 | 
			
		||||
        Add a new line in textbuffer
 | 
			
		||||
        """
 | 
			
		||||
        if not message and kind not in (KindConstant.STATUS,
 | 
			
		||||
                KindConstant.GCSTATUS):
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        buf = self.history_buffer
 | 
			
		||||
        end_iter = buf.get_end_iter()
 | 
			
		||||
 | 
			
		||||
        # Make the beginning of every message searchable by its log_line_id
 | 
			
		||||
        buf.create_mark(str(log_line_id), end_iter, left_gravity=True)
 | 
			
		||||
 | 
			
		||||
        if gajim.config.get('print_time') == 'always':
 | 
			
		||||
            timestamp_str = gajim.config.get('time_stamp')
 | 
			
		||||
            timestamp_str = helpers.from_one_line(timestamp_str)
 | 
			
		||||
| 
						 | 
				
			
			@ -429,12 +433,6 @@ class HistoryWindow:
 | 
			
		|||
                tim = time.strftime('%X ', time.localtime(float(tim)))
 | 
			
		||||
                buf.insert_with_tags_by_name(end_iter, tim + '\n',
 | 
			
		||||
                        'time_sometimes')
 | 
			
		||||
        else: # don't print time. So we print it as invisible to be able to
 | 
			
		||||
              # search for it
 | 
			
		||||
            timestamp_str = gajim.config.get('time_stamp')
 | 
			
		||||
            timestamp_str = helpers.from_one_line(timestamp_str)
 | 
			
		||||
            tim = time.strftime(timestamp_str, time.localtime(float(tim)))
 | 
			
		||||
            buf.insert_with_tags_by_name(end_iter, tim, 'invisible')
 | 
			
		||||
 | 
			
		||||
        tag_name = ''
 | 
			
		||||
        tag_msg = ''
 | 
			
		||||
| 
						 | 
				
			
			@ -512,9 +510,7 @@ class HistoryWindow:
 | 
			
		|||
        else:
 | 
			
		||||
            self.history_textview.print_real_text(message, name=contact_name,
 | 
			
		||||
                xhtml=xhtml, additional_data=additional_data)
 | 
			
		||||
        buffer_ = self.history_textview.tv.get_buffer()
 | 
			
		||||
        eob = buffer_.get_end_iter()
 | 
			
		||||
        buffer_.insert_with_tags_by_name(eob, '\n', 'eol')
 | 
			
		||||
        self.history_textview.print_real_text('\n', text_tags=['eol'])
 | 
			
		||||
 | 
			
		||||
    def on_search_entry_activate(self, widget):
 | 
			
		||||
        text = self.search_entry.get_text()
 | 
			
		||||
| 
						 | 
				
			
			@ -563,12 +559,13 @@ class HistoryWindow:
 | 
			
		|||
                        contact_name = self.completion_dict[jid][InfoColumn.NAME]
 | 
			
		||||
                tim = row[1]
 | 
			
		||||
                message = row[4]
 | 
			
		||||
                log_line_id = row[6]
 | 
			
		||||
                local_time = time.localtime(tim)
 | 
			
		||||
                date = time.strftime('%Y-%m-%d', local_time)
 | 
			
		||||
 | 
			
		||||
                #  jid (to which log is assigned to), name, date, message,
 | 
			
		||||
                # time (full unix time)
 | 
			
		||||
                model.append((jid, contact_name, date, message, str(tim)))
 | 
			
		||||
                model.append((jid, contact_name, date, message, str(tim), log_line_id))
 | 
			
		||||
 | 
			
		||||
    def on_results_treeview_row_activated(self, widget, path, column):
 | 
			
		||||
        """
 | 
			
		||||
| 
						 | 
				
			
			@ -576,7 +573,7 @@ class HistoryWindow:
 | 
			
		|||
        which results to showing conversation logs for that date
 | 
			
		||||
        """
 | 
			
		||||
        # get currently selected date
 | 
			
		||||
        cur_year, cur_month = self.calendar.get_date()[0:2]
 | 
			
		||||
        cur_year, cur_month, cur_day = self.calendar.get_date()
 | 
			
		||||
        cur_month = gtkgui_helpers.make_gtk_month_python_month(cur_month)
 | 
			
		||||
        model = widget.get_model()
 | 
			
		||||
        # make it a tupple (Y, M, D, 0, 0, 0...)
 | 
			
		||||
| 
						 | 
				
			
			@ -595,33 +592,41 @@ class HistoryWindow:
 | 
			
		|||
        if year != cur_year or gtk_month != cur_month:
 | 
			
		||||
            self.calendar.select_month(month, year)
 | 
			
		||||
 | 
			
		||||
        self.calendar.select_day(day)
 | 
			
		||||
        unix_time = model[path][Column.TIME]
 | 
			
		||||
        self._scroll_to_result(unix_time)
 | 
			
		||||
        #FIXME: one day do not search just for unix_time but the whole and user
 | 
			
		||||
        # specific format of the textbuffer line [time] nick: message
 | 
			
		||||
        # and highlight all that
 | 
			
		||||
        if year != cur_year or gtk_month != cur_month or day != cur_day:
 | 
			
		||||
            self.calendar.select_day(day)
 | 
			
		||||
 | 
			
		||||
    def _scroll_to_result(self, unix_time):
 | 
			
		||||
        self._scroll_to_message_and_highlight(model[path][Column.LOG_LINE_ID])
 | 
			
		||||
 | 
			
		||||
    def _scroll_to_message_and_highlight(self, log_line_id):
 | 
			
		||||
        """
 | 
			
		||||
        Scroll to the result using unix_time and highlight line
 | 
			
		||||
        Scroll to a message and highlight it
 | 
			
		||||
        """
 | 
			
		||||
        start_iter = self.history_buffer.get_start_iter()
 | 
			
		||||
        local_time = time.localtime(float(unix_time))
 | 
			
		||||
        timestamp_str = gajim.config.get('time_stamp')
 | 
			
		||||
        timestamp_str = helpers.from_one_line(timestamp_str)
 | 
			
		||||
        tim = time.strftime(timestamp_str, local_time)
 | 
			
		||||
        result = start_iter.forward_search(tim, Gtk.TextSearchFlags.TEXT_ONLY,
 | 
			
		||||
            None)
 | 
			
		||||
        if result is not None:
 | 
			
		||||
            match_start_iter, match_end_iter = result
 | 
			
		||||
            match_start_iter.backward_char() # include '[' or other character before time
 | 
			
		||||
            match_end_iter.forward_line() # highlight all message not just time
 | 
			
		||||
            self.history_buffer.apply_tag_by_name('highlight', match_start_iter,
 | 
			
		||||
                    match_end_iter)
 | 
			
		||||
            mark = self.history_buffer.create_mark('match', match_start_iter, True)
 | 
			
		||||
            GLib.idle_add(self.history_textview.tv.scroll_to_mark, mark,
 | 
			
		||||
                0, True, 0.0, 0.5)
 | 
			
		||||
 | 
			
		||||
        def iterator_has_mark(iterator, mark_name):
 | 
			
		||||
            for mark in iterator.get_marks():
 | 
			
		||||
                if mark.get_name() == mark_name:
 | 
			
		||||
                    return True
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        # Clear previous search result by removing the highlighting. The scroll
 | 
			
		||||
        # mark is automatically removed when the new one is set.
 | 
			
		||||
        start = self.history_buffer.get_start_iter()
 | 
			
		||||
        end = self.history_buffer.get_end_iter()
 | 
			
		||||
        self.history_buffer.remove_tag_by_name('highlight', start, end)
 | 
			
		||||
 | 
			
		||||
        log_line_id = str(log_line_id)
 | 
			
		||||
        line = start
 | 
			
		||||
        while not iterator_has_mark(line, log_line_id):
 | 
			
		||||
            if not line.forward_line():
 | 
			
		||||
                return
 | 
			
		||||
 | 
			
		||||
        match_start = line
 | 
			
		||||
        match_end = match_start.copy()
 | 
			
		||||
        match_end.forward_to_tag_toggle(self.history_buffer.eol_tag)
 | 
			
		||||
 | 
			
		||||
        self.history_buffer.apply_tag_by_name('highlight', match_start, match_end)
 | 
			
		||||
        mark = self.history_buffer.create_mark('match', match_start, True)
 | 
			
		||||
        GLib.idle_add(self.history_textview.tv.scroll_to_mark, mark, 0, True, 0.0, 0.5)
 | 
			
		||||
 | 
			
		||||
    def on_log_history_checkbutton_toggled(self, widget):
 | 
			
		||||
        # log conversation history?
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -850,7 +850,7 @@ class HtmlTextView(Gtk.TextView):
 | 
			
		|||
        self.connect('copy-clipboard', self.on_html_text_view_copy_clipboard)
 | 
			
		||||
        self.id_ = self.connect('button-release-event',
 | 
			
		||||
            self.on_left_mouse_button_release)
 | 
			
		||||
        self.get_buffer().create_tag('eol')
 | 
			
		||||
        self.get_buffer().eol_tag = self.get_buffer().create_tag('eol')
 | 
			
		||||
        self.tooltip = tooltips.BaseTooltip()
 | 
			
		||||
        self.config = gajim.config
 | 
			
		||||
        self.interface = gajim.interface
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue