Skip to content

Commit

Permalink
add select remote dir
Browse files Browse the repository at this point in the history
  • Loading branch information
alex8224 committed Apr 24, 2015
1 parent 9343558 commit a4f2539
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 71 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ bcloud 是[百度网盘](http://pan.baidu.com)的Linux桌面客户端.

1. 增加文件同步的功能, 在首选项界面中可以选择打开同步目录的功能, 目前仅支持单向同步(同步本地目录到网盘中)

TODO
======
1. 在同步目录编辑文件时会产生临时文件, 需要修改成监听 CLOSE_WRITE 事件, 只在文件写完后同步, 并增加删除检测的功能.
2. 增加选择远程目录的功能
3. 去掉对 pyinotify 的依赖, 使用 GIO 自带的 FileMonitor 功能


类似项目
=======
Expand Down
3 changes: 2 additions & 1 deletion bcloud/App.py
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,8 @@ def init_filewatcher(self):
enable_sync = self.profile['enable-sync']
if enable_sync:
sync_dir = self.profile['sync-dir']
self.filewatcher = WatchFileChange(sync_dir, self.upload_page.add_bg_task)
#self.filewatcher = WatchFileChange(sync_dir, self.upload_page.add_bg_task)
self.filewatcher = WatchFileChange(sync_dir, self)
self.filewatcher.start()

def reload_current_page(self, *args, **kwds):
Expand Down
118 changes: 50 additions & 68 deletions bcloud/FileWatcher.py
Original file line number Diff line number Diff line change
@@ -1,111 +1,93 @@
import os
import time
import pyinotify
from queue import Queue, Empty, Full
from bcloud import pcs
from bcloud import gutil
from threading import Thread
from pyinotify import IN_CREATE, IN_DELETE, IN_ACCESS, IN_CLOSE_NOWRITE, IN_CLOSE_WRITE, IN_MODIFY, IN_MOVED_FROM, IN_MOVED_TO, IN_OPEN
from pyinotify import ALL_EVENTS


# MASK = IN_CREATE|IN_DELETE|IN_ACCESS|IN_CLOSE_NOWRITE|IN_CLOSE_WRITE|IN_MODIFY|IN_MOVED_FROM|IN_MOVED_TO|IN_OPEN
MASK = IN_CREATE
MASK = ALL_EVENTS

class EventHandler(pyinotify.ProcessEvent):

def __init__(self, source, upload_func, limiter):
def __init__(self, source, bcloud_app):
super(EventHandler, self).__init__()
self.source = source
self.upload_func = upload_func
self.limiter = limiter
self.bcloud_app = bcloud_app
self.cloud_root = bcloud_app.profile['dest-sync-dir']

def process_IN_CREATE(self, event):
if os.path.isfile(event.pathname):
remotepath = self.process_Remote_Path(event.pathname)
# self.limiter.put_task((event.pathname, remotepath))
self.upload_func(event.pathname, remotepath)
if not event.dir:
self.process_IN_CLOSE_WRITE(event)

def process_Remote_Path(self, pathname):
return os.path.dirname(pathname[len(self.source):])
def process_Remote_Path(self, pathname, dir=False):
if dir:
return os.path.join(self.cloud_root, pathname[len(self.source)+1:])
else:
return os.path.join(self.cloud_root, os.path.dirname(pathname[len(self.source)+1:]))


def process_IN_DELETE(self, event):
print("Deleteing", event.pathname)
def is_valid_filename(self, filename):
invalid_prefixs = (".", "~")
invalid_suffixs = (".swp", "crdownload")
not_startwith = lambda prefix: not filename.startswith(prefix)
not_endwith = lambda suffix: not filename.endswith(suffix)

return all(map(not_startwith, invalid_prefixs)) and all(map(not_endwith, invalid_suffixs))

def process_IN_DELETE(self, event):
if event.dir:
remotepath = self.process_Remote_Path(event.pathname, True)
else:
remotepath = os.path.join(self.process_Remote_Path(event.pathname), event.name)

def process_IN_CLOSE_NOWRITE(self, event):
print("closenowrite", event.pathname)
gutil.async_call(pcs.delete_files, self.bcloud_app.cookie, \
self.bcloud_app.tokens, [remotepath], callback=lambda noop:noop)

def process_IN_CLOSE_WRITE(self, event):
print("IN_CLOSE_WRITE", event.pathname)
if not event.dir and self.is_valid_filename(event.name):
remotepath = self.process_Remote_Path(event.pathname)
self.bcloud_app.upload_page.add_bg_task(event.pathname, remotepath)

def process_IN_MODIFY(self, event):
print("IN_MODIFY", event.pathname)

def process_IN_MOVED_FROM(self, event):
print("move from", event.pathname)
self.process_IN_DELETE(event)

def process_IN_MOVED_TO(self, event):
print("in_moved_to", event.pathname)
self.process_IN_CLOSE_WRITE(event)

def process_IN_OPEN(self, event):
print("OPEN FILE", event.pathname)

class WatchFileChange(Thread):


def __init__(self, monitor_path, upload_func):
def __init__(self, monitor_path, bcloud_app):

super(WatchFileChange, self).__init__()
self.setDaemon(True)
self.monitor_path = monitor_path
self.upload_func = upload_func
self.limiter = TaskLimiter(self.upload_func)
self.handler = EventHandler(self.monitor_path, self.upload_func, self.limiter)
self.setDaemon(True)
self.monitor_path = monitor_path
self.bcloud_app = bcloud_app
self.handler = EventHandler(self.monitor_path, self.bcloud_app)
self.wm = pyinotify.WatchManager()
self.wdds = self.wm.add_watch(self.monitor_path, MASK, rec=True, auto_add=True)
self.notifyer = pyinotify.Notifier(self.wm, self.handler)

def stop(self):
self.wm.rm_watch(self.wdds)
self.wm.close()
self.notifyer.stop()
self.limiter.stop()

def chain_handler(self, event):
print(event)

def run(self):
# self.limiter.start()
self.wm.add_watch(self.monitor_path, MASK, rec=True, auto_add=True)
self.notifyer.loop()

class TaskLimiter(Thread):

def __init__(self, upload_func):
super(TaskLimiter, self).__init__()
self.queue = Queue(10000)
self.setDaemon(True)
self.runflag = True
self.upload_func = upload_func

def put_task(self, task):
for retry in range(3):
try:
self.queue.put_nowait(task)
except Full:
pass
if __name__ == '__main__':

def stop(self):
self.runflag = False

def batch_get(self, num):
tasks = []
try:
for i in range(num):
task = self.queue.get_nowait()
tasks.append(task)
except Empty:
pass
return tasks
def mock(source, dest):
print(source, dest)

def run(self):
while self.runflag:
tasks = self.batch_get(50)
for task in tasks:
source, dest = task
self.upload_func(source, dest)
time.sleep(0.5)
source = "/home/alex/Documents"
watcher = WatchFileChange(source, mock)
watcher.start()
watcher.join()
19 changes: 19 additions & 0 deletions bcloud/PreferencesDialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from bcloud import Config
_ = Config._

from bcloud.FolderBrowserDialog import FolderBrowserDialog

class PreferencesDialog(Gtk.Dialog):

Expand Down Expand Up @@ -111,6 +112,13 @@ def __init__(self, app):
sync_dir_button.connect('file-set', self.on_sync_dir_update)
general_grid.attach(sync_dir_button, 1, 7, 1, 1)

sync_dest_dir_label = Gtk.Label.new(_('Dest Sync Dir:'))
sync_dest_dir_label.props.xalign = 1
general_grid.attach(sync_dir_label, 0, 8, 1, 1)
dest_dir_button = Gtk.Button.new_with_label(app.profile['dest-sync-dir'])
dest_dir_button.connect('clicked', self.on_destdir_clicked)
general_grid.attach(dest_dir_button, 1, 8, 1, 1)


# network tab
network_grid = Gtk.Grid()
Expand Down Expand Up @@ -216,6 +224,17 @@ def on_sync_dir_update(self, file_button):
if dir_name:
self.app.profile['sync-dir'] = dir_name

def on_destdir_clicked(self, button):
folder_dialog = FolderBrowserDialog(self, self.app)
response = folder_dialog.run()
if response != Gtk.ResponseType.OK:
folder_dialog.destroy()
return
dir_name = folder_dialog.get_path()
folder_dialog.destroy()
button.set_label(dir_name)
self.app.profile['dest-sync-dir'] = dir_name

def on_upload_hidden_switch_activate(self, switch, event):
self.app.profile['upload-hidden-files'] = switch.get_active()

Expand Down
Binary file added bcloud/__pycache__/__init__.cpython-34.pyc
Binary file not shown.
1 change: 1 addition & 0 deletions bcloud/gutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
'first-run': True,
'save-dir': Config.HOME_DIR,
'sync-dir': Config.HOME_DIR,
'dest-sync-dir': '/',
'enable-sync': False,
'use-streaming': True, # 使用流媒体方式播放视频
'username': '',
Expand Down
8 changes: 6 additions & 2 deletions po/zh_CN.po
Original file line number Diff line number Diff line change
Expand Up @@ -842,8 +842,12 @@ msgstr "文件名不能以 \\r \\n \\t \\0 \\x0B 或空格开头或结束"

#: ../bcloud/PreferencesDialog.py:95
msgid "Enable Sync:"
msgstr "打开同步"
msgstr "打开同步:"

#: ../bcloud/PreferencesDialog.py:105
msgid "Sync Dir:"
msgstr "同步目录"
msgstr "同步目录:"

#: ../bcloud/PreferencesDialog.py:115
msgid "Dest Sync Dir:"
msgstr "远程目录:"
4 changes: 4 additions & 0 deletions po/zh_TW.po
Original file line number Diff line number Diff line change
Expand Up @@ -847,3 +847,7 @@ msgstr "開啓同步:"
#: ../bcloud/PreferencesDialog.py:105
msgid "Sync Dir:"
msgstr "同步資料夾:"

#: ../bcloud/PreferencesDialog.py:115
msgid "Dest Sync Dir:"
msgstr "遠端資料夾:"

0 comments on commit a4f2539

Please sign in to comment.