* when in common, no need to do from common import FOO, just import FOO

* we now migrate automaticaly at startup in a thread
 * progressDialog now scroll textvew to the end
This commit is contained in:
Yann Leboulanger 2005-12-05 11:13:08 +00:00
parent ed47580227
commit 637c903d68
8 changed files with 226 additions and 197 deletions

View file

@ -20,7 +20,7 @@ import os
import sys import sys
import stat import stat
import gajim from common import gajim
import logger import logger
import i18n import i18n

View file

@ -22,7 +22,7 @@
import sre import sre
import copy import copy
from common import i18n import i18n
_ = i18n._ _ = i18n._
OPT_TYPE = 0 OPT_TYPE = 0

View file

@ -22,12 +22,12 @@ import sys
import logging import logging
import mutex import mutex
import common.config import config
interface = None # The actual interface (the gtk one for the moment) interface = None # The actual interface (the gtk one for the moment)
version = '0.9' version = '0.9'
config = common.config.Config() config = config.Config()
connections = {} connections = {}
verbose = False verbose = False
@ -37,8 +37,8 @@ h.setFormatter(f)
log = logging.getLogger('Gajim') log = logging.getLogger('Gajim')
log.addHandler(h) log.addHandler(h)
import common.logger import logger
logger = common.logger.Logger() # init the logger logger = logger.Logger() # init the logger
if os.name == 'nt': if os.name == 'nt':
if '.svn' in os.listdir('.') or '_svn' in os.listdir('.'): if '.svn' in os.listdir('.') or '_svn' in os.listdir('.'):

View file

@ -27,8 +27,8 @@ from pysqlite2 import dbapi2 as sqlite
import gajim import gajim
import logger import logger
from common import i18n import i18n
from common.xmpp_stringprep import nodeprep, resourceprep, nameprep from xmpp_stringprep import nodeprep, resourceprep, nameprep
try: try:
import winsound # windows-only built-in module for playing wav import winsound # windows-only built-in module for playing wav

View file

@ -22,8 +22,8 @@ import sys
import time import time
import datetime import datetime
from common import exceptions import exceptions
from common import i18n import i18n
_ = i18n._ _ = i18n._
try: try:

View file

@ -13,8 +13,6 @@ signal.signal(signal.SIGINT, signal.SIG_DFL) # ^C exits the application
from pysqlite2 import dbapi2 as sqlite from pysqlite2 import dbapi2 as sqlite
constants = logger.Constants()
if os.name == 'nt': if os.name == 'nt':
try: try:
PATH_TO_LOGS_BASE_DIR = os.path.join(os.environ['appdata'], 'Gajim', 'Logs') PATH_TO_LOGS_BASE_DIR = os.path.join(os.environ['appdata'], 'Gajim', 'Logs')
@ -25,46 +23,20 @@ if os.name == 'nt':
PATH_TO_DB = '../src/logs.db' PATH_TO_DB = '../src/logs.db'
else: else:
PATH_TO_LOGS_BASE_DIR = os.path.expanduser('~/.gajim/logs') PATH_TO_LOGS_BASE_DIR = os.path.expanduser('~/.gajim/logs')
PATH_TO_DB = os.path.expanduser('~/.gajim/logs.db') # database is called logs.db PATH_TO_DB = os.path.expanduser('~/.gajim/logs2.db') # database is called logs.db
if os.path.exists(PATH_TO_DB): class migration:
def __init__(self):
self.constants = logger.Constants()
self.DONE = False
if os.path.exists(PATH_TO_DB):
print '%s already exists. Exiting..' % PATH_TO_DB print '%s already exists. Exiting..' % PATH_TO_DB
sys.exit() sys.exit()
jids_already_in = [] # jid we already put in DB self.jids_already_in = [] # jid we already put in DB
con = sqlite.connect(PATH_TO_DB)
os.chmod(PATH_TO_DB, 0600) # rw only for us
cur = con.cursor()
# create the tables
# kind can be
# status, gcstatus, gc_msg, (we only recv for those 3),
# single_msg_recv, chat_msg_recv, chat_msg_sent, single_msg_sent
# to meet all our needs
# logs.jid_id --> jids.jid_id but Sqlite doesn't do FK etc so it's done in python code
cur.executescript(
'''
CREATE TABLE jids(
jid_id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
jid TEXT UNIQUE,
type INTEGER
);
CREATE TABLE logs( def get_jid(self, dirname, filename):
log_line_id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
jid_id INTEGER,
contact_name TEXT,
time INTEGER,
kind INTEGER,
show INTEGER,
message TEXT,
subject TEXT
);
'''
)
con.commit()
def get_jid(dirname, filename):
# jids.jid text column will be JID if TC-related, room_jid if GC-related, # jids.jid text column will be JID if TC-related, room_jid if GC-related,
# ROOM_JID/nick if pm-related. Here I get names from filenames # ROOM_JID/nick if pm-related. Here I get names from filenames
if dirname.endswith('logs') or dirname.endswith('Logs'): if dirname.endswith('logs') or dirname.endswith('Logs'):
@ -83,15 +55,18 @@ def get_jid(dirname, filename):
jid = jid.lower() jid = jid.lower()
return jid return jid
def decode_jid(string): def decode_jid(self, string):
'''try to decode (to make it Unicode instance) given jid''' '''try to decode (to make it Unicode instance) given jid'''
string = decode_string(string) string = decode_string(string)
if isinstance(string, str): if isinstance(string, str):
return None # decode failed return None # decode failed
return string return string
def visit(arg, dirname, filenames): def visit(self, arg, dirname, filenames):
s = _('Visiting %s') % dirname s = _('Visiting %s') % dirname
if self.queue:
self.queue.put(s)
else:
print s print s
for filename in filenames: for filename in filenames:
# Don't take this file into account, this is dup info # Don't take this file into account, this is dup info
@ -102,21 +77,24 @@ def visit(arg, dirname, filenames):
if os.path.isdir(path_to_text_file): if os.path.isdir(path_to_text_file):
continue continue
jid = get_jid(dirname, filename) jid = self.get_jid(dirname, filename)
jid = decode_jid(jid) jid = self.decode_jid(jid)
if not jid: if not jid:
continue continue
if filename == os.path.basename(dirname): # gajim@conf/gajim@conf then gajim@conf is type room if filename == os.path.basename(dirname): # gajim@conf/gajim@conf then gajim@conf is type room
jid_type = constants.JID_ROOM_TYPE jid_type = self.constants.JID_ROOM_TYPE
#Type of log #Type of log
typ = 'room' typ = 'room'
else: else:
jid_type = constants.JID_NORMAL_TYPE jid_type = self.constants.JID_NORMAL_TYPE
#Type of log #Type of log
typ = _('normal') typ = _('normal')
s = _('Processing %s of type %s') % (jid.encode('utf-8'), typ) s = _('Processing %s of type %s') % (jid.encode('utf-8'), typ)
if self.queue:
self.queue.put(s)
else:
print s print s
JID_ID = None JID_ID = None
@ -150,20 +128,20 @@ def visit(arg, dirname, filenames):
if typ == 'gc': if typ == 'gc':
contact_name = message_data[0] contact_name = message_data[0]
message = ':'.join(message_data[1:]) message = ':'.join(message_data[1:])
kind = constants.KIND_GC_MSG kind = self.constants.KIND_GC_MSG
elif typ == 'gcstatus': elif typ == 'gcstatus':
contact_name = message_data[0] contact_name = message_data[0]
show = message_data[1] show = message_data[1]
message = ':'.join(message_data[2:]) # status msg message = ':'.join(message_data[2:]) # status msg
kind = constants.KIND_GCSTATUS kind = self.constants.KIND_GCSTATUS
elif typ == 'recv': elif typ == 'recv':
message = ':'.join(message_data[0:]) message = ':'.join(message_data[0:])
kind = constants.KIND_CHAT_MSG_RECV kind = self.constants.KIND_CHAT_MSG_RECV
elif typ == 'sent': elif typ == 'sent':
message = ':'.join(message_data[0:]) message = ':'.join(message_data[0:])
kind = constants.KIND_CHAT_MSG_SENT kind = self.constants.KIND_CHAT_MSG_SENT
else: # status else: # status
kind = constants.KIND_STATUS kind = self.constants.KIND_STATUS
show = message_data[0] show = message_data[0]
message = ':'.join(message_data[1:]) # status msg message = ':'.join(message_data[1:]) # status msg
@ -174,25 +152,58 @@ def visit(arg, dirname, filenames):
# jid is already in the DB, don't create a new row, just get his jid_id # jid is already in the DB, don't create a new row, just get his jid_id
if not JID_ID: if not JID_ID:
if jid in jids_already_in: if jid in self.jids_already_in:
cur.execute('SELECT jid_id FROM jids WHERE jid = "%s"' % jid) self.cur.execute('SELECT jid_id FROM jids WHERE jid = "%s"' % jid)
JID_ID = cur.fetchone()[0] JID_ID = self.cur.fetchone()[0]
else: else:
jids_already_in.append(jid) self.jids_already_in.append(jid)
cur.execute('INSERT INTO jids (jid, type) VALUES (?, ?)', self.cur.execute('INSERT INTO jids (jid, type) VALUES (?, ?)',
(jid, jid_type)) (jid, jid_type))
con.commit() self.con.commit()
JID_ID = cur.lastrowid JID_ID = self.cur.lastrowid
sql = 'INSERT INTO logs (jid_id, contact_name, time, kind, show, message) '\ sql = 'INSERT INTO logs (jid_id, contact_name, time, kind, show, message) '\
'VALUES (?, ?, ?, ?, ?, ?)' 'VALUES (?, ?, ?, ?, ?, ?)'
values = (JID_ID, contact_name, tim, kind, show, message) values = (JID_ID, contact_name, tim, kind, show, message)
cur.execute(sql, values) self.cur.execute(sql, values)
con.commit() self.con.commit()
def migrate(): def migrate(self, queue = None):
os.path.walk(PATH_TO_LOGS_BASE_DIR, visit, None) self.queue = queue
self.con = sqlite.connect(PATH_TO_DB)
os.chmod(PATH_TO_DB, 0600) # rw only for us
self.cur = self.con.cursor()
# create the tables
# kind can be
# status, gcstatus, gc_msg, (we only recv for those 3),
# single_msg_recv, chat_msg_recv, chat_msg_sent, single_msg_sent
# to meet all our needs
# logs.jid_id --> jids.jid_id but Sqlite doesn't do FK etc so it's done in python code
self.cur.executescript(
'''
CREATE TABLE jids(
jid_id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
jid TEXT UNIQUE,
type INTEGER
);
CREATE TABLE logs(
log_line_id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
jid_id INTEGER,
contact_name TEXT,
time INTEGER,
kind INTEGER,
show INTEGER,
message TEXT,
subject TEXT
);
'''
)
self.con.commit()
os.path.walk(PATH_TO_LOGS_BASE_DIR, self.visit, None)
s = '''We do not use plain-text files anymore, because they do not scale. s = '''We do not use plain-text files anymore, because they do not scale.
Those files here are logs for Gajim up until 0.8.2 Those files here are logs for Gajim up until 0.8.2
We now use an sqlite database called logs.db found in ~/.gajim We now use an sqlite database called logs.db found in ~/.gajim
@ -201,6 +212,9 @@ Thank you''' % PATH_TO_LOGS_BASE_DIR
f = open(os.path.join(PATH_TO_LOGS_BASE_DIR, 'README'), 'w') f = open(os.path.join(PATH_TO_LOGS_BASE_DIR, 'README'), 'w')
f.write(s) f.write(s)
f.close() f.close()
if queue:
queue.put(s)
self.DONE = True
if __name__ == '__main__': if __name__ == '__main__':
print 'IMPORTNANT: PLEASE READ http://trac.gajim.org/wiki/MigrateLogToDot9DB' print 'IMPORTNANT: PLEASE READ http://trac.gajim.org/wiki/MigrateLogToDot9DB'
@ -210,4 +224,5 @@ if __name__ == '__main__':
print 'Starting Logs Migration' print 'Starting Logs Migration'
print '=======================' print '======================='
print 'Please do NOT run Gajim until this script is over' print 'Please do NOT run Gajim until this script is over'
migrate() m = migration()
m.migrate()

View file

@ -1277,35 +1277,36 @@ class ProgressDialog:
messages_queue has the message to show messages_queue has the message to show
in the textview''' in the textview'''
self.xml = gtk.glade.XML(GTKGUI_GLADE, 'progress_dialog', APP) self.xml = gtk.glade.XML(GTKGUI_GLADE, 'progress_dialog', APP)
dialog = self.xml.get_widget('progress_dialog') self.dialog = self.xml.get_widget('progress_dialog')
self.messages_queue = messages_queue
self.label = self.xml.get_widget('label') self.label = self.xml.get_widget('label')
self.label.set_markup('<big>' + during_text + '</big>') self.label.set_markup('<big>' + during_text + '</big>')
self.progressbar = self.xml.get_widget('progressbar') self.progressbar = self.xml.get_widget('progressbar')
self.textview_buffer = self.xml.get_widget('textview').get_buffer() self.textview = self.xml.get_widget('textview')
self.textview_buffer = self.textview.get_buffer()
end_iter = self.textview_buffer.get_end_iter()
self.textview_buffer.create_mark('end', end_iter, False)
dialog.set_title(title_text) self.dialog.set_title(title_text)
dialog.show_all() self.dialog.show_all()
self.xml.signal_autoconnect(self) self.xml.signal_autoconnect(self)
self.update_progressbar_timeout_id = gobject.timeout_add(100, self.update_progressbar_timeout_id = gobject.timeout_add(100,
self.update_progressbar) self.update_progressbar)
self.read_from_queue_id = gobject.timeout_add(1000, self.read_from_queue_id = gobject.timeout_add(200,
self.read_from_queue_and_update_textview, messages_queue) self.read_from_queue_and_update_textview)
def update_progressbar(self): def update_progressbar(self):
self.progressbar.pulse() self.progressbar.pulse()
return True # loop forever return True # loop forever
def read_from_queue_and_update_textview(self, messages_queue): def read_from_queue_and_update_textview(self):
try: while not self.messages_queue.empty():
message = messages_queue.get_nowait() message = self.messages_queue.get()
print message
except Queue.Empty:
pass
else:
end_iter = self.textview_buffer.get_end_iter() end_iter = self.textview_buffer.get_end_iter()
self.textview_buffer.insert(end_iter, message) self.textview_buffer.insert(end_iter, message + '\n')
self.textview.scroll_to_mark(self.textview_buffer.get_mark('end'), 0, True, 0, 1)
return True # loop for ever return True # loop for ever
@ -1316,6 +1317,7 @@ class ProgressDialog:
'''whatever we were doing is done (either we problems or not), '''whatever we were doing is done (either we problems or not),
make close button sensitive and show the done_text in label''' make close button sensitive and show the done_text in label'''
self.xml.get_widget('close_button').set_sensitive(True) self.xml.get_widget('close_button').set_sensitive(True)
self.label.set_markup('<big>' + done_text + '</big') self.label.set_markup('<big>' + done_text + '</big>')
gobject.source_remove(self.update_progressbar_timeout_id) gobject.source_remove(self.update_progressbar_timeout_id)
gobject.source_remove(self.read_from_queue_id) gobject.source_remove(self.read_from_queue_id)
self.read_from_queue_and_update_textview()

View file

@ -71,12 +71,6 @@ if pritext:
dlg.destroy() dlg.destroy()
sys.exit() sys.exit()
from common import logger
LOG_DB_PATH = logger.LOG_DB_PATH
NO_DB = False
if not os.path.isfile(LOG_DB_PATH):
NO_DB = True
path = os.getcwd() path = os.getcwd()
if '.svn' in os.listdir(path) or '_svn' in os.listdir(path): if '.svn' in os.listdir(path) or '_svn' in os.listdir(path):
# import gtkexcepthook only for those that run svn # import gtkexcepthook only for those that run svn
@ -94,6 +88,7 @@ import sre
import signal import signal
import getopt import getopt
import time import time
import threading
import gtkgui_helpers import gtkgui_helpers
import notify import notify
@ -1399,6 +1394,14 @@ class Interface:
gobject.timeout_add(200, self.process_connections) gobject.timeout_add(200, self.process_connections)
gobject.timeout_add(500, self.read_sleepy) gobject.timeout_add(500, self.read_sleepy)
def wait_migration(migration):
if not migration.DONE:
return True
dialog.done(_('Logs have been successfully migrated to the database.'))
dialog.dialog.run()
dialog.dialog.destroy()
gtk.main_quit()
if __name__ == '__main__': if __name__ == '__main__':
signal.signal(signal.SIGINT, signal.SIG_DFL) # ^C exits the application signal.signal(signal.SIGINT, signal.SIG_DFL) # ^C exits the application
@ -1460,9 +1463,18 @@ if __name__ == '__main__':
pass pass
# Migrate old logs if user wants that # Migrate old logs if user wants that
if NO_DB: from common import logger
pass # launch migration script LOG_DB_PATH = logger.LOG_DB_PATH
del NO_DB if not os.path.isfile(LOG_DB_PATH):
import Queue
q = Queue.Queue(100)
from common import migrate_logs_to_dot9_db
m = migrate_logs_to_dot9_db.migration()
dialog = dialogs.ProgressDialog(_('Migrating logs...'), _('Please wait while logs are being migrated...'), q)
t = threading.Thread(target = m.migrate, args = (q,))
t.start()
gobject.timeout_add(500, wait_migration, m)
gtk.main()
check_paths.check_and_possibly_create_paths() check_paths.check_and_possibly_create_paths()
Interface() Interface()