Welcome to mirror list, hosted at ThFree Co, Russian Federation.

dev.gajim.org/gajim/gajim-plugins.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJefry Lagrange <jefry.reyes@gmail.com>2012-10-28 22:45:00 +0400
committerJefry Lagrange <jefry.reyes@gmail.com>2012-10-28 22:45:00 +0400
commitf9271e98092880a04dc3ecb87554e391c498e0be (patch)
treea867e92718b9c592bd90afc7ae4ea2d6bd53b817 /file_sharing/fileshare_window.py
parent511b37dd911cc3fb30047a024db6f3f45b6da312 (diff)
initial commit for file_share plugin
Diffstat (limited to 'file_sharing/fileshare_window.py')
-rw-r--r--file_sharing/fileshare_window.py411
1 files changed, 411 insertions, 0 deletions
diff --git a/file_sharing/fileshare_window.py b/file_sharing/fileshare_window.py
new file mode 100644
index 0000000..a53491f
--- /dev/null
+++ b/file_sharing/fileshare_window.py
@@ -0,0 +1,411 @@
+import database
+import gtk
+import gobject
+from common import gajim
+from common import helpers
+from common.file_props import FilesProp
+import fshare
+import os
+import fshare_protocol
+import config
+
+class FileShareWindow(gtk.Window):
+
+ def __init__(self):
+ gtk.Window.__init__(self)
+ self.set_title('File Share')
+ self.connect('delete_event', self.delete_event)
+ self.set_position(gtk.WIN_POS_CENTER)
+ self.set_default_size(400, 400)
+ # Children
+ self.notebook = gtk.Notebook()
+ # Browse page
+ self.bt_search = gtk.Button('Search')
+ self.bt_search.connect('clicked', self.on_bt_search_clicked)
+ self.entry_search = gtk.Entry(max=0)
+ self.entry_search.set_size_request(300, -1)
+ self.exp_advance = gtk.Expander('Advance')
+ self.ts_search = gtk.TreeStore(gobject.TYPE_STRING)
+ self.tv_search = gtk.TreeView(self.ts_search)
+ self.tv_search.connect('row-expanded', self.row_expanded)
+ self.tv_search.connect('button-press-event',
+ self.on_treeview_button_press_event)
+ self.browse_popup = gtk.Menu()
+ mi_download = gtk.MenuItem('Download')
+ mi_property = gtk.MenuItem('Property')
+ mi_download.show()
+ mi_property.show()
+ mi_download.connect('activate', self.on_download_clicked)
+ self.browse_popup.append(mi_download)
+ self.browse_popup.append(mi_property)
+ self.browse_sw = gtk.ScrolledWindow()
+ self.browse_sw.add(self.tv_search)
+ self.tvcolumn_browse = gtk.TreeViewColumn('')
+ self.tv_search.append_column(self.tvcolumn_browse)
+ self.cell_browse = gtk.CellRendererText()
+ self.tvcolumn_browse.pack_start(self.cell_browse, True)
+ self.tvcolumn_browse.add_attribute(self.cell_browse, 'text', 0)
+ self.lbl_browse = gtk.Label('Browse')
+ self.browse_hbox = gtk.HBox()
+ self.browse_hbox2 = gtk.HBox()
+ self.browse_vbox = gtk.VBox()
+ self.browse_hbox.pack_start(self.entry_search, True, True, 10)
+ self.browse_hbox.pack_start(self.bt_search, False, False, 10)
+ self.browse_vbox.pack_start(self.browse_hbox, False, False, 10)
+ self.browse_vbox.pack_start(self.exp_advance, False, False, 10)
+ self.browse_vbox.pack_start(self.browse_sw, True, True, 10)
+ self.notebook.append_page(self.browse_vbox, self.lbl_browse)
+ # file references for tv_search
+ self.browse_fref = {}
+ # contact references for tv_search
+ self.browse_jid = {}
+ # Information of the files inserted in the treeview: name, size, etc
+ self.brw_file_info = {}
+ # dummy row children so that we can get expanders
+ self.empty_row_child = {}
+ # Manage page
+ self.bt_add_file = gtk.Button('Add file')
+ self.bt_add_file.connect('clicked', self.add_file)
+ self.bt_add_dir = gtk.Button('Add directory')
+ self.bt_add_dir.connect('clicked', self.add_directory)
+ self.bt_remove = gtk.Button('Remove')
+ self.bt_remove.connect('clicked', self.remove_file_clicked)
+ self.bt_remove_all = gtk.Button('Remove all')
+ self.bt_remove_all.connect('clicked', self.remove_all_clicked)
+ self.ts_contacts = gtk.TreeStore(gobject.TYPE_STRING)
+ self.cbb_contacts = gtk.ComboBoxEntry(self.ts_contacts)
+ self.cbb_contacts.connect('changed', self.__check_combo_edit)
+ cbb_entry = self.cbb_contacts.child
+ self.cbb_completion = gtk.EntryCompletion()
+ cbb_entry.set_completion(self.cbb_completion)
+ self.cbb_completion.set_model(self.ts_contacts)
+ self.cbb_completion.set_text_column(0)
+ self.bt_stophash = gtk.Button('Calculating hash')
+ self.lbl_manage = gtk.Label('Manage Shared Files')
+ self.ts_files = gtk.TreeStore(gobject.TYPE_STRING)
+ self.tv_files = gtk.TreeView(self.ts_files)
+ self.treeSelection_files = self.tv_files.get_selection()
+ self.treeSelection_files.connect('changed', self.row_selected)
+ self.manage_sw = gtk.ScrolledWindow()
+ self.manage_sw.add(self.tv_files)
+ self.tvcolumn = gtk.TreeViewColumn('')
+ self.tv_files.append_column(self.tvcolumn)
+ self.cell = gtk.CellRendererText()
+ self.tvcolumn.pack_start(self.cell, True)
+ self.tvcolumn.add_attribute(self.cell, 'text', 0)
+ self.pb_filehash = gtk.ProgressBar()
+ self.manage_hbox = gtk.HBox()
+ self.manage_hbox2 = gtk.HBox()
+ self.manage_vbox = gtk.VBox()
+ self.manage_vbox2 = gtk.VBox()
+ self.manage_hbox.pack_start(self.bt_stophash , False, False, 10)
+ self.manage_hbox.pack_start(self.pb_filehash, True, True, 10)
+ self.manage_hbox.set_sensitive(False)
+ self.manage_vbox.pack_start(self.cbb_contacts, False, False, 10)
+ self.manage_vbox.pack_start(self.manage_hbox, False, False, 10)
+ self.manage_hbox2.pack_start(self.manage_sw, True, True, 10)
+ self.manage_hbox2.pack_start(self.manage_vbox2, False, False, 10)
+ self.manage_vbox2.pack_start(self.bt_add_file, False, False, 10)
+ self.manage_vbox2.pack_start(self.bt_add_dir, False, False, 10)
+ self.manage_vbox2.pack_start(self.bt_remove, False, False, 10)
+ self.manage_vbox2.pack_start(self.bt_remove_all, False, False, 10)
+ self.manage_vbox2.set_sensitive(False)
+ self.manage_vbox.pack_start(self.manage_hbox2, True, True, 10)
+ self.notebook.append_page(self.manage_vbox, self.lbl_manage)
+ # Preferences page
+ self.lbl_pref = gtk.Label('Preferences')
+ self.entry_dir_pref = gtk.Entry(max=0)
+ self.entry_dir_pref.set_text(config.INCOMING_DIR)
+ self.bt_sel_dir_pref = gtk.Button('Select dir', gtk.STOCK_OPEN)
+ self.bt_sel_dir_pref.connect('clicked', self.on_bt_sel_dir_pref_clicked)
+ self.frm_dir_pref = gtk.Frame('Incoming files directory')
+ self.frm_dir_pref.set_shadow_type(gtk.SHADOW_IN)
+ self.pref_hbox = gtk.HBox()
+ self.pref_vbox = gtk.VBox()
+ self.pref_hbox.pack_start(self.entry_dir_pref, True, True, 10)
+ self.pref_hbox.pack_start(self.bt_sel_dir_pref, False, False, 10)
+ self.frm_dir_pref.add(self.pref_hbox)
+ self.pref_vbox.pack_start(self.frm_dir_pref, False, False, 10)
+ self.notebook.append_page(self.pref_vbox , self.lbl_pref)
+ self.add(self.notebook)
+ self.show_all()
+
+ def set_account(self, account):
+ self.account = account
+ # connect window to protocol
+ pro = fshare.FileSharePlugin.prohandler[self.account]
+ pro.set_window(self)
+
+ def add_file(self, widget):
+ dialog = gtk.FileChooserDialog('Add file to be shared', self,
+ gtk.FILE_CHOOSER_ACTION_OPEN,
+ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
+ gtk.STOCK_OPEN, gtk.RESPONSE_OK)
+ )
+ dialog.set_select_multiple(True)
+ response = dialog.run()
+ if response == gtk.RESPONSE_OK:
+ file_list = dialog.get_filenames()
+ self.add_items_tvcontacts(file_list)
+ dialog.destroy()
+
+ def add_directory(self, widget):
+ dialog = gtk.FileChooserDialog('Add directory to be shared', self,
+ gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
+ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
+ gtk.STOCK_OPEN, gtk.RESPONSE_ACCEPT)
+ )
+ response = dialog.run()
+ if response == gtk.RESPONSE_ACCEPT:
+ file_list = []
+ file_list.append(dialog.get_filename())
+ self.add_items_tvcontacts(file_list)
+ dialog.destroy()
+
+ def add_file_list(self, flist, treestore, fref = {}, root = None):
+ # file references to their in the treeStore
+ for f in flist:
+ # keeps track of the relative dir path
+ tail = ''
+ # keeps track of the parent row
+ parent = None
+ dirpath = f.split('/')
+ if len(dirpath) == 1:
+ # Top level file, it doesnt have parent, add it right away
+ fref[dirpath[0]] = treestore.insert(root,
+ 0,
+ (dirpath[0],)
+ )
+ else:
+ for dir_ in dirpath:
+ if tail + dir_ not in fref:
+ fref[tail + dir_] = treestore.append(
+ parent,
+ (dir_,)
+ )
+ parent = fref[tail + dir_]
+ tail = tail + dir_ + '/'
+ return fref
+
+ def __convert_date(self, epoch):
+ # Converts date-time from seconds from epoch to iso 8601
+ import time, datetime
+ ts = time.gmtime(epoch)
+ dt = datetime.datetime(ts.tm_year, ts.tm_mon, ts.tm_mday, ts.tm_hour,
+ ts.tm_min, ts.tm_sec)
+ return dt.isoformat()
+
+ def add_items_tvcontacts(self, file_list, parentdir = None, parent = None):
+ # TODO: execute this method inside of a thread
+ for f in file_list:
+ # Relative name to be used internally in the shared folders
+ relative_name = f.split('/')[-1]
+ if parentdir:
+ relative_name = parentdir + '/' + relative_name
+ short_name = relative_name.split('/')[-1]
+ if short_name[0] == '.':
+ # Return if it is a hidden file
+ return
+ if parent:
+ row = self.ts_files.append(parent, (short_name,))
+ else:
+ row = self.ts_files.insert(None, 0, (short_name,))
+ # File info
+ size = os.path.getsize(f)
+ is_dir = os.path.isdir(f)
+ mod_date = os.path.getmtime(f)
+ mod_date = self.__convert_date(mod_date)
+ # TODO: add hash
+ file_ = (f, relative_name, '', size, '', mod_date, is_dir)
+ requester = self.cbb_contacts.get_active_text()
+ try:
+ fid = database.add_file(self.account, requester, file_)
+ except Exception, e:
+ if e == 'Duplicated entry':
+ print 'Error: ' + e
+ continue
+ else:
+ raise Exception(e)
+ if is_dir:
+ tmpfl = os.listdir(f)
+ fl = []
+ for item in tmpfl:
+ fl.append(f + '/' + item)
+ self.add_items_tvcontacts(fl, relative_name, row)
+
+ def add_contact_browse(self, contact):
+ fjid = contact.get_full_jid()
+ jid = gajim.get_jid_without_resource(fjid)
+ contacts = gajim.contacts.get_contacts(self.account, jid)
+ for con in contacts:
+ if con.show in ('offline', 'error') and not \
+ con.supports(fshare_protocol.NS_FILE_SHARING):
+ break
+ cjid = con.get_full_jid()
+ r = self.ts_search.insert(None, 0,
+ (cjid, ))
+ self.browse_jid[cjid] = r
+ pro = fshare.FileSharePlugin.prohandler[self.account]
+ # Request list of files from peer
+ stanza = pro.request(cjid)
+ if pro.conn.connection:
+ pro.conn.connection.send(stanza)
+
+ def add_contact_manage(self, contact):
+ self.contacts_rows = []
+ self.cbb_contacts.grab_focus()
+ for c in gajim.contacts.iter_contacts(self.account):
+ jid = gajim.get_jid_without_resource(c.get_full_jid())
+ r = self.ts_contacts.insert(None, len(self.ts_contacts),
+ (jid, ))
+ if c.get_full_jid() == contact.get_full_jid():
+ self.cbb_contacts.set_active_iter(r)
+ self.contacts_rows.append(r)
+ self.manage_vbox2.set_sensitive(True)
+ self.bt_remove.set_sensitive(False)
+ self.add_file_list(database.get_files_name(self.account,
+ gajim.get_jid_without_resource(contact.get_full_jid())),
+ self.ts_files
+ )
+
+ def delete_event(self, widget, data=None):
+ fshare.FileSharePlugin.filesharewindow = {}
+ return False
+
+ def __check_combo_edit(self, widget, data=None):
+ self.ts_files.clear()
+ entry = self.cbb_contacts.child
+ contact = entry.get_text()
+ self.manage_vbox2.set_sensitive(False)
+ for i in self.contacts_rows:
+ # If the contact in the comboboxentry is include inside of the
+ # combobox
+ if contact == self.ts_contacts.get_value(i, 0):
+ self.add_file_list(database.get_files_name(self.account,
+ contact),
+ self.ts_files
+ )
+ self.manage_vbox2.set_sensitive(True)
+ self.bt_remove.set_sensitive(False)
+ break
+
+ def remove_file_clicked(self, widget, data=None):
+ entry = self.cbb_contacts.child
+ contact = entry.get_text()
+ sel = self.treeSelection_files.get_selected()
+ relative_name = self.ts_files.get_value(sel[1], 0)
+ self.ts_files.remove(sel[1])
+ database.delete(self.account, contact, relative_name)
+ widget.set_sensitive(False)
+
+ def remove_all_clicked(self, widget, data=None):
+ entry = self.cbb_contacts.child
+ contact = entry.get_text()
+ database.delete_all(self.account, contact)
+ self.ts_files.clear()
+
+ def row_selected(self, widget, data=None):
+ # When row is selected in tv_files
+ sel = self.treeSelection_files.get_selected()
+ if not sel[1]:
+ return
+ depth = self.ts_files.iter_depth(sel[1])
+ # Don't remove file and dirs that aren't at the root level
+ if depth == 0:
+ self.bt_remove.set_sensitive(True)
+ else:
+ self.bt_remove.set_sensitive(False)
+
+ def row_expanded(self, widget, iter_, path, data=None):
+ name = None
+ for key in self.empty_row_child:
+ parent = self.ts_search.iter_parent(self.empty_row_child[key])
+ p = self.ts_search.get_path(parent)
+ if p == path:
+ name = key
+ break
+ if name:
+ # if we found that the expanded row is the parent of the empty row
+ # remove it from the treestore and empty_row dictionary. Then ask
+ # peer for list of files of that directory
+ i = self.empty_row_child[name]
+ pro = fshare.FileSharePlugin.prohandler[self.account]
+ contact = self.get_contact_from_iter(self.ts_search, i)
+ contact = gajim.contacts.get_contact_with_highest_priority(
+ self.account,
+ contact )
+ stanza = pro.request(contact.get_full_jid(), name, isFile=False)
+ if pro.conn.connection:
+ pro.conn.connection.send(stanza)
+ self.ts_search.remove(i)
+ del self.empty_row_child[name]
+
+ def get_contact_from_iter(self, treestore, iter_):
+ toplevel = treestore.get_iter_root()
+ while toplevel:
+ if treestore.is_ancestor(toplevel, iter_):
+ return treestore.get_value(toplevel, 0)
+ toplevel = treestore.iter_next(toplevel)
+
+ def on_treeview_button_press_event(self, treeview, event):
+ if event.button == 3:
+ x = int(event.x)
+ y = int(event.y)
+ time = event.time
+ pthinfo = treeview.get_path_at_pos(x, y)
+ if pthinfo is not None:
+ path, col, cellx, celly = pthinfo
+ treeview.grab_focus()
+ treeview.set_cursor( path, col, 0)
+ treestore = treeview.get_model()
+ it = treestore.get_iter(path)
+ if treestore.iter_depth(it) != 0:
+ self.browse_popup.popup(None, None, None, event.button, time)
+ return True
+
+ def on_bt_search_clicked(self, widget, data=None):
+ pass
+
+ def on_download_clicked(self, widget, data=None):
+ tree, row = self.tv_search.get_selection().get_selected()
+ path = tree.get_path(row)
+ file_info = self.brw_file_info[path]
+ fjid = self.get_contact_from_iter(tree, row)
+ # Request the file
+ file_path = config.INCOMING_DIR + '/%s' % file_info[0]
+ sid = helpers.get_random_string_16()
+ new_file_props = FilesProp.getNewFileProp(self.account, sid)
+ new_file_props.file_name = file_path
+ print file_path
+ new_file_props.name = file_info[0]
+ new_file_props.desc = file_info[4]
+ new_file_props.size = file_info[2]
+ new_file_props.date = file_info[1]
+ new_file_props.hash_ = None if file_info[3] == '' else file_info[3]
+ new_file_props.type_ = 'r'
+ tsid = gajim.connections[self.account].start_file_transfer(fjid,
+ new_file_props,
+ True)
+ new_file_props.transport_sid = tsid
+ ft_window = gajim.interface.instances['file_transfers']
+ contact = gajim.contacts.get_contact_from_full_jid(self.account, fjid)
+ ft_window .add_transfer(self.account, contact, new_file_props)
+
+ def on_bt_sel_dir_pref_clicked(self, widget, data=None):
+ chooser = gtk.FileChooserDialog(title='Incoming files directory',
+ action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
+ buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,
+ gtk.STOCK_OPEN,gtk.RESPONSE_OK))
+ response = chooser.run()
+ if response == gtk.RESPONSE_OK:
+ file_name = chooser.get_filename()
+ self.entry_dir_pref.set_text(file_name)
+ config.set('incoming_dir', file_name)
+ chooser.destroy()
+
+
+if __name__ == "__main__":
+ f = FileShareWindow()
+ f.show()
+ gtk.main()
+