97
106
col.pack_start(renderer)
98
107
col.set_attributes(renderer, text = C_MESSAGE)
99
108
col.set_resizable(True)
101
contact = gajim.contacts.get_first_contact_from_jid(account, jid)
103
title = _('Conversation History with %s') % contact.get_shown_name()
105
title = _('Conversation History with %s') % jid
106
self.window.set_title(title)
110
self.jid = None # The history we are currently viewing
112
self.completion_dict = {}
113
self.accounts_seen_online = [] # Update dict when new accounts connect
114
self.jids_to_search = []
116
# This will load history too
117
gobject.idle_add(self._fill_completion_dict().next)
120
self.jid_entry.set_text(jid)
108
122
xml.signal_autoconnect(self)
110
# fake event so we start mark days procedure for selected month
111
# selected month is current month as calendar defaults to selecting
113
self.calendar.emit('month-changed')
115
# select and show logs for last date we have logs with contact
116
# and if we don't have logs at all, default to today
117
result = gajim.logger.get_last_date_that_has_logs(self.jid, self.account)
119
date = time.localtime()
122
date = time.localtime(tim)
124
y, m, d = date[0], date[1], date[2]
125
gtk_month = gtkgui_helpers.make_python_month_gtk_month(m)
126
self.calendar.select_month(gtk_month, y)
127
self.calendar.select_day(d)
128
self.add_lines_for_date(y, m, d)
130
123
self.window.show_all()
125
def _fill_completion_dict(self):
126
'''Fill completion_dict for key auto completion. Then load history for
127
current jid (by calling another function).
129
Key will be either jid or full_completion_name
130
(contact name or long description like "pm-contact from groupchat....")
132
{key : (jid, account, nick_name, full_completion_name}
133
this is a generator and does pseudo-threading via idle_add()
135
liststore = gtkgui_helpers.get_completion_liststore(self.jid_entry)
137
# Add all jids in logs.db:
138
db_jids = gajim.logger.get_jids_in_db()
139
self.completion_dict = dict.fromkeys(db_jids)
141
self.accounts_seen_online = gajim.contacts.get_accounts()[:]
143
# Enhance contacts of online accounts with contact. Needed for mapping below
144
for account in self.accounts_seen_online:
145
self.completion_dict.update(
146
helpers.get_contact_dict_for_account(account))
148
muc_active_img = gtkgui_helpers.load_icon('muc_active')
149
contact_img = gajim.interface.jabber_state_images['16']['online']
150
muc_active_pix = muc_active_img.get_pixbuf()
151
contact_pix = contact_img.get_pixbuf()
153
keys = self.completion_dict.keys()
154
# Move the actual jid at first so we load history faster
155
actual_jid = self.jid_entry.get_text().decode('utf-8')
156
if actual_jid in keys:
157
keys.remove(actual_jid)
158
keys.insert(0, actual_jid)
161
# Map jid to info tuple
162
# Warning : This for is time critical with big DB
165
contact = self.completion_dict[completed]
167
info_name = contact.get_shown_name()
168
info_completion = info_name
169
info_jid = contact.jid
171
# Corrensponding account is offline, we know nothing
172
info_name = completed.split('@')[0]
173
info_completion = completed
176
info_acc = self._get_account_for_jid(info_jid)
178
if gajim.logger.jid_is_room_jid(completed) or\
179
gajim.logger.jid_is_from_pm(completed):
181
if gajim.logger.jid_is_from_pm(completed):
182
# It's PM. Make it easier to find
183
room, nick = gajim.get_room_and_nick_from_fjid(completed)
184
info_completion = '%s from %s' % (nick, room)
185
completed = info_completion
190
liststore.append((pix, completed))
191
self.completion_dict[key] = (info_jid, info_acc, info_name,
193
self.completion_dict[completed] = (info_jid, info_acc,
194
info_name, info_completion)
195
if key == actual_jid:
196
self._load_history(info_jid, info_acc)
201
def _get_account_for_jid(self, jid):
202
'''Return the corresponding account of the jid.
203
May be None if an account could not be found'''
204
accounts = gajim.contacts.get_accounts()
207
jid_list = gajim.contacts.get_jid_list(acc)
208
gc_list = gajim.contacts.get_gc_list(acc)
209
if jid in jid_list or jid in gc_list:
132
214
def on_history_window_destroy(self, widget):
133
if self.mark_days_idle_call_id:
134
# if user destroys the window, and we have a generator filling mark days
136
gobject.source_remove(self.mark_days_idle_call_id)
137
215
self.history_textview.del_handlers()
138
del gajim.interface.instances['logs'][self.jid]
216
del gajim.interface.instances['logs']
218
def on_history_window_key_press_event(self, widget, event):
219
if event.keyval == gtk.keysyms.Escape:
220
self.window.destroy()
140
222
def on_close_button_clicked(self, widget):
141
223
self.window.destroy()
225
def on_jid_entry_activate(self, widget):
226
if not self.query_combobox.get_active() < 0:
227
# Don't disable querybox when we have changed the combobox
228
# to GC or All and hit enter
230
jid = self.jid_entry.get_text().decode('utf-8')
231
account = None # we don't know the account, could be any. Search for it!
232
self._load_history(jid, account)
233
self.results_window.set_property('visible', False)
235
def on_jid_entry_focus(self, widget, event):
236
widget.select_region(0, -1) # select text
238
def _load_history(self, jid_or_name, account = None):
239
'''Load history for the given jid/name and show it'''
240
if jid_or_name and jid_or_name in self.completion_dict:
241
# a full qualified jid or a contact name was entered
242
info_jid, info_account, info_name, info_completion = self.completion_dict[jid_or_name]
243
self.jids_to_search = [info_jid]
247
self.account = account
249
self.account = info_account
250
if self.account is None:
251
# We don't know account. Probably a gc not opened or an
252
# account not connected.
253
# Disable possibility to say if we want to log or not
254
self.checkbutton.set_sensitive(False)
256
# Are log disabled for account ?
257
if self.account in gajim.config.get_per('accounts', self.account,
258
'no_log_for').split(' '):
259
self.checkbutton.set_active(False)
260
self.checkbutton.set_sensitive(False)
262
# Are log disabled for jid ?
264
if self.jid in gajim.config.get_per('accounts', self.account,
265
'no_log_for').split(' '):
267
self.checkbutton.set_active(log)
268
self.checkbutton.set_sensitive(True)
270
self.jids_to_search = [info_jid]
272
# select logs for last date we have logs with contact
273
self.calendar.set_sensitive(True)
275
gajim.logger.get_last_date_that_has_logs(self.jid, self.account)
277
date = time.localtime(last_log)
279
y, m, d = date[0], date[1], date[2]
280
gtk_month = gtkgui_helpers.make_python_month_gtk_month(m)
281
self.calendar.select_month(gtk_month, y)
282
self.calendar.select_day(d)
284
self.query_entry.set_sensitive(True)
285
self.query_entry.grab_focus()
287
title = _('Conversation History with %s') % info_name
288
self.window.set_title(title)
289
self.jid_entry.set_text(info_completion)
291
else: # neither a valid jid, nor an existing contact name was entered
292
# we have got nothing to show or to search in
296
self.history_buffer.set_text('') # clear the buffer
297
self.query_entry.set_sensitive(False)
299
self.checkbutton.set_sensitive(False)
300
self.calendar.set_sensitive(False)
301
self.calendar.clear_marks()
303
self.results_window.set_property('visible', False)
305
title = _('Conversation History')
306
self.window.set_title(title)
143
308
def on_calendar_day_selected(self, widget):
144
311
year, month, day = widget.get_date() # integers
145
312
month = gtkgui_helpers.make_gtk_month_python_month(month)
146
self.add_lines_for_date(year, month, day)
313
self._add_lines_for_date(year, month, day)
148
def do_possible_mark_for_days_in_this_month(self, widget, year, month):
149
'''this is a generator and does pseudo-threading via idle_add()
150
so it runs progressively! yea :)
151
asks for days in this month if they have logs it bolds them (marks them)'''
152
weekday, days_in_this_month = calendar.monthrange(year, month)
153
log_days = gajim.logger.get_days_with_logs(self.jid, year,
154
month, days_in_this_month, self.account)
160
315
def on_calendar_month_changed(self, widget):
316
'''asks for days in this month if they have logs it bolds them (marks
161
321
year, month, day = widget.get_date() # integers
162
322
# in gtk January is 1, in python January is 0,
163
323
# I want the second
164
324
# first day of month is 1 not 0
165
if self.mark_days_idle_call_id:
166
# if user changed month, and we have a generator filling mark days
167
# stop him from marking dates for the previously selected month
168
gobject.source_remove(self.mark_days_idle_call_id)
169
325
widget.clear_marks()
170
326
month = gtkgui_helpers.make_gtk_month_python_month(month)
171
self.mark_days_idle_call_id = gobject.idle_add(
172
self.do_possible_mark_for_days_in_this_month(widget, year, month).next)
327
weekday, days_in_this_month = calendar.monthrange(year, month)
329
log_days = gajim.logger.get_days_with_logs(self.jid, year, month,
330
days_in_this_month, self.account)
331
except exceptions.PysqliteOperationalError, e:
332
dialogs.ErrorDialog(_('Disk Error'), str(e))
174
def get_string_show_from_constant_int(self, show):
337
def _get_string_show_from_constant_int(self, show):
175
338
if show == constants.SHOW_ONLINE:
177
340
elif show == constants.SHOW_CHAT:
290
445
self.history_textview.print_real_text(message)
292
def set_unset_expand_on_expander(self, widget):
293
'''expander has to have expand to TRUE so scrolledwindow resizes properly
294
and does not have a static size. when expander is not expanded we set
295
expand property (note the Box one) to FALSE
296
to do this, we first get the box and then apply to expander widget
297
the True/False thingy depending if it's expanded or not
298
this function is called in a timeout just after expanded state changes'''
299
parent = widget.get_parent() # vbox
301
# Windows closed since we launch timeout
303
expanded = widget.get_expanded()
304
w, h = self.window.get_size()
305
if expanded: # resize to larger in height the window
306
self.window.resize(w, int(h*1.3))
307
else: # resize to smaller in height the window
308
self.window.resize(w, int(h/1.3))
309
# now set expand so if manually resizing scrolledwindow resizes too
310
parent.child_set_property(widget, 'expand', expanded)
312
def on_search_expander_activate(self, widget):
313
if widget.get_expanded(): # it's the OPPOSITE!, it's not expanded
314
gobject.timeout_add(200, self.set_unset_expand_on_expander, widget)
316
gobject.timeout_add(200, self.set_unset_expand_on_expander, widget)
317
self.search_button.grab_default()
318
self.query_entry.grab_focus()
320
def on_search_button_clicked(self, widget):
447
def on_query_entry_activate(self, widget):
321
448
text = self.query_entry.get_text()
322
449
model = self.results_treeview.get_model()
452
self.results_window.set_property('visible', False)
326
# contact_name, time, kind, show, message, subject
327
results = gajim.logger.get_search_results_for_query(
328
self.jid, text, self.account)
330
# add "subject: | message: " in message column if kind is single
331
# also do we need show at all? (we do not search on subject)
333
contact_name = row[0]
336
if kind == constants.KIND_CHAT_MSG_SENT: # it's us! :)
337
contact_name = gajim.nicks[self.account]
339
contact = gajim.contacts.get_first_contact_from_jid(self.account,
342
contact_name = contact.get_shown_name()
455
self.results_window.set_property('visible', True)
457
# perform search in preselected jids
458
# jids are preselected with the query_combobox (all, single jid...)
459
for jid in self.jids_to_search:
460
account = self.completion_dict[jid][C_INFO_ACCOUNT]
462
# We do not know an account. This can only happen if the contact is offine,
463
# or if we browse a groupchat history. The account is not needed, a dummy can
465
# This may leed to wrong self nick in the displayed history (Uggh!)
466
account = gajim.contacts.get_accounts()[0]
468
# contact_name, time, kind, show, message, subject
469
results = gajim.logger.get_search_results_for_query(
472
# add "subject: | message: " in message column if kind is single
473
# also do we need show at all? (we do not search on subject)
475
contact_name = row[0]
478
if kind == constants.KIND_CHAT_MSG_SENT: # it's us! :)
479
contact_name = gajim.nicks[account]
344
contact_name = self.jid
347
local_time = time.localtime(tim)
348
date = time.strftime('%x', local_time)
349
# name, date, message, time (full unix time)
350
model.append((contact_name, date, message, tim))
481
contact_name = self.completion_dict[jid][C_INFO_NAME]
484
local_time = time.localtime(tim)
485
date = time.strftime('%Y-%m-%d', local_time)
487
# jid (to which log is assigned to), name, date, message,
488
# time (full unix time)
489
model.append((jid, contact_name, date, message, tim))
491
def on_query_combobox_changed(self, widget):
492
if self.query_combobox.get_active() < 0:
493
return # custom entry
496
self.jids_to_search = []
497
self._load_history(None) # clear textview
499
if self.query_combobox.get_active() == 0:
500
# JID or Contact name
501
self.query_entry.set_sensitive(False)
502
self.jid_entry.grab_focus()
503
if self.query_combobox.get_active() == 1:
504
# Groupchat Histories
505
self.query_entry.set_sensitive(True)
506
self.query_entry.grab_focus()
507
self.jids_to_search = (jid for jid in gajim.logger.get_jids_in_db()
508
if gajim.logger.jid_is_room_jid(jid))
509
if self.query_combobox.get_active() == 2:
511
self.query_entry.set_sensitive(True)
512
self.query_entry.grab_focus()
513
self.jids_to_search = gajim.logger.get_jids_in_db()
352
515
def on_results_treeview_row_activated(self, widget, path, column):
353
516
'''a row was double clicked, get date from row, and select it in calendar
354
517
which results to showing conversation logs for that date'''