Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send a file to multiple friends: Fixes #1471 #681

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 53 additions & 45 deletions src/jarabe/journal/palettes.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,17 @@
from sugar3.graphics.alert import Alert
from sugar3 import mime
from sugar3 import profile
from sugar3.graphics.popwindow import PopWindow
from sugar3.graphics.toolbutton import ToolButton

from jarabe.model import friends
from jarabe.model import filetransfer
from jarabe.model import mimeregistry
from jarabe.journal import misc
from jarabe.journal import model
from jarabe.journal import journalwindow
from jarabe.webservice import accountsmanager
from jarabe.journal.misc import get_mount_color
from jarabe.view.friendlistview import FriendListView


class ObjectPalette(Palette):
Expand Down Expand Up @@ -125,9 +127,7 @@ def __init__(self, journalactivity, metadata, detail=False):
self.menu.append(menu_item)
menu_item.show()

friends_menu = FriendsMenu()
friends_menu.connect('friend-selected', self.__friend_selected_cb)
menu_item.set_submenu(friends_menu)
menu_item.connect('activate', self.__friendlist_popup_cb)

if detail is True:
menu_item = MenuItem(_('View Details'), 'go-right')
Expand All @@ -143,6 +143,9 @@ def __init__(self, journalactivity, metadata, detail=False):
def __get_uid_list_cb(self):
return [self._metadata['uid']]

def __friend_activate_cb(self, menu_item):
FriendListView()

def __start_activate_cb(self, menu_item):
misc.resume(self._metadata,
alert_window=journalwindow.get_journal_window())
Expand Down Expand Up @@ -183,7 +186,7 @@ def __detail_activate_cb(self, menu_item):
def __volume_error_cb(self, menu_item, message, severity):
self.emit('volume-error', message, severity)

def __friend_selected_cb(self, menu_item, buddy):
def __friend_selected_cb(self, menu_item, buddies):
logging.debug('__friend_selected_cb')
file_name = model.get_file(self._metadata['uid'])

Expand All @@ -201,15 +204,58 @@ def __friend_selected_cb(self, menu_item, buddy):
if not mime_type:
mime_type = mime.get_for_file(file_name)

filetransfer.start_transfer(buddy, file_name, title, description,
mime_type)
for buddy in buddies:
filetransfer.start_transfer(buddy, file_name, title, description,
mime_type)

def popup(self, immediate=False, state=None):
if self._journalactivity.get_list_view().is_dragging():
return

Palette.popup(self, immediate)

def __friendlist_popup_cb(self, menu_item):
pop_up = FriendListPopup()
pop_up.connect('friend-selected', self.__friend_selected_cb)


class FriendListPopup(PopWindow):
__gtype_name__ = 'FriendListPopup'

__gsignals__ = {
'friend-selected': (GObject.SignalFlags.RUN_FIRST, None,
([object])),
}

def __init__(self):
PopWindow.__init__(self, True)
self.view = FriendListView()
self._scrolled_window = Gtk.ScrolledWindow()
self._scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC,
Gtk.PolicyType.AUTOMATIC)

self._scrolled_window.add(self.view)
width, height = PopWindow.FULLSCREEN
self.set_size_request(width*1/3, height*2/3)
self.modify_fg(Gtk.StateType.NORMAL,
style.COLOR_BLACK.get_gdk_color())
self.get_vbox().pack_start(self._scrolled_window, True, True, 0)
self.get_title_box().props.title = 'Send to'
self._scrolled_window.show()
self.view.show()
self.show()

ok_button = ToolButton(icon_name='document-send')
self.get_title_box().add_widget(ok_button, False, -1)
ok_button.connect('clicked', self.__send_clicked_cb)
ok_button.show()

def __send_clicked_cb(self, button):
model = self.view.get_model()
selected = model.get_selected()
self.emit('friend-selected', selected)
self.destroy()


class CopyMenu(Gtk.Menu):
__gtype_name__ = 'JournalCopyMenu'
Expand Down Expand Up @@ -451,44 +497,6 @@ def __clipboard_clear_func_cb(self, clipboard, data):
self._temp_file_path = None


class FriendsMenu(Gtk.Menu):
__gtype_name__ = 'JournalFriendsMenu'

__gsignals__ = {
'friend-selected': (GObject.SignalFlags.RUN_FIRST, None,
([object])),
}

def __init__(self):
Gtk.Menu.__init__(self)

if filetransfer.file_transfer_available():
friends_model = friends.get_model()
for friend in friends_model:
if friend.is_present():
menu_item = MenuItem(text_label=friend.get_nick(),
icon_name='computer-xo',
xo_color=friend.get_color())
menu_item.connect('activate', self.__item_activate_cb,
friend)
self.append(menu_item)
menu_item.show()

if not self.get_children():
menu_item = MenuItem(_('No friends present'))
menu_item.set_sensitive(False)
self.append(menu_item)
menu_item.show()
else:
menu_item = MenuItem(_('No valid connection found'))
menu_item.set_sensitive(False)
self.append(menu_item)
menu_item.show()

def __item_activate_cb(self, menu_item, friend):
self.emit('friend-selected', friend)


class StartWithMenu(Gtk.Menu):
__gtype_name__ = 'JournalStartWithMenu'

Expand Down
2 changes: 2 additions & 0 deletions src/jarabe/view/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ sugar_PYTHON = \
buddymenu.py \
cursortracker.py \
customizebundle.py \
friendlistmodel.py \
friendlistview.py \
gesturehandler.py \
keyhandler.py \
launcher.py \
Expand Down
67 changes: 67 additions & 0 deletions src/jarabe/view/friendlistmodel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Copyright (C) 2016, Abhijit Patel
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

import logging

from gi.repository import GObject
from gi.repository import Gtk
from jarabe.model import friends


class FriendListModel(GObject.GObject):
__gtype_name__ = 'FriendListModel'

COLUMN_SELECT = 0
COLUMN_XO_COLOR = 1
COLUMN_NICK = 2
COLUMN_FRIEND = 3

_COLUMN_TYPES = {
COLUMN_SELECT: bool,
COLUMN_XO_COLOR: object,
COLUMN_NICK: str,
COLUMN_FRIEND: object
}

def __init__(self):
GObject.GObject.__init__(self)

self.friend_list = friends.get_model()
self._selected = []

self._list_store = Gtk.ListStore(bool, object, str, object)

for friend in self.friend_list:
if friend.get_handle() is not None:
nick = friend.get_nick()
color = friend.get_color()
row = (False, color, nick, friend)
self._list_store.append(row)

def get_selected(self):
return self._selected

def get_liststore(self):
return self._list_store

def is_selected(self, friend):
return friend in self._selected

def set_selected(self, friend, value):
if value:
self._selected.append(friend)
else:
self._selected.remove(friend)
130 changes: 130 additions & 0 deletions src/jarabe/view/friendlistview.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Copyright (C) 2016, Abhijit Patel
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

import logging

from gi.repository import GObject
from gi.repository import Gtk

from sugar3.graphics import style
from sugar3.graphics.icon import CellRendererIcon

from jarabe.view.friendlistmodel import FriendListModel


class FriendListView(Gtk.TreeView):
__gtype_name__ = 'FriendListView'

def __init__(self):
Gtk.TreeView.__init__(self)

self._model = FriendListModel()
self.set_model(self._model.get_liststore())
selection = self.get_selection()
selection.set_mode(Gtk.SelectionMode.NONE)

cell_select = Gtk.CellRendererToggle()
cell_select.connect('toggled', self.__cell_select_toggled_cb)
cell_select.props.activatable = True
cell_select.props.xpad = style.DEFAULT_PADDING
cell_select.props.indicator_size = style.zoom(26)

column = Gtk.TreeViewColumn()
column.props.sizing = Gtk.TreeViewColumnSizing.FIXED
column.props.fixed_width = style.GRID_CELL_SIZE
column.pack_start(cell_select, True)
column.set_cell_data_func(cell_select, self.__select_set_data_cb)
self.append_column(column)

buddies_column = Gtk.TreeViewColumn()
buddies_column.props.sizing = Gtk.TreeViewColumnSizing.FIXED
self.append_column(buddies_column)

cell_icon = CellRendererBuddy()
cell_icon.props.sensitive = False
buddies_column.pack_start(cell_icon, True)
buddies_column.props.fixed_width += cell_icon.props.width
buddies_column.add_attribute(cell_icon,
'xo-color',
FriendListModel.COLUMN_XO_COLOR)
buddies_column.set_cell_data_func(cell_icon,
self.__buddies_set_data_cb)
self.append_column(buddies_column)

self.cell_title = Gtk.CellRendererText()
self.cell_title.props.ellipsize = style.ELLIPSIZE_MODE_DEFAULT
self.cell_title.props.ellipsize_set = True

self._title_column = Gtk.TreeViewColumn()
self._title_column.props.sizing = Gtk.TreeViewColumnSizing.FIXED
self._title_column.props.expand = True
self._title_column.props.clickable = False
self._title_column.pack_start(self.cell_title, True)
self._title_column.add_attribute(self.cell_title, 'markup',
FriendListModel.COLUMN_NICK)
self.append_column(self._title_column)

def get_model(self):
return self._model

def __select_set_data_cb(self, column, cell, tree_model, tree_iter,
data):
logging.debug('select_set_data_cb')
friend = tree_model[tree_iter]

if friend is None:
return
cell.props.active = \
self._model.is_selected(friend[FriendListModel.COLUMN_FRIEND])

def __cell_select_toggled_cb(self, cell, path):
logging.debug('cell_select_toggled_cb')
friend = self._model.get_liststore()[path]
if friend is None:
return
self._model.set_selected(friend[FriendListModel.COLUMN_FRIEND],
not cell.get_active())
cell.props.active = \
self._model.is_selected(friend[FriendListModel.COLUMN_FRIEND])

def __buddies_set_data_cb(self, column, cell, tree_model, tree_iter,
data):
friend = tree_model[tree_iter]
cell.props.xo_color = friend[FriendListModel.COLUMN_XO_COLOR]


class CellRendererBuddy(CellRendererIcon):
__gtype_name__ = 'CellRendererBuddy'

def __init__(self):
CellRendererIcon.__init__(self)

self.props.width = style.STANDARD_ICON_SIZE
self.props.height = style.STANDARD_ICON_SIZE
self.props.size = style.STANDARD_ICON_SIZE
self.props.mode = Gtk.CellRendererMode.ACTIVATABLE
self.props.icon_name = 'computer-xo'
self.nick = None

def set_buddy(self, buddy):
if buddy is None:
self.props.icon_name = None
self.nick = None
else:
self.nick, xo_color = buddy
self.props.xo_color = xo_color

buddy = GObject.property(type=object, setter=set_buddy)