Philipp Hörist pushed to branch master at gajim / gajim
Commits:
cdc2ec92 by Philipp Hörist at 2017-07-19T10:52:02+02:00
Fix not requesting roster on empty cache.db
The purpose of
`if version and not gajim.contacts.get_contacts_jid_list()`
seemed to be that when cache.db is empty (maybe it was deleted)
`gajim.contacts.get_contacts_jid_list()` should come back empty.
So on an empty roster cache, version was set to None, so that we
request in any case a new roster.
The Problem is that `gajim.contacts.get_contacts_jid_list()` is not
a good indication for an empty cache.db. On start we trigger a
`RosterReceivedEvent` which does a DB query to get the roster. Even
if that DB query comes up empty, the Event is still pushed.
In the event handler `_nec_roster_received` in roster_window.py we
add then previously open controls and our self (if the option is set)
to the roster, making `gajim.contacts.get_contacts_jid_list()` return
these contacts and hence the condition in `request_roster()` always
False.
So the version is set in the roster request, and if there is no new
version on the server, we request no new roster even though we only
have ourself and previously open controls in our roster.
As a solution for this we delete the roster version from the config
in `RosterReceivedEvent` if the DB query comes back empty, which
triggers a new roster request.
- - - - -
2 changed files:
- gajim/common/connection.py
- gajim/common/connection_handlers_events.py
Changes:
=====================================
gajim/common/connection.py
=====================================
--- a/gajim/common/connection.py
+++ b/gajim/common/connection.py
@@ -2501,16 +2501,11 @@ class Connection(CommonConnection, ConnectionHandlers):
def request_roster(self):
version = None
- features = self.connection.Dispatcher.Stream.features
+ features = self.connection.Dispatcher.Stream.features
if features and features.getTag('ver',
namespace=nbxmpp.NS_ROSTER_VER):
version = gajim.config.get_per('accounts', self.name,
'roster_version')
- if version and not gajim.contacts.get_contacts_jid_list(
- self.name):
- gajim.config.set_per('accounts', self.name, 'roster_version',
- '')
- version = None
iq_id = self.connection.initRoster(version=version)
self.awaiting_answers[iq_id] = (ROSTER_ARRIVED, )
=====================================
gajim/common/connection_handlers_events.py
=====================================
--- a/gajim/common/connection_handlers_events.py
+++ b/gajim/common/connection_handlers_events.py
@@ -410,6 +410,9 @@ class RosterReceivedEvent(nec.NetworkIncomingEvent):
'roster_version')
self.roster = gajim.logger.get_roster(gajim.get_jid_from_account(
self.conn.name))
+ if not self.roster:
+ gajim.config.set_per(
+ 'accounts', self.conn.name, 'roster_version', '')
return True
class RosterSetReceivedEvent(nec.NetworkIncomingEvent):
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/cdc2ec920500e50f85bc66f762b1653d7d…
Philipp Hörist pushed to branch master at gajim / gajim
Commits:
ef38afcf by Philipp Hörist at 2017-07-12T22:34:55+02:00
Use namedtuples for results from the DB
This makes the code much easier to read, and much less error prone.
- - - - -
08773642 by Philipp Hörist at 2017-07-12T22:34:55+02:00
Disable encryption if plugin is missing
- - - - -
4 changed files:
- gajim/chat_control.py
- gajim/chat_control_base.py
- gajim/common/logger.py
- gajim/roster_window.py
Changes:
=====================================
gajim/chat_control.py
=====================================
--- a/gajim/chat_control.py
+++ b/gajim/chat_control.py
@@ -1424,24 +1424,24 @@ class ChatControl(ChatControlBase):
local_old_kind = None
self.conv_textview.just_cleared = True
- for row in rows: # row[0] time, row[1] has kind, row[2] the message, row[3] subject, row[4] additional_data
- msg = row[2]
- additional_data = row[4]
+ for row in rows: # time, kind, message, subject, additional_data
+ msg = row.message
+ additional_data = row.additional_data
if not msg: # message is empty, we don't print it
continue
- if row[1] in (KindConstant.CHAT_MSG_SENT,
+ if row.kind in (KindConstant.CHAT_MSG_SENT,
KindConstant.SINGLE_MSG_SENT):
kind = 'outgoing'
name = self.get_our_nick()
- elif row[1] in (KindConstant.SINGLE_MSG_RECV,
+ elif row.kind in (KindConstant.SINGLE_MSG_RECV,
KindConstant.CHAT_MSG_RECV):
kind = 'incoming'
name = self.contact.get_shown_name()
- elif row[1] == KindConstant.ERROR:
+ elif row.kind == KindConstant.ERROR:
kind = 'status'
name = self.contact.get_shown_name()
- tim = float(row[0])
+ tim = float(row.time)
if gajim.config.get('restored_messages_small'):
small_attr = ['small']
@@ -1450,14 +1450,14 @@ class ChatControl(ChatControlBase):
xhtml = None
if msg.startswith('<body '):
xhtml = msg
- if row[3]:
+ if row.subject:
msg = _('Subject: %(subject)s\n%(message)s') % \
- {'subject': row[3], 'message': msg}
+ {'subject': row.subject, 'message': msg}
ChatControlBase.print_conversation_line(self, msg, kind, name,
tim, small_attr, small_attr + ['restored_message'],
small_attr + ['restored_message'], False,
old_kind=local_old_kind, xhtml=xhtml, additional_data=additional_data)
- if row[2].startswith('/me ') or row[2].startswith('/me\n'):
+ if row.message.startswith('/me ') or row.message.startswith('/me\n'):
local_old_kind = None
else:
local_old_kind = kind
=====================================
gajim/chat_control_base.py
=====================================
--- a/gajim/chat_control_base.py
+++ b/gajim/chat_control_base.py
@@ -444,7 +444,12 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
def get_encryption_state(self):
config_key = '%s-%s' % (self.account, self.contact.jid)
state = gajim.config.get_per('encryption', config_key, 'encryption')
- return state or None
+ if not state:
+ return None
+ if state not in gajim.plugin_manager.encryption_plugins:
+ self.set_encryption_state(None)
+ return None
+ return state
def set_encryption_menu_icon(self):
for child in self.encryption_menu.get_children():
=====================================
gajim/common/logger.py
=====================================
--- a/gajim/common/logger.py
+++ b/gajim/common/logger.py
@@ -121,6 +121,20 @@ class Logger:
gajim.ged.register_event_handler('gc-message-received',
ged.POSTCORE, self._nec_gc_message_received)
+ @staticmethod
+ def namedtuple_factory(cursor, row):
+ """
+ Usage:
+ con.row_factory = namedtuple_factory
+ """
+ fields = [col[0] for col in cursor.description]
+ Row = namedtuple("Row", fields)
+ named_row = Row(*row)
+ if 'additional_data' in fields:
+ named_row = named_row._replace(
+ additional_data=json.loads(named_row.additional_data))
+ return named_row
+
def dispatch(self, event, error):
gajim.ged.raise_event(event, None, str(error))
@@ -145,6 +159,7 @@ class Logger:
self.con = sqlite.connect(LOG_DB_FILE, timeout=20.0,
isolation_level='IMMEDIATE')
os.chdir(back)
+ self.con.row_factory = self.namedtuple_factory
self.cur = self.con.cursor()
self.set_synchronous(False)
@@ -191,18 +206,16 @@ class Logger:
def get_jids_already_in_db(self):
try:
self.cur.execute('SELECT jid FROM jids')
- # list of tuples: [('aaa@bbb',), ('cc@dd',)]
rows = self.cur.fetchall()
except sqlite.DatabaseError:
raise exceptions.DatabaseMalformed(LOG_DB_PATH)
self.jids_already_in = []
for row in rows:
- # row[0] is first item of row (the only result here, the jid)
- if row[0] == '':
+ if not row.jid:
# malformed jid, ignore line
pass
else:
- self.jids_already_in.append(row[0])
+ self.jids_already_in.append(row.jid)
def get_jids_in_db(self):
return self.jids_already_in
@@ -232,7 +245,7 @@ class Logger:
if row is None:
return None
else:
- if row[0] == JIDConstant.ROOM_TYPE:
+ if row.type == JIDConstant.ROOM_TYPE:
return True
return False
@@ -253,7 +266,7 @@ class Logger:
self.cur.execute('SELECT jid_id FROM jids WHERE jid=?', [jid])
row = self.cur.fetchone()
if row:
- return row[0]
+ return row.jid_id
# oh! a new jid :), we add it now
if typestr == 'ROOM':
typ = JIDConstant.ROOM_TYPE
@@ -476,8 +489,8 @@ class Logger:
except Exception:
unread_results = []
for message in unread_results:
- msg_log_id = message[0]
- shown = message[1]
+ msg_log_id = message.message_id
+ shown = message.shown
# here we get infos for that message, and related jid from jids table
# do NOT change order of SELECTed things, unless you change function(s)
# that called this function
@@ -488,15 +501,13 @@ class Logger:
WHERE logs.log_line_id = %d AND logs.jid_id = jids.jid_id
''' % msg_log_id
)
- results = self.cur.fetchall()
+ results = self.cur.fetchone()
if len(results) == 0:
# Log line is no more in logs table. remove it from unread_messages
self.set_read_messages([msg_log_id])
continue
- results[0] = list(results[0])
- results[0][5] = json.loads(results[0][5])
- results[0].append(shown)
- all_messages.append(results[0])
+
+ all_messages.append((results, shown))
return all_messages
def write(self, kind, jid, message=None, show=None, tim=None, subject=None,
@@ -619,12 +630,7 @@ class Logger:
KindConstant.CHAT_MSG_SENT, KindConstant.ERROR, timeout,
restore_how_many, pending_how_many), jid_tuple)
- results = self.cur.fetchall()
- messages = []
- for entry in results:
- additional_data = json.loads(entry[4])
- parsed_entry = entry[:4] + (additional_data, ) + entry[5:]
- messages.append(parsed_entry)
+ messages = self.cur.fetchall()
except sqlite.DatabaseError:
self.dispatch('DB_ERROR',
exceptions.DatabaseMalformed(LOG_DB_PATH))
@@ -643,10 +649,6 @@ class Logger:
start_of_day = int(time.mktime(local_time))
return start_of_day
- Message = namedtuple('Message',
- ['contact_name', 'time', 'kind', 'show', 'message', 'subject',
- 'additional_data', 'log_line_id'])
-
def get_conversation_for_date(self, jid, year, month, day, account):
"""
Load the complete conversation with a given jid on a specific date
@@ -680,11 +682,7 @@ class Logger:
ORDER BY time
''' % (where_sql, start_of_day, last_second_of_day), jid_tuple)
- results = [self.Message(*row) for row in self.cur.fetchall()]
- for message in results:
- message._replace(additional_data=json.loads(message.additional_data))
-
- return results
+ return self.cur.fetchall()
def search_log(self, jid, query, account, year=None, month=None, day=None):
"""
@@ -728,11 +726,7 @@ class Logger:
ORDER BY time
''' % (where_sql, like_sql), jid_tuple)
- results = [self.Message(*row) for row in self.cur.fetchall()]
- for message in results:
- message._replace(additional_data=json.loads(message.additional_data))
-
- return results
+ return self.cur.fetchall()
def get_days_with_logs(self, jid, year, month, max_day, account):
"""
@@ -756,7 +750,7 @@ class Logger:
# and take only one of the same values (distinct)
# Now we have timestamps of time 0:00 of every day with logs
self.cur.execute('''
- SELECT DISTINCT time/(86400)*86400 FROM logs
+ SELECT DISTINCT time/(86400)*86400 as time FROM logs
WHERE (%s)
AND time BETWEEN %d AND %d
AND kind NOT IN (%d, %d)
@@ -767,7 +761,7 @@ class Logger:
# convert timestamps to day of month
for line in result:
- days_with_logs[0:0]=[time.gmtime(line[0])[2]]
+ days_with_logs[0:0]=[time.gmtime(line.time)[2]]
return days_with_logs
@@ -788,7 +782,7 @@ class Logger:
where_sql = 'jid_id = ?'
jid_tuple = (jid_id,)
self.cur.execute('''
- SELECT MAX(time) FROM logs
+ SELECT MAX(time) as time FROM logs
WHERE (%s)
AND kind NOT IN (%d, %d)
''' % (where_sql, KindConstant.STATUS, KindConstant.GCSTATUS),
@@ -796,7 +790,7 @@ class Logger:
results = self.cur.fetchone()
if results is not None:
- result = results[0]
+ result = results.time
else:
result = None
return result
@@ -819,7 +813,7 @@ class Logger:
results = self.cur.fetchone()
if results is not None:
- result = results[0]
+ result = results.time
else:
result = None
return result
@@ -870,10 +864,9 @@ class Logger:
return
self.cur.execute(
'SELECT type from transports_cache WHERE transport = "%s"' % jid)
- results = self.cur.fetchall()
+ results = self.cur.fetchone()
if results:
- result = results[0][0]
- if result == type_id:
+ if results.type == type_id:
return
sql = 'UPDATE transports_cache SET type = %d WHERE transport = "%s"' %\
(type_id, jid)
@@ -893,8 +886,8 @@ class Logger:
return {}
answer = {}
for result in results:
- answer[result[0]] = self.convert_api_values_to_human_transport_type(
- result[1])
+ answer[result.transport] = self.convert_api_values_to_human_transport_type(
+ result.type)
return answer
# A longer note here:
@@ -924,16 +917,16 @@ class Logger:
# list of corrupted entries that will be removed
to_be_removed = []
- for hash_method, hash_, data in self.cur:
+ for row in self.cur:
# for each row: unpack the data field
# (format: (category, type, name, category, type, name, ...
# ..., 'FEAT', feature1, feature2, ...).join(' '))
# NOTE: if there's a need to do more gzip, put that to a function
try:
- data = GzipFile(fileobj=BytesIO(data)).read().decode('utf-8').split('\0')
+ data = GzipFile(fileobj=BytesIO(row.data)).read().decode('utf-8').split('\0')
except IOError:
# This data is corrupted. It probably contains non-ascii chars
- to_be_removed.append((hash_method, hash_))
+ to_be_removed.append((row.hash_method, row.hash))
continue
i = 0
identities = list()
@@ -952,7 +945,7 @@ class Logger:
i += 1
# yield the row
- yield hash_method, hash_, identities, features
+ yield row.hash_method, row.hash, identities, features
for hash_method, hash_ in to_be_removed:
sql = '''DELETE FROM caps_cache WHERE hash_method = "%s" AND
hash = "%s"''' % (hash_method, hash_)
@@ -1091,9 +1084,10 @@ class Logger:
SELECT j.jid, re.jid_id, re.name, re.subscription, re.ask
FROM roster_entry re, jids j
WHERE re.account_jid_id=? AND j.jid_id=re.jid_id''', (account_jid_id,))
- for jid, jid_id, name, subscription, ask in self.cur:
- jid = jid
- name = name
+ for row in self.cur:
+ #jid, jid_id, name, subscription, ask
+ jid = row.jid
+ name = row.name
data[jid] = {}
if name:
data[jid]['name'] = name
@@ -1101,14 +1095,14 @@ class Logger:
data[jid]['name'] = None
data[jid]['subscription'] = \
self.convert_db_api_values_to_human_subscription_values(
- subscription)
+ row.subscription)
data[jid]['groups'] = []
data[jid]['resources'] = {}
- if ask:
+ if row.ask:
data[jid]['ask'] = 'subscribe'
else:
data[jid]['ask'] = None
- data[jid]['id'] = jid_id
+ data[jid]['id'] = row.jid_id
# Then we add group for roster entries
for jid in data:
@@ -1116,8 +1110,8 @@ class Logger:
SELECT group_name FROM roster_group
WHERE account_jid_id=? AND jid_id=?''',
(account_jid_id, data[jid]['id']))
- for (group_name,) in self.cur:
- group_name = group_name
+ for row in self.cur:
+ group_name = row.group_name
data[jid]['groups'].append(group_name)
del data[jid]['id']
=====================================
gajim/roster_window.py
=====================================
--- a/gajim/roster_window.py
+++ b/gajim/roster_window.py
@@ -1842,10 +1842,9 @@ class RosterWindow:
old unread messages, delete them from unread table
"""
results = gajim.logger.get_unread_msgs()
- for result in results:
- jid = result[4]
- additional_data = result[5]
- shown = result[6]
+ for result, shown in results:
+ jid = result.jid
+ additional_data = result.additional_data
if gajim.contacts.get_first_contact_from_jid(account, jid) and not \
shown:
# We have this jid in our contacts list
@@ -1853,17 +1852,17 @@ class RosterWindow:
# with them
session = gajim.connections[account].make_new_session(jid)
- tim = float(result[2])
- session.roster_message(jid, result[1], tim, msg_type='chat',
- msg_log_id=result[0], additional_data=additional_data)
- gajim.logger.set_shown_unread_msgs(result[0])
+ tim = float(result.time)
+ session.roster_message(jid, result.message, tim, msg_type='chat',
+ msg_log_id=result.log_line_id, additional_data=additional_data)
+ gajim.logger.set_shown_unread_msgs(result.log_line_id)
- elif (time.time() - result[2]) > 2592000:
+ elif (time.time() - result.time) > 2592000:
# ok, here we see that we have a message in unread messages
# table that is older than a month. It is probably from someone
# not in our roster for accounts we usually launch, so we will
# delete this id from unread message tables.
- gajim.logger.set_read_messages([result[0]])
+ gajim.logger.set_read_messages([result.log_line_id])
def fill_contacts_and_groups_dicts(self, array, account):
"""
View it on GitLab: https://dev.gajim.org/gajim/gajim/compare/84f48a400c5bb4a5ca17be0c8b452d934…
Philipp Hörist pushed to branch master at gajim / gajim
Commits:
b625199c by Philipp Hörist at 2017-07-10T18:26:17+02:00
Allow for a no limit option on restore_timeout
- - - - -
a818b60b by Philipp Hörist at 2017-07-10T20:13:10+02:00
Fix unlimited muc_restore_timeout
muc_restore_timeout set to -1 means we want no particular time set, up
to which we request messages. But we should not deliberate request
messages we already have. Hence even if muc_restore_timeout is set
to -1, we should only request up to the last message we received.
- - - - -
cc682d24 by Philipp Hörist at 2017-07-10T21:03:45+02:00
Change defaults on history restore options
Set restore timeout inactiv, this should be really an advanced option,
probably only set for specific MUCs not as default for every MUC.
Set restore_lines to 10, so the User has an indication that Gajim can
display history, and that there is probably a setting to adjust.
Set muc_restore_lines to 100, this is a try to get a reasonable amount
of history, especially in small Groupchats. Most server will limit this
to 20-50 anyway. The limit 100 is more of a precaution if we run into a
misconfigured server. This is intended as a workaround until we can
implement MAM for Groupchats.
- - - - -
6 changed files:
- gajim/chat_control.py
- gajim/common/config.py
- gajim/common/connection.py
- gajim/common/defs.py
- gajim/common/logger.py
- gajim/common/optparser.py
Changes:
=====================================
gajim/chat_control.py
=====================================
--- a/gajim/chat_control.py
+++ b/gajim/chat_control.py
@@ -1411,12 +1411,6 @@ class ChatControl(ChatControlBase):
if gajim.jid_is_transport(jid):
return
- # How many lines to restore and when to time them out
- restore_how_many = gajim.config.get('restore_lines')
- if restore_how_many <= 0:
- return
- timeout = gajim.config.get('restore_timeout') # in minutes
-
# number of messages that are in queue and are already logged, we want
# to avoid duplication
pending_how_many = len(gajim.events.get_events(self.account, jid,
@@ -1425,8 +1419,8 @@ class ChatControl(ChatControlBase):
pending_how_many += len(gajim.events.get_events(self.account,
self.contact.get_full_jid(), ['chat', 'pm']))
- rows = gajim.logger.get_last_conversation_lines(jid, restore_how_many,
- pending_how_many, timeout, self.account)
+ rows = gajim.logger.get_last_conversation_lines(
+ jid, pending_how_many, self.account)
local_old_kind = None
self.conv_textview.just_cleared = True
=====================================
gajim/common/config.py
=====================================
--- a/gajim/common/config.py
+++ b/gajim/common/config.py
@@ -178,10 +178,10 @@ class Config:
'notify_on_new_gmail_email_command': [ opt_str, '', _('Specify the command to run when new mail arrives, e.g.: /usr/bin/getmail -q') ],
'use_gpg_agent': [ opt_bool, False ],
'change_roster_title': [ opt_bool, True, _('Add * and [n] in roster title?')],
- 'restore_lines': [opt_int, 4, _('Amount of previous messages to include when reopening a chat')],
- 'restore_timeout': [opt_int, 60, _('How many minutes should last lines from previous conversation last.')],
- 'muc_restore_lines': [opt_int, 20, _('How many lines to request from server when entering a groupchat. -1 means no limit')],
- 'muc_restore_timeout': [opt_int, 60, _('Minutes of backlog to request when entering a groupchat. -1 means no limit')],
+ 'restore_lines': [opt_int, 10, _('How many history messages should be restored when a chat tab/window is reopened?')],
+ 'restore_timeout': [opt_int, -1, _('How far back in time (minutes) history is restored. -1 means no limit.')],
+ 'muc_restore_lines': [opt_int, 100, _('How many lines to request from server when entering a groupchat. -1 means no limit')],
+ 'muc_restore_timeout': [opt_int, -1, _('Minutes of backlog to request when entering a groupchat. -1 means no limit')],
'muc_autorejoin_timeout': [opt_int, 1, _('How many seconds to wait before trying to autorejoin to a conference you are being disconnected from. Set to 0 to disable autorejoining.')],
'muc_autorejoin_on_kick': [opt_bool, False, _('Should autorejoin be activated when we are being kicked from a conference?')],
'send_on_ctrl_enter': [opt_bool, False, _('Send message on Ctrl+Enter and with Enter make new line (Mirabilis ICQ Client default behaviour).')],
=====================================
gajim/common/connection.py
=====================================
--- a/gajim/common/connection.py
+++ b/gajim/common/connection.py
@@ -2592,16 +2592,15 @@ class Connection(CommonConnection, ConnectionHandlers):
'muc_restore_timeout')
if timeout is None or timeout == -2:
timeout = gajim.config.get('muc_restore_timeout')
- timeout *= 60
- if timeout >= 0:
- last_date = self.last_history_time[room_jid]
- if last_date == 0:
- last_date = time.time() - timeout
- elif not rejoin:
- last_date = max(last_date, time.time() - timeout)
- last_date = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(
- last_date))
- tags['since'] = last_date
+ last_date = self.last_history_time[room_jid]
+ if last_date == 0 and timeout >= 0:
+ last_date = time.time() - timeout * 60
+ elif not rejoin and timeout >= 0:
+ last_date = max(last_date, time.time() - timeout * 60)
+ last_date = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(
+ last_date))
+ tags['since'] = last_date
+
nb = gajim.config.get_per('rooms', room_jid, 'muc_restore_lines')
if nb is None or nb == -2:
nb = gajim.config.get('muc_restore_lines')
=====================================
gajim/common/defs.py
=====================================
--- a/gajim/common/defs.py
+++ b/gajim/common/defs.py
@@ -30,7 +30,7 @@ import os.path
docdir = '../'
basedir = '../'
localedir = '../po'
-version = '0.16.10.4'
+version = '0.16.10.5'
try:
node = subprocess.Popen('git rev-parse --short=12 HEAD', shell=True,
=====================================
gajim/common/logger.py
=====================================
--- a/gajim/common/logger.py
+++ b/gajim/common/logger.py
@@ -582,8 +582,7 @@ class Logger:
exceptions.PysqliteOperationalError) as error:
self.dispatch('DB_ERROR', error)
- def get_last_conversation_lines(self, jid, restore_how_many_rows,
- pending_how_many, timeout, account):
+ def get_last_conversation_lines(self, jid, pending_how_many, account):
"""
Accept how many rows to restore and when to time them out (in minutes)
(mark them as too old) and number of messages that are in queue and are
@@ -598,8 +597,16 @@ class Logger:
return []
where_sql, jid_tuple = self._build_contact_where(account, jid)
+ # How many lines to restore and when to time them out
+ restore_how_many = gajim.config.get('restore_lines')
+ if restore_how_many <= 0:
+ return []
+ timeout = gajim.config.get('restore_timeout') # in minutes
+
now = int(float(time.time()))
- timed_out = now - (timeout * 60) # before that they are too old
+ if timeout > 0:
+ timeout = now - (timeout * 60) # before that they are too old
+
# so if we ask last 5 lines and we have 2 pending we get
# 3 - 8 (we avoid the last 2 lines but we still return 5 asked)
try:
@@ -609,8 +616,8 @@ class Logger:
ORDER BY time DESC LIMIT %d OFFSET %d
''' % (where_sql, KindConstant.SINGLE_MSG_RECV,
KindConstant.CHAT_MSG_RECV, KindConstant.SINGLE_MSG_SENT,
- KindConstant.CHAT_MSG_SENT, KindConstant.ERROR, timed_out,
- restore_how_many_rows, pending_how_many), jid_tuple)
+ KindConstant.CHAT_MSG_SENT, KindConstant.ERROR, timeout,
+ restore_how_many, pending_how_many), jid_tuple)
results = self.cur.fetchall()
messages = []
=====================================
gajim/common/optparser.py
=====================================
--- a/gajim/common/optparser.py
+++ b/gajim/common/optparser.py
@@ -238,6 +238,8 @@ class OptionsParser:
self.update_config_to_016103()
if old < [0, 16, 10, 4] and new >= [0, 16, 10, 4]:
self.update_config_to_016104()
+ if old < [0, 16, 10, 5] and new >= [0, 16, 10, 5]:
+ self.update_config_to_016105()
gajim.logger.init_vars()
gajim.logger.attach_cache_database()
@@ -1005,3 +1007,8 @@ class OptionsParser:
def update_config_to_016104(self):
gajim.config.set('emoticons_theme', 'noto-emoticons')
gajim.config.set('version', '0.16.10.4')
+
+ def update_config_to_016105(self):
+ gajim.config.set('muc_restore_timeout', -1)
+ gajim.config.set('restore_timeout', -1)
+ gajim.config.set('version', '0.16.10.5')
View it on GitLab: https://dev.gajim.org/gajim/gajim/compare/aeb64a516c65c8073874df38182045723…
Philipp Hörist pushed to branch master at gajim / gajim
Commits:
5a896579 by Philipp Hörist at 2017-07-10T16:25:26+02:00
Commit to DB before shutdown
Because some operations use the _timeout_commit() it happens that a timeout
is active while we shutdown.
This makes sure everything is commited before shutdown.
- - - - -
aeb64a51 by Philipp Hörist at 2017-07-10T16:39:27+02:00
Use correct history date on muc join
Example:
If we receive a message the last message date is now.
If we restart Gajim and join the MUC again, `time.time() - timeout`
will be most likly smaller then when we received the last message
If the timeout is an hour, this would mean that many messages are requested
from the archive which we already received.
So we always want the most current timestamp (MAX).
- - - - -
3 changed files:
- gajim/common/connection.py
- gajim/common/logger.py
- gajim/roster_window.py
Changes:
=====================================
gajim/common/connection.py
=====================================
--- a/gajim/common/connection.py
+++ b/gajim/common/connection.py
@@ -2598,7 +2598,7 @@ class Connection(CommonConnection, ConnectionHandlers):
if last_date == 0:
last_date = time.time() - timeout
elif not rejoin:
- last_date = min(last_date, time.time() - timeout)
+ last_date = max(last_date, time.time() - timeout)
last_date = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(
last_date))
tags['since'] = last_date
=====================================
gajim/common/logger.py
=====================================
--- a/gajim/common/logger.py
+++ b/gajim/common/logger.py
@@ -168,7 +168,7 @@ class Logger:
self.open_db()
self.get_jids_already_in_db()
- def _really_commit(self):
+ def commit(self):
try:
self.con.commit()
except sqlite.OperationalError as e:
@@ -179,7 +179,7 @@ class Logger:
def _timeout_commit(self):
if self.commit_timout_id:
return
- self.commit_timout_id = GLib.timeout_add(500, self._really_commit)
+ self.commit_timout_id = GLib.timeout_add(500, self.commit)
def simple_commit(self, sql_to_commit):
"""
=====================================
gajim/roster_window.py
=====================================
--- a/gajim/roster_window.py
+++ b/gajim/roster_window.py
@@ -2469,6 +2469,9 @@ class RosterWindow:
gajim.interface.hide_systray()
self.save_done = True
+ # Commit any outstanding SQL transactions
+ gajim.logger.commit()
+
def quit_gtkgui_interface(self):
"""
When we quit the gtk interface - exit gtk
View it on GitLab: https://dev.gajim.org/gajim/gajim/compare/0eca29d4848a230a2a85bfd3f37dd1ef9…
Philipp Hörist pushed to branch master at gajim / gajim
Commits:
0eca29d4 by Philipp Hörist at 2017-07-10T01:15:30+02:00
Fix memory leak in plugins window
- remove gui extension point on close, to remove the reference the plugin manager holds to the Class.
- reduce scope of var that holds reference to Gtk.Builder(). We have to be careful with
Gtk.Builder, because it can hold a reference to our Class (methods bound to signals) which creates a reference cycle
which python is not able to detect. Hence neither Gtk.Builder nor our Class are garbage collected.
Why this is not detected as a reference cylce is unclear at the moment.
There are two approaches to circumvent the problem:
1. we lose our reference to Gtk.Builder when closing the window, which lets python garbage
collect the builder, afterwards it can garbage collect our class.
2. we reduce the scope of the var that holds a reference to Gtk.Builder, so that the builder
can be garbage collected at the end of __init__.
I chose to reduce the scope because the builder is not needed class wide.
- - - - -
1 changed file:
- gajim/plugins/gui.py
Changes:
=====================================
gajim/plugins/gui.py
=====================================
--- a/gajim/plugins/gui.py
+++ b/gajim/plugins/gui.py
@@ -58,22 +58,23 @@ class PluginsWindow(object):
@log_calls('PluginsWindow')
def __init__(self):
'''Initialize Plugins window'''
- self.xml = gtkgui_helpers.get_gtk_builder('plugins_window.ui')
- self.window = self.xml.get_object('plugins_window')
+ builder = gtkgui_helpers.get_gtk_builder('plugins_window.ui')
+ self.window = builder.get_object('plugins_window')
self.window.set_transient_for(gajim.interface.roster.window)
widgets_to_extract = ('plugins_notebook', 'plugin_name_label',
'plugin_version_label', 'plugin_authors_label',
'plugin_homepage_linkbutton', 'uninstall_plugin_button',
- 'configure_plugin_button', 'installed_plugins_treeview')
+ 'configure_plugin_button', 'installed_plugins_treeview',
+ 'close_button')
for widget_name in widgets_to_extract:
- setattr(self, widget_name, self.xml.get_object(widget_name))
+ setattr(self, widget_name, builder.get_object(widget_name))
self.plugin_description_textview = HtmlTextView()
self.plugin_description_textview.connect_tooltip()
self.plugin_description_textview.set_wrap_mode(Gtk.WrapMode.WORD)
- sw = self.xml.get_object('scrolledwindow2')
+ sw = builder.get_object('scrolledwindow2')
sw.add(self.plugin_description_textview)
self.installed_plugins_model = Gtk.ListStore(object, str, bool, bool,
GdkPixbuf.Pixbuf)
@@ -109,12 +110,12 @@ class PluginsWindow(object):
self.fill_installed_plugins_model()
root_iter = self.installed_plugins_model.get_iter_first()
if root_iter:
- selection.select_iter(root_iter )
+ selection.select_iter(root_iter)
- self.xml.connect_signals(self)
+ builder.connect_signals(self)
self.plugins_notebook.set_current_page(0)
- self.xml.get_object('close_button').grab_focus()
+ self.close_button.grab_focus()
# Adding GUI extension point for Plugins that want to hook the Plugin Window
gajim.plugin_manager.gui_extension_point('plugin_window', self)
@@ -127,7 +128,7 @@ class PluginsWindow(object):
self.window.destroy()
def on_plugins_notebook_switch_page(self, widget, page, page_num):
- GLib.idle_add(self.xml.get_object('close_button').grab_focus)
+ GLib.idle_add(self.close_button.grab_focus)
@log_calls('PluginsWindow')
def installed_plugins_treeview_selection_changed(self, treeview_selection):
@@ -222,6 +223,7 @@ class PluginsWindow(object):
@log_calls('PluginsWindow')
def on_plugins_window_destroy(self, widget):
'''Close window'''
+ gajim.plugin_manager.remove_gui_extension_point('plugin_window', self)
del gajim.interface.instances['plugins']
@log_calls('PluginsWindow')
View it on GitLab: https://dev.gajim.org/gajim/gajim/commit/0eca29d4848a230a2a85bfd3f37dd1ef98…