Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- # Insync Nautilus Plugin
- #
- # Authors
- # Brett Hartshorn <brett@insynchq.com>
- # Luis Manuel R. Pugoy <lpugoy@insynchq.com>
- #
- # Copyright Insynchq Pte. Ltd., ("Insync") | http://www.insynchq.com
- # License: GNU GPL v2
- DEV_MODE = False
- import json
- import os
- import socket
- import sys
- import urllib
- from gi.repository import GObject
- GTK3 = False
- try:
- from gi.repository import Nautilus
- GTK3 = True # this might not be true
- except:
- print('WARN - using Nautilus2 wrapper')
- import nautilus as Nautilus # Nautilus2
- if GTK3:
- # http://python-gtk-3-tutorial.readthedocs.org/en/latest/drag_and_drop.html
- from gi.repository import Gtk
- from gi.repository import Gdk
- (TARGET_ENTRY_TEXT, TARGET_ENTRY_PIXBUF) = range(2)
- (COLUMN_TEXT, COLUMN_PIXBUF) = range(2)
- DRAG_ACTION = Gdk.DragAction.COPY
- print(Nautilus)
- if __name__ == '__main__': ## this is only for testing ##
- if '--install-local' in sys.argv:
- ## Nautilus2 is no longer supported ##
- #if os.path.isdir( os.path.expanduser('~/.nautilus') ):
- # path = os.path.expanduser('~/.nautilus/python-extensions')
- # if not os.path.isdir(path): os.makedirs( path )
- # os.system('cp -v %s ~/.nautilus/python-extensions/.' %__file__)
- ## Nautilus3 ##
- path = os.path.expanduser('~/.local/share/nautilus-python/extensions')
- if not os.path.isdir(path):
- os.makedirs(path)
- os.system('cp -v %s ~/.local/share/nautilus-python/extensions/.' %__file__)
- else:
- os.system('cp -v %s /usr/share/nautilus-python/extensions/.' %__file__)
- os.system('nautilus -q')
- sys.exit()
- print('Insync Nautilus Plugin')
- FS_ENCODING = sys.getfilesystemencoding() # C is 'ANSI_X3.4-1968'
- def ipc_insync(**kw):
- data = json.dumps(kw)
- socket_file = u'/tmp/insync%r.sock' % os.getuid()
- if not os.path.exists(socket_file):
- if DEV_MODE:
- print('WARN: insync socket not found')
- return None
- sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- sock.settimeout(0.1)
- try:
- sock.connect(socket_file)
- sock.send(data)
- res = sock.recv(4096)
- sock.close()
- except:
- return None
- if res.strip():
- return json.loads(res.strip())
- else:
- return None
- _EMBLEM_KEYS = {
- 'SYNCED': 'emblem-insync-synced',
- 'SYNCING': 'emblem-insync-syncing',
- 'ERROR': 'emblem-insync-error',
- 'DES_ERROR': 'emblem-insync-des-error',
- 'DES_SYNCING': 'emblem-insync-syncing',
- }
- class InsyncExtension(GObject.GObject, Nautilus.MenuProvider, Nautilus.InfoProvider):
- '''
- see: /usr/share/doc/python-nautilus/examples/
- 1. nautilus.ColumnProvider - It exposes a single function get_columns . This function has to return a sequence of nautilus.Column objects.
- 2. nautilus.InfoProvider - Exposes a single function update_file_info with a file as an argument.
- 3. nautilus.LocationWidgetProvider - Exposes a single function get_widget, return some gtk widget near the location bar.
- 4. nautilus.MenuProvider - Probably the most used interface. It exposes three functions :
- get_file_items, get_background_items and get_toolbar_items . The first two functions determine the entries that appear in the context menu. The difference is that get_background_items is usually called for a folder.
- The last function is used for toolbar items hence you must name the icon parameter of the menuItem.
- 5. nautilus.PropertyPageProvider - Exposes get_property_pages function where you reture one or more "pages" or tabs.
- '''
- def __init__(self):
- print('[__init__ insync plugin]', self)
- def get_background_items(self, window, folder):
- '''
- This method needs to be defined to avoid this warning:
- ** (nautilus:2913): CRITICAL **: nautilus_menu_provider_get_background_items: assertion
- `NAUTILUS_IS_MENU_PROVIDER (provider)' failed
- '''
- #print('background items', window, folder)
- return None
- def get_file_items(self, window, files):
- if DEV_MODE:
- print('get file items', files)
- if len(files) != 1:
- # TODO what can we do with mutiple files here
- return None
- file = files[0]
- if file.get_uri_scheme() != 'file':
- return None
- path = urllib.unquote(file.get_uri()[len('file://'):])
- path = unicode(path, FS_ENCODING)
- if DEV_MODE:
- print path
- is_dir = os.path.isdir(path)
- cm_info = ipc_insync(command='CONTEXT-MENU-ITEMS', full_path=path)
- if cm_info:
- title, cm_items = cm_info
- tip = 'Insync folder actions' if is_dir else 'Insync file actions'
- item = Nautilus.MenuItem(
- name=title,
- label=title,
- tip=tip,
- icon='insync'
- )
- sub_menu = Nautilus.Menu()
- item.set_submenu(sub_menu)
- sep_id = 0
- for text, cmd in cm_items:
- if text == 'separator':
- text = u'\u2015' * 10
- name = 'separator:' + str(sep_id)
- sep_id += 1
- else:
- name = text
- menu_item = Nautilus.MenuItem(name=name, label=text, tip=text)
- if cmd:
- menu_item.connect('activate', self.do_action, file, cmd)
- else:
- menu_item.sensitive = False
- sub_menu.append_item(menu_item)
- return [item]
- return None
- def do_action(self, menu, file, method):
- path = urllib.unquote(
- file.get_uri()[len('file://'):]
- )
- ipc_insync(method=method, full_path=path)
- def update_file_info_full(self, provider, handle, closure, file):
- if file.get_uri_scheme() != 'file':
- return
- file.invalidate_extension_info()
- GObject.timeout_add(1, self.add_emblem, provider, handle, closure, file)
- return Nautilus.OperationResult.IN_PROGRESS
- def cancel_update(self, provider, handle):
- pass
- def add_emblem(self, provider, handle, closure, file):
- filename = urllib.unquote(file.get_uri()[len('file://'):])
- filename = os.path.realpath(filename)
- status = ipc_insync(command='GET-FILE-STATUS', full_path=filename)
- if status and status != 'UNKNOWN':
- emblem = _EMBLEM_KEYS[status]
- if os.path.isdir(filename):
- is_shared = ipc_insync(command='IS-FILE-SHARED', full_path=filename)
- if is_shared:
- emblem += '-shared'
- file.add_emblem(emblem)
- Nautilus.info_provider_update_complete_invoke(closure, provider, handle,
- Nautilus.OperationResult.COMPLETE)
- return False
- print(InsyncExtension)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement