Source

mygrsync / mygrsyncdlg.py

windwiny 9bab1f8 
windwiny 154c3d6 
windwiny 6462b7f 


windwiny 289264a 
windwiny 7c355be 
windwiny 3981f46 
windwiny 9076cda 
windwiny 6462b7f 
windwiny 5a54085 
windwiny 6462b7f 



windwiny 9bab1f8 

windwiny 6fff432 
windwiny be73fd7 








windwiny 6462b7f 
windwiny 289264a 
windwiny 6462b7f 















windwiny 289264a 
windwiny 41a96b7 
windwiny 9bab1f8 
windwiny 6462b7f 
windwiny 2e2fc47 
windwiny 6462b7f 
windwiny 9bab1f8 

windwiny 6462b7f 

windwiny 9bab1f8 
windwiny 6462b7f 


windwiny 9bab1f8 


windwiny 6462b7f 
windwiny 9bab1f8 
windwiny 6462b7f 


windwiny 41a96b7 



windwiny 9bab1f8 
windwiny 6462b7f 


windwiny 41a96b7 











windwiny 9bab1f8 
windwiny 41a96b7 
windwiny 6462b7f 

windwiny 9bab1f8 
windwiny 6462b7f 



windwiny 9bab1f8 
windwiny 6462b7f 
windwiny 9bab1f8 


windwiny 6462b7f 
windwiny 9bab1f8 
windwiny 6462b7f 
windwiny 05d1d85 

windwiny 9bab1f8 
windwiny 05d1d85 




windwiny 9076cda 
windwiny 6462b7f 
windwiny 9bab1f8 
windwiny 6462b7f 
windwiny 9bab1f8 
windwiny 6462b7f 



windwiny 9bab1f8 
windwiny 6462b7f 
windwiny 9bab1f8 
windwiny 6462b7f 



windwiny 9bab1f8 
windwiny 6462b7f 
windwiny 9bab1f8 


windwiny 289264a 
windwiny 9bab1f8 
windwiny 6462b7f 
windwiny 9bab1f8 

windwiny 9076cda 
windwiny 289264a 
windwiny 9bab1f8 
windwiny 6462b7f 
windwiny be73fd7 












windwiny 9076cda 


windwiny 6462b7f 
windwiny 9bab1f8 
windwiny 6462b7f 
windwiny 9076cda 


windwiny 05d1d85 


windwiny 6fff432 






windwiny 6462b7f 



windwiny 71362f5 
windwiny 5a54085 
windwiny 71362f5 
windwiny ab276f8 





windwiny 71362f5 

windwiny ab276f8 
windwiny 5a54085 


windwiny ab276f8 




windwiny bb97c85 
windwiny 2e2fc47 

windwiny bb97c85 


windwiny be73fd7 
windwiny bb97c85 


windwiny 2e2fc47 
windwiny be73fd7 



windwiny 2e2fc47 


windwiny 05d1d85 
windwiny 2e2fc47 
windwiny 05d1d85 

windwiny 2e2fc47 
windwiny bb97c85 

windwiny a9e503b 

windwiny 5a54085 





windwiny 3e74357 

windwiny a9e503b 





windwiny 6462b7f 
windwiny bb97c85 
windwiny 386be3b 

windwiny 5a54085 

windwiny bb97c85 


windwiny 25c1f69 

windwiny bb97c85 

windwiny 4779b7a 


windwiny 25c1f69 
windwiny 4779b7a 
windwiny 25c1f69 

windwiny 8a0217e 

windwiny 4779b7a 
windwiny 8a0217e 
windwiny bb97c85 
windwiny 8a0217e 





windwiny bb97c85 



windwiny 7c355be 
windwiny 71362f5 



windwiny 9076cda 
windwiny be73fd7 
windwiny efde9f3 
windwiny 71362f5 



windwiny 9076cda 
windwiny be73fd7 
windwiny efde9f3 
windwiny 7c355be 
windwiny 71362f5 
windwiny 386be3b 
windwiny 6462b7f 

windwiny 05d1d85 
windwiny 6462b7f 




windwiny 9076cda 
windwiny 6462b7f 
windwiny 9076cda 
windwiny 3981f46 
windwiny a858dfb 
windwiny 3981f46 
windwiny a858dfb 
windwiny 9076cda 
windwiny f6f1554 
windwiny a858dfb 
windwiny 9076cda 
windwiny 6462b7f 
windwiny f6f1554 


windwiny bb97c85 
windwiny 3981f46 
windwiny 71362f5 
windwiny 05d1d85 





windwiny 6fff432 


windwiny 386be3b 


windwiny 6fff432 















windwiny 05d1d85 






windwiny 9076cda 
windwiny 05d1d85 




windwiny 6fff432 
windwiny 9076cda 
windwiny 6fff432 
windwiny 9076cda 
windwiny 6fff432 
#Boa:MiniFrame:grsyncdlg
# -*- coding: utf-8 -*-

import sys
import os
import subprocess
import threading
import shlex
import locale
import time
import traceback
import wx
import wx.stc

def create(parent):
    return grsyncdlg(parent)

[wxID_GRSYNCDLG, wxID_GRSYNCDLGBTNCLOSE, wxID_GRSYNCDLGBTNHELP, 
 wxID_GRSYNCDLGBTNSTOP, wxID_GRSYNCDLGBTNSYNC, wxID_GRSYNCDLGCHKPIN, 
 wxID_GRSYNCDLGCHK_A, wxID_GRSYNCDLGCHK_R, wxID_GRSYNCDLGCHK_T, 
 wxID_GRSYNCDLGCHK_V, wxID_GRSYNCDLGCHK_Z, wxID_GRSYNCDLGCHK__DELETE, 
 wxID_GRSYNCDLGCHK__DRY_RUN, wxID_GRSYNCDLGCHK__UPDATE, wxID_GRSYNCDLGPANEL1, 
 wxID_GRSYNCDLGSTATICTEXT1, wxID_GRSYNCDLGSTATICTEXT2, 
 wxID_GRSYNCDLGSTATICTEXT3, wxID_GRSYNCDLGSTATICTEXT4, 
 wxID_GRSYNCDLGSTCSYNCLOG, wxID_GRSYNCDLGTXTDST, wxID_GRSYNCDLGTXTEXCLUDE, 
 wxID_GRSYNCDLGTXTOTHER, wxID_GRSYNCDLGTXTSRC, 
] = [wx.NewId() for _init_ctrls in range(24)]

class grsyncdlg(wx.Frame):
    def _init_coll_boxSizer1_Items(self, parent):
        # generated method, don't edit

        parent.AddWindow(self.panel1, 0, border=0, flag=wx.EXPAND)
        parent.AddWindow(self.stcSyncLog, 1, border=0, flag=wx.EXPAND)

    def _init_sizers(self):
        # generated method, don't edit
        self.boxSizer1 = wx.BoxSizer(orient=wx.VERTICAL)

        self._init_coll_boxSizer1_Items(self.boxSizer1)

        self.SetSizer(self.boxSizer1)

    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Frame.__init__(self, id=wxID_GRSYNCDLG, name=u'grsyncdlg',
              parent=prnt, pos=wx.Point(504, 120), size=wx.Size(719, 569),
              style=wx.DEFAULT_FRAME_STYLE, title=u'grsyncdlg')
        self.SetClientSize(wx.Size(703, 531))
        self.Bind(wx.EVT_CLOSE, self.OnGrsyncdlgClose)

        self.panel1 = wx.Panel(id=wxID_GRSYNCDLGPANEL1, name='panel1',
              parent=self, pos=wx.Point(0, 0), size=wx.Size(703, 112),
              style=wx.TAB_TRAVERSAL)

        self.stcSyncLog = wx.stc.StyledTextCtrl(id=wxID_GRSYNCDLGSTCSYNCLOG,
              name=u'stcSyncLog', parent=self, pos=wx.Point(0, 112),
              size=wx.Size(703, 419), style=0)

        self.staticText1 = wx.StaticText(id=wxID_GRSYNCDLGSTATICTEXT1,
              label=u'SRC', name='staticText1', parent=self.panel1,
              pos=wx.Point(8, 8), size=wx.Size(21, 14), style=0)

        self.txtSRC = wx.TextCtrl(id=wxID_GRSYNCDLGTXTSRC, name=u'txtSRC',
              parent=self.panel1, pos=wx.Point(32, 8), size=wx.Size(320, 22),
              style=0, value=u'')

        self.staticText2 = wx.StaticText(id=wxID_GRSYNCDLGSTATICTEXT2,
              label=u'DST', name='staticText2', parent=self.panel1,
              pos=wx.Point(8, 32), size=wx.Size(23, 14), style=0)

        self.txtDST = wx.TextCtrl(id=wxID_GRSYNCDLGTXTDST, name=u'txtDST',
              parent=self.panel1, pos=wx.Point(32, 32), size=wx.Size(320, 22),
              style=0, value=u'')

        self.staticText4 = wx.StaticText(id=wxID_GRSYNCDLGSTATICTEXT4,
              label=u'exclude dir', name='staticText4', parent=self.panel1,
              pos=wx.Point(8, 64), size=wx.Size(59, 14), style=0)

        self.txtExclude = wx.TextCtrl(id=wxID_GRSYNCDLGTXTEXCLUDE,
              name=u'txtExclude', parent=self.panel1, pos=wx.Point(80, 64),
              size=wx.Size(376, 22), style=0, value=u'')

        self.staticText3 = wx.StaticText(id=wxID_GRSYNCDLGSTATICTEXT3,
              label=u'Other Param', name='staticText3', parent=self.panel1,
              pos=wx.Point(8, 88), size=wx.Size(69, 14), style=0)

        self.txtOther = wx.TextCtrl(id=wxID_GRSYNCDLGTXTOTHER, name=u'txtOther',
              parent=self.panel1, pos=wx.Point(80, 88), size=wx.Size(376, 22),
              style=0, value=u'')

        self.chk__dry_run = wx.CheckBox(id=wxID_GRSYNCDLGCHK__DRY_RUN,
              label=u'--dry-run', name=u'chk__dry_run', parent=self.panel1,
              pos=wx.Point(376, 8), size=wx.Size(79, 14), style=0)
        self.chk__dry_run.SetValue(True)
        self.chk__dry_run.Bind(wx.EVT_CHECKBOX, self.OnChk_x,
              id=wxID_GRSYNCDLGCHK__DRY_RUN)

        self.chk_v = wx.CheckBox(id=wxID_GRSYNCDLGCHK_V, label=u'-v',
              name=u'chk_v', parent=self.panel1, pos=wx.Point(464, 8),
              size=wx.Size(72, 14), style=0)
        self.chk_v.SetValue(True)
        self.chk_v.Bind(wx.EVT_CHECKBOX, self.OnChk_x, id=wxID_GRSYNCDLGCHK_V)

        self.chk_z = wx.CheckBox(id=wxID_GRSYNCDLGCHK_Z, label=u'-z',
              name=u'chk_z', parent=self.panel1, pos=wx.Point(552, 8),
              size=wx.Size(48, 14), style=0)
        self.chk_z.SetValue(True)
        self.chk_z.Bind(wx.EVT_CHECKBOX, self.OnChk_x, id=wxID_GRSYNCDLGCHK_Z)

        self.chk_a = wx.CheckBox(id=wxID_GRSYNCDLGCHK_A, label=u'-a',
              name=u'chk_a', parent=self.panel1, pos=wx.Point(616, 8),
              size=wx.Size(40, 14), style=0)
        self.chk_a.SetValue(True)
        self.chk_a.Bind(wx.EVT_CHECKBOX, self.OnChk_x, id=wxID_GRSYNCDLGCHK_A)

        self.chk__delete = wx.CheckBox(id=wxID_GRSYNCDLGCHK__DELETE,
              label=u'--delete', name=u'chk__delete', parent=self.panel1,
              pos=wx.Point(376, 40), size=wx.Size(79, 14), style=0)
        self.chk__delete.SetValue(False)
        self.chk__delete.Bind(wx.EVT_CHECKBOX, self.OnChk_x,
              id=wxID_GRSYNCDLGCHK__DELETE)

        self.chk__update = wx.CheckBox(id=wxID_GRSYNCDLGCHK__UPDATE,
              label=u'--update', name=u'chk__update', parent=self.panel1,
              pos=wx.Point(464, 40), size=wx.Size(72, 14), style=0)
        self.chk__update.SetValue(True)
        self.chk__update.Bind(wx.EVT_CHECKBOX, self.OnChk_x,
              id=wxID_GRSYNCDLGCHK__UPDATE)

        self.chk_t = wx.CheckBox(id=wxID_GRSYNCDLGCHK_T, label=u'-t',
              name=u'chk_t', parent=self.panel1, pos=wx.Point(552, 40),
              size=wx.Size(48, 14), style=0)
        self.chk_t.SetValue(False)
        self.chk_t.Bind(wx.EVT_CHECKBOX, self.OnChk_x, id=wxID_GRSYNCDLGCHK_T)

        self.chk_r = wx.CheckBox(id=wxID_GRSYNCDLGCHK_R, label=u'-r',
              name=u'chk_r', parent=self.panel1, pos=wx.Point(616, 40),
              size=wx.Size(40, 14), style=0)
        self.chk_r.SetValue(False)
        self.chk_r.Bind(wx.EVT_CHECKBOX, self.OnChk_x, id=wxID_GRSYNCDLGCHK_R)

        self.chkpin = wx.CheckBox(id=wxID_GRSYNCDLGCHKPIN, label=u'pin',
              name=u'chkpin', parent=self.panel1, pos=wx.Point(664, 40),
              size=wx.Size(63, 14), style=0)
        self.chkpin.SetValue(False)
        self.chkpin.Bind(wx.EVT_CHECKBOX, self.OnChkpinCheckbox,
              id=wxID_GRSYNCDLGCHKPIN)

        self.btnHelp = wx.Button(id=wxID_GRSYNCDLGBTNHELP, label=u'?',
              name=u'btnHelp', parent=self.panel1, pos=wx.Point(664, 8),
              size=wx.Size(35, 24), style=0)
        self.btnHelp.Bind(wx.EVT_BUTTON, self.OnBtnHelpButton,
              id=wxID_GRSYNCDLGBTNHELP)

        self.btnsync = wx.Button(id=wxID_GRSYNCDLGBTNSYNC, label=u'RUN ...',
              name=u'btnsync', parent=self.panel1, pos=wx.Point(480, 64),
              size=wx.Size(80, 48), style=0)
        self.btnsync.Bind(wx.EVT_BUTTON, self.OnBtnsyncButton,
              id=wxID_GRSYNCDLGBTNSYNC)

        self.btnStop = wx.Button(id=wxID_GRSYNCDLGBTNSTOP, label=u'STOP',
              name=u'btnStop', parent=self.panel1, pos=wx.Point(576, 64),
              size=wx.Size(48, 48), style=0)
        self.btnStop.Bind(wx.EVT_BUTTON, self.OnBtnStopButton,
              id=wxID_GRSYNCDLGBTNSTOP)

        self.btnClose = wx.Button(id=wxID_GRSYNCDLGBTNCLOSE, label=u'Close',
              name=u'btnClose', parent=self.panel1, pos=wx.Point(640, 64),
              size=wx.Size(51, 48), style=0)
        self.btnClose.SetForegroundColour(wx.Colour(255, 0, 0))
        self.btnClose.Bind(wx.EVT_BUTTON, self.OnBtnCloseButton,
              id=wxID_GRSYNCDLGBTNCLOSE)

        self._init_sizers()

    def __init__(self, parent):
        self._init_ctrls(parent)
        self.init2()

    def init2(self):
        ff = wx.Font(9, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Courier New')
        self.txtSRC.SetFont(ff)
        self.txtDST.SetFont(ff)
        self.txtExclude.SetFont(ff)
        self.txtOther.SetFont(ff)
        self.stcSyncLog.StyleSetFont(wx.stc.STC_STYLE_DEFAULT, ff)
        self.stcSyncLog.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
        self.stcSyncLog.SetMarginWidth(1, 38)
        self.stcSyncLog.SetLexer(wx.stc.STC_LEX_SQL)
        self.stcSyncLog.SetKeyWords(0, 'sigint sigterm sighup error failed '
                                    'unexpectedly warning vanished deleting '
                                    'inserting sending incremental')
        self.stcSyncLog.StyleSetSpec(wx.stc.STC_SQL_WORD, "fore:#FFFFFF,bold")
        self.stcSyncLog.StyleSetSpec(wx.stc.STC_SQL_WORD, "back:#FF0000")
        self.stcSyncLog.SetKeyWords(1, 'total size dry run')
        self.stcSyncLog.StyleSetSpec(wx.stc.STC_SQL_WORD2, "fore:#FFFFFF,bold")
        self.stcSyncLog.StyleSetSpec(wx.stc.STC_SQL_WORD2, "back:#0000FF")

        nid = wx.NewId()
        self.timer1 = wx.Timer(id=nid, owner=self)
        self.Bind(wx.EVT_TIMER, self.OnTimerUp, id=nid)
        self.timer1.Start(100)

        self.autoscroll = True
        self.sp = []
        self.dataout = []
        self.dataerr = []

    def OnChkpinCheckbox(self, event):
        event.Skip()
        self.autoscroll = not self.autoscroll

    def OnGrsyncdlgClose(self, event):
        event.Skip()
        print ' OnGrsyncdlgClose'
        self.terminalsps()
        self.timer1.Stop()

    def terminalsps(self):
        for sp in self.sp[:]:
            if sp.poll() is None:
                sp.terminate()
                if sp.poll() is None: # XXXX win32 sp may has problem
                    print '  Terminate %s, Failed !!!' % str(sp)
                    try:    # win32 py>=2.7 0:signal.CTRL_C_EVENT 1:signal.CTRL_BREAK_EVENT
                        sp.send_signal(1)
                    except:
                        print '---------\n%s\n---------\n' % traceback.format_exc()
                    try:    # not win32
                        sp.kill()
                    except:
                        if sp in self.sp: self.sp.remove(sp)
                else:
                    print '  Terminate %s, Success' % str(sp)
                    if sp in self.sp: self.sp.remove(sp)
            else:
                print ' sp terminated, remove it'
                if sp in self.sp: self.sp.remove(sp)

    def create_subproc_logthread(self, cmd):
        sp = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE,
                              startupinfo=G.startupinfo,
                              creationflags=G.creationflags)
        self.sp.append(sp)

        def thpg(sp, self):
            t0 = time.time()
            self.dataout.append('\n/=========== stdout ===========\\\n')
            while True:
                msg = sp.stdout.readline()
                if sp.poll() is not None and msg == '':
                    try:
                        if sp in self.sp: self.sp.remove(sp)
                        self.dataerr.append('\n|=========== stderr ===========|\n')
                        self.dataerr.append(sp.stderr.read())
                        self.dataerr.append('\n\\=========== theend ===========/')
                        self.dataerr.append('\n Time: %s\n' % (time.time() - t0))
                    except Exception as e:
                        print ' window closed, thread break'
                        break
                    break
                if msg:
                    try:
                        self.dataout.append(msg)
                    except Exception as e:
                        print ' window closed, thread break'
                        break

        th1 = threading.Thread(target=thpg, args=(sp, self, ))
        th1.setDaemon(True)
        th1.start()

    def OnTimerUp(self, event):
        i = len(self.dataout)
        if i != 0:
            data = ''.join(self.dataout[:i])
            del self.dataout[:i]
            self.stcSyncLog.AppendText(data.decode(G.str_encode, 'replace'))
            if self.autoscroll:
                self.stcSyncLog.GotoLine(self.stcSyncLog.GetLineCount())
        i = len(self.dataerr)
        if i != 0:
            data = ''.join(self.dataerr[:i])
            del self.dataerr[:i]
            self.stcSyncLog.AppendText(data.decode(G.str_encode, 'replace'))
            if self.autoscroll:
                self.stcSyncLog.GotoLine(self.stcSyncLog.GetLineCount())

    def getcmd(self):
        cmds = [G._pg_RSYNC]
        if self.chk__dry_run.GetValue(): cmds.append('-n')
        if self.chk_v.GetValue(): cmds.append('-v')
        if self.chk_z.GetValue(): cmds.append('-z')
        if self.chk_a.GetValue(): cmds.append('-a')
        if self.chk__delete.GetValue(): cmds.append('--delete')
        if self.chk__update.GetValue(): cmds.append('--update')
        if self.chk_t.GetValue(): cmds.append('-t')
        if self.chk_r.GetValue(): cmds.append('-r')
        expar = self.txtOther.GetValue().encode(G.str_encode)
        if expar: cmds.append(expar)
        expar = self.txtExclude.GetValue().encode(G.str_encode)
        if expar: cmds.append(' '.join(['--exclude="%s"' % i for i in shlex.split(expar) if i]))

        cmds.append('  ')

        lu = self.txtSRC.GetValue().encode(G.str_encode)
        if lu[-1] != '/': # FUXX
            lu = lu + '/'
        ru = self.txtDST.GetValue().encode(G.str_encode)
        cmds.append('"%s"' % lu)
        if ru[-1] != '/':
            ru = ru + '/'
        cmds.append('"%s"' % ru)

        cmd = ' '.join(cmds)
        return cmd

    def OnChk_x(self, event):
        event.Skip()
        cmd = self.getcmd()
        self.dataout.append(cmd + '\n')

    def OnBtnHelpButton(self, event):
        event.Skip()
        if not hasattr(self, '_rsyncdoc'):
            sp = subprocess.Popen('%s --help -v' % G._pg_RSYNC, shell=True,
                                  stdout=subprocess.PIPE,
                                  startupinfo=G.startupinfo)
            self._rsyncdoc = sp.stdout.read().decode(G.str_encode)
            self._dlg = wx.Dialog(self, title=u"rsync --help", size=wx.Size(640,480),
                                  style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
            self._stc = wx.stc.StyledTextCtrl(self._dlg)
            ff = wx.Font(9, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Courier New')
            self._stc.StyleSetFont(wx.stc.STC_STYLE_DEFAULT, ff)
            self._stc.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
            self._stc.SetMarginWidth(1, 38)
            self._stc.SetSize(self._dlg.GetClientSize())
        if self._dlg.IsShown():
            self._dlg.Hide()
        else:
            self._stc.SetText(self._rsyncdoc)
            self._stc.EmptyUndoBuffer()
            self._dlg.Show()

    def OnBtnsyncButton(self, event):
        if self.sp:
            print 'has rsync sub process running ... '
            return
        cmd = self.getcmd()
        print cmd
        self.stcSyncLog.SetText(time.strftime('Time: %Y-%m-%d %H:%M:%S\n'))
        self.stcSyncLog.AppendText(cmd.decode(G.str_encode) + '\n\n')
        self.create_subproc_logthread(cmd)
        print '---------'

    def OnBtnStopButton(self, event):
        event.Skip()
        self.terminalsps()

    def OnBtnCloseButton(self, event):
        event.Skip()
        self.Close()