Philipp Hörist pushed to branch master at gajim / gajim
Commits:
-
8df8486d
by Markus Böhme at 2017-03-29T10:56:31+02:00
-
167cf02a
by Markus Böhme at 2017-03-29T10:56:31+02:00
-
d612e80a
by Markus Böhme at 2017-03-30T21:23:03+02:00
-
08f4e171
by Markus Böhme at 2017-03-30T21:23:03+02:00
-
65e926c1
by Markus Böhme at 2017-03-30T21:24:31+02:00
-
e735bfe7
by Markus Böhme at 2017-03-30T21:57:44+02:00
-
21d15dec
by Markus Böhme at 2017-03-30T22:19:40+02:00
-
1a5d6fbf
by Philipp Hörist at 2017-03-31T16:44:32+02:00
16 changed files:
- src/advanced_configuration_window.py
- src/command_system/implementation/standard.py
- src/common/config.py
- src/common/configpaths.py
- src/common/jingle_ft.py
- src/common/jingle_session.py
- src/common/jingle_transport.py
- src/common/logger.py
- src/common/zeroconf/zeroconf.py
- src/filetransfers_window.py
- src/groupchat_control.py
- src/history_manager.py
- src/history_window.py
- src/message_control.py
- src/plugins/gui.py
- src/roster_window.py
Changes:
| ... | ... | @@ -23,7 +23,7 @@ |
| 23 | 23 |
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
| 24 | 24 |
##
|
| 25 | 25 |
|
| 26 |
-from enum import IntEnum
|
|
| 26 |
+from enum import IntEnum, unique
|
|
| 27 | 27 |
|
| 28 | 28 |
from gi.repository import Gtk
|
| 29 | 29 |
import gtkgui_helpers
|
| ... | ... | @@ -32,6 +32,7 @@ from gi.repository import Pango |
| 32 | 32 |
|
| 33 | 33 |
from common import gajim
|
| 34 | 34 |
|
| 35 |
+@unique
|
|
| 35 | 36 |
class Column(IntEnum):
|
| 36 | 37 |
PREFERENCE_NAME = 0
|
| 37 | 38 |
VALUE = 1
|
| ... | ... | @@ -87,8 +87,7 @@ class StandardCommonCommands(CommandContainer): |
| 87 | 87 |
@command('lastlog', overlap=True)
|
| 88 | 88 |
@doc(_("Show logged messages which mention given text"))
|
| 89 | 89 |
def grep(self, text, limit=None):
|
| 90 |
- results = gajim.logger.get_search_results_for_query(self.contact.jid,
|
|
| 91 |
- text, self.account)
|
|
| 90 |
+ results = gajim.logger.search_log(self.contact.jid, text, self.account)
|
|
| 92 | 91 |
|
| 93 | 92 |
if not results:
|
| 94 | 93 |
raise CommandError(_("%s: Nothing found") % text)
|
| ... | ... | @@ -100,23 +99,22 @@ class StandardCommonCommands(CommandContainer): |
| 100 | 99 |
raise CommandError(_("Limit must be an integer"))
|
| 101 | 100 |
|
| 102 | 101 |
for row in results:
|
| 103 |
- contact, time, kind, show, message, subject, log_line_id = row
|
|
| 104 |
- |
|
| 102 |
+ contact = row.contact_name
|
|
| 105 | 103 |
if not contact:
|
| 106 |
- if kind == KindConstant.CHAT_MSG_SENT:
|
|
| 104 |
+ if row.kind == KindConstant.CHAT_MSG_SENT:
|
|
| 107 | 105 |
contact = gajim.nicks[self.account]
|
| 108 | 106 |
else:
|
| 109 | 107 |
contact = self.contact.name
|
| 110 | 108 |
|
| 111 |
- time_obj = localtime(time)
|
|
| 112 |
- date_obj = date.fromtimestamp(time)
|
|
| 109 |
+ time_obj = localtime(row.time)
|
|
| 110 |
+ date_obj = date.fromtimestamp(row.time)
|
|
| 113 | 111 |
date_ = strftime('%Y-%m-%d', time_obj)
|
| 114 | 112 |
time_ = strftime('%H:%M:%S', time_obj)
|
| 115 | 113 |
|
| 116 | 114 |
if date_obj == date.today():
|
| 117 |
- formatted = "[%s] %s: %s" % (time_, contact, message)
|
|
| 115 |
+ formatted = "[%s] %s: %s" % (time_, contact, row.message)
|
|
| 118 | 116 |
else:
|
| 119 |
- formatted = "[%s, %s] %s: %s" % (date_, time_, contact, message)
|
|
| 117 |
+ formatted = "[%s, %s] %s: %s" % (date_, time_, contact, row.message)
|
|
| 120 | 118 |
|
| 121 | 119 |
self.echo(formatted)
|
| 122 | 120 |
|
| ... | ... | @@ -35,8 +35,9 @@ |
| 35 | 35 |
import re
|
| 36 | 36 |
from common import defs
|
| 37 | 37 |
from gi.repository import GLib
|
| 38 |
-from enum import IntEnum
|
|
| 38 |
+from enum import IntEnum, unique
|
|
| 39 | 39 |
|
| 40 |
+@unique
|
|
| 40 | 41 |
class Option(IntEnum):
|
| 41 | 42 |
TYPE = 0
|
| 42 | 43 |
VAL = 1
|
| ... | ... | @@ -26,8 +26,9 @@ import os |
| 26 | 26 |
import sys
|
| 27 | 27 |
import tempfile
|
| 28 | 28 |
from common import defs
|
| 29 |
-from enum import Enum
|
|
| 29 |
+from enum import Enum, unique
|
|
| 30 | 30 |
|
| 31 |
+@unique
|
|
| 31 | 32 |
class Type(Enum):
|
| 32 | 33 |
CONFIG = 0
|
| 33 | 34 |
CACHE = 1
|
| ... | ... | @@ -23,7 +23,7 @@ import hashlib |
| 23 | 23 |
import logging
|
| 24 | 24 |
import os
|
| 25 | 25 |
import threading
|
| 26 |
-from enum import IntEnum
|
|
| 26 |
+from enum import IntEnum, unique
|
|
| 27 | 27 |
import nbxmpp
|
| 28 | 28 |
from common import gajim
|
| 29 | 29 |
from common import configpaths
|
| ... | ... | @@ -39,6 +39,7 @@ from common.jingle_ftstates import ( |
| 39 | 39 |
log = logging.getLogger('gajim.c.jingle_ft')
|
| 40 | 40 |
|
| 41 | 41 |
|
| 42 |
+@unique
|
|
| 42 | 43 |
class State(IntEnum):
|
| 43 | 44 |
NOT_STARTED = 0
|
| 44 | 45 |
INITIALIZED = 1
|
| ... | ... | @@ -29,7 +29,7 @@ Handles Jingle sessions (XEP 0166) |
| 29 | 29 |
# * timeout
|
| 30 | 30 |
|
| 31 | 31 |
import logging
|
| 32 |
-from enum import Enum
|
|
| 32 |
+from enum import Enum, unique
|
|
| 33 | 33 |
import nbxmpp
|
| 34 | 34 |
from common import gajim
|
| 35 | 35 |
from common.jingle_transport import get_jingle_transport, JingleTransportIBB
|
| ... | ... | @@ -43,6 +43,7 @@ from common.connection_handlers_events import ( |
| 43 | 43 |
log = logging.getLogger("gajim.c.jingle_session")
|
| 44 | 44 |
|
| 45 | 45 |
# FIXME: Move it to JingleSession.States?
|
| 46 |
+@unique
|
|
| 46 | 47 |
class JingleStates(Enum):
|
| 47 | 48 |
"""
|
| 48 | 49 |
States in which jingle session may exist
|
| ... | ... | @@ -19,7 +19,7 @@ Handles Jingle Transports (currently only ICE-UDP) |
| 19 | 19 |
|
| 20 | 20 |
import logging
|
| 21 | 21 |
import socket
|
| 22 |
-from enum import IntEnum
|
|
| 22 |
+from enum import IntEnum, unique
|
|
| 23 | 23 |
import nbxmpp
|
| 24 | 24 |
from common import gajim
|
| 25 | 25 |
|
| ... | ... | @@ -34,6 +34,7 @@ def get_jingle_transport(node): |
| 34 | 34 |
return transports[namespace](node)
|
| 35 | 35 |
|
| 36 | 36 |
|
| 37 |
+@unique
|
|
| 37 | 38 |
class TransportType(IntEnum):
|
| 38 | 39 |
"""
|
| 39 | 40 |
Possible types of a JingleTransport
|
| ... | ... | @@ -33,10 +33,11 @@ import sys |
| 33 | 33 |
import time
|
| 34 | 34 |
import datetime
|
| 35 | 35 |
import json
|
| 36 |
+from collections import namedtuple
|
|
| 36 | 37 |
from gzip import GzipFile
|
| 37 | 38 |
from io import BytesIO
|
| 38 | 39 |
from gi.repository import GLib
|
| 39 |
-from enum import IntEnum
|
|
| 40 |
+from enum import IntEnum, unique
|
|
| 40 | 41 |
|
| 41 | 42 |
from common import exceptions
|
| 42 | 43 |
from common import gajim
|
| ... | ... | @@ -51,10 +52,12 @@ CACHE_DB_PATH = gajim.gajimpaths['CACHE_DB'] |
| 51 | 52 |
import logging
|
| 52 | 53 |
log = logging.getLogger('gajim.c.logger')
|
| 53 | 54 |
|
| 55 |
+@unique
|
|
| 54 | 56 |
class JIDConstant(IntEnum):
|
| 55 | 57 |
NORMAL_TYPE = 0
|
| 56 | 58 |
ROOM_TYPE = 1
|
| 57 | 59 |
|
| 60 |
+@unique
|
|
| 58 | 61 |
class KindConstant(IntEnum):
|
| 59 | 62 |
STATUS = 0
|
| 60 | 63 |
GCSTATUS = 1
|
| ... | ... | @@ -65,6 +68,7 @@ class KindConstant(IntEnum): |
| 65 | 68 |
CHAT_MSG_SENT = 6
|
| 66 | 69 |
ERROR = 7
|
| 67 | 70 |
|
| 71 |
+@unique
|
|
| 68 | 72 |
class ShowConstant(IntEnum):
|
| 69 | 73 |
ONLINE = 0
|
| 70 | 74 |
CHAT = 1
|
| ... | ... | @@ -73,6 +77,7 @@ class ShowConstant(IntEnum): |
| 73 | 77 |
DND = 4
|
| 74 | 78 |
OFFLINE = 5
|
| 75 | 79 |
|
| 80 |
+@unique
|
|
| 76 | 81 |
class TypeConstant(IntEnum):
|
| 77 | 82 |
AIM = 0
|
| 78 | 83 |
GG = 1
|
| ... | ... | @@ -90,6 +95,7 @@ class TypeConstant(IntEnum): |
| 90 | 95 |
MRIM = 13
|
| 91 | 96 |
NO_TRANSPORT = 14
|
| 92 | 97 |
|
| 98 |
+@unique
|
|
| 93 | 99 |
class SubscriptionConstant(IntEnum):
|
| 94 | 100 |
NONE = 0
|
| 95 | 101 |
TO = 1
|
| ... | ... | @@ -182,7 +188,7 @@ class Logger: |
| 182 | 188 |
def get_jids_already_in_db(self):
|
| 183 | 189 |
try:
|
| 184 | 190 |
self.cur.execute('SELECT jid FROM jids')
|
| 185 |
- # list of tupples: [('aaa@bbb',), ('cc@dd',)]
|
|
| 191 |
+ # list of tuples: [('aaa@bbb',), ('cc@dd',)]
|
|
| 186 | 192 |
rows = self.cur.fetchall()
|
| 187 | 193 |
except sqlite.DatabaseError:
|
| 188 | 194 |
raise exceptions.DatabaseMalformed
|
| ... | ... | @@ -583,8 +589,8 @@ class Logger: |
| 583 | 589 |
"""
|
| 584 | 590 |
Accept how many rows to restore and when to time them out (in minutes)
|
| 585 | 591 |
(mark them as too old) and number of messages that are in queue and are
|
| 586 |
- already logged but pending to be viewed, returns a list of tupples
|
|
| 587 |
- containg time, kind, message, sibject list with empty tupple if nothing
|
|
| 592 |
+ already logged but pending to be viewed, returns a list of tuples
|
|
| 593 |
+ containg time, kind, message, subject list with empty tuple if nothing
|
|
| 588 | 594 |
found to meet our demands
|
| 589 | 595 |
"""
|
| 590 | 596 |
try:
|
| ... | ... | @@ -625,17 +631,27 @@ class Logger: |
| 625 | 631 |
# returns time in seconds for the second that starts that date since epoch
|
| 626 | 632 |
# gimme unixtime from year month day:
|
| 627 | 633 |
d = datetime.date(year, month, day)
|
| 628 |
- local_time = d.timetuple() # time tupple (compat with time.localtime())
|
|
| 634 |
+ local_time = d.timetuple() # time tuple (compat with time.localtime())
|
|
| 629 | 635 |
# we have time since epoch baby :)
|
| 630 | 636 |
start_of_day = int(time.mktime(local_time))
|
| 631 | 637 |
return start_of_day
|
| 632 | 638 |
|
| 639 |
+ Message = namedtuple('Message',
|
|
| 640 |
+ ['contact_name', 'time', 'kind', 'show', 'message', 'subject',
|
|
| 641 |
+ 'additional_data', 'log_line_id'])
|
|
| 642 |
+ |
|
| 633 | 643 |
def get_conversation_for_date(self, jid, year, month, day, account):
|
| 634 | 644 |
"""
|
| 635 |
- Return contact_name, time, kind, show, message, subject, additional_data, log_line_id
|
|
| 645 |
+ Load the complete conversation with a given jid on a specific date
|
|
| 646 |
+ |
|
| 647 |
+ The conversation contains all messages that were exchanged between
|
|
| 648 |
+ `account` and `jid` on the day specified by `year`, `month` and `day`,
|
|
| 649 |
+ where `month` and `day` are 1-based.
|
|
| 636 | 650 |
|
| 637 |
- For each row in a list of tupples, returns list with empty tupple if we
|
|
| 638 |
- found nothing to meet our demands
|
|
| 651 |
+ The conversation will be returned as a list of single messages of type
|
|
| 652 |
+ `Logger.Message`. Messages in the list are sorted chronologically. An
|
|
| 653 |
+ empty list will be returned if there are no messages in the log database
|
|
| 654 |
+ for the requested combination of `jid` and `account` on the given date.
|
|
| 639 | 655 |
"""
|
| 640 | 656 |
try:
|
| 641 | 657 |
self.get_jid_id(jid)
|
| ... | ... | @@ -657,22 +673,23 @@ class Logger: |
| 657 | 673 |
ORDER BY time
|
| 658 | 674 |
''' % (where_sql, start_of_day, last_second_of_day), jid_tuple)
|
| 659 | 675 |
|
| 660 |
- results = self.cur.fetchall()
|
|
| 661 |
- messages = []
|
|
| 662 |
- for entry in results:
|
|
| 663 |
- additional_data = json.loads(entry[6])
|
|
| 664 |
- parsed_entry = entry[:6] + (additional_data, ) + entry[7:]
|
|
| 665 |
- messages.append(parsed_entry)
|
|
| 676 |
+ results = [self.Message(*row) for row in self.cur.fetchall()]
|
|
| 677 |
+ for message in results:
|
|
| 678 |
+ message._replace(additional_data=json.loads(message.additional_data))
|
|
| 666 | 679 |
|
| 667 |
- return messages
|
|
| 680 |
+ return results
|
|
| 668 | 681 |
|
| 669 |
- def get_search_results_for_query(self, jid, query, account, year=False,
|
|
| 670 |
- month=False, day=False):
|
|
| 682 |
+ def search_log(self, jid, query, account, year=None, month=None, day=None):
|
|
| 671 | 683 |
"""
|
| 672 |
- Returns contact_name, time, kind, show, message, subject, log_line_id
|
|
| 684 |
+ Search the conversation log for messages containing the `query` string.
|
|
| 685 |
+ |
|
| 686 |
+ The search can either span the complete log for the given `account` and
|
|
| 687 |
+ `jid` or be restriced to a single day by specifying `year`, `month` and
|
|
| 688 |
+ `day`, where `month` and `day` are 1-based.
|
|
| 673 | 689 |
|
| 674 |
- For each row in a list of tupples, returns list with empty tupple if we
|
|
| 675 |
- found nothing to meet our demands
|
|
| 690 |
+ All messages matching the specified criteria will be returned in a list
|
|
| 691 |
+ containing tuples of type `Logger.Message`. If no messages match the
|
|
| 692 |
+ criteria, an empty list will be returned.
|
|
| 676 | 693 |
"""
|
| 677 | 694 |
try:
|
| 678 | 695 |
self.get_jid_id(jid)
|
| ... | ... | @@ -682,12 +699,14 @@ class Logger: |
| 682 | 699 |
|
| 683 | 700 |
where_sql, jid_tuple = self._build_contact_where(account, jid)
|
| 684 | 701 |
like_sql = '%' + query.replace("'", "''") + '%'
|
| 685 |
- if year:
|
|
| 702 |
+ if year and month and day:
|
|
| 686 | 703 |
start_of_day = self.get_unix_time_from_date(year, month, day)
|
| 687 | 704 |
seconds_in_a_day = 86400 # 60 * 60 * 24
|
| 688 | 705 |
last_second_of_day = start_of_day + seconds_in_a_day - 1
|
| 689 | 706 |
self.cur.execute('''
|
| 690 |
- SELECT contact_name, time, kind, show, message, subject, log_line_id FROM logs
|
|
| 707 |
+ SELECT contact_name, time, kind, show, message, subject,
|
|
| 708 |
+ additional_data, log_line_id
|
|
| 709 |
+ FROM logs
|
|
| 691 | 710 |
WHERE (%s) AND message LIKE '%s'
|
| 692 | 711 |
AND time BETWEEN %d AND %d
|
| 693 | 712 |
ORDER BY time
|
| ... | ... | @@ -695,12 +714,17 @@ class Logger: |
| 695 | 714 |
jid_tuple)
|
| 696 | 715 |
else:
|
| 697 | 716 |
self.cur.execute('''
|
| 698 |
- SELECT contact_name, time, kind, show, message, subject, log_line_id FROM logs
|
|
| 717 |
+ SELECT contact_name, time, kind, show, message, subject,
|
|
| 718 |
+ additional_data, log_line_id
|
|
| 719 |
+ FROM logs
|
|
| 699 | 720 |
WHERE (%s) AND message LIKE '%s'
|
| 700 | 721 |
ORDER BY time
|
| 701 | 722 |
''' % (where_sql, like_sql), jid_tuple)
|
| 702 | 723 |
|
| 703 |
- results = self.cur.fetchall()
|
|
| 724 |
+ results = [self.Message(*row) for row in self.cur.fetchall()]
|
|
| 725 |
+ for message in results:
|
|
| 726 |
+ message._replace(additional_data=json.loads(message.additional_data))
|
|
| 727 |
+ |
|
| 704 | 728 |
return results
|
| 705 | 729 |
|
| 706 | 730 |
def get_days_with_logs(self, jid, year, month, max_day, account):
|
| ... | ... | @@ -17,8 +17,9 @@ |
| 17 | 17 |
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
| 18 | 18 |
##
|
| 19 | 19 |
|
| 20 |
-from enum import IntEnum
|
|
| 20 |
+from enum import IntEnum, unique
|
|
| 21 | 21 |
|
| 22 |
+@unique
|
|
| 22 | 23 |
class Constant(IntEnum):
|
| 23 | 24 |
NAME = 0
|
| 24 | 25 |
DOMAIN = 1
|
| ... | ... | @@ -26,6 +27,7 @@ class Constant(IntEnum): |
| 26 | 27 |
BARE_NAME = 3
|
| 27 | 28 |
TXT = 4
|
| 28 | 29 |
|
| 30 |
+@unique
|
|
| 29 | 31 |
class ConstantRI(IntEnum):
|
| 30 | 32 |
INTERFACE = 0
|
| 31 | 33 |
PROTOCOL = 1
|
| ... | ... | @@ -29,7 +29,7 @@ from gi.repository import Pango |
| 29 | 29 |
import os
|
| 30 | 30 |
import time
|
| 31 | 31 |
|
| 32 |
-from enum import IntEnum
|
|
| 32 |
+from enum import IntEnum, unique
|
|
| 33 | 33 |
|
| 34 | 34 |
import gtkgui_helpers
|
| 35 | 35 |
import tooltips
|
| ... | ... | @@ -44,6 +44,7 @@ from nbxmpp.protocol import NS_JINGLE_FILE_TRANSFER |
| 44 | 44 |
import logging
|
| 45 | 45 |
log = logging.getLogger('gajim.filetransfer_window')
|
| 46 | 46 |
|
| 47 |
+@unique
|
|
| 47 | 48 |
class Column(IntEnum):
|
| 48 | 49 |
IMAGE = 0
|
| 49 | 50 |
LABELS = 1
|
| ... | ... | @@ -46,7 +46,7 @@ import cell_renderer_image |
| 46 | 46 |
import dataforms_widget
|
| 47 | 47 |
import nbxmpp
|
| 48 | 48 |
|
| 49 |
-from enum import IntEnum
|
|
| 49 |
+from enum import IntEnum, unique
|
|
| 50 | 50 |
|
| 51 | 51 |
from common import events
|
| 52 | 52 |
from common import gajim
|
| ... | ... | @@ -65,6 +65,7 @@ from common.connection_handlers_events import GcMessageOutgoingEvent |
| 65 | 65 |
import logging
|
| 66 | 66 |
log = logging.getLogger('gajim.groupchat_control')
|
| 67 | 67 |
|
| 68 |
+@unique
|
|
| 68 | 69 |
class Column(IntEnum):
|
| 69 | 70 |
IMG = 0 # image to show state (online, new message etc)
|
| 70 | 71 |
NICK = 1 # contact nickame or ROLE name
|
| ... | ... | @@ -77,8 +77,9 @@ from common.logger import LOG_DB_PATH, JIDConstant, KindConstant |
| 77 | 77 |
from common import helpers
|
| 78 | 78 |
import dialogs
|
| 79 | 79 |
|
| 80 |
-from enum import IntEnum
|
|
| 80 |
+from enum import IntEnum, unique
|
|
| 81 | 81 |
|
| 82 |
+@unique
|
|
| 82 | 83 |
class Column(IntEnum):
|
| 83 | 84 |
UNIXTIME = 2
|
| 84 | 85 |
MESSAGE = 3
|
| ... | ... | @@ -252,7 +253,7 @@ class HistoryManager: |
| 252 | 253 |
# get those jids that have at least one entry in logs
|
| 253 | 254 |
self.cur.execute('SELECT jid, jid_id FROM jids WHERE jid_id IN ('
|
| 254 | 255 |
'SELECT distinct logs.jid_id FROM logs) ORDER BY jid')
|
| 255 |
- # list of tupples: [('aaa@bbb',), ('cc@dd',)]
|
|
| 256 |
+ # list of tuples: [('aaa@bbb',), ('cc@dd',)]
|
|
| 256 | 257 |
rows = self.cur.fetchall()
|
| 257 | 258 |
for row in rows:
|
| 258 | 259 |
self.jids_already_in.append(row[0]) # jid
|
| ... | ... | @@ -31,7 +31,7 @@ from gi.repository import GLib |
| 31 | 31 |
import time
|
| 32 | 32 |
import calendar
|
| 33 | 33 |
|
| 34 |
-from enum import IntEnum
|
|
| 34 |
+from enum import IntEnum, unique
|
|
| 35 | 35 |
|
| 36 | 36 |
import gtkgui_helpers
|
| 37 | 37 |
import conversation_textview
|
| ... | ... | @@ -43,6 +43,7 @@ from common import exceptions |
| 43 | 43 |
|
| 44 | 44 |
from common.logger import ShowConstant, KindConstant
|
| 45 | 45 |
|
| 46 |
+@unique
|
|
| 46 | 47 |
class InfoColumn(IntEnum):
|
| 47 | 48 |
'''Completion dict'''
|
| 48 | 49 |
JID = 0
|
| ... | ... | @@ -50,6 +51,7 @@ class InfoColumn(IntEnum): |
| 50 | 51 |
NAME = 2
|
| 51 | 52 |
COMPLETION = 3
|
| 52 | 53 |
|
| 54 |
+@unique
|
|
| 53 | 55 |
class Column(IntEnum):
|
| 54 | 56 |
LOG_JID = 0
|
| 55 | 57 |
CONTACT_NAME = 1
|
| ... | ... | @@ -340,7 +342,7 @@ class HistoryWindow: |
| 340 | 342 |
return
|
| 341 | 343 |
year, month, day = self.calendar.get_date() # integers
|
| 342 | 344 |
month = gtkgui_helpers.make_gtk_month_python_month(month)
|
| 343 |
- self._add_lines_for_date(year, month, day)
|
|
| 345 |
+ self._load_conversation(year, month, day)
|
|
| 344 | 346 |
|
| 345 | 347 |
def on_calendar_month_changed(self, widget):
|
| 346 | 348 |
"""
|
| ... | ... | @@ -385,34 +387,38 @@ class HistoryWindow: |
| 385 | 387 |
|
| 386 | 388 |
return show
|
| 387 | 389 |
|
| 388 |
- def _add_lines_for_date(self, year, month, day):
|
|
| 390 |
+ def _load_conversation(self, year, month, day):
|
|
| 389 | 391 |
"""
|
| 390 |
- Add all the lines for given date in textbuffer
|
|
| 392 |
+ Load the conversation between `self.jid` and `self.account` held on the
|
|
| 393 |
+ given date into the history textbuffer. Values for `month` and `day`
|
|
| 394 |
+ are 1-based.
|
|
| 391 | 395 |
"""
|
| 392 |
- self.history_buffer.set_text('') # clear the buffer first
|
|
| 396 |
+ self.history_buffer.set_text('')
|
|
| 393 | 397 |
self.last_time_printout = 0
|
| 394 | 398 |
show_status = self.show_status_checkbutton.get_active()
|
| 395 | 399 |
|
| 396 |
- lines = gajim.logger.get_conversation_for_date(self.jid, year, month, day, self.account)
|
|
| 397 |
- for line in lines:
|
|
| 398 |
- # line[0] is contact_name, line[1] is time of message
|
|
| 399 |
- # line[2] is kind, line[3] is show, line[4] is message, line[5] is subject
|
|
| 400 |
- # line[6] is additional_data, line[7] is log_line_id
|
|
| 401 |
- if not show_status and line[2] in (KindConstant.GCSTATUS,
|
|
| 402 |
- KindConstant.STATUS):
|
|
| 400 |
+ conversation = gajim.logger.get_conversation_for_date(
|
|
| 401 |
+ self.jid, year, month, day, self.account)
|
|
| 402 |
+ for message in conversation:
|
|
| 403 |
+ if not show_status and message.kind in (KindConstant.GCSTATUS,
|
|
| 404 |
+ KindConstant.STATUS):
|
|
| 403 | 405 |
continue
|
| 404 |
- self._add_new_line(line[0], line[1], line[2], line[3], line[4],
|
|
| 405 |
- line[5], line[6], line[7])
|
|
| 406 |
+ self._add_message(message)
|
|
| 406 | 407 |
|
| 407 |
- def _add_new_line(self, contact_name, tim, kind, show, message, subject,
|
|
| 408 |
- additional_data, log_line_id):
|
|
| 409 |
- """
|
|
| 410 |
- Add a new line in textbuffer
|
|
| 411 |
- """
|
|
| 412 |
- if not message and kind not in (KindConstant.STATUS,
|
|
| 413 |
- KindConstant.GCSTATUS):
|
|
| 408 |
+ def _add_message(self, msg):
|
|
| 409 |
+ if not msg.message and msg.kind not in (KindConstant.STATUS,
|
|
| 410 |
+ KindConstant.GCSTATUS):
|
|
| 414 | 411 |
return
|
| 415 | 412 |
|
| 413 |
+ tim = msg.time
|
|
| 414 |
+ kind = msg.kind
|
|
| 415 |
+ show = msg.show
|
|
| 416 |
+ message = msg.message
|
|
| 417 |
+ subject = msg.subject
|
|
| 418 |
+ log_line_id = msg.log_line_id
|
|
| 419 |
+ contact_name = msg.contact_name
|
|
| 420 |
+ additional_data = msg.additional_data
|
|
| 421 |
+ |
|
| 416 | 422 |
buf = self.history_buffer
|
| 417 | 423 |
end_iter = buf.get_end_iter()
|
| 418 | 424 |
|
| ... | ... | @@ -423,7 +429,7 @@ class HistoryWindow: |
| 423 | 429 |
timestamp_str = gajim.config.get('time_stamp')
|
| 424 | 430 |
timestamp_str = helpers.from_one_line(timestamp_str)
|
| 425 | 431 |
tim = time.strftime(timestamp_str, time.localtime(float(tim)))
|
| 426 |
- buf.insert(end_iter, tim) # add time
|
|
| 432 |
+ buf.insert(end_iter, tim)
|
|
| 427 | 433 |
elif gajim.config.get('print_time') == 'sometimes':
|
| 428 | 434 |
every_foo_seconds = 60 * gajim.config.get(
|
| 429 | 435 |
'print_ichat_every_foo_minutes')
|
| ... | ... | @@ -441,13 +447,11 @@ class HistoryWindow: |
| 441 | 447 |
|
| 442 | 448 |
if kind == KindConstant.GC_MSG:
|
| 443 | 449 |
tag_name = 'incoming'
|
| 444 |
- elif kind in (KindConstant.SINGLE_MSG_RECV,
|
|
| 445 |
- KindConstant.CHAT_MSG_RECV):
|
|
| 450 |
+ elif kind in (KindConstant.SINGLE_MSG_RECV, KindConstant.CHAT_MSG_RECV):
|
|
| 446 | 451 |
contact_name = self.completion_dict[self.jid][InfoColumn.NAME]
|
| 447 | 452 |
tag_name = 'incoming'
|
| 448 | 453 |
tag_msg = 'incomingtxt'
|
| 449 |
- elif kind in (KindConstant.SINGLE_MSG_SENT,
|
|
| 450 |
- KindConstant.CHAT_MSG_SENT):
|
|
| 454 |
+ elif kind in (KindConstant.SINGLE_MSG_SENT, KindConstant.CHAT_MSG_SENT):
|
|
| 451 | 455 |
if self.account:
|
| 452 | 456 |
contact_name = gajim.nicks[self.account]
|
| 453 | 457 |
else:
|
| ... | ... | @@ -539,33 +543,27 @@ class HistoryWindow: |
| 539 | 543 |
month = gtkgui_helpers.make_gtk_month_python_month(month)
|
| 540 | 544 |
|
| 541 | 545 |
show_status = self.show_status_checkbutton.get_active()
|
| 542 |
- |
|
| 543 |
- # contact_name, time, kind, show, message, subject
|
|
| 544 |
- results = gajim.logger.get_search_results_for_query(
|
|
| 545 |
- jid, text, account, year, month, day)
|
|
| 546 |
+ results = gajim.logger.search_log(jid, text, account, year, month, day)
|
|
| 546 | 547 |
#FIXME:
|
| 547 | 548 |
# add "subject: | message: " in message column if kind is single
|
| 548 | 549 |
# also do we need show at all? (we do not search on subject)
|
| 549 | 550 |
for row in results:
|
| 550 |
- if not show_status and row[2] in (KindConstant.GCSTATUS,
|
|
| 551 |
- KindConstant.STATUS):
|
|
| 551 |
+ if not show_status and row.kind in (KindConstant.GCSTATUS,
|
|
| 552 |
+ KindConstant.STATUS):
|
|
| 552 | 553 |
continue
|
| 553 |
- contact_name = row[0]
|
|
| 554 |
+ |
|
| 555 |
+ contact_name = row.contact_name
|
|
| 554 | 556 |
if not contact_name:
|
| 555 |
- kind = row[2]
|
|
| 556 |
- if kind == KindConstant.CHAT_MSG_SENT: # it's us! :)
|
|
| 557 |
+ if row.kind == KindConstant.CHAT_MSG_SENT: # it's us! :)
|
|
| 557 | 558 |
contact_name = gajim.nicks[account]
|
| 558 | 559 |
else:
|
| 559 | 560 |
contact_name = self.completion_dict[jid][InfoColumn.NAME]
|
| 560 |
- tim = row[1]
|
|
| 561 |
- message = row[4]
|
|
| 562 |
- log_line_id = row[6]
|
|
| 563 |
- local_time = time.localtime(tim)
|
|
| 561 |
+ |
|
| 562 |
+ local_time = time.localtime(row.time)
|
|
| 564 | 563 |
date = time.strftime('%Y-%m-%d', local_time)
|
| 565 | 564 |
|
| 566 |
- # jid (to which log is assigned to), name, date, message,
|
|
| 567 |
- # time (full unix time)
|
|
| 568 |
- model.append((jid, contact_name, date, message, str(tim), log_line_id))
|
|
| 565 |
+ model.append((jid, contact_name, date, row.message,
|
|
| 566 |
+ str(row.time), row.log_line_id))
|
|
| 569 | 567 |
|
| 570 | 568 |
def on_results_treeview_row_activated(self, widget, path, column):
|
| 571 | 569 |
"""
|
| ... | ... | @@ -576,7 +574,7 @@ class HistoryWindow: |
| 576 | 574 |
cur_year, cur_month, cur_day = self.calendar.get_date()
|
| 577 | 575 |
cur_month = gtkgui_helpers.make_gtk_month_python_month(cur_month)
|
| 578 | 576 |
model = widget.get_model()
|
| 579 |
- # make it a tupple (Y, M, D, 0, 0, 0...)
|
|
| 577 |
+ # make it a tuple (Y, M, D, 0, 0, 0...)
|
|
| 580 | 578 |
tim = time.strptime(model[path][Column.UNIXTIME], '%Y-%m-%d')
|
| 581 | 579 |
year = tim[0]
|
| 582 | 580 |
gtk_month = tim[1]
|
| ... | ... | @@ -157,7 +157,7 @@ class MessageControl(object): |
| 157 | 157 |
|
| 158 | 158 |
Derivded classes MUST implement this.
|
| 159 | 159 |
"""
|
| 160 |
- # Return a markup'd label and optional Gtk.Color in a tupple like:
|
|
| 160 |
+ # Return a markup'd label and optional Gtk.Color in a tuple like:
|
|
| 161 | 161 |
# return (label_str, None)
|
| 162 | 162 |
pass
|
| 163 | 163 |
|
| ... | ... | @@ -32,7 +32,7 @@ from gi.repository import GdkPixbuf |
| 32 | 32 |
from gi.repository import GLib, Gdk
|
| 33 | 33 |
import os
|
| 34 | 34 |
|
| 35 |
-from enum import IntEnum
|
|
| 35 |
+from enum import IntEnum, unique
|
|
| 36 | 36 |
|
| 37 | 37 |
import gtkgui_helpers
|
| 38 | 38 |
from dialogs import WarningDialog, YesNoDialog, ArchiveChooserDialog
|
| ... | ... | @@ -43,6 +43,7 @@ from plugins.helpers import GajimPluginActivateException |
| 43 | 43 |
from plugins.plugins_i18n import _
|
| 44 | 44 |
from common.exceptions import PluginsystemError
|
| 45 | 45 |
|
| 46 |
+@unique
|
|
| 46 | 47 |
class Column(IntEnum):
|
| 47 | 48 |
PLUGIN = 0
|
| 48 | 49 |
NAME = 1
|
| ... | ... | @@ -43,7 +43,7 @@ import os |
| 43 | 43 |
import time
|
| 44 | 44 |
import locale
|
| 45 | 45 |
|
| 46 |
-from enum import IntEnum
|
|
| 46 |
+from enum import IntEnum, unique
|
|
| 47 | 47 |
|
| 48 | 48 |
import common.sleepy
|
| 49 | 49 |
import history_window
|
| ... | ... | @@ -69,6 +69,7 @@ from message_window import MessageWindowMgr |
| 69 | 69 |
from nbxmpp.protocol import NS_FILE, NS_ROSTERX, NS_CONFERENCE
|
| 70 | 70 |
|
| 71 | 71 |
|
| 72 |
+@unique
|
|
| 72 | 73 |
class Column(IntEnum):
|
| 73 | 74 |
IMG = 0 # image to show state (online, new message etc)
|
| 74 | 75 |
NAME = 1 # cellrenderer text that holds contact nickame
|
| ... | ... | @@ -5792,7 +5793,7 @@ class RosterWindow: |
| 5792 | 5793 |
self._iters = {}
|
| 5793 | 5794 |
# for merged mode
|
| 5794 | 5795 |
self._iters['MERGED'] = {'account': None, 'groups': {}}
|
| 5795 |
- # holds a list of (jid, account) tupples
|
|
| 5796 |
+ # holds a list of (jid, account) tuples
|
|
| 5796 | 5797 |
self._last_selected_contact = []
|
| 5797 | 5798 |
self.transports_state_images = {'16': {}, '32': {}, 'opened': {},
|
| 5798 | 5799 |
'closed': {}}
|