diff options
author | Ajay Garg <ajay@activitycentral.com> | 2012-09-18 08:22:42 (GMT) |
---|---|---|
committer | Ajay Garg <ajay@activitycentral.com> | 2012-09-18 08:22:42 (GMT) |
commit | bf9c09bc421a4ed2c0d38d0fca196091a02033c0 (patch) | |
tree | e3d4d80b81e20597eff6ecae45ba8ed7e1812cd1 | |
parent | 38d82aaf6d54bc7f9798950a6d064fd6ce6a767a (diff) |
sdxo#2334: Drag-and-Copy now works to- and from- locally mounted shares (except drag-and-copy to PEER-shares, as that is disallowed)
-rw-r--r-- | rpms/sugar/0130-1-to-N-feature-via-School-Server.patch | 240 |
1 files changed, 168 insertions, 72 deletions
diff --git a/rpms/sugar/0130-1-to-N-feature-via-School-Server.patch b/rpms/sugar/0130-1-to-N-feature-via-School-Server.patch index 1ef3dd9..47584a0 100644 --- a/rpms/sugar/0130-1-to-N-feature-via-School-Server.patch +++ b/rpms/sugar/0130-1-to-N-feature-via-School-Server.patch @@ -1,6 +1,6 @@ -From aa06134ada3e9022c680addddae4e6ce0a9ef1ed Mon Sep 17 00:00:00 2001 +From 865725f2c4a76b6a52267623ba6546954ad2dccc Mon Sep 17 00:00:00 2001 From: Ajay Garg <ajay@activitycentral.com> -Date: Tue, 18 Sep 2012 13:38:36 +0530 +Date: Tue, 18 Sep 2012 13:49:44 +0530 Subject: [sugar PATCH] 1-to-N-feature via Peer-to-Peer mechanism; and Via-School-Server mechanism. Organization: Sugar Labs Foundation Signed-off-by: Ajay Garg <ajay@activitycentral.com> @@ -9,18 +9,18 @@ Signed-off-by: Ajay Garg <ajay@activitycentral.com> src/jarabe/frame/frame.py | 3 + src/jarabe/intro/window.py | 12 + src/jarabe/journal/expandedentry.py | 24 ++- - src/jarabe/journal/journalactivity.py | 17 ++- + src/jarabe/journal/journalactivity.py | 17 +- src/jarabe/journal/journaltoolbox.py | 44 ++++- - src/jarabe/journal/model.py | 379 +++++++++++++++++++++++---------- - src/jarabe/journal/palettes.py | 284 ++++++++++++++++++++++--- - src/jarabe/journal/volumestoolbar.py | 94 ++++++--- + src/jarabe/journal/model.py | 388 +++++++++++++++++++++++---------- + src/jarabe/journal/palettes.py | 303 ++++++++++++++++++++++--- + src/jarabe/journal/volumestoolbar.py | 135 ++++++++---- src/jarabe/journal/webdavmanager.py | 172 ++++++++++----- src/jarabe/view/buddymenu.py | 45 ++++- src/jarabe/view/palettes.py | 35 +++- src/webdav/Connection.py | 11 +- src/webdav/WebdavClient.py | 16 +- src/webdav/davlib.py | 9 +- - 15 files changed, 880 insertions(+), 270 deletions(-) + 15 files changed, 929 insertions(+), 290 deletions(-) diff --git a/src/jarabe/frame/activitiestray.py b/src/jarabe/frame/activitiestray.py index 55e0c31..7cbeefb 100644 @@ -255,7 +255,7 @@ index 6b2494e..b1c0cac 100644 return self._selected_entries diff --git a/src/jarabe/journal/model.py b/src/jarabe/journal/model.py -index 422e947..7756f5c 100644 +index 422e947..1a47556 100644 --- a/src/jarabe/journal/model.py +++ b/src/jarabe/journal/model.py @@ -43,7 +43,7 @@ from sugar import dispatch @@ -277,7 +277,7 @@ index 422e947..7756f5c 100644 JOURNAL_METADATA_DIR = '.Sugar-Metadata' _datastore = None -@@ -66,6 +69,56 @@ updated = dispatch.Signal() +@@ -66,6 +69,65 @@ updated = dispatch.Signal() deleted = dispatch.Signal() @@ -302,16 +302,25 @@ index 422e947..7756f5c 100644 + return None + + -+def is_mount_point_for_school_server(mount_point): ++def _check_remote_sharing_mount_point(mount_point, share_type): + from jarabe.journal.journalactivity import get_journal -+ from jarabe.journal.volumestoolbar import SHARE_TYPE_SCHOOL_SERVER + + mount_point_button = get_journal().get_volumes_toolbar()._get_button_for_mount_point(mount_point) -+ if mount_point_button._share_type == SHARE_TYPE_SCHOOL_SERVER: ++ if mount_point_button._share_type == share_type: + return True + return False + + ++def is_mount_point_for_school_server(mount_point): ++ from jarabe.journal.volumestoolbar import SHARE_TYPE_SCHOOL_SERVER ++ return _check_remote_sharing_mount_point(mount_point, SHARE_TYPE_SCHOOL_SERVER) ++ ++ ++def is_mount_point_for_peer_share(mount_point): ++ from jarabe.journal.volumestoolbar import SHARE_TYPE_PEER ++ return _check_remote_sharing_mount_point(mount_point, SHARE_TYPE_PEER) ++ ++ +def extract_ip_address_or_dns_name_from_locally_mounted_remote_share_path(path): + """ + Path is of type :: @@ -334,7 +343,7 @@ index 422e947..7756f5c 100644 class _Cache(object): __gtype_name__ = 'model_Cache' -@@ -430,8 +483,8 @@ class InplaceResultSet(BaseResultSet): +@@ -430,8 +492,8 @@ class InplaceResultSet(BaseResultSet): class RemoteShareResultSet(object): @@ -345,7 +354,7 @@ index 422e947..7756f5c 100644 self._file_list = [] self.ready = dispatch.Signal() -@@ -464,7 +517,11 @@ class RemoteShareResultSet(object): +@@ -464,7 +526,11 @@ class RemoteShareResultSet(object): self._sort = query.get('order_by', ['+timestamp'])[0] def setup(self): @@ -358,7 +367,7 @@ index 422e947..7756f5c 100644 for metadata in metadata_list_complete: add_to_list = False -@@ -553,15 +610,8 @@ def _get_file_metadata(path, stat, fetch_preview=True): +@@ -553,15 +619,8 @@ def _get_file_metadata(path, stat, fetch_preview=True): metadata based on the file properties. """ @@ -375,7 +384,7 @@ index 422e947..7756f5c 100644 if 'filesize' not in metadata: if stat is not None: metadata['filesize'] = stat.st_size -@@ -582,17 +632,26 @@ def _get_file_metadata(path, stat, fetch_preview=True): +@@ -582,17 +641,26 @@ def _get_file_metadata(path, stat, fetch_preview=True): 'description': path} @@ -405,7 +414,7 @@ index 422e947..7756f5c 100644 filename + '.preview') if not os.path.exists(metadata_path): -@@ -670,7 +729,8 @@ def find(query_, page_size): +@@ -670,7 +738,8 @@ def find(query_, page_size): Regex Matching is used, to ensure that the mount-point is an IP-Address. """ @@ -415,7 +424,7 @@ index 422e947..7756f5c 100644 else: """ For Documents/Shares/Mounted-Drives. -@@ -678,56 +738,13 @@ def find(query_, page_size): +@@ -678,56 +747,13 @@ def find(query_, page_size): return InplaceResultSet(query, page_size, mount_points[0]) @@ -472,7 +481,7 @@ index 422e947..7756f5c 100644 stat = None metadata = _get_file_metadata(object_id, stat) -@@ -812,7 +829,21 @@ def delete(object_id): +@@ -812,7 +838,21 @@ def delete(object_id): def copy(metadata, mount_point): """Copies an object to another mount point """ @@ -494,7 +503,7 @@ index 422e947..7756f5c 100644 if mount_point == '/' and metadata['icon-color'] == '#000000,#ffffff': client = gconf.client_get_default() metadata['icon-color'] = client.get_string('/desktop/sugar/user/color') -@@ -823,7 +854,7 @@ def copy(metadata, mount_point): +@@ -823,7 +863,7 @@ def copy(metadata, mount_point): metadata['mountpoint'] = mount_point del metadata['uid'] @@ -503,7 +512,7 @@ index 422e947..7756f5c 100644 def write(metadata, file_path='', update_mtime=True, transfer_ownership=True): -@@ -845,27 +876,105 @@ def write(metadata, file_path='', update_mtime=True, transfer_ownership=True): +@@ -845,27 +885,105 @@ def write(metadata, file_path='', update_mtime=True, transfer_ownership=True): object_id = _get_datastore().create(dbus.Dictionary(metadata), file_path, transfer_ownership) @@ -512,7 +521,7 @@ index 422e947..7756f5c 100644 - from jarabe.journal.journalactivity import get_mount_point - if get_mount_point() == get_documents_path(): - metadata['mountpoint'] = get_documents_path() -+ elif metadata.get('mountpoint', '/') == WEBDAV_MOUNT_POINT: ++ elif metadata.get('mountpoint', '/') == (WEBDAV_MOUNT_POINT + SCHOOL_SERVER_IP_ADDRESS_OR_DNS_NAME): + filename = metadata['title'] + + ip_address_or_dns_name = SCHOOL_SERVER_IP_ADDRESS_OR_DNS_NAME @@ -620,7 +629,7 @@ index 422e947..7756f5c 100644 old_fname + '.preview')] for ofile in old_files: if os.path.exists(ofile): -@@ -876,41 +985,32 @@ def _rename_entry_on_external_device(file_path, destination_path, +@@ -876,41 +994,32 @@ def _rename_entry_on_external_device(file_path, destination_path, 'for file=%s', ofile, old_fname) @@ -635,29 +644,29 @@ index 422e947..7756f5c 100644 - This function handles renames of an entry on the - external device and avoids name collisions. Renames are - handled failsafe. +- +- """ +- if 'uid' in metadata and os.path.exists(metadata['uid']): +- file_path = metadata['uid'] +def _write_metadata_and_preview_files_and_return_file_paths(metadata, + file_name): + metadata_copy = metadata.copy() + metadata_copy.pop('mountpoint', None) + metadata_copy.pop('uid', None) -- """ -- if 'uid' in metadata and os.path.exists(metadata['uid']): -- file_path = metadata['uid'] - - if not file_path or not os.path.exists(file_path): - raise ValueError('Entries without a file cannot be copied to ' - 'removable devices') + +- if not metadata.get('title'): +- metadata['title'] = _('Untitled') +- file_name = get_file_name(metadata['title'], metadata['mime_type']) + # For copying to School-Server, we need to retain this property. + # Else wise, I have no idea why this property is being removed !! -+ if (metadata.get('mountpoint', '/') != WEBDAV_MOUNT_POINT) and \ ++ if (metadata.get('mountpoint', '/') != (WEBDAV_MOUNT_POINT + SCHOOL_SERVER_IP_ADDRESS_OR_DNS_NAME)) and \ + (metadata.get('mountpoint', '/') != LOCAL_SHARES_MOUNT_POINT): + metadata_copy.pop('filesize', None) -- if not metadata.get('title'): -- metadata['title'] = _('Untitled') -- file_name = get_file_name(metadata['title'], metadata['mime_type']) -- - destination_path = os.path.join(metadata['mountpoint'], file_name) - if destination_path != file_path: - file_name = get_unique_file_name(metadata['mountpoint'], file_name) @@ -684,7 +693,7 @@ index 422e947..7756f5c 100644 metadata_dir_path = os.path.join(metadata['mountpoint'], JOURNAL_METADATA_DIR) -@@ -939,25 +1039,64 @@ def _write_entry_on_external_device(metadata, file_path): +@@ -939,25 +1048,64 @@ def _write_entry_on_external_device(metadata, file_path): os.close(fh) os.rename(fn, os.path.join(metadata_dir_path, preview_fname)) @@ -707,19 +716,8 @@ index 422e947..7756f5c 100644 + file_name = get_file_name(metadata['title'], metadata['mime_type']) + _write_metadata_and_preview_files_and_return_file_paths(metadata, + file_name) - -- # For "Shares" folder, we need to set the permissions of the newly -- # copied file to 0777, else it will not be accessible by "httpd" -- # service. -- if metadata['mountpoint'] == '/var/www/web1/web': -- fd = os.open(destination_path, os.O_RDONLY) -- os.fchmod(fd, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) -- os.close(fd) - -- metadata_file_path = os.path.join(metadata_dir_path, file_name + '.metadata') -- fd = os.open(metadata_file_path, os.O_RDONLY) -- os.fchmod(fd, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) -- os.close(fd) ++ ++ +def _write_entry_on_external_device(metadata, file_path, + transfer_ownership): + """Create and update an entry copied from the @@ -732,7 +730,7 @@ index 422e947..7756f5c 100644 + This function handles renames of an entry on the + external device and avoids name collisions. Renames are + handled failsafe. - ++ + """ + if 'uid' in metadata and os.path.exists(metadata['uid']): + file_path = metadata['uid'] @@ -744,17 +742,28 @@ index 422e947..7756f5c 100644 + if not metadata.get('title'): + metadata['title'] = _('Untitled') + file_name = get_file_name(metadata['title'], metadata['mime_type']) -+ + +- # For "Shares" folder, we need to set the permissions of the newly +- # copied file to 0777, else it will not be accessible by "httpd" +- # service. +- if metadata['mountpoint'] == '/var/www/web1/web': +- fd = os.open(destination_path, os.O_RDONLY) +- os.fchmod(fd, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) +- os.close(fd) + destination_path = os.path.join(metadata['mountpoint'], file_name) + if destination_path != file_path: + file_name = get_unique_file_name(metadata['mountpoint'], file_name) + destination_path = os.path.join(metadata['mountpoint'], file_name) + clean_name, extension_ = os.path.splitext(file_name) + metadata['title'] = clean_name -+ + +- metadata_file_path = os.path.join(metadata_dir_path, file_name + '.metadata') +- fd = os.open(metadata_file_path, os.O_RDONLY) +- os.fchmod(fd, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) +- os.close(fd) + _write_metadata_and_preview_files_and_return_file_paths(metadata, + file_name) -+ + + if (os.path.dirname(destination_path) == os.path.dirname(file_path)) or \ + (transfer_ownership == True): + _rename_entry_on_external_device(file_path, destination_path) @@ -764,7 +773,7 @@ index 422e947..7756f5c 100644 object_id = destination_path created.send(None, object_id=object_id) -@@ -1013,7 +1152,11 @@ def is_editable(metadata): +@@ -1013,7 +1161,11 @@ def is_editable(metadata): # called, upon an entry in the context of a singular # mount-point. from jarabe.journal.journalactivity import get_mount_point @@ -778,7 +787,7 @@ index 422e947..7756f5c 100644 def get_documents_path(): diff --git a/src/jarabe/journal/palettes.py b/src/jarabe/journal/palettes.py -index 66dcadc..bdd09bd 100644 +index 66dcadc..94922ec 100644 --- a/src/jarabe/journal/palettes.py +++ b/src/jarabe/journal/palettes.py @@ -30,6 +30,7 @@ import gio @@ -1014,7 +1023,27 @@ index 66dcadc..bdd09bd 100644 return False finally: self._set_bundle_installation_allowed(True) -@@ -751,6 +842,30 @@ class BaseCopyMenuItem(MenuItem, ActionItem): +@@ -725,7 +816,7 @@ class BaseCopyMenuItem(MenuItem, ActionItem): + } + + def __init__(self, metadata_list, label, show_editing_alert, +- show_progress_info_alert, batch_mode): ++ show_progress_info_alert, batch_mode, mount_point): + MenuItem.__init__(self, label) + ActionItem.__init__(self, label, metadata_list, show_editing_alert, + show_progress_info_alert, batch_mode, +@@ -733,6 +824,10 @@ class BaseCopyMenuItem(MenuItem, ActionItem): + need_to_popup_options=False, + operate_on_deselected_entries=False, + show_not_completed_ops_info=True) ++ self._mount_point = mount_point ++ ++ def get_mount_point(self): ++ return self._mount_point + + def _get_actionable_signal(self): + return 'activate' +@@ -751,6 +846,30 @@ class BaseCopyMenuItem(MenuItem, ActionItem): def _get_info_alert_title(self): return _('Copying') @@ -1045,9 +1074,14 @@ index 66dcadc..bdd09bd 100644 class VolumeMenu(BaseCopyMenuItem): def __init__(self, metadata_list, label, mount_point, -@@ -761,9 +876,10 @@ class VolumeMenu(BaseCopyMenuItem): - show_progress_info_alert, batch_mode) - self._mount_point = mount_point +@@ -758,12 +877,13 @@ class VolumeMenu(BaseCopyMenuItem): + batch_mode): + BaseCopyMenuItem.__init__(self, metadata_list, label, + show_editing_alert, +- show_progress_info_alert, batch_mode) +- self._mount_point = mount_point ++ show_progress_info_alert, batch_mode, ++ mount_point) - def _operate(self, metadata): + def _proceed_with_copy(self, metadata): @@ -1057,8 +1091,12 @@ index 66dcadc..bdd09bd 100644 if not self._metadata_copy_valid(metadata, self._mount_point): return False -@@ -780,7 +896,7 @@ class ClipboardMenu(BaseCopyMenuItem): - batch_mode) +@@ -777,10 +897,10 @@ class ClipboardMenu(BaseCopyMenuItem): + BaseCopyMenuItem.__init__(self, metadata_list, _('Clipboard'), + show_editing_alert, + show_progress_info_alert, +- batch_mode) ++ batch_mode, None) self._temp_file_path_list = [] - def _operate(self, metadata): @@ -1066,9 +1104,13 @@ index 66dcadc..bdd09bd 100644 if not self._file_path_valid(metadata): return False -@@ -813,9 +929,10 @@ class DocumentsMenu(BaseCopyMenuItem): +@@ -811,11 +931,13 @@ class DocumentsMenu(BaseCopyMenuItem): + BaseCopyMenuItem.__init__(self, metadata_list, _('Documents'), + show_editing_alert, show_progress_info_alert, - batch_mode) +- batch_mode) ++ batch_mode, ++ model.get_documents_path()) - def _operate(self, metadata): + def _proceed_with_copy(self, metadata): @@ -1078,7 +1120,7 @@ index 66dcadc..bdd09bd 100644 if not self._metadata_copy_valid(metadata, model.get_documents_path()): return False -@@ -824,10 +941,41 @@ class DocumentsMenu(BaseCopyMenuItem): +@@ -824,24 +946,119 @@ class DocumentsMenu(BaseCopyMenuItem): self._post_operate_per_metadata_per_action(metadata) @@ -1089,7 +1131,8 @@ index 66dcadc..bdd09bd 100644 + BaseCopyMenuItem.__init__(self, metadata_list, _('Local Shares'), + show_editing_alert, + show_progress_info_alert, -+ batch_mode) ++ batch_mode, ++ model.LOCAL_SHARES_MOUNT_POINT) + + def _proceed_with_copy(self, metadata): + if not self._file_path_valid(metadata): @@ -1121,8 +1164,10 @@ index 66dcadc..bdd09bd 100644 + BaseCopyMenuItem.__init__(self, metadata_list, _('School Server'), show_editing_alert, show_progress_info_alert, - batch_mode) -@@ -835,13 +983,75 @@ class SharesMenu(BaseCopyMenuItem): +- batch_mode) ++ batch_mode, ++ model.WEBDAV_MOUNT_POINT + model.SCHOOL_SERVER_IP_ADDRESS_OR_DNS_NAME) + def _operate(self, metadata): if not self._file_path_valid(metadata): return False @@ -1160,7 +1205,7 @@ index 66dcadc..bdd09bd 100644 + if not self._metadata_copy_valid(metadata, - '/var/www/web1/web'): -+ model.WEBDAV_MOUNT_POINT): ++ model.WEBDAV_MOUNT_POINT + model.SCHOOL_SERVER_IP_ADDRESS_OR_DNS_NAME): return False # This is sync-operation. Call the post-operation now. @@ -1199,7 +1244,7 @@ index 66dcadc..bdd09bd 100644 class FriendsMenu(gtk.Menu): __gtype_name__ = 'JournalFriendsMenu' -@@ -970,12 +1180,24 @@ class CopyMenuHelper(gtk.Menu): +@@ -970,12 +1187,24 @@ class CopyMenuHelper(gtk.Menu): menu.append(documents_menu) documents_menu.show() @@ -1228,7 +1273,7 @@ index 66dcadc..bdd09bd 100644 documents_menu.connect('volume-error', self.__volume_error_cb) menu.append(documents_menu) diff --git a/src/jarabe/journal/volumestoolbar.py b/src/jarabe/journal/volumestoolbar.py -index c24475d..07b178f 100644 +index c24475d..29a8619 100644 --- a/src/jarabe/journal/volumestoolbar.py +++ b/src/jarabe/journal/volumestoolbar.py @@ -37,7 +37,6 @@ from sugar.graphics.palette import Palette @@ -1374,7 +1419,58 @@ index c24475d..07b178f 100644 self.hide() break; -@@ -478,6 +505,7 @@ class DirectoryButton(BaseButton): +@@ -379,23 +406,36 @@ class BaseButton(RadioToolButton): + + def _drag_data_received_cb(self, widget, drag_context, x, y, + selection_data, info, timestamp): ++ # Disallow copying to mounted-shares for peers. ++ if (model.is_mount_point_for_locally_mounted_remote_share(self.mount_point)) and \ ++ (model.is_mount_point_for_peer_share(self.mount_point)): ++ from jarabe.journal.journalactivity import get_journal ++ ++ journal = get_journal() ++ journal._show_alert(_('Entries cannot be copied to Peer-Shares.'), _('Error')) ++ return ++ + object_id = selection_data.data + metadata = model.get(object_id) +- file_path = model.get_file(metadata['uid']) +- if not file_path or not os.path.exists(file_path): +- logging.warn('Entries without a file cannot be copied.') +- self.emit('volume-error', +- _('Entries without a file cannot be copied.'), +- _('Warning')) +- return + +- try: +- model.copy(metadata, self.mount_point) +- except IOError, e: +- logging.exception('Error while copying the entry. %s', e.strerror) +- self.emit('volume-error', +- _('Error while copying the entry. %s') % e.strerror, +- _('Error')) ++ from jarabe.journal.palettes import CopyMenu, get_copy_menu_helper ++ copy_menu_helper = get_copy_menu_helper() ++ ++ dummy_copy_menu = CopyMenu() ++ copy_menu_helper.insert_copy_to_menu_items(dummy_copy_menu, ++ [metadata], ++ False, ++ False, ++ False) ++ ++ # Now, activate the menuitem, whose mount-point matches the ++ # mount-point of the button, upon whom the item has been ++ # dragged. ++ children_menu_items = dummy_copy_menu.get_children() ++ for child in children_menu_items: ++ if child.get_mount_point() == self.mount_point: ++ child.activate() ++ return + + + class VolumeButton(BaseButton): +@@ -478,6 +518,7 @@ class DirectoryButton(BaseButton): def __init__(self, dir_path, icon_name): BaseButton.__init__(self, mount_point=dir_path) @@ -1382,7 +1478,7 @@ index c24475d..07b178f 100644 self.props.named_icon = icon_name -@@ -488,16 +516,22 @@ class DirectoryButton(BaseButton): +@@ -488,16 +529,22 @@ class DirectoryButton(BaseButton): class RemoteSharesButton(BaseButton): @@ -1391,14 +1487,14 @@ index c24475d..07b178f 100644 + def __init__(self, primary_text, ip_address_or_dns_name, color, + share_type): + BaseButton.__init__(self, mount_point=(model.WEBDAV_MOUNT_POINT + ip_address_or_dns_name)) ++ ++ self._primary_text = primary_text ++ self._ip_address_or_dns_name = ip_address_or_dns_name - self._buddy = buddy - self.props.named_icon = 'emblem-neighborhood-shared' - self.props.xo_color = buddy.props.color - self._buddy_ip_address = buddy.props.ip_address -+ self._primary_text = primary_text -+ self._ip_address_or_dns_name = ip_address_or_dns_name -+ + if share_type == SHARE_TYPE_PEER: + self.props.named_icon = 'emblem-neighborhood-shared' + elif share_type == SHARE_TYPE_SCHOOL_SERVER: |