import time
import threading
import ctypes
import cfiler_mainwindow
import cfiler_threadutil
import cfiler_filelist
FindFirstChangeNotification = ctypes.windll.kernel32.FindFirstChangeNotificationW
FindNextChangeNotification = ctypes.windll.kernel32.FindNextChangeNotification
FindCloseChangeNotification = ctypes.windll.kernel32.FindCloseChangeNotification
WaitForMultipleObjects = ctypes.windll.kernel32.WaitForMultipleObjects
CreateEvent = ctypes.windll.kernel32.CreateEventW
SetEvent = ctypes.windll.kernel32.SetEvent
CloseHandle = ctypes.windll.kernel32.CloseHandle
IsWindow = ctypes.windll.user32.IsWindow
class DirectoryWatchThread(threading.Thread):
def __init__(self, window, pane, lister):
threading.Thread.__init__(self)
self.directory = lister.location
def _exec_refresh_(item):
window.refreshFileList( pane, True, False )
window.paint(cfiler_mainwindow.PAINT_ALL)
self.exec_refresh = _exec_refresh_
self.delay = lambda (item): time.sleep(0.1)
self.event = CreateEvent(0, 0, 0, 0)
self.window = window
def run(self):
handle = FindFirstChangeNotification(
ctypes.c_wchar_p(self.directory), 0, 3)
if handle == 0xffffffff:
CloseHandle(self.event)
return
handles = (ctypes.c_uint * 2)()
handles[0] = self.event
handles[1] = handle
hWnd = self.window.getHWND()
jobQueue = self.window.refreshJobQueue
while True:
ret = WaitForMultipleObjects(2, ctypes.addressof(handles), 0, 1)
if ret == 0: break
elif ret == 0x102: # WAIT_TIMEOUT
if IsWindow(hWnd): continue
else: break
jobQueue.cancel()
jobQueue.enqueue(cfiler_threadutil.JobItem(
self.delay, self.exec_refresh))
if not FindNextChangeNotification(handle):
break
CloseHandle(self.event)
FindCloseChangeNotification(handle)
def stop(self):
SetEvent(self.event)
def start_directory_watch(window):
original_subThreadCall = window.subThreadCall
def subThreadCall(*args, **kw):
window.killTimer(window.onTimerJob)
window.killTimer(window.onTimerSyncCall)
original_subThreadCall(*args, **kw)
window.setTimer(window.onTimerJob, 10)
window.setTimer(window.onTimerSyncCall, 10)
window.subThreadCall = subThreadCall
window.refreshJobQueue = cfiler_threadutil.JobQueue()
def rebind_setLister(pane):
original_setLister = pane.file_list.setLister
def setLister(lister):
if hasattr(lister, "watch_thread"):
lister.watch_thread.stop()
del lister.watch_thread
if isinstance(lister, cfiler_filelist.lister_Default):
lister.watch_thread = DirectoryWatchThread(window, pane, lister)
lister.watch_thread.start()
if lister: original_setLister(lister)
pane.file_list.setLister = setLister
rebind_setLister(window.left_pane)
rebind_setLister(window.right_pane)