Exemple #1
0
    def __init__(self, configFileName, mode, time_cycle, d):
        # 多线程用,quit flag
        self.quit = False

        # 同步模式
        self.mode = mode

        # 自动同步时间
        self.time_cycle = time_cycle

        # 自动在同步前清空远端文件夹
        self.autoDelete = d

        # RPC 端口
        self.rpc_port = slave.PORT

        # 符合条件的路径会被排除   {dir:[re]}
        self.ignoreExp = defaultdict(list)

        # 文件对应的修改时间和md5   {file:(md5,time)}
        self.file2md5time = {}

        # 读取配置文件
        self.config = ConfigData(configFileName)
        self.config.show()

        # 建立存放同步用数据的文件夹
        self.infoDir = os.path.join(self.config.currentDir, self.INFO_DIR)
        if not os.path.exists(self.infoDir):
            os.makedirs(self.infoDir)

        self.remoteInfoDir = os.path.join(self.config.remoteDir, self.INFO_DIR)

        # 读取本地同步文件夹信息
        self._loadDir()
Exemple #2
0
 def OnInit(self):
     """Called after instantiation
     
     Calls the Splash screen and returns true
     
     """
     ConfigData.__init__(self)
     #self.doSplash()
     self.doMainFrame()
     return True
Exemple #3
0
 def OnInit(self):
     """Called after instantiation
     
     Calls the Splash screen and returns true
     
     """
     ConfigData.__init__(self)
     #self.doSplash()
     self.doMainFrame()
     return True
Exemple #4
0
    def __init__(self, *args, **kwargs):
        """Default Constructor for wx.Frame"""
        super(MainWindow, self).__init__(*args, **kwargs)
        icon = PyEmbeddedImage(
            "iVBORw0KGgoAAAANSUhEUgAAAE4AAABECAYAAAAvMQN7AAAD+klEQVR42u1cP08yMRg//6CA"
            "KEhCSBwY3VwcNOED8AHcTEx4+QysjHwBJjYSRhIkzk6EWROjm4sTMXyKvj6XKynH9dq7a3tt"
            "735JAxJp6a/Pvz7PA46TI4dWGI/H6O8BHR4euo/k86OjI/yaMXh5eXE/P94Dfl4oFNDBwUHy"
            "/by+vroTEZPt/E0+J0jVFsvlcmcvpCCQ+yH/J/Ii7XYblcvlnYlpAxY6Pj72v64NVqsVKpVK"
            "rnZgsnzkBO4J3nN6eop+fn649+MSwZo8bBCqkCpqtZpLGGFSYo3RaIS49D/JIn4C05DAAJVL"
            "NDziw6VNJHF4A7Dw1dUVc/Fer4cqlcqOhID0wxgOh8z3Y5UU9fnJfVA16Pr6Wugp+QfMT9vw"
            "5+en+8HC1sd2h3XwsgZ8vu/v7/31wR2LlDZe4sDbRT39NIgjnIu6RRkSF5k48HaqiSOih/SJ"
            "u7y8RHENOcXmIdnqqgVxxWIx9umDE8kscQKckdI9BNpXlleTZOPEbiINicuJY68HkYcuXtUo"
            "Vb27u0PK4yAbiAu9soi+59lAHNed++TkRMp9z1TiwK7RbNseLi4uhEueicTFze7gq03WVTU6"
            "np+ft8wnlT4TiMOCwpN/4wJMmJQ83YmDvYGJ6nQ64hOv1Wo1NoG6Ewd7k5qWDijMGE0ceMyz"
            "szM16X2ogEUNWXQlzsvQqAPEe1HshwrieDPYcOhESks9vBoAVzwUlLWNQj5PpiJK6h8cQWp1"
            "y/V6PQL7wHIWtFYJATWOWPk9WgpcOVjkEbeQQFWNYi8x2e/v7zvzPT4+8pClD2l+taMRGHJ9"
            "ESJtYLNYB8B951QNLxYKHb+/v//ikkerNdzf3zOLydpJmh9w6mFqG1JU9rda7ama1wi0g263"
            "y1RtTxv0Rr/fZ54+raj89va2tXnYLhKemxpThhHHUf3XB6yyHxAiIvBkpb4gBJpMJkY1PnKH"
            "Gk9PT5E31mq1EJlwpZEn/f4pAx8fH1xNfNhwh7Q1bNFsNgO7KYPmFJYaSkvqeLofiY26Kkwm"
            "EnCzixdKcOfVGo2GucQJuh2IqrkaB9WEoZubG/OJ22w2TdUS59gCVepK2EZroEzaZrOZVcQ5"
            "CiXOLpyfn0vthrLOvmGEXeBFedSgJIDxeHh4UCFx1iIPeuPm6mQRV6/X7SVOZjxnRLIyLqCo"
            "E7cTIJOhiApVtdo5JP0ebGadQ05cAucgS11vb2/tjuNkEbdYLOwlbjAYSPlOrA7f/zfu9kB0"
            "POXERR3T6TQTxDle66iwGoOTJXjNM7EHNAYaWXBOiq+vLyRA8jIN7hCF/DEpJ4fjQPBKSl9Q"
            "JR97z/l8npPmB/wGCbRAkE3ZkHL3ekZy5Mgw/gMoRoA7F6WE6gAAAABJRU5ErkJggg=="
        )
        self.SetIcon(icon.GetIcon())

        self.sx = 0
        self.sy = 0 - 20
        self.mainpan = wx.Panel(self)
        self.configs = ConfigData()
        self.online_status = False
        self.goodcolor = self.configs.colors['online']
        self.warningcolor = self.configs.colors['offline']
        self.on_off_flag = threading.Event()
        self.running_flag = threading.Event()
        self.configs.VK_CODE

        self.__init_ui()
        self._start_watcher_thread()
Exemple #5
0
    def __init__(self,
                 parent,
                 style=wx.FULL_REPAINT_ON_RESIZE,
                 flag=wx.ADJUST_MINSIZE):
        wx.Frame.__init__(self, parent, -1, _(u"Template-Designer"))

        self.myConfig = ConfigData()
        self.myConfig.saveConfig()
        """
        Set taskbar icon. If you remove this, do not forget to 
        remove the RemoveIcon() and Destroy() methods 
        in self.OnExitWindow()
        """
        self.taskBarIcon = wx.TaskBarIcon()
        iconPath = self.myConfig.skinGraphics() + "/domtreeviewer.png"
        icon = wx.Icon(iconPath, wx.BITMAP_TYPE_PNG)
        self.taskBarIcon.SetIcon(icon, _(u"Template-Designer"))

        #Set titlebar icon
        self.SetIcon(icon)

        self.logoPanel = wx.Panel(self, -1)
        self.settingsPanel = wx.Panel(self, -1)

        self.fullRadio = wx.RadioButton(self.settingsPanel,
                                        -1,
                                        _(u"Full Access"),
                                        name="fullAccess")
        self.fullRadio.SetValidator(WelcomeValidator(self))

        self.restrictedRadio = wx.RadioButton(self.settingsPanel,
                                              -1,
                                              _(u"Restricted Access"),
                                              name="restrictedAccess")
        self.restrictedRadio.SetValidator(WelcomeValidator(self))

        self.viewRadio = wx.RadioButton(self.settingsPanel,
                                        -1,
                                        _(u"View available templates"),
                                        name="viewAccess")
        self.viewRadio.SetValidator(WelcomeValidator(self))

        self.placeholderPanel = wx.Panel(self.settingsPanel, -1)

        self.passwordLabel = wx.StaticText(self.settingsPanel,
                                           -1,
                                           _(u"Password"),
                                           name="passwordLabel")
        self.passwordTextCtrl = wx.TextCtrl(self.settingsPanel,
                                            -1,
                                            "",
                                            style=wx.TE_PASSWORD,
                                            name="password")
        self.passwordTextCtrl.SetValidator(WelcomeValidator(self))

        logo = wx.Bitmap("logo.png", wx.BITMAP_TYPE_ANY)
        self.logoBitmap = wx.StaticBitmap(self.logoPanel, -1, logo)

        self.staticLine = wx.StaticLine(self, -1)

        self.bitplantLabel = wx.StaticText(self, -1,
                                           _(u"Bitplant Template-Designer"))
        self.goButton = wx.Button(self, -1, _(u"OK"), name="goButton")
        self.goButton.SetValidator(WelcomeValidator(self))
        self.exitButton = wx.Button(self, -1, _(u"Exit"), name="exitButton")

        self.__doProperties()
        self.__doBindings()
        self.__doLayout()
Exemple #6
0
class TemplateDesignerWelcome(wx.Frame):
    """Generally called by class TemplateDesigner
    
    returns nothing but calls  class TemplateDesignerFrame 
    if user decides not to leave the dialog
    
    """
    def __init__(self,
                 parent,
                 style=wx.FULL_REPAINT_ON_RESIZE,
                 flag=wx.ADJUST_MINSIZE):
        wx.Frame.__init__(self, parent, -1, _(u"Template-Designer"))

        self.myConfig = ConfigData()
        self.myConfig.saveConfig()
        """
        Set taskbar icon. If you remove this, do not forget to 
        remove the RemoveIcon() and Destroy() methods 
        in self.OnExitWindow()
        """
        self.taskBarIcon = wx.TaskBarIcon()
        iconPath = self.myConfig.skinGraphics() + "/domtreeviewer.png"
        icon = wx.Icon(iconPath, wx.BITMAP_TYPE_PNG)
        self.taskBarIcon.SetIcon(icon, _(u"Template-Designer"))

        #Set titlebar icon
        self.SetIcon(icon)

        self.logoPanel = wx.Panel(self, -1)
        self.settingsPanel = wx.Panel(self, -1)

        self.fullRadio = wx.RadioButton(self.settingsPanel,
                                        -1,
                                        _(u"Full Access"),
                                        name="fullAccess")
        self.fullRadio.SetValidator(WelcomeValidator(self))

        self.restrictedRadio = wx.RadioButton(self.settingsPanel,
                                              -1,
                                              _(u"Restricted Access"),
                                              name="restrictedAccess")
        self.restrictedRadio.SetValidator(WelcomeValidator(self))

        self.viewRadio = wx.RadioButton(self.settingsPanel,
                                        -1,
                                        _(u"View available templates"),
                                        name="viewAccess")
        self.viewRadio.SetValidator(WelcomeValidator(self))

        self.placeholderPanel = wx.Panel(self.settingsPanel, -1)

        self.passwordLabel = wx.StaticText(self.settingsPanel,
                                           -1,
                                           _(u"Password"),
                                           name="passwordLabel")
        self.passwordTextCtrl = wx.TextCtrl(self.settingsPanel,
                                            -1,
                                            "",
                                            style=wx.TE_PASSWORD,
                                            name="password")
        self.passwordTextCtrl.SetValidator(WelcomeValidator(self))

        logo = wx.Bitmap("logo.png", wx.BITMAP_TYPE_ANY)
        self.logoBitmap = wx.StaticBitmap(self.logoPanel, -1, logo)

        self.staticLine = wx.StaticLine(self, -1)

        self.bitplantLabel = wx.StaticText(self, -1,
                                           _(u"Bitplant Template-Designer"))
        self.goButton = wx.Button(self, -1, _(u"OK"), name="goButton")
        self.goButton.SetValidator(WelcomeValidator(self))
        self.exitButton = wx.Button(self, -1, _(u"Exit"), name="exitButton")

        self.__doProperties()
        self.__doBindings()
        self.__doLayout()

    def OnExitWindow(self, event=None):
        """close the Welcome dialog
        
        removes the taskbar icon and destroys the dialog 
        if user clicked the exitButton
        
        """
        self.taskBarIcon.RemoveIcon()
        self.taskBarIcon.Destroy()
        self.Destroy()

    def __doBindings(self):
        self.Bind(wx.EVT_CLOSE, self.OnExitWindow)
        self.Bind(wx.EVT_BUTTON, self.OnExitWindow, self.exitButton)

    def __doProperties(self):
        self.SetTitle(_(u"Bitplant Template-Designer"))
        self.SetMinSize((600, 250))
        white = wx.Colour(255, 255, 255)
        self.logoPanel.SetBackgroundColour(white)
        font = wx.Font(9, wx.SWISS, wx.ITALIC, wx.LIGHT, 0, "")
        self.bitplantLabel.SetFont(font)
        self.goButton.Disable()
        self.passwordLabel.Disable()
        self.passwordTextCtrl.Disable()
        self.restrictedRadio.SetValue(True)

    def __doLayout(self):
        sizerStyle = wx.ALL | wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL

        radioSizer = wx.BoxSizer(wx.VERTICAL)
        radioSizer.Add(self.fullRadio, 1, wx.EXPAND, 0)
        radioSizer.Add(self.restrictedRadio, 1, wx.EXPAND, 0)
        radioSizer.Add(self.viewRadio, 1, wx.EXPAND, 0)
        radioSizer.Add(self.placeholderPanel, 2, wx.EXPAND, 0)

        passwordSizer = wx.BoxSizer(wx.HORIZONTAL)
        passwordSizer.Add(self.passwordLabel, 0, wx.RIGHT, 4)
        passwordSizer.Add(self.passwordTextCtrl, 1, 0, 0)

        settingsSizer = wx.BoxSizer(wx.VERTICAL)
        settingsSizer.Add(radioSizer, 1, wx.ALL | wx.EXPAND, 0)
        settingsSizer.Add(passwordSizer, 0, sizerStyle, 4)
        self.settingsPanel.SetSizer(settingsSizer)

        logoSizer = wx.BoxSizer(wx.HORIZONTAL)
        logoSizer.Add(self.logoBitmap, 0,
                      wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 24)
        self.logoPanel.SetSizer(logoSizer)

        settingsLogoSizer = wx.BoxSizer(wx.HORIZONTAL)
        settingsLogoSizer.Add(self.settingsPanel, 1, wx.ALL | wx.EXPAND, 4)
        settingsLogoSizer.Add(self.logoPanel, 0, sizerStyle, 0)

        buttonBoxSizer = wx.BoxSizer(wx.HORIZONTAL)
        buttonBoxSizer.Add(self.bitplantLabel, 1, wx.ALL | wx.ALIGN_BOTTOM, 4)
        buttonBoxSizer.Add(self.goButton, 0, wx.ALL, 4)
        buttonBoxSizer.Add(self.exitButton, 0, wx.ALL, 4)

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        mainSizer.Add(settingsLogoSizer, 1, wx.ALL | wx.EXPAND, 0)
        mainSizer.Add(self.staticLine, 0, wx.ALL | wx.EXPAND, 4)
        mainSizer.Add(buttonBoxSizer, 0, wx.ALL | wx.EXPAND, 4)
        self.SetSizer(mainSizer)

        mainSizer.Fit(self)
        self.Layout()
Exemple #7
0
class MainWindow(wx.Frame):
    """Primary Window"""
    def __init__(self, *args, **kwargs):
        """Default Constructor for wx.Frame"""
        super(MainWindow, self).__init__(*args, **kwargs)
        icon = PyEmbeddedImage(
            "iVBORw0KGgoAAAANSUhEUgAAAE4AAABECAYAAAAvMQN7AAAD+klEQVR42u1cP08yMRg//6CA"
            "KEhCSBwY3VwcNOED8AHcTEx4+QysjHwBJjYSRhIkzk6EWROjm4sTMXyKvj6XKynH9dq7a3tt"
            "735JAxJp6a/Pvz7PA46TI4dWGI/H6O8BHR4euo/k86OjI/yaMXh5eXE/P94Dfl4oFNDBwUHy"
            "/by+vroTEZPt/E0+J0jVFsvlcmcvpCCQ+yH/J/Ii7XYblcvlnYlpAxY6Pj72v64NVqsVKpVK"
            "rnZgsnzkBO4J3nN6eop+fn649+MSwZo8bBCqkCpqtZpLGGFSYo3RaIS49D/JIn4C05DAAJVL"
            "NDziw6VNJHF4A7Dw1dUVc/Fer4cqlcqOhID0wxgOh8z3Y5UU9fnJfVA16Pr6Wugp+QfMT9vw"
            "5+en+8HC1sd2h3XwsgZ8vu/v7/31wR2LlDZe4sDbRT39NIgjnIu6RRkSF5k48HaqiSOih/SJ"
            "u7y8RHENOcXmIdnqqgVxxWIx9umDE8kscQKckdI9BNpXlleTZOPEbiINicuJY68HkYcuXtUo"
            "Vb27u0PK4yAbiAu9soi+59lAHNed++TkRMp9z1TiwK7RbNseLi4uhEueicTFze7gq03WVTU6"
            "np+ft8wnlT4TiMOCwpN/4wJMmJQ83YmDvYGJ6nQ64hOv1Wo1NoG6Ewd7k5qWDijMGE0ceMyz"
            "szM16X2ogEUNWXQlzsvQqAPEe1HshwrieDPYcOhESks9vBoAVzwUlLWNQj5PpiJK6h8cQWp1"
            "y/V6PQL7wHIWtFYJATWOWPk9WgpcOVjkEbeQQFWNYi8x2e/v7zvzPT4+8pClD2l+taMRGHJ9"
            "ESJtYLNYB8B951QNLxYKHb+/v//ikkerNdzf3zOLydpJmh9w6mFqG1JU9rda7ama1wi0g263"
            "y1RtTxv0Rr/fZ54+raj89va2tXnYLhKemxpThhHHUf3XB6yyHxAiIvBkpb4gBJpMJkY1PnKH"
            "Gk9PT5E31mq1EJlwpZEn/f4pAx8fH1xNfNhwh7Q1bNFsNgO7KYPmFJYaSkvqeLofiY26Kkwm"
            "EnCzixdKcOfVGo2GucQJuh2IqrkaB9WEoZubG/OJ22w2TdUS59gCVepK2EZroEzaZrOZVcQ5"
            "CiXOLpyfn0vthrLOvmGEXeBFedSgJIDxeHh4UCFx1iIPeuPm6mQRV6/X7SVOZjxnRLIyLqCo"
            "E7cTIJOhiApVtdo5JP0ebGadQ05cAucgS11vb2/tjuNkEbdYLOwlbjAYSPlOrA7f/zfu9kB0"
            "POXERR3T6TQTxDle66iwGoOTJXjNM7EHNAYaWXBOiq+vLyRA8jIN7hCF/DEpJ4fjQPBKSl9Q"
            "JR97z/l8npPmB/wGCbRAkE3ZkHL3ekZy5Mgw/gMoRoA7F6WE6gAAAABJRU5ErkJggg=="
        )
        self.SetIcon(icon.GetIcon())

        self.sx = 0
        self.sy = 0 - 20
        self.mainpan = wx.Panel(self)
        self.configs = ConfigData()
        self.online_status = False
        self.goodcolor = self.configs.colors['online']
        self.warningcolor = self.configs.colors['offline']
        self.on_off_flag = threading.Event()
        self.running_flag = threading.Event()
        self.configs.VK_CODE

        self.__init_ui()
        self._start_watcher_thread()

    def _start_watcher_thread(self):
        logging.debug("Creating Key Watcher thread")
        # Start the Key_Watch thread
        self.key_watcher = dismantle_thread.DismantleThread(
            self._gather_settings_data(), self.configs, self.running_flag,
            self.on_off_flag)

        self.key_watcher.daemon = True
        self.key_watcher.start()
        self.running_flag.set()

    def __init_ui(self):
        self.sizers = {}
        self.gui_items = {
            "action_but": {
                "start":
                wx.Button(self.mainpan,
                          wx.ID_ANY,
                          "Start",
                          name="Start",
                          pos=(self.sx + 113, self.sy + 129),
                          size=(203, 50)),
                "stop":
                wx.Button(self.mainpan,
                          wx.ID_ANY,
                          "Stop",
                          name="Stop",
                          pos=(self.sx + 113, self.sy + 129),
                          size=(203, 50))
            },
            "online_box":
            wx.TextCtrl(self.mainpan,
                        wx.ID_ANY,
                        "",
                        name="Offline",
                        pos=(self.sx + 10, self.sy + 130),
                        size=(100, 50),
                        style=wx.TE_READONLY),
            "keybinds": {
                "labels": {
                    "amount":
                    wx.StaticText(self.mainpan,
                                  wx.ID_ANY,
                                  "Amount",
                                  pos=(self.sx + 10, self.sy + 25)),
                    "keybind":
                    wx.StaticText(self.mainpan,
                                  wx.ID_ANY,
                                  "Keybind",
                                  pos=(self.sx + 113, self.sy + 25))
                },
                "ten": {
                    "amount_txt":
                    wx.TextCtrl(self.mainpan,
                                wx.ID_ANY,
                                self.configs.bind_one['amount'],
                                name="Amount to Dismantle",
                                pos=(self.sx + 10, self.sy + 45),
                                size=(100, 25)),
                    "txt":
                    wx.ComboBox(
                        self.mainpan,
                        size=(203, 25),
                        choices=self.configs.VK_KEYS,
                        value=self.configs.bind_one['keybind'],
                        style=wx.CB_DROPDOWN | wx.TE_READONLY,
                        name='Keybind 1',
                        pos=(self.sx + 113, self.sy + 45),
                    )
                },
                "twenty_five": {
                    "amount_txt":
                    wx.TextCtrl(self.mainpan,
                                wx.ID_ANY,
                                self.configs.bind_two['amount'],
                                name="Amount to Dismantle",
                                pos=(self.sx + 10, self.sy + 73),
                                size=(100, 25)),
                    "txt":
                    wx.ComboBox(
                        self.mainpan,
                        size=(203, 25),
                        choices=self.configs.VK_KEYS,
                        value=self.configs.bind_two['keybind'],
                        style=wx.CB_DROPDOWN | wx.TE_READONLY,
                        name='Keybind 2',
                        pos=(self.sx + 113, self.sy + 73),
                    )
                },
                "fifty": {
                    "amount_txt":
                    wx.TextCtrl(self.mainpan,
                                wx.ID_ANY,
                                self.configs.bind_three['amount'],
                                name="Amount to Dismantle",
                                pos=(self.sx + 10, self.sy + 101),
                                size=(100, 25)),
                    "txt":
                    wx.ComboBox(
                        self.mainpan,
                        size=(203, 25),
                        choices=self.configs.VK_KEYS,
                        value=self.configs.bind_three['keybind'],
                        style=wx.CB_DROPDOWN | wx.TE_READONLY,
                        name='Keybind 3',
                        pos=(self.sx + 113, self.sy + 101),
                    )
                }
            }
        }

        self.gui_items['online_box'].SetBackgroundColour(self.warningcolor)
        self.gui_items['action_but']['stop'].Hide()

        # Binds
        self.Bind(wx.EVT_BUTTON, self.on_start_stop,
                  self.gui_items['action_but']['start'])
        self.Bind(wx.EVT_BUTTON, self.on_start_stop,
                  self.gui_items['action_but']['stop'])

        self.Bind(wx.EVT_COMBOBOX, self._on_bind_one_sel,
                  self.gui_items['keybinds']['ten']['txt'])
        self.Bind(wx.EVT_TEXT, self._on_bind_one_amt,
                  self.gui_items['keybinds']['ten']['amount_txt'])

        self.Bind(wx.EVT_COMBOBOX, self._on_bind_one_sel,
                  self.gui_items['keybinds']['twenty_five']['txt'])
        self.Bind(wx.EVT_TEXT, self._on_bind_one_amt,
                  self.gui_items['keybinds']['twenty_five']['amount_txt'])

        self.Bind(wx.EVT_COMBOBOX, self._on_bind_one_sel,
                  self.gui_items['keybinds']['fifty']['txt'])
        self.Bind(wx.EVT_TEXT, self._on_bind_one_amt,
                  self.gui_items['keybinds']['fifty']['amount_txt'])

        self.Bind(wx.EVT_CLOSE, self.on_close)

        self.SetMinSize((200, 115))
        self.SetMaxSize((340, 205))
        dw, dh = wx.DisplaySize()
        w, h = self.GetSize()
        x = (dw / 2) - w
        y = (dh / 2) - h
        self.SetPosition((x - 10 + 1400, y - 45))

        self.Show()

    def on_start_stop(self, e):
        if self.online_status:
            # Switch to Offline
            self.gui_items['online_box'].SetBackgroundColour(self.warningcolor)
            self.gui_items['action_but']['stop'].Hide()
            self.gui_items['action_but']['start'].Show()
            self.SetTitle('Destiny 2 Auto-Dismantler - Offline')
            self.online_status = False

            # Stop the Key_Watch thread
            self.on_off_flag.clear()
        else:
            # Switch to Online
            self.gui_items['online_box'].SetBackgroundColour(self.goodcolor)
            self.gui_items['action_but']['start'].Hide()
            self.gui_items['action_but']['stop'].Show()
            self.SetTitle('Destiny 2 Auto-Dismantler - Online')
            self.online_status = True
            self.on_off_flag.set()

        self.Refresh()

    def _gather_settings_data(self):
        k_one = self.gui_items['keybinds']['ten']['txt'].GetValue()
        k_two = self.gui_items['keybinds']['twenty_five']['txt'].GetValue()
        k_three = self.gui_items['keybinds']['fifty']['txt'].GetValue()

        setting_data = {
            "ten": {
                "amount":
                int(self.gui_items['keybinds']['ten']
                    ['amount_txt'].GetValue()),
                "keybind": {
                    "key": k_one,
                    "key_code": self.configs.VK_CODE[k_one]
                }
            },
            "twenty_five": {
                "amount":
                int(self.gui_items['keybinds']['twenty_five']
                    ['amount_txt'].GetValue()),
                "keybind": {
                    "key": k_two,
                    "key_code": self.configs.VK_CODE[k_two]
                }
            },
            "fifty": {
                "amount":
                int(self.gui_items['keybinds']['fifty']
                    ['amount_txt'].GetValue()),
                "keybind": {
                    "key": k_three,
                    "key_code": self.configs.VK_CODE[k_three]
                }
            }
        }

        return setting_data

    def _on_bind_one_sel(self, e):
        logging.debug("Bind one changed to |{}|".format(
            self.gui_items['keybinds']['ten']['txt'].GetValue()))
        self.key_watcher.settings['ten']['keybind']['key'] = self.gui_items[
            'keybinds']['ten']['txt'].GetValue()

    def _on_bind_one_amt(self, e):
        if self.gui_items['keybinds']['ten']['amount_txt'].GetValue():
            self.key_watcher.settings['ten']['amount'] = int(
                self.gui_items['keybinds']['ten']['amount_txt'].GetValue())
        else:
            self.key_watcher.settings['ten']['amount'] = 10

    def _on_bind_two_sel(self, e):
        logging.debug("Bind two changed to |{}|".format(
            self.gui_items['keybinds']['twenty_five']['txt'].GetValue()))
        self.key_watcher.settings['twenty_five']['keybind'][
            'key'] = self.gui_items['keybinds']['twenty_five']['txt'].GetValue(
            )

    def _on_bind_two_amt(self, e):
        if self.gui_items['keybinds']['twenty_five']['amount_txt'].GetValue():
            self.key_watcher.settings['twenty_five']['amount'] = int(
                self.gui_items['keybinds']['twenty_five']
                ['amount_txt'].GetValue())
        else:
            self.key_watcher.settings['twenty_five']['amount'] = 25

    def _on_bind_three_sel(self, e):
        logging.debug("Bind three changed to |{}|".format(
            self.gui_items['keybinds']['fifty']['txt'].GetValue()))
        self.key_watcher.settings['fifty']['keybind']['key'] = self.gui_items[
            'keybinds']['fifty']['txt'].GetValue()

    def _on_bind_three_amt(self, e):
        if self.gui_items['keybinds']['fifty']['amount_txt'].GetValue():
            self.key_watcher.settings['fifty']['amount'] = int(
                self.gui_items['keybinds']['fifty']['amount_txt'].GetValue())
        else:
            self.key_watcher.settings['fifty']['amount'] = 50

    def _save_settings(self):
        save_settings = {
            "keybinds": {
                "bind1": {
                    "amount":
                    str(self.gui_items['keybinds']['ten']
                        ['amount_txt'].GetValue()),
                    "keybind":
                    self.gui_items['keybinds']['ten']['txt'].GetValue()
                },
                "bind2": {
                    "amount":
                    str(self.gui_items['keybinds']['twenty_five']
                        ['amount_txt'].GetValue()),
                    "keybind":
                    self.gui_items['keybinds']['twenty_five']
                    ['txt'].GetValue()
                },
                "bind3": {
                    "amount":
                    str(self.gui_items['keybinds']['fifty']
                        ['amount_txt'].GetValue()),
                    "keybind":
                    self.gui_items['keybinds']['fifty']['txt'].GetValue()
                }
            },
            "colors": {
                "online": [13, 255, 19],
                "offline": [255, 128, 0]
            }
        }

        self.configs.save_config_data(save_settings)

    def on_close(self, e):
        self._save_settings()
        if self.online_status:
            self.on_start_stop(None)

        logging.debug("Closing application...")
        self.Destroy()
Exemple #8
0
parser = argparse.ArgumentParser()
parser.add_argument('--config_file',
                    help='path/to/config/file',
                    default='./conf.xml')
parser.add_argument('--mode',
                    choices=['synchronize', 'echo'],
                    help='synchronize mode',
                    default='echo')

args = parser.parse_args()

confFile = args.config_file
mode = args.mode

conf = ConfigData(confFile)
conf.show()

md5FilePath = os.path.join(conf.currentDir, MD5FILE)
conf.hashDict = {}

# 初始化
if os.path.exists(md5FilePath):
    with open(md5FilePath) as f:
        for _line in f:
            _path, _md5 = _line.split()
            conf.hashDict[_path] = _md5

# 初始化更新文件md5
for root, dirs, files in os.walk(conf.currentDir):
    for name in files:
Exemple #9
0
    def __init__(self, parent, safetyMode="viewAccess", *args, **kwargs):
        wx.Frame.__init__(self, parent, *args, **kwargs)
        self.safetyMode = safetyMode
        ConfigData.__init__(self, *args, **kwargs)
        StatusBar.__init__(self, parent, *args, **kwargs)
        MenuBar.__init__(self, parent, *args, **kwargs)
        ToolBar.__init__(self, parent, *args, **kwargs)
        TreeContextMenu.__init__(self, parent, *args, **kwargs)

        # Some actions which are not relevant for any specific area
        Actions.__init__(self, *args, **kwargs)
        # The functions to enable printing
        Printing.__init__(self, parent, *args, **kwargs)
        # The functions to enable the help system
        Help.__init__(self, *args, **kwargs)
        # The functions to enable the about dialog
        About.__init__(self, *args, **kwargs)
        # The functions to enable the about dialog
        Settings.__init__(self, *args, **kwargs)
        #Set main splitter
        MainSplitter.__init__(self, *args, **kwargs)
        #Add the xml tree
        Document.__init__(self, *args, **kwargs)
        #Fill xml tree
        GetData.__init__(self, *args, **kwargs)
        #Add functions to modify the view of the xml tree
        ViewData.__init__(self, *args, **kwargs)
        #Add functions to edit the xml tree
        EditData.__init__(self, *args, **kwargs)

        #Copy example files: Comment this out if Template-Designer is in productive use.
        #self.getExamples()
        #Some kind of self check
        self.saveConfig()

        #Set panels
        #self.propertiesPanel = wx.Panel(self.mainSplitter)
        self.propertiesPanel = wx.ScrolledWindow(self.mainSplitter)
        self.templatePanel   = wx.Panel(self.mainSplitter)

        #Buttons on main frame
        self.applyButton       = wx.Button(self.propertiesPanel, 
                                           wx.ID_APPLY, 
                                           _(u"Apply changes"), 
                                           name="applyButton")
        self.defaultsButton    = wx.Button(self.propertiesPanel, 
                                           wx.ID_RESET, 
                                           _(u"Restore settings"), 
                                           name="defaultsButtons")

        expandAllButtonPath = self.documentTreeGraphics() + "/2downarrow.png"
        expandAllButtonBmp = wx.Image(expandAllButtonPath, wx.BITMAP_TYPE_PNG).ConvertToBitmap()
        self.expandAllButton   = wx.BitmapButton(self.templatePanel, 
                                                 -1, 
                                                 expandAllButtonBmp, 
                                                 name="expandButton")

        collapseAllButtonPath = self.documentTreeGraphics() + "/2uparrow.png"
        collapseAllButtonBmp = wx.Image(collapseAllButtonPath, wx.BITMAP_TYPE_PNG).ConvertToBitmap()
        self.collapseAllButton   = wx.BitmapButton(self.templatePanel, 
                                                 -1, 
                                                 collapseAllButtonBmp, 
                                                 name="collapseButton")

        addButtonPath = self.documentTreeGraphics() + "/filenew.png"
        addButtonBmp = wx.Image(addButtonPath, wx.BITMAP_TYPE_PNG).ConvertToBitmap()
        self.addButton   = wx.BitmapButton(self.templatePanel, 
                                                 -1, 
                                                 addButtonBmp, 
                                                 name="addButton")

        deleteButtonPath = self.documentTreeGraphics() + "/edit_delete.png"
        deleteButtonBmp = wx.Image(deleteButtonPath, wx.BITMAP_TYPE_PNG).ConvertToBitmap()
        self.deleteButton   = wx.BitmapButton(self.templatePanel, 
                                                 -1, 
                                                 deleteButtonBmp, 
                                                 name="deleteButton")

        """
        Set taskbar icon. If you remove this, do not forget to remove 
        the RemoveIcon() and Destroy() methods 
        in self.onCloseWindow()
        
        """
        self.taskBarIcon = wx.TaskBarIcon()
        iconPath = self.skinGraphics() + "/domtreeviewer.png"
        icon = wx.Icon(iconPath, wx.BITMAP_TYPE_PNG)
        self.taskBarIcon.SetIcon(icon, _(u"Template-Designer"))

        #Set titlebar icon
        self.SetIcon(icon)

        #Initiate the contents of the property panel
        self.pp = pp

        self.__doProperties()
        self.__doBindings()
        self.__doLayout()
        Safety(self)
Exemple #10
0
class TemplateDesignerWelcome(wx.Frame):
    """Generally called by class TemplateDesigner
    
    returns nothing but calls  class TemplateDesignerFrame 
    if user decides not to leave the dialog
    
    """
    def __init__(self, 
                 parent, 
                 style = wx.FULL_REPAINT_ON_RESIZE, 
                 flag = wx.ADJUST_MINSIZE):
        wx.Frame.__init__(self, parent, -1, _(u"Template-Designer"))

        self.myConfig = ConfigData()
        self.myConfig.saveConfig()

        """
        Set taskbar icon. If you remove this, do not forget to 
        remove the RemoveIcon() and Destroy() methods 
        in self.OnExitWindow()
        """
        self.taskBarIcon = wx.TaskBarIcon()
        iconPath = self.myConfig.skinGraphics() + "/domtreeviewer.png"
        icon = wx.Icon(iconPath, wx.BITMAP_TYPE_PNG)
        self.taskBarIcon.SetIcon(icon, _(u"Template-Designer"))

        #Set titlebar icon
        self.SetIcon(icon)

        self.logoPanel = wx.Panel(self, -1)
        self.settingsPanel = wx.Panel(self, -1)

        self.fullRadio = wx.RadioButton(self.settingsPanel,
                                        -1, _(u"Full Access"),
                                        name="fullAccess")
        self.fullRadio.SetValidator(WelcomeValidator(self))

        self.restrictedRadio = wx.RadioButton(self.settingsPanel, 
                                              -1, _(u"Restricted Access"), 
                                              name="restrictedAccess")
        self.restrictedRadio.SetValidator(WelcomeValidator(self))

        self.viewRadio = wx.RadioButton(self.settingsPanel, 
                                        -1, _(u"View available templates"), 
                                        name="viewAccess")
        self.viewRadio.SetValidator(WelcomeValidator(self))

        self.placeholderPanel = wx.Panel(self.settingsPanel, -1)

        self.passwordLabel = wx.StaticText(self.settingsPanel, 
                                           -1, _(u"Password"), 
                                           name="passwordLabel")
        self.passwordTextCtrl = wx.TextCtrl(self.settingsPanel, 
                                            -1, "", 
                                            style=wx.TE_PASSWORD, 
                                            name="password")
        self.passwordTextCtrl.SetValidator(WelcomeValidator(self))

        logo = wx.Bitmap("logo.png", wx.BITMAP_TYPE_ANY)
        self.logoBitmap = wx.StaticBitmap(self.logoPanel, 
                                          -1, 
                                          logo)

        self.staticLine = wx.StaticLine(self, -1)

        self.bitplantLabel = wx.StaticText(self, -1, _(u"Bitplant Template-Designer"))
        self.goButton = wx.Button(self, -1, _(u"OK"), name="goButton")
        self.goButton.SetValidator(WelcomeValidator(self))
        self.exitButton = wx.Button(self, -1, _(u"Exit"), name="exitButton")

        self.__doProperties()
        self.__doBindings()
        self.__doLayout()

    def OnExitWindow(self, event=None):
        """close the Welcome dialog
        
        removes the taskbar icon and destroys the dialog 
        if user clicked the exitButton
        
        """
        self.taskBarIcon.RemoveIcon()
        self.taskBarIcon.Destroy()
        self.Destroy()

    def __doBindings(self):
        self.Bind(wx.EVT_CLOSE, self.OnExitWindow)
        self.Bind(wx.EVT_BUTTON, self.OnExitWindow, self.exitButton)

    def __doProperties(self):
        self.SetTitle(_(u"Bitplant Template-Designer"))
        self.SetMinSize((600, 250))
        white = wx.Colour(255, 255, 255)
        self.logoPanel.SetBackgroundColour(white)
        font = wx.Font(9, wx.SWISS, wx.ITALIC, wx.LIGHT, 0, "")
        self.bitplantLabel.SetFont(font)
        self.goButton.Disable()
        self.passwordLabel.Disable()
        self.passwordTextCtrl.Disable()
        self.restrictedRadio.SetValue(True)

    def __doLayout(self):
        sizerStyle = wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL

        radioSizer = wx.BoxSizer(wx.VERTICAL)
        radioSizer.Add(self.fullRadio, 1, wx.EXPAND, 0)
        radioSizer.Add(self.restrictedRadio, 1, wx.EXPAND, 0)
        radioSizer.Add(self.viewRadio, 1, wx.EXPAND, 0)
        radioSizer.Add(self.placeholderPanel, 2, wx.EXPAND, 0)

        passwordSizer = wx.BoxSizer(wx.HORIZONTAL)
        passwordSizer.Add(self.passwordLabel, 0, wx.RIGHT, 4)
        passwordSizer.Add(self.passwordTextCtrl, 1, 0, 0)

        settingsSizer = wx.BoxSizer(wx.VERTICAL)
        settingsSizer.Add(radioSizer, 1, wx.ALL|wx.EXPAND, 0)
        settingsSizer.Add(passwordSizer, 0, sizerStyle, 4)
        self.settingsPanel.SetSizer(settingsSizer)

        logoSizer = wx.BoxSizer(wx.HORIZONTAL)
        logoSizer.Add(self.logoBitmap, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 24)
        self.logoPanel.SetSizer(logoSizer)

        settingsLogoSizer = wx.BoxSizer(wx.HORIZONTAL)
        settingsLogoSizer.Add(self.settingsPanel, 1, wx.ALL|wx.EXPAND, 4)
        settingsLogoSizer.Add(self.logoPanel, 0, sizerStyle, 0)

        buttonBoxSizer = wx.BoxSizer(wx.HORIZONTAL)
        buttonBoxSizer.Add(self.bitplantLabel, 1, wx.ALL|wx.ALIGN_BOTTOM, 4)
        buttonBoxSizer.Add(self.goButton, 0, wx.ALL, 4)
        buttonBoxSizer.Add(self.exitButton, 0, wx.ALL, 4)

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        mainSizer.Add(settingsLogoSizer, 1, wx.ALL|wx.EXPAND, 0)
        mainSizer.Add(self.staticLine, 0, wx.ALL|wx.EXPAND, 4)
        mainSizer.Add(buttonBoxSizer, 0, wx.ALL|wx.EXPAND, 4)
        self.SetSizer(mainSizer)

        mainSizer.Fit(self)
        self.Layout()
Exemple #11
0
    def __init__(self, 
                 parent, 
                 style = wx.FULL_REPAINT_ON_RESIZE, 
                 flag = wx.ADJUST_MINSIZE):
        wx.Frame.__init__(self, parent, -1, _(u"Template-Designer"))

        self.myConfig = ConfigData()
        self.myConfig.saveConfig()

        """
        Set taskbar icon. If you remove this, do not forget to 
        remove the RemoveIcon() and Destroy() methods 
        in self.OnExitWindow()
        """
        self.taskBarIcon = wx.TaskBarIcon()
        iconPath = self.myConfig.skinGraphics() + "/domtreeviewer.png"
        icon = wx.Icon(iconPath, wx.BITMAP_TYPE_PNG)
        self.taskBarIcon.SetIcon(icon, _(u"Template-Designer"))

        #Set titlebar icon
        self.SetIcon(icon)

        self.logoPanel = wx.Panel(self, -1)
        self.settingsPanel = wx.Panel(self, -1)

        self.fullRadio = wx.RadioButton(self.settingsPanel,
                                        -1, _(u"Full Access"),
                                        name="fullAccess")
        self.fullRadio.SetValidator(WelcomeValidator(self))

        self.restrictedRadio = wx.RadioButton(self.settingsPanel, 
                                              -1, _(u"Restricted Access"), 
                                              name="restrictedAccess")
        self.restrictedRadio.SetValidator(WelcomeValidator(self))

        self.viewRadio = wx.RadioButton(self.settingsPanel, 
                                        -1, _(u"View available templates"), 
                                        name="viewAccess")
        self.viewRadio.SetValidator(WelcomeValidator(self))

        self.placeholderPanel = wx.Panel(self.settingsPanel, -1)

        self.passwordLabel = wx.StaticText(self.settingsPanel, 
                                           -1, _(u"Password"), 
                                           name="passwordLabel")
        self.passwordTextCtrl = wx.TextCtrl(self.settingsPanel, 
                                            -1, "", 
                                            style=wx.TE_PASSWORD, 
                                            name="password")
        self.passwordTextCtrl.SetValidator(WelcomeValidator(self))

        logo = wx.Bitmap("logo.png", wx.BITMAP_TYPE_ANY)
        self.logoBitmap = wx.StaticBitmap(self.logoPanel, 
                                          -1, 
                                          logo)

        self.staticLine = wx.StaticLine(self, -1)

        self.bitplantLabel = wx.StaticText(self, -1, _(u"Bitplant Template-Designer"))
        self.goButton = wx.Button(self, -1, _(u"OK"), name="goButton")
        self.goButton.SetValidator(WelcomeValidator(self))
        self.exitButton = wx.Button(self, -1, _(u"Exit"), name="exitButton")

        self.__doProperties()
        self.__doBindings()
        self.__doLayout()
Exemple #12
0
class FileSync:
    INFO_DIR = '.filesync/'
    MD5_FILE = 'md5'
    IGNORE_FILE = '.fileignore'

    MODE_ECHO = 'echo'
    MODE_SYNCHRONIZE = 'synchronize'

    def __init__(self, configFileName, mode, time_cycle, d):
        # 多线程用,quit flag
        self.quit = False

        # 同步模式
        self.mode = mode

        # 自动同步时间
        self.time_cycle = time_cycle

        # 自动在同步前清空远端文件夹
        self.autoDelete = d

        # RPC 端口
        self.rpc_port = slave.PORT

        # 符合条件的路径会被排除   {dir:[re]}
        self.ignoreExp = defaultdict(list)

        # 文件对应的修改时间和md5   {file:(md5,time)}
        self.file2md5time = {}

        # 读取配置文件
        self.config = ConfigData(configFileName)
        self.config.show()

        # 建立存放同步用数据的文件夹
        self.infoDir = os.path.join(self.config.currentDir, self.INFO_DIR)
        if not os.path.exists(self.infoDir):
            os.makedirs(self.infoDir)

        self.remoteInfoDir = os.path.join(self.config.remoteDir, self.INFO_DIR)

        # 读取本地同步文件夹信息
        self._loadDir()

    def _loadDir(self):
        """
        读取.fileignore文件
        读取文件目录结构
        导出.filesync文件
        :return:
        """
        self.__updateDirIgnore(self.config.currentDir)
        self.__updateDirMD5(self.config.currentDir)
        self.dumpMD5(self.infoDir)

    def updateIgnore(self, curDir):
        """
        读取`curDir`路径下的.fileignore文件
        当文件不存在时,删除`self.ignoreExp`中对应键值对
        :param curDir:
        :return:
        """
        changed = False

        ignoreFile = os.path.join(curDir, self.IGNORE_FILE)

        if not os.path.exists(ignoreFile):
            if not self.ignoreExp[curDir]:
                return False
            else:
                del self.ignoreExp[curDir]
                return True

        with open(ignoreFile, 'r') as f:
            exps = f.read().split('\n')

        exps.sort()  # 保证用户以不同顺序写的两组相同表达式不会影响`changed`变量

        oldExps = self.ignoreExp.get(curDir, [])

        newExps = []
        for exp in map(str.strip, exps):
            try:
                re.compile(exp)  # 测试表达式
                newExps.append(exp)  # 无法处理 修改.fileignore事件 故取消预编译设计
            except:
                print(traceback.format_exc())

        if newExps != oldExps:  # 这里的比较是逐元素比较
            self.ignoreExp[curDir] = newExps
            changed = True

        return changed

    def __updateDirIgnore(self, curDir):
        """
        DFS文件路径,读取所有的.fileignore文件
        :param curDir:
        :return:
        """
        if curDir[-1] != '/':
            curDir += '/'

        fileNames = os.listdir(curDir)

        if self.IGNORE_FILE in fileNames:
            self.updateIgnore(curDir)

        for filename in os.listdir(curDir):
            fullPath = os.path.join(curDir, filename)
            if os.path.isdir(fullPath):
                self.__updateDirIgnore(fullPath)

    def __DFSIncludedFile(self, curDir, fun):
        """
        辅助函数DFS遍历未被忽略的函数
        :param curDir:
        :param fun: function(fullPath):void
        :return:
        """
        if curDir[-1] != '/':
            curDir += '/'

        for filename in os.listdir(curDir):
            # 检查是否忽略
            if self.__isIgnore(filename, curDir):
                continue

            fullPath = os.path.join(curDir, filename)
            if os.path.isdir(fullPath):
                self.__DFSIncludedFile(fullPath, fun)
            else:
                fun(fullPath)

    def updateMD5(self, fullPath):
        """
        当md5变化时,文件粒度更新`self.file2md5time`
        当文件不存在时,删除`self.file2md5time`中对应键值对
        :param fullPath:
        :return: bool 是否更新了self.file2md5time
        """

        oldMd5, oldTime = self.file2md5time.get(fullPath, (None, None))

        if not os.path.exists(fullPath):
            if oldMd5 is None:
                return False, oldMd5, oldTime
            else:
                del self.file2md5time[fullPath]
                return True, oldMd5, oldTime

        newMd5 = file2md5(fullPath)
        if oldMd5 != newMd5:
            time = os.stat(fullPath).st_mtime  # 文件修改时间 时间戳
            self.file2md5time[fullPath] = (newMd5, time)
            return True, oldMd5, oldTime

        return False, oldMd5, oldTime

    def __updateDirMD5(self, curDir):
        """
        文件夹粒度更新md5
        :param curDir:
        :return:
        """
        self.__DFSIncludedFile(curDir, self.updateMD5)

    def __isIgnore(self, fileName, parentDir):
        """
        检查一个文件是否符合忽略规则
        !!!无法检测祖先文件夹是否被忽略,在此情况下失效
        :param fileName:
        :param parentDir:
        :return:
        """
        if fileName == self.INFO_DIR[:-1] or fileName == self.IGNORE_FILE:
            return True
        assert parentDir[-1] == '/'

        ignore = False
        # if not self.ignoreExp[parentDir] : skip for loop
        for exp in self.ignoreExp[parentDir]:
            if re.match(exp, fileName):
                ignore = True
                break
        return ignore

    def isIgnorePlus(self, fullPath):
        """
        检查一个文件是否符合忽略规则
        :param fullPath:
        :return:
        """
        curFile = os.path.basename(fullPath)
        curDir = os.path.dirname(fullPath) + '/'

        while True:
            ignore = self.__isIgnore(curFile, curDir)
            if ignore:
                return True

            if curDir == self.config.currentDir:
                break

            curFile = os.path.basename(curDir[:-1])
            curDir = os.path.dirname(curDir[:-1]) + '/'

        return False

    def dumpMD5(self, path=None):
        """
        将self.file2md5time中的数据导出到文件
        :param path:
        :return:
        """
        if not path:
            path = self.infoDir

        if path[-1] != '/':
            path += '/'

        md5FilePath = os.path.join(path, self.MD5_FILE)
        data = [(fileName, md5, time)
                for fileName, (md5, time) in self.file2md5time.iteritems()]
        content = '\n'.join(
            ['|'.join(map(str, i)) for i in sorted(data, key=lambda x: x[0])])
        with open(md5FilePath, 'w') as f:
            f.write(content)

    def _init(self):
        """
        初始化
        将slave发送到对应目录下并运行
        echo mode        检查文件夹是否为空并询问是否删除,结束
        synchronize mode 检查文件夹是否为空并询问是否删除,开始运行
        :return:
        """

        # 暂时存放slave.py的位置
        TEMP_DIR = '/tmp/filesync/'

        # create remore TEMP_DIR
        cmd = "mkdir -p %s" % TEMP_DIR
        doRemoteCmd(self.config, cmd, printOut=True)

        # 传输slave脚本并运行
        # slaveDest = os.path.join(self.remoteInfoDir, 'slave.py')
        slaveDest = os.path.join(TEMP_DIR, 'slave.py')
        sftp_put('./slave.py', slaveDest, self.config)  # 需要添加故障检测?
        # slaveLog = os.path.join(self.remoteInfoDir, 'slave.log')
        slaveLog = os.path.join(TEMP_DIR, 'slave.log')
        cmd = 'nohup python %s 1>%s 2>&1 &'  # no mode flag
        doRemoteCmd(self.config, cmd % (slaveDest, slaveLog))

        # check if the remote directory exists
        server = create_server(self.config.ssh_host, self.rpc_port)
        code = check_path(self.config.remoteDir, server)
        close_server(server)
        if code == slave.CODE_DIR_EMPTY:
            print('remote directory is empty')
        elif code == slave.CODE_DIR_NOT_EMPTY:
            print('remote directory %s is NOT empty!' % self.config.remoteDir)
            if self.autoDelete:
                agree = True
            else:
                agree = getAnswer('delete all before sync? y/n\n')
            if agree:
                doRemoteCmd(self.config, 'rm %s -rf' % self.config.remoteDir)
            else:
                exit(0)
        elif code == slave.CODE_FILE_EXIST:
            print('remote directory name conflicts with an existing file!')
            exit(1)
        else:
            print('can not understand return code')
            exit(1)

        print('\nstart sync now...\n')

        # create remore infoDir
        cmd = "mkdir -p %s" % self.remoteInfoDir
        doRemoteCmd(self.config, cmd, printOut=True)

        # scp all included file
        self.__DFSIncludedFile(self.config.currentDir,
                               lambda path: doScp(path, self.config))

        if self.mode == self.MODE_ECHO:
            pass
        elif self.mode == self.MODE_SYNCHRONIZE:
            self.__initSynchronize()

    def __initSynchronize(self):
        """
        将slave传到remoteInfoDir
        启动slave,建立远端md5文件,开始远端的本地监听,在本地要求同步时,提供对应文件的md5和时间标记
        todo 通信安全
        :return:
        """
        # 传输slave脚本并运行
        slaveDest = os.path.join(self.remoteInfoDir, 'slave.py')
        sftp_put('./slave.py', slaveDest, self.config)  # 需要添加故障检测?
        slaveLog = os.path.join(self.remoteInfoDir, 'slave.log')
        cmd = 'nohup python %s --mode %s --time_cycle %s --working_dir %s 1>%s 2>&1 &'
        doRemoteCmd(
            self.config, cmd % (slaveDest, self.mode, self.time_cycle,
                                self.config.remoteDir, slaveLog))

    def _run(self):
        """
        开始监听本地动作
        :return:
        """
        # do sync on modify
        event_handler = SyncHandler(self)
        observer = Observer()
        observer.schedule(event_handler,
                          path=self.config.currentDir,
                          recursive=True)
        observer.start()

        print("\n----watchdog start working----\n")

        try:
            while True:
                sleep(1)
        except KeyboardInterrupt:
            print('stop observer...')
            self.quit = True
            observer.stop()
        observer.join()
        server = create_server(self.config.ssh_host, self.rpc_port)
        close_server(server)

    def runforever(self):
        self._init()
        self._run()