| 
									
										
										
										
											2018-09-05 02:59:34 +02:00
										 |  |  | # Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com> | 
					
						
							|  |  |  | # Copyright (C) 2006-2007 Jean-Marie Traissard <jim AT lapin.org> | 
					
						
							|  |  |  | #                         Nikos Kouremenos <kourem AT gmail.com> | 
					
						
							|  |  |  | # Copyright (C) 2006-2014 Yann Leboulanger <asterix AT lagaule.org> | 
					
						
							|  |  |  | # Copyright (C) 2007 Stephan Erb <steve-e AT h3c.de> | 
					
						
							|  |  |  | # Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org> | 
					
						
							|  |  |  | # Copyright (C) 2018 Philipp Hörist <philipp AT hoerist.com> | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # This file is part of Gajim. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Gajim is free software; you can redistribute it and/or modify | 
					
						
							|  |  |  | # it under the terms of the GNU General Public License as published | 
					
						
							|  |  |  | # by the Free Software Foundation; version 3 only. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Gajim is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | # but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | # GNU General Public License for more details. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  | # along with Gajim. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2006-02-03 00:01:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-05 02:59:34 +02:00
										 |  |  | # NOTE: some method names may match those of logger.py but that's it | 
					
						
							|  |  |  | # someday (TM) should have common class | 
					
						
							|  |  |  | # that abstracts db connections and helpers on it | 
					
						
							|  |  |  | # the same can be said for history.py | 
					
						
							| 
									
										
										
										
											2007-12-09 21:03:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | import os | 
					
						
							| 
									
										
										
										
											2006-02-03 00:01:53 +00:00
										 |  |  | import sys | 
					
						
							| 
									
										
										
										
											2018-04-21 13:48:08 +02:00
										 |  |  | import time | 
					
						
							|  |  |  | import getopt | 
					
						
							|  |  |  | import sqlite3 | 
					
						
							|  |  |  | from enum import IntEnum, unique | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  | from gi.repository import Gtk | 
					
						
							| 
									
										
										
										
											2013-05-15 12:51:23 +04:00
										 |  |  | from gi.repository import Gdk | 
					
						
							| 
									
										
										
										
											2013-07-29 21:41:01 +02:00
										 |  |  | from gi.repository import GLib | 
					
						
							| 
									
										
										
										
											2018-04-21 13:48:08 +02:00
										 |  |  | from gi.repository import Gio | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  | from gi.repository import Pango | 
					
						
							| 
									
										
										
										
											2006-02-03 00:01:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-15 11:41:12 +02:00
										 |  |  | from gajim.common import app | 
					
						
							| 
									
										
										
										
											2018-04-25 20:49:37 +02:00
										 |  |  | from gajim.common import configpaths | 
					
						
							| 
									
										
										
										
											2018-09-18 16:29:26 +02:00
										 |  |  | from gajim.common.i18n import _ | 
					
						
							| 
									
										
										
										
											2019-03-26 21:47:18 +01:00
										 |  |  | from gajim.common.i18n import ngettext | 
					
						
							| 
									
										
										
										
											2018-03-01 22:47:01 +01:00
										 |  |  | from gajim.common.const import StyleAttr | 
					
						
							| 
									
										
										
										
											2018-10-28 22:42:02 +01:00
										 |  |  | from gajim.common.const import JIDConstant | 
					
						
							|  |  |  | from gajim.common.const import KindConstant | 
					
						
							| 
									
										
										
										
											2019-03-06 23:03:45 +01:00
										 |  |  | from gajim.common.const import ShowConstant | 
					
						
							| 
									
										
										
										
											2018-04-21 13:48:08 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | def is_standalone(): | 
					
						
							|  |  |  |     # Determine if we are in standalone mode | 
					
						
							|  |  |  |     if Gio.Application.get_default() is None: | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  |     if __name__ == '__main__': | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  |     return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if is_standalone(): | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |     try: | 
					
						
							| 
									
										
										
										
											2018-03-25 20:52:36 +02:00
										 |  |  |         shortargs = 'hvsc:l:p:' | 
					
						
							|  |  |  |         longargs = 'help verbose separate config-path= loglevel= profile=' | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         opts = getopt.getopt(sys.argv[1:], shortargs, longargs.split())[0] | 
					
						
							| 
									
										
										
										
											2013-01-01 23:18:36 +01:00
										 |  |  |     except getopt.error as msg: | 
					
						
							| 
									
										
										
										
											2013-01-01 19:44:25 +01:00
										 |  |  |         print(str(msg)) | 
					
						
							|  |  |  |         print('for help use --help') | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         sys.exit(2) | 
					
						
							|  |  |  |     for o, a in opts: | 
					
						
							|  |  |  |         if o in ('-h', '--help'): | 
					
						
							| 
									
										
										
										
											2013-08-26 09:16:51 +04:00
										 |  |  |             print(_('Usage:') + \ | 
					
						
							|  |  |  |                 '\n  gajim-history-manager [options] filename\n\n' + \ | 
					
						
							|  |  |  |                 _('Options:') + \ | 
					
						
							|  |  |  |                 '\n  -h, --help         ' + \ | 
					
						
							|  |  |  |                     _('Show this help message and exit') + \ | 
					
						
							| 
									
										
										
										
											2017-02-04 23:29:45 +01:00
										 |  |  |                 '\n  -c, --config-path  ' + _('Choose folder for logfile') + '\n') | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             sys.exit() | 
					
						
							|  |  |  |         elif o in ('-c', '--config-path'): | 
					
						
							| 
									
										
										
										
											2018-04-21 13:48:08 +02:00
										 |  |  |             configpaths.set_config_root(a) | 
					
						
							| 
									
										
										
										
											2009-05-29 09:18:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-21 13:48:08 +02:00
										 |  |  |     configpaths.init() | 
					
						
							| 
									
										
										
										
											2018-09-15 11:41:12 +02:00
										 |  |  |     app.load_css_config() | 
					
						
							| 
									
										
										
										
											2009-05-29 09:18:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-07 21:15:39 +02:00
										 |  |  | # pylint: disable=C0413 | 
					
						
							| 
									
										
										
										
											2017-06-13 23:58:06 +02:00
										 |  |  | from gajim.common import helpers | 
					
						
							| 
									
										
										
										
											2018-09-26 19:06:47 +02:00
										 |  |  | from gajim.gtk.dialogs import YesNoDialog | 
					
						
							|  |  |  | from gajim.gtk.dialogs import ErrorDialog | 
					
						
							| 
									
										
										
										
											2019-03-26 21:47:18 +01:00
										 |  |  | from gajim.gtk.dialogs import NewConfirmationDialog | 
					
						
							|  |  |  | from gajim.gtk.dialogs import DialogButton | 
					
						
							| 
									
										
										
										
											2018-08-19 17:44:17 +02:00
										 |  |  | from gajim.gtk.filechoosers import FileSaveDialog | 
					
						
							| 
									
										
										
										
											2018-08-19 23:48:07 +02:00
										 |  |  | from gajim.gtk.util import convert_rgb_to_hex | 
					
						
							| 
									
										
										
										
											2018-10-28 22:42:02 +01:00
										 |  |  | from gajim.gtk.util import get_builder | 
					
						
							|  |  |  | from gajim.gtk.util import get_app_icon_list | 
					
						
							| 
									
										
										
										
											2019-04-07 21:15:39 +02:00
										 |  |  | # pylint: enable=C0413 | 
					
						
							| 
									
										
										
										
											2017-02-07 20:18:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-04 21:22:46 +01:00
										 |  |  | @unique | 
					
						
							| 
									
										
										
										
											2017-02-07 20:18:41 +00:00
										 |  |  | class Column(IntEnum): | 
					
						
							|  |  |  |     UNIXTIME = 2 | 
					
						
							|  |  |  |     MESSAGE = 3 | 
					
						
							|  |  |  |     SUBJECT = 4 | 
					
						
							|  |  |  |     NICKNAME = 5 | 
					
						
							| 
									
										
										
										
											2006-02-03 00:01:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-11 22:31:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-03 00:01:53 +00:00
										 |  |  | class HistoryManager: | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |     def __init__(self): | 
					
						
							| 
									
										
										
										
											2018-04-25 21:26:02 +02:00
										 |  |  |         log_db_path = configpaths.get('LOG_DB') | 
					
						
							|  |  |  |         if not os.path.exists(log_db_path): | 
					
						
							| 
									
										
										
										
											2018-07-16 23:22:33 +02:00
										 |  |  |             ErrorDialog(_('Cannot find history logs database'), | 
					
						
							|  |  |  |                         '%s does not exist.' % log_db_path) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             sys.exit() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui = get_builder('history_manager.ui') | 
					
						
							|  |  |  |         Gtk.Window.set_default_icon_list(get_app_icon_list( | 
					
						
							|  |  |  |             self._ui.history_manager_window)) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         self.jids_already_in = []  # holds jids that we already have in DB | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         self.AT_LEAST_ONE_DELETION_DONE = False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 21:26:02 +02:00
										 |  |  |         self.con = sqlite3.connect( | 
					
						
							|  |  |  |             log_db_path, timeout=20.0, isolation_level='IMMEDIATE') | 
					
						
							| 
									
										
										
										
											2018-06-12 23:34:28 +03:00
										 |  |  |         self.con.execute("PRAGMA secure_delete=1") | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         self.cur = self.con.cursor() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self._init_jids_listview() | 
					
						
							|  |  |  |         self._init_logs_listview() | 
					
						
							|  |  |  |         self._init_search_results_listview() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self._fill_jids_listview() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.search_entry.grab_focus() | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.history_manager_window.show_all() | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.connect_signals(self) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _init_jids_listview(self): | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  |         self.jids_liststore = Gtk.ListStore(str, str)  # jid, jid_id | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.jids_listview.set_model(self.jids_liststore) | 
					
						
							|  |  |  |         self._ui.jids_listview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  |         renderer_text = Gtk.CellRendererText()  # holds jid | 
					
						
							| 
									
										
										
										
											2017-02-04 23:29:45 +01:00
										 |  |  |         col = Gtk.TreeViewColumn(_('JID'), renderer_text, text=0) | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.jids_listview.append_column(col) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.jids_listview.get_selection().connect('changed', | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |                 self.on_jids_listview_selection_changed) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _init_logs_listview(self): | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         # log_line_id(HIDDEN), jid_id(HIDDEN), time, message, subject, nickname | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  |         self.logs_liststore = Gtk.ListStore(str, str, str, str, str, str) | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.logs_listview.set_model(self.logs_liststore) | 
					
						
							|  |  |  |         self._ui.logs_listview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  |         renderer_text = Gtk.CellRendererText()  # holds time | 
					
						
							| 
									
										
										
										
											2017-02-07 20:18:41 +00:00
										 |  |  |         col = Gtk.TreeViewColumn(_('Date'), renderer_text, text=Column.UNIXTIME) | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         # user can click this header and sort | 
					
						
							| 
									
										
										
										
											2017-02-07 20:18:41 +00:00
										 |  |  |         col.set_sort_column_id(Column.UNIXTIME) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         col.set_resizable(True) | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.logs_listview.append_column(col) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  |         renderer_text = Gtk.CellRendererText()  # holds nickname | 
					
						
							| 
									
										
										
										
											2017-02-07 20:18:41 +00:00
										 |  |  |         col = Gtk.TreeViewColumn(_('Nickname'), renderer_text, text=Column.NICKNAME) | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         # user can click this header and sort | 
					
						
							| 
									
										
										
										
											2017-02-07 20:18:41 +00:00
										 |  |  |         col.set_sort_column_id(Column.NICKNAME) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         col.set_resizable(True) | 
					
						
							|  |  |  |         col.set_visible(False) | 
					
						
							|  |  |  |         self.nickname_col_for_logs = col | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.logs_listview.append_column(col) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  |         renderer_text = Gtk.CellRendererText()  # holds message | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         renderer_text.set_property('width_chars', 60) | 
					
						
							|  |  |  |         renderer_text.set_property('ellipsize', Pango.EllipsizeMode.END) | 
					
						
							| 
									
										
										
										
											2017-02-07 20:18:41 +00:00
										 |  |  |         col = Gtk.TreeViewColumn(_('Message'), renderer_text, markup=Column.MESSAGE) | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         # user can click this header and sort | 
					
						
							| 
									
										
										
										
											2017-02-07 20:18:41 +00:00
										 |  |  |         col.set_sort_column_id(Column.MESSAGE) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         col.set_resizable(True) | 
					
						
							|  |  |  |         self.message_col_for_logs = col | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.logs_listview.append_column(col) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  |         renderer_text = Gtk.CellRendererText()  # holds subject | 
					
						
							| 
									
										
										
										
											2017-02-07 20:18:41 +00:00
										 |  |  |         col = Gtk.TreeViewColumn(_('Subject'), renderer_text, text=Column.SUBJECT) | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         # user can click this header and sort | 
					
						
							|  |  |  |         col.set_sort_column_id(Column.SUBJECT) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         col.set_resizable(True) | 
					
						
							|  |  |  |         col.set_visible(False) | 
					
						
							|  |  |  |         self.subject_col_for_logs = col | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.logs_listview.append_column(col) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _init_search_results_listview(self): | 
					
						
							|  |  |  |         # log_line_id (HIDDEN), jid, time, message, subject, nickname | 
					
						
							| 
									
										
										
										
											2013-01-11 22:54:12 +04:00
										 |  |  |         self.search_results_liststore = Gtk.ListStore(int, str, str, str, str, | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |             str) | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.search_results_listview.set_model(self.search_results_liststore) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  |         renderer_text = Gtk.CellRendererText()  # holds JID (who said this) | 
					
						
							|  |  |  |         col = Gtk.TreeViewColumn(_('JID'), renderer_text, text=1) | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         # user can click this header and sort | 
					
						
							|  |  |  |         col.set_sort_column_id(1) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         col.set_resizable(True) | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.search_results_listview.append_column(col) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  |         renderer_text = Gtk.CellRendererText()  # holds time | 
					
						
							| 
									
										
										
										
											2017-02-07 20:18:41 +00:00
										 |  |  |         col = Gtk.TreeViewColumn(_('Date'), renderer_text, text=Column.UNIXTIME) | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         # user can click this header and sort | 
					
						
							| 
									
										
										
										
											2017-02-07 20:18:41 +00:00
										 |  |  |         col.set_sort_column_id(Column.UNIXTIME) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         col.set_resizable(True) | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.search_results_listview.append_column(col) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  |         renderer_text = Gtk.CellRendererText()  # holds message | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         renderer_text.set_property('width_chars', 60) | 
					
						
							|  |  |  |         renderer_text.set_property('ellipsize', Pango.EllipsizeMode.END) | 
					
						
							| 
									
										
										
										
											2017-02-07 20:18:41 +00:00
										 |  |  |         col = Gtk.TreeViewColumn(_('Message'), renderer_text, text=Column.MESSAGE) | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         # user can click this header and sort | 
					
						
							|  |  |  |         col.set_sort_column_id(Column.MESSAGE) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         col.set_resizable(True) | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.search_results_listview.append_column(col) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  |         renderer_text = Gtk.CellRendererText()  # holds subject | 
					
						
							| 
									
										
										
										
											2017-02-07 20:18:41 +00:00
										 |  |  |         col = Gtk.TreeViewColumn(_('Subject'), renderer_text, text=Column.SUBJECT) | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         # user can click this header and sort | 
					
						
							|  |  |  |         col.set_sort_column_id(Column.SUBJECT) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         col.set_resizable(True) | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.search_results_listview.append_column(col) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  |         renderer_text = Gtk.CellRendererText()  # holds nickname | 
					
						
							| 
									
										
										
										
											2017-02-07 20:18:41 +00:00
										 |  |  |         col = Gtk.TreeViewColumn(_('Nickname'), renderer_text, text=Column.NICKNAME) | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         # user can click this header and sort | 
					
						
							| 
									
										
										
										
											2017-02-07 20:18:41 +00:00
										 |  |  |         col.set_sort_column_id(Column.NICKNAME) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         col.set_resizable(True) | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.search_results_listview.append_column(col) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def on_history_manager_window_delete_event(self, widget, event): | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         if not self.AT_LEAST_ONE_DELETION_DONE: | 
					
						
							| 
									
										
										
										
											2018-04-21 13:48:08 +02:00
										 |  |  |             if is_standalone(): | 
					
						
							| 
									
										
										
										
											2018-03-18 14:05:51 +01:00
										 |  |  |                 Gtk.main_quit() | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         def on_yes(clicked): | 
					
						
							|  |  |  |             self.cur.execute('VACUUM') | 
					
						
							|  |  |  |             self.con.commit() | 
					
						
							| 
									
										
										
										
											2018-04-21 13:48:08 +02:00
										 |  |  |             if is_standalone(): | 
					
						
							| 
									
										
										
										
											2018-03-18 14:05:51 +01:00
										 |  |  |                 Gtk.main_quit() | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |         def on_no(): | 
					
						
							| 
									
										
										
										
											2018-04-21 13:48:08 +02:00
										 |  |  |             if is_standalone(): | 
					
						
							| 
									
										
										
										
											2018-03-18 14:05:51 +01:00
										 |  |  |                 Gtk.main_quit() | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-16 23:22:33 +02:00
										 |  |  |         dialog = YesNoDialog( | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |             _('Do you want to clean up the database? ' | 
					
						
							|  |  |  |             '(STRONGLY NOT RECOMMENDED IF GAJIM IS RUNNING)'), | 
					
						
							|  |  |  |             _('Normally allocated database size will not be freed, ' | 
					
						
							|  |  |  |                 'it will just become reusable. If you really want to reduce ' | 
					
						
							|  |  |  |                 'database filesize, click YES, else click NO.' | 
					
						
							| 
									
										
										
										
											2017-02-04 23:29:45 +01:00
										 |  |  |                 '\n\nIn case you click YES, please wait…'), | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |             on_response_yes=on_yes, on_response_no=on_no) | 
					
						
							| 
									
										
										
										
											2011-05-25 19:11:04 +04:00
										 |  |  |         dialog.set_title(_('Database Cleanup')) | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         button_box = dialog.get_children()[0].get_children()[1] | 
					
						
							|  |  |  |         button_box.get_children()[0].grab_focus() | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _fill_jids_listview(self): | 
					
						
							|  |  |  |         # get those jids that have at least one entry in logs | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         self.cur.execute('SELECT jid, jid_id FROM jids WHERE jid_id IN (' | 
					
						
							|  |  |  |                 'SELECT distinct logs.jid_id FROM logs) ORDER BY jid') | 
					
						
							| 
									
										
										
										
											2017-03-06 20:38:29 +01:00
										 |  |  |         # list of tuples: [('aaa@bbb',), ('cc@dd',)] | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         rows = self.cur.fetchall() | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         for row in rows: | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |             self.jids_already_in.append(row[0])  # jid | 
					
						
							| 
									
										
										
										
											2013-01-11 22:54:12 +04:00
										 |  |  |             self.jids_liststore.append([row[0], str(row[1])])  # jid, jid_id | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |     def on_jids_listview_selection_changed(self, widget, data=None): | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         liststore, list_of_paths = self._ui.jids_listview.get_selection()\ | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |                 .get_selected_rows() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-24 17:25:49 +01:00
										 |  |  |         self.logs_liststore.clear() | 
					
						
							|  |  |  |         if not list_of_paths: | 
					
						
							|  |  |  |             return | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.welcome_box.hide() | 
					
						
							|  |  |  |         self._ui.search_results_scrolledwindow.hide() | 
					
						
							|  |  |  |         self._ui.logs_scrolledwindow.show() | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         list_of_rowrefs = [] | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         for path in list_of_paths:  # make them treerowrefs (it's needed) | 
					
						
							| 
									
										
										
										
											2013-01-11 22:54:12 +04:00
										 |  |  |             list_of_rowrefs.append(Gtk.TreeRowReference.new(liststore, path)) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         for rowref in list_of_rowrefs:  # FILL THE STORE, for all rows selected | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             path = rowref.get_path() | 
					
						
							|  |  |  |             if path is None: | 
					
						
							|  |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2013-01-01 19:44:25 +01:00
										 |  |  |             jid = liststore[path][0]  # jid | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             self._fill_logs_listview(jid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _get_jid_id(self, jid): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         jids table has jid and jid_id | 
					
						
							|  |  |  |         logs table has log_id, jid_id, contact_name, time, kind, show, message | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         So to ask logs we need jid_id that matches our jid in jids table this | 
					
						
							|  |  |  |         method wants jid and returns the jid_id for later sql-ing on logs | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         if jid.find('/') != -1:  # if it has a / | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             jid_is_from_pm = self._jid_is_from_pm(jid) | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |             if not jid_is_from_pm:  # it's normal jid with resource | 
					
						
							|  |  |  |                 jid = jid.split('/', 1)[0]  # remove the resource | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         self.cur.execute('SELECT jid_id FROM jids WHERE jid = ?', (jid,)) | 
					
						
							|  |  |  |         jid_id = self.cur.fetchone()[0] | 
					
						
							|  |  |  |         return str(jid_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _get_jid_from_jid_id(self, jid_id): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         jids table has jid and jid_id | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         This method accepts jid_id and returns the jid for later sql-ing on logs | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         self.cur.execute('SELECT jid FROM jids WHERE jid_id = ?', (jid_id,)) | 
					
						
							|  |  |  |         jid = self.cur.fetchone()[0] | 
					
						
							|  |  |  |         return jid | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _jid_is_from_pm(self, jid): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         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 | 
					
						
							|  |  |  |         is already in jids (with type room jid). This fails if user disables | 
					
						
							|  |  |  |         logging for room and only enables for pm (so higly unlikely) and if we | 
					
						
							|  |  |  |         fail we do not go chaos (user will see the first pm as if it was message | 
					
						
							|  |  |  |         in room's public chat) and after that everything is ok | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         possible_room_jid = jid.split('/', 1)[0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.cur.execute('SELECT jid_id FROM jids WHERE jid = ? AND type = ?', | 
					
						
							| 
									
										
										
										
											2017-02-12 14:14:29 +01:00
										 |  |  |                 (possible_room_jid, JIDConstant.ROOM_TYPE)) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         row = self.cur.fetchone() | 
					
						
							|  |  |  |         if row is None: | 
					
						
							|  |  |  |             return False | 
					
						
							| 
									
										
										
										
											2018-09-18 10:14:04 +02:00
										 |  |  |         return True | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _jid_is_room_type(self, jid): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Return True/False if given id is room type or not eg. if it is room | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         self.cur.execute('SELECT type FROM jids WHERE jid = ?', (jid,)) | 
					
						
							|  |  |  |         row = self.cur.fetchone() | 
					
						
							| 
									
										
										
										
											2018-09-18 16:29:26 +02:00
										 |  |  |         return row[0] == JIDConstant.ROOM_TYPE | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _fill_logs_listview(self, jid): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Fill the listview with all messages that user sent to or received from | 
					
						
							|  |  |  |         JID | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         # no need to lower jid in this context as jid is already lowered | 
					
						
							|  |  |  |         # as we use those jids from db | 
					
						
							|  |  |  |         jid_id = self._get_jid_id(jid) | 
					
						
							|  |  |  |         self.cur.execute('''
 | 
					
						
							|  |  |  |                 SELECT log_line_id, jid_id, time, kind, message, subject, contact_name, show | 
					
						
							|  |  |  |                 FROM logs | 
					
						
							|  |  |  |                 WHERE jid_id = ? | 
					
						
							|  |  |  |                 ORDER BY time | 
					
						
							|  |  |  |                 ''', (jid_id,))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         results = self.cur.fetchall() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         if self._jid_is_room_type(jid):  # is it room? | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             self.nickname_col_for_logs.set_visible(True) | 
					
						
							|  |  |  |             self.subject_col_for_logs.set_visible(False) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.nickname_col_for_logs.set_visible(False) | 
					
						
							|  |  |  |             self.subject_col_for_logs.set_visible(True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for row in results: | 
					
						
							|  |  |  |             # exposed in UI (TreeViewColumns) are only | 
					
						
							|  |  |  |             # time, message, subject, nickname | 
					
						
							|  |  |  |             # but store in liststore | 
					
						
							|  |  |  |             # log_line_id, jid_id, time, message, subject, nickname | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |             log_line_id, jid_id, time_, kind, message, subject, nickname, \ | 
					
						
							|  |  |  |                 show = row | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             try: | 
					
						
							| 
									
										
										
										
											2013-01-11 22:54:12 +04:00
										 |  |  |                 time_ = time.strftime('%x', time.localtime(float(time_))) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             except ValueError: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 color = None | 
					
						
							| 
									
										
										
										
											2017-02-12 14:14:29 +01:00
										 |  |  |                 if kind in (KindConstant.SINGLE_MSG_RECV, | 
					
						
							| 
									
										
										
										
											2018-08-19 23:48:07 +02:00
										 |  |  |                             KindConstant.CHAT_MSG_RECV, | 
					
						
							|  |  |  |                             KindConstant.GC_MSG): | 
					
						
							|  |  |  |                     color = app.css_config.get_value( | 
					
						
							|  |  |  |                         '.gajim-incoming-nickname', StyleAttr.COLOR) | 
					
						
							| 
									
										
										
										
											2017-02-12 14:14:29 +01:00
										 |  |  |                 elif kind in (KindConstant.SINGLE_MSG_SENT, | 
					
						
							| 
									
										
										
										
											2018-08-19 23:48:07 +02:00
										 |  |  |                               KindConstant.CHAT_MSG_SENT): | 
					
						
							|  |  |  |                     color = app.css_config.get_value( | 
					
						
							|  |  |  |                         '.gajim-outgoing-nickname', StyleAttr.COLOR) | 
					
						
							| 
									
										
										
										
											2017-02-12 14:14:29 +01:00
										 |  |  |                 elif kind in (KindConstant.STATUS, | 
					
						
							| 
									
										
										
										
											2018-08-19 23:48:07 +02:00
										 |  |  |                               KindConstant.GCSTATUS): | 
					
						
							|  |  |  |                     color = app.css_config.get_value( | 
					
						
							|  |  |  |                         '.gajim-status-message', StyleAttr.COLOR) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |                     # include status into (status) message | 
					
						
							|  |  |  |                     if message is None: | 
					
						
							|  |  |  |                         message = '' | 
					
						
							|  |  |  |                     else: | 
					
						
							|  |  |  |                         message = ' : ' + message | 
					
						
							| 
									
										
										
										
											2019-03-06 23:03:45 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     message = helpers.get_uf_show(ShowConstant(show)) + message | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 message_ = '<span' | 
					
						
							|  |  |  |                 if color: | 
					
						
							| 
									
										
										
										
											2018-08-19 23:48:07 +02:00
										 |  |  |                     message_ += ' foreground="%s"' % convert_rgb_to_hex(color) | 
					
						
							| 
									
										
										
										
											2013-07-29 21:41:01 +02:00
										 |  |  |                 message_ += '>%s</span>' % GLib.markup_escape_text(message) | 
					
						
							| 
									
										
										
										
											2018-08-19 23:48:07 +02:00
										 |  |  |                 self.logs_liststore.append( | 
					
						
							|  |  |  |                     (str(log_line_id), str(jid_id), | 
					
						
							|  |  |  |                      time_, message_, subject, nickname)) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _fill_search_results_listview(self, text): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Ask db and fill listview with results that match text | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         self.search_results_liststore.clear() | 
					
						
							|  |  |  |         like_sql = '%' + text + '%' | 
					
						
							|  |  |  |         self.cur.execute('''
 | 
					
						
							|  |  |  |                 SELECT log_line_id, jid_id, time, message, subject, contact_name | 
					
						
							|  |  |  |                 FROM logs | 
					
						
							|  |  |  |                 WHERE message LIKE ? OR subject LIKE ? | 
					
						
							|  |  |  |                 ORDER BY time | 
					
						
							|  |  |  |                 ''', (like_sql, like_sql))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         results = self.cur.fetchall() | 
					
						
							|  |  |  |         for row in results: | 
					
						
							|  |  |  |             # exposed in UI (TreeViewColumns) are only | 
					
						
							|  |  |  |             # JID, time, message, subject, nickname | 
					
						
							|  |  |  |             # but store in liststore | 
					
						
							|  |  |  |             # log_line_id, jid (from jid_id), time, message, subject, nickname | 
					
						
							|  |  |  |             log_line_id, jid_id, time_, message, subject, nickname = row | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2013-01-11 22:54:12 +04:00
										 |  |  |                 time_ = time.strftime('%x', time.localtime(float(time_))) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             except ValueError: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 jid = self._get_jid_from_jid_id(jid_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 self.search_results_liststore.append((log_line_id, jid, time_, | 
					
						
							|  |  |  |                         message, subject, nickname)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def on_logs_listview_key_press_event(self, widget, event): | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         liststore, list_of_paths = self._ui.logs_listview.get_selection()\ | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |                 .get_selected_rows() | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  |         if event.keyval == Gdk.KEY_Delete: | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             self._delete_logs(liststore, list_of_paths) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def on_listview_button_press_event(self, widget, event): | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         if event.button == 3:  # right click | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |             _ui = get_builder('history_manager.ui', ['context_menu']) | 
					
						
							| 
									
										
										
										
											2013-01-11 22:54:12 +04:00
										 |  |  |             if Gtk.Buildable.get_name(widget) != 'jids_listview': | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |                 _ui.export_menuitem.hide() | 
					
						
							|  |  |  |             _ui.delete_menuitem.connect('activate', | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |                     self.on_delete_menuitem_activate, widget) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |             _ui.connect_signals(self) | 
					
						
							|  |  |  |             _ui.context_menu.popup(None, None, None, None, | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |                     event.button, event.time) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def on_export_menuitem_activate(self, widget): | 
					
						
							| 
									
										
										
										
											2018-05-04 00:36:10 +02:00
										 |  |  |         FileSaveDialog(self._on_export, | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |                        transient_for=self._ui.history_manager_window, | 
					
						
							| 
									
										
										
										
											2018-05-04 00:36:10 +02:00
										 |  |  |                        modal=True) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-04 00:36:10 +02:00
										 |  |  |     def _on_export(self, filename): | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         liststore, list_of_paths = self._ui.jids_listview.get_selection()\ | 
					
						
							| 
									
										
										
										
											2018-05-04 00:36:10 +02:00
										 |  |  |                 .get_selected_rows() | 
					
						
							|  |  |  |         self._export_jids_logs_to_file(liststore, list_of_paths, filename) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def on_delete_menuitem_activate(self, widget, listview): | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  |         widget_name = Gtk.Buildable.get_name(listview) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         liststore, list_of_paths = listview.get_selection().get_selected_rows() | 
					
						
							| 
									
										
										
										
											2010-11-01 21:34:17 +01:00
										 |  |  |         if widget_name == 'jids_listview': | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             self._delete_jid_logs(liststore, list_of_paths) | 
					
						
							| 
									
										
										
										
											2010-11-01 21:34:17 +01:00
										 |  |  |         elif widget_name in ('logs_listview', 'search_results_listview'): | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             self._delete_logs(liststore, list_of_paths) | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         else:  # Huh ? We don't know this widget | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def on_jids_listview_key_press_event(self, widget, event): | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         liststore, list_of_paths = self._ui.jids_listview.get_selection()\ | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |                 .get_selected_rows() | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  |         if event.keyval == Gdk.KEY_Delete: | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             self._delete_jid_logs(liststore, list_of_paths) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _export_jids_logs_to_file(self, liststore, list_of_paths, path_to_file): | 
					
						
							|  |  |  |         paths_len = len(list_of_paths) | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         if paths_len == 0:  # nothing is selected | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         list_of_rowrefs = [] | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         for path in list_of_paths:  # make them treerowrefs (it's needed) | 
					
						
							| 
									
										
										
										
											2013-01-11 22:54:12 +04:00
										 |  |  |             list_of_rowrefs.append(Gtk.TreeRowReference.new(liststore, path)) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for rowref in list_of_rowrefs: | 
					
						
							|  |  |  |             path = rowref.get_path() | 
					
						
							|  |  |  |             if path is None: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             jid_id = liststore[path][1] | 
					
						
							|  |  |  |             self.cur.execute('''
 | 
					
						
							|  |  |  |                     SELECT time, kind, message, contact_name FROM logs | 
					
						
							|  |  |  |                     WHERE jid_id = ? | 
					
						
							|  |  |  |                     ORDER BY time | 
					
						
							|  |  |  |                     ''', (jid_id,))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # FIXME: we may have two contacts selected to export. fix that | 
					
						
							|  |  |  |         # AT THIS TIME FIRST EXECUTE IS LOST! WTH!!!!! | 
					
						
							|  |  |  |         results = self.cur.fetchall() | 
					
						
							|  |  |  |         #print results[0] | 
					
						
							| 
									
										
										
										
											2018-04-17 22:00:15 +02:00
										 |  |  |         file_ = open(path_to_file, 'w', encoding='utf-8') | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         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 | 
					
						
							| 
									
										
										
										
											2017-02-12 14:14:29 +01:00
										 |  |  |             if kind in (KindConstant.SINGLE_MSG_RECV, | 
					
						
							|  |  |  |                     KindConstant.CHAT_MSG_RECV): | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |                 who = self._get_jid_from_jid_id(jid_id) | 
					
						
							| 
									
										
										
										
											2017-02-12 14:14:29 +01:00
										 |  |  |             elif kind in (KindConstant.SINGLE_MSG_SENT, | 
					
						
							|  |  |  |                     KindConstant.CHAT_MSG_SENT): | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |                 who = _('You') | 
					
						
							| 
									
										
										
										
											2017-02-12 14:14:29 +01:00
										 |  |  |             elif kind == KindConstant.GC_MSG: | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |                 who = nickname | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |             else:  # status or gc_status. do not save | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |                 #print kind | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2013-01-11 22:54:12 +04:00
										 |  |  |                 time_ = time.strftime('%c', time.localtime(float(time_))) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             except ValueError: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |             file_.write(_('%(who)s on %(time)s said: %(message)s\n') % { | 
					
						
							|  |  |  |                 'who': who, 'time': time_, 'message': message}) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _delete_jid_logs(self, liststore, list_of_paths): | 
					
						
							|  |  |  |         paths_len = len(list_of_paths) | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         if paths_len == 0:  # nothing is selected | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-26 21:47:18 +01:00
										 |  |  |         def on_ok(): | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             # delete all rows from db that match jid_id | 
					
						
							|  |  |  |             list_of_rowrefs = [] | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |             for path in list_of_paths:  # make them treerowrefs (it's needed) | 
					
						
							| 
									
										
										
										
											2013-01-11 22:54:12 +04:00
										 |  |  |                 list_of_rowrefs.append(Gtk.TreeRowReference.new(liststore, path)) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             for rowref in list_of_rowrefs: | 
					
						
							|  |  |  |                 path = rowref.get_path() | 
					
						
							|  |  |  |                 if path is None: | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 jid_id = liststore[path][1] | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |                 del liststore[path]  # remove from UI | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |                 # remove from db | 
					
						
							|  |  |  |                 self.cur.execute('''
 | 
					
						
							|  |  |  |                         DELETE FROM logs | 
					
						
							|  |  |  |                         WHERE jid_id = ? | 
					
						
							|  |  |  |                         ''', (jid_id,))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # now delete "jid, jid_id" row from jids table | 
					
						
							|  |  |  |                 self.cur.execute('''
 | 
					
						
							|  |  |  |                                 DELETE FROM jids | 
					
						
							|  |  |  |                                 WHERE jid_id = ? | 
					
						
							|  |  |  |                                 ''', (jid_id,))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self.con.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self.AT_LEAST_ONE_DELETION_DONE = True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-26 21:47:18 +01:00
										 |  |  |         NewConfirmationDialog( | 
					
						
							|  |  |  |             _('Delete'), | 
					
						
							|  |  |  |             ngettext('Delete Conversation', 'Delete Conversations', paths_len), | 
					
						
							|  |  |  |             ngettext('Do you want to permanently delete this ' | 
					
						
							|  |  |  |                      'conversation with <b>%s</b>', | 
					
						
							|  |  |  |                      'Do you want to permanently delete these Conversations', | 
					
						
							|  |  |  |                      paths_len, liststore[list_of_paths[0]][0]), | 
					
						
							|  |  |  |             [DialogButton.make('Cancel'), | 
					
						
							|  |  |  |              DialogButton.make('Delete', callback=on_ok)], | 
					
						
							| 
									
										
										
										
											2019-03-26 23:53:12 +01:00
										 |  |  |             transient_for=self._ui.history_manager_window).show() | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _delete_logs(self, liststore, list_of_paths): | 
					
						
							|  |  |  |         paths_len = len(list_of_paths) | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |         if paths_len == 0:  # nothing is selected | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def on_ok(liststore, list_of_paths): | 
					
						
							|  |  |  |             # delete rows from db that match log_line_id | 
					
						
							|  |  |  |             list_of_rowrefs = [] | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |             for path in list_of_paths:  # make them treerowrefs (it's needed) | 
					
						
							| 
									
										
										
										
											2013-01-11 22:54:12 +04:00
										 |  |  |                 list_of_rowrefs.append(Gtk.TreeRowReference.new(liststore, path)) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             for rowref in list_of_rowrefs: | 
					
						
							|  |  |  |                 path = rowref.get_path() | 
					
						
							|  |  |  |                 if path is None: | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 log_line_id = liststore[path][0] | 
					
						
							| 
									
										
										
										
											2011-03-20 12:15:57 +03:00
										 |  |  |                 del liststore[path]  # remove from UI | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |                 # remove from db | 
					
						
							|  |  |  |                 self.cur.execute('''
 | 
					
						
							|  |  |  |                         DELETE FROM logs | 
					
						
							|  |  |  |                         WHERE log_line_id = ? | 
					
						
							|  |  |  |                         ''', (log_line_id,))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self.con.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self.AT_LEAST_ONE_DELETION_DONE = True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-26 21:47:18 +01:00
										 |  |  |         NewConfirmationDialog( | 
					
						
							|  |  |  |             _('Delete'), | 
					
						
							|  |  |  |             ngettext('Delete Message', 'Delete Messages', paths_len), | 
					
						
							|  |  |  |             ngettext('Do you want to permanently delete this message', | 
					
						
							|  |  |  |                      'Do you want to permanently delete these messages', | 
					
						
							|  |  |  |                      paths_len), | 
					
						
							|  |  |  |             [DialogButton.make('Cancel'), | 
					
						
							|  |  |  |              DialogButton.make('Delete', callback=on_ok)], | 
					
						
							| 
									
										
										
										
											2019-03-26 23:53:12 +01:00
										 |  |  |             transient_for=self._ui.history_manager_window).show() | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def on_search_db_button_clicked(self, widget): | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         text = self._ui.search_entry.get_text() | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         if not text: | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.welcome_box.hide() | 
					
						
							|  |  |  |         self._ui.logs_scrolledwindow.hide() | 
					
						
							|  |  |  |         self._ui.search_results_scrolledwindow.show() | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self._fill_search_results_listview(text) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def on_search_results_listview_row_activated(self, widget, path, column): | 
					
						
							|  |  |  |         # get log_line_id, jid_id from row we double clicked | 
					
						
							| 
									
										
										
										
											2018-04-15 22:45:04 +02:00
										 |  |  |         log_line_id = str(self.search_results_liststore[path][0]) | 
					
						
							| 
									
										
										
										
											2013-01-01 19:44:25 +01:00
										 |  |  |         jid = self.search_results_liststore[path][1] | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         # make it string as in gtk liststores I have them all as strings | 
					
						
							|  |  |  |         # as this is what db returns so I don't have to fight with types | 
					
						
							|  |  |  |         jid_id = self._get_jid_id(jid) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  |         iter_ = self.jids_liststore.get_iter_first() | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         while iter_: | 
					
						
							|  |  |  |             # self.jids_liststore[iter_][1] holds jid_ids | 
					
						
							|  |  |  |             if self.jids_liststore[iter_][1] == jid_id: | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |             iter_ = self.jids_liststore.iter_next(iter_) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if iter_ is None: | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         path = self.jids_liststore.get_path(iter_) | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.jids_listview.set_cursor(path) | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  |         iter_ = self.logs_liststore.get_iter_first() | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |         while iter_: | 
					
						
							| 
									
										
										
										
											2018-04-15 22:45:04 +02:00
										 |  |  |             # self.logs_liststore[iter_][0] holds log_line_ids | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |             if self.logs_liststore[iter_][0] == log_line_id: | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |             iter_ = self.logs_liststore.iter_next(iter_) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         path = self.logs_liststore.get_path(iter_) | 
					
						
							| 
									
										
										
										
											2018-11-07 22:52:23 +01:00
										 |  |  |         self._ui.logs_listview.scroll_to_cell(path) | 
					
						
							|  |  |  |         self._ui.logs_listview.get_selection().select_path(path) | 
					
						
							| 
									
										
										
										
											2006-02-04 20:35:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-13 22:07:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | def main(): | 
					
						
							|  |  |  |     if sys.platform != 'win32': | 
					
						
							|  |  |  |         if os.geteuid() == 0: | 
					
						
							|  |  |  |             sys.exit("You must not launch gajim as root, it is insecure.") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-08 15:08:40 +01:00
										 |  |  |     HistoryManager() | 
					
						
							| 
									
										
										
										
											2012-12-23 16:23:43 +01:00
										 |  |  |     Gtk.main() | 
					
						
							| 
									
										
										
										
											2018-01-13 22:07:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |     main() |