Exemple #1
0
 def test_set_and_get_token(self):
     board  = BoardModel(3)
     board.set_token(0, 0, 'white')
     board.set_token(2, 1, 'black')
     self.assertEqual('black', board.get_token(2, 1))
     self.assertEqual('white', board.get_token(0, 0))
     self.assertEqual('empty', board.get_token(1, 1))
Exemple #2
0
    def __init__(self, host='', port=2222):
        self.host = host    # Symbolic name meaning all available interfaces
        self.port = port    # Arbitrary non-privileged port
        self.network_data = None

        # Datagram (udp) socket
        try :
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            print('Socket created')
        except socket.error as exp :
            print('Failed to create socket. Because: %s', str(exp))
            raise

        # Bind socket to local host and port
        try:
            self.socket.bind((self.host, self.port))
            print('Socket bind complete.')
        except socket.error as exp:
            print('Failed to bind the socket. Because: %s', str(exp))
            raise
            
        try:
            self.db_connection = sqlite3.connect(DB_PATH)
            self.db_connection_cursor = self.db_connection.cursor()
            print('Data base connected.')
        except Exception as exp:
            print('Failed to connect to the database. Because: %s', str(exp))
            raise
        
        self.board_model = BoardModel(self.get_all_device_list())
Exemple #3
0
 def test_get_neighbours(self):
     board = BoardModel(3)
     self.assertEqual(
             [(0, 1), (1, 0), (1, 2), (2, 1)],
             sorted(board.get_neighbours(1, 1)))
     self.assertEqual(
             [(0, 1), (1, 0)],
             sorted(board.get_neighbours(0, 0)))
Exemple #4
0
 def test_on_board(self):
     board  = BoardModel(3)
     self.assertTrue(board.on_board(0, 0))
     self.assertTrue(board.on_board(2, 1))
     self.assertFalse(board.on_board(-1, 0))
     self.assertFalse(board.on_board(0, 3))
     self.assertFalse(board.on_board(3, 0))
     self.assertFalse(board.on_board(2, -2))
Exemple #5
0
 def test_str_and_unicode(self):
     board = BoardModel(3)
     board.set_token(0, 0, 'white')
     board.set_token(2, 1, 'black')
     board_text = (
             u"w e e\n"
             u"e e e\n"
             u"e b e")
     self.assertEqual(board_text, unicode(board))
     self.assertEqual(board_text, str(board))
Exemple #6
0
    def newgame(self):
        '''Creates a new game based on the player's options'''
        player1AI = None
        player2AI = None
        model = BoardModel(
            width=int(self.width.get()),
            height=int(self.height.get()),
            k=int(self.k.get()),
            gravity=True if self.gravity.get() == "On" else False)
        #Setup human or AI player
        if (self.player1.get()):
            p1 = self.listbox_p1_AI.get()
            if len(p1) != 0:
                player1AI = p1  #Load AI Player
            else:
                raise NoAISelectedError("Select file for plater 1 AI.")

        if (self.player2.get()):
            p2 = self.listbox_p2_AI.get()
            if len(p2) != 0:
                player2AI = p2  #Load AI Player
            else:
                raise NoAISelectedError("Select file for plater 2 AI.")

        self.destroy()
        self.parent.destroy()
        create_newgame(model, player1AI, player2AI)
Exemple #7
0
 def test_board_from_string(self):
     board_string = (
             "w e e\n"
             "e e e\n"
             "e b e")
     board = BoardModel.from_string(board_string)
     self.assertEqual(board_string, str(board))
Exemple #8
0
 def setUp(self):
     self.board_string = (
             "w e e\n"
             "e b e\n"
             "w w b")
     self.board = BoardModel.from_string(self.board_string)
     self.game_state = GameState()
     self.game_state.board = self.board
Exemple #9
0
 def test_is_dead(self):
     board_string = (
             "b b w e e\n"
             "b w e w e\n"
             "w b b e w\n"
             "e w w b b\n"
             "e e b w w")
     board = BoardModel.from_string(board_string)
     self.assertTrue(board.is_dead(0, 0))
     self.assertFalse(board.is_dead(0, 3))
     self.assertTrue(board.is_dead(4, 4))
     self.assertFalse(board.is_dead(3, 0))
     board_string = (
             "e e e\n"
             "e b e\n"
             "e e e")
     board = BoardModel.from_string(board_string)
     self.assertFalse(board.is_dead(1, 1))
Exemple #10
0
 def setUp(self):
     self.board_string = (
             "w e e\n"
             "w b e\n"
             "w w b")
     self.board = BoardModel.from_string(self.board_string)
     self.game_state = GameState()
     self.game_state.board = self.board
     self.game_state.stage = "dead stones removing"
Exemple #11
0
 def setUp(self):
     self.score_area = AreaScoring()
     self.game_state = GameState()
     self.game_state.board = BoardModel.from_string(
             "e e w e\n"
             "w e w b\n"
             "b w b e\n"
             "e b e e")
     self.game_state.stage = "dead stones removing"
     self.captives_count = {
             "black": 15,
             "white": 15
             }
Exemple #12
0
 def __init__(self, app):
     QMainWindow.__init__(self, None)
     self.app = app
     self.boardModel = BoardModel(self.app)
     self._setupUi()
     self._refreshActionsState()
     
     self.connect(self.browserView.selectionModel(), SIGNAL('selectionChanged(QItemSelection,QItemSelection)'), self.browserSelectionChanged)
     self.connect(self.app, SIGNAL('boardChanged()'), self.boardChanged)
     
     # Actions
     self.connect(self.actionActions, SIGNAL('triggered()'), self.actionsTriggered)
     self.connect(self.actionMaterialize, SIGNAL('triggered()'), self.materializeTriggered)
     self.connect(self.actionShowLocations, SIGNAL('triggered()'), self.showLocationsTriggered)
     self.connect(self.actionShowDetails, SIGNAL('triggered()'), self.showDetailsTriggered)
     self.connect(self.actionShowIgnoreBox, SIGNAL('triggered()'), self.showIgnoreBoxTriggered)
     self.connect(self.actionAddLocation, SIGNAL('triggered()'), self.addLocationTriggered)
     self.connect(self.actionRemoveLocation, SIGNAL('triggered()'), self.removeLocationTriggered)
     self.connect(self.actionUpdateLocation, SIGNAL('triggered()'), self.updateLocationTriggered)
     self.connect(self.actionQuit, SIGNAL('triggered()'), QCoreApplication.instance().quit)
     self.connect(self.actionNewFolder, SIGNAL('triggered()'), self.newFolderTriggered)
     self.connect(self.actionRemoveEmptyFolders, SIGNAL('triggered()'), self.removeEmptyFoldersTriggered)
     self.connect(self.actionRenameSelected, SIGNAL('triggered()'), self.renameSelectedTriggered)
     self.connect(self.actionMoveSelectedToIgnoreBox, SIGNAL('triggered()'), self.moveSelectedToIgnoreBoxTriggered)
     self.connect(self.actionSwitchConflictAndOriginal, SIGNAL('triggered()'), self.switchConflictAndOriginalTriggered)
     self.connect(self.actionMassRename, SIGNAL('triggered()'), self.massRenameTriggered)
     self.connect(self.actionSplit, SIGNAL('triggered()'), self.splitTriggered)
     self.connect(self.actionUndoSplit, SIGNAL('triggered()'), self.undoSplitTriggered)
     self.connect(self.actionMoveConflicts, SIGNAL('triggered()'), self.moveConflictsTriggered)
     self.connect(self.actionMoveConflictsAndOriginals, SIGNAL('triggered()'), self.moveConflictsAndOriginalsTriggered)
     self.connect(self.actionRenameInRespectiveLocations, SIGNAL('triggered()'), self.renameInRespectiveLocationsTriggered)
     self.connect(self.actionCopyToOtherLocation, SIGNAL('triggered()'), self.copyToOtherLocationTriggered)
     self.connect(self.actionMoveToOtherLocation, SIGNAL('triggered()'), self.moveToOtherLocationTriggered)
     self.connect(self.actionShowHelp, SIGNAL('triggered()'), self.showHelpTriggered)
     self.connect(self.actionRegister, SIGNAL('triggered()'), self.registerTrigerred)
     self.connect(self.actionCheckForUpdate, SIGNAL('triggered()'), self.checkForUpdateTriggered)
     self.connect(self.actionOpenDebugLog, SIGNAL('triggered()'), self.openDebugLogTriggered)
     self.connect(self.actionAbout, SIGNAL('triggered()'), self.aboutTriggered)
Exemple #13
0
 def test_remove_group(self):
     board_string = (
             "b b w e e\n"
             "b w e w e\n"
             "w b b e w\n"
             "e w w b b\n"
             "e e b w w")
     board = BoardModel.from_string(board_string)
     self.assertEquals(3, deepcopy(board).remove_group(0, 0))
     self.assertEquals(2, deepcopy(board).remove_group(3, 1))
     self.assertEquals(0, deepcopy(board).remove_group(4, 0))
     self.assertEquals(3, board.remove_group(0, 0))
     self.assertEquals((
             "e e w e e\n"
             "e w e w e\n"
             "w b b e w\n"
             "e w w b b\n"
             "e e b w w"), str(board))
Exemple #14
0
 def test_get_group(self):
     board_string = (
             "b b w e e\n"
             "b w e w e\n"
             "w b b w w\n"
             "e w w w e\n"
             "e e e w e")
     board = BoardModel.from_string(board_string)
     self.assertEqual(([(0, 0), (0, 1), (1, 0)], ("white", )),
             board.get_group(0, 0))
     self.assertEqual(([(2, 0)], ("black", "empty")),
             board.get_group(2, 0))
     self.assertEqual(([(3, 4), (4, 4)], ("white", )),
             board.get_group(4, 4))
     doctest.run_docstring_examples(
             BoardModel.get_group,
             {"BoardModel": BoardModel},
             name="get_group")
Exemple #15
0
 def test_ko(self):
     board = BoardModel.from_string((
             "e e e e\n"
             "e b w e\n"
             "b w e w\n"
             "e b w e"))
     self.game_state.board = board
     game_state = self.game_state
     move = PlaceStoneMove(2, 2)
     self.assertTrue(move.validate(game_state))
     game_state = move(game_state)
     move = PlaceStoneMove(2, 1)
     self.assertFalse(move.validate(game_state))
     move = PlaceStoneMove(0, 1)
     self.assertTrue(move.validate(game_state))
     game_state = move(game_state)
     move = PlaceStoneMove(2, 1)
     self.assertTrue(move.validate(game_state))
Exemple #16
0
def create_newgame(model=None,
                   player1AI=None,
                   player2AI=None,
                   gui=True,
                   stepmode=False):
    '''Creates a new game. If no_gui, both players must be AI players'''
    if not gui:
        '''No GUI'''
        if player1AI is not None and player2AI is not None:
            player1 = AIPlayer(1, model, player1AI)
            player2 = AIPlayer(2, model, player2AI)
            game = connectk.ConnectK(model, player1, player2)
            p = Thread(target=game.play)
            p.start()
            return
        else:
            raise NoGUIError(
                "If no GUI option is used, both players must be AIs.")
    else:
        '''GUI'''
        root = TK.Tk()
        if model is None:
            model = BoardModel()  #New instance with default settings
        gui = ConnectKGUI(root, model)
        if stepmode:
            gui.stepmode.set(True)

        if player1AI is None:
            player1 = GUIPlayer(1, model)
            gui.add_button_listener(player1.action_listener, 1)
        else:
            player1 = AIPlayer(1, model, player1AI)

        if player2AI is None:
            player2 = GUIPlayer(2, model)
            gui.add_button_listener(player2.action_listener, 2)
        else:
            player2 = AIPlayer(2, model, player2AI)

        game = connectk.ConnectK(model, player1, player2, gui)
        p = Thread(target=game.play)
        gui.update_gui(time=2)
        p.start()
        root.mainloop()
Exemple #17
0
class Sender:
    def __init__(self, host='192.168.1.1', port=2223):
        self.HOST = host  # Symbolic name meaning all available interfaces
        self.PORT = port  # Arbitrary non-privileged port

        # Datagram (udp) socket
        try:
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            print('Socket created')
        except socket.error as exp:
            print('Failed to create socket. Because: %s', str(exp))
            raise

        # Bind socket to local host and port
        try:
            self.socket.bind(('', self.PORT))
            print('Socket bind complete')
        except socket.error as exp:
            print('Failed to bind the socket. Because: %s', str(exp))
            raise

        try:
            self.db_connection = sqlite3.connect(DB_PATH)
            self.db_cursor_connection = self.db_connection.cursor()
            print('Data base connected.')
        except Exception as exp:
            print('Failed to connect to the database. Because: %s', str(exp))
            raise

        self.board_model = BoardModel(self.get_all_device_list())

    def destruct(self):
        self.socket.close()
        self.db_connection.close()

    def get_all_device_list(self):
        res = self.db_connection.execute(
            "SELECT id,channel,pos,isAnalog FROM backend_accessories")
        res = [{
            'id': x[0],
            'channel': x[1],
            'pos': x[2],
            'isAnalog': x[3]
        } for x in res]
        return res

    def get_device_status(self):
        res = self.db_connection.execute(
            "SELECT id,status,analogValue FROM backend_accessories")
        res = [{'id': x[0], 'status': x[1], 'analogValue': x[2]} for x in res]
        return res

    def print_changes(self):
        changes = self.board_model.get_changed_keys()
        if changes:
            for _, d in changes.items():
                if d.type == 'hvac':
                    print('%d) change hvac to %d (status=%d)' %
                          (d.id, d.value, d.status))
                elif d.type == 'key':
                    print('%d) change key to %d' % (d.id, d.status))

    def send_payload(self):
        if DEBUG:
            print('sending: ', [r for r in self.board_model.to_byte_array()])
        res = self.socket.sendto(self.board_model.to_byte_array(),
                                 (self.HOST, self.PORT))
        if res and res != 14 and DEBUG:
            res_text = ('  (%s)' %
                        error_list[res]) if res in error_list else ''
            print('send-to function fail: %d%s' % (res, res_text))

    def send(self):
        status_list = self.get_device_status()
        self.board_model.load_status(status_list)
        self.print_changes()
        self.send_payload()
Exemple #18
0
class Receiver:
    def __init__(self, host='', port=2222):
        self.host = host    # Symbolic name meaning all available interfaces
        self.port = port    # Arbitrary non-privileged port
        self.network_data = None

        # Datagram (udp) socket
        try :
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            print('Socket created')
        except socket.error as exp :
            print('Failed to create socket. Because: %s', str(exp))
            raise

        # Bind socket to local host and port
        try:
            self.socket.bind((self.host, self.port))
            print('Socket bind complete.')
        except socket.error as exp:
            print('Failed to bind the socket. Because: %s', str(exp))
            raise
            
        try:
            self.db_connection = sqlite3.connect(DB_PATH)
            self.db_connection_cursor = self.db_connection.cursor()
            print('Data base connected.')
        except Exception as exp:
            print('Failed to connect to the database. Because: %s', str(exp))
            raise
        
        self.board_model = BoardModel(self.get_all_device_list())

    def get_all_device_list(self):
        res = self.db_connection.execute("SELECT id,channel,pos,isAnalog FROM backend_accessories")
        res = [{'id': x[0], 'channel': x[1], 'pos': x[2], 'isAnalog': x[3]} for x in res]
        return res

    def get_device_status(self):
        res = self.db_connection.execute("SELECT id,status,analogValue,isActive FROM backend_accessories")
        res = [{'id': x[0], 'status': x[1], 'analogValue': x[2], 'isActive': x[3]} for x in res]
        # FIXME: make digital status only boolean
        return res

    def destruct(self):
        self.socket.close()
        self.db_connection.close()

    def update_data_from_network(self):
        data, addr = self.socket.recvfrom(1024)
        if not data: 
            raise Exception('invalid data recieved.')
        self.network_data = bytearray(data.strip())

    def apply_changes(self):
        changed_keys = self.board_model.get_changed_keys()
        if changed_keys:
            for _, k in changed_keys.items():
                if k.type == 'key':
                    self.set_key_on_db(k.id, k.status)
                elif k.type == 'hvac':
                    self.set_hvac_on_db(k.id, k.status)
            self.db_connection.commit()

    def process_key_channel(self, channel_id, channel_payload):
        for pos in range(8):
            val = channel_payload & (1 << pos)
            try:
                self.board_model.set_key_by_channel_pos((channel_id, pos), val)
            except KeyError:
                pass

    def process_net_data(self):
        # process keys
        for i in range(1, 8):
            self.process_key_channel(i, self.network_data[i])
        
        # process hvacs
        for i in range(8, 14):
            try:
                self.board_model.set_hvac_by_channel(i, self.network_data[i])
            except KeyError:
                pass

    def cycle(self):
        status_list = self.get_device_status()
        self.board_model.load_status(status_list)
        self.board_model.reset_changes()

        self.update_data_from_network()
        self.process_net_data()
        self.apply_changes()
    
    def set_key_on_db(self, id, value):
        print('toggeling %d to %d' % (id, value))
        self.db_connection.execute('UPDATE backend_accessories SET status=%d WHERE id=%d' % (value, id))

    def set_hvac_on_db(self, id, value):
        self.db_connection.execute('UPDATE backend_accessories SET status=%d WHERE id=%d' % (value, id))
Exemple #19
0
 def test_validate_dead_stone(self):
     self.game_state.board = BoardModel.from_string(
             "e w e\n"
             "w w w\n"
             "e b b")
     self.assertFalse(PlaceStoneMove(2, 0).validate(self.game_state))
Exemple #20
0
class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, app):
        QMainWindow.__init__(self, None)
        self.app = app
        self.boardModel = BoardModel(self.app)
        self._setupUi()
        self._refreshActionsState()
        
        self.connect(self.browserView.selectionModel(), SIGNAL('selectionChanged(QItemSelection,QItemSelection)'), self.browserSelectionChanged)
        self.connect(self.app, SIGNAL('boardChanged()'), self.boardChanged)
        
        # Actions
        self.connect(self.actionActions, SIGNAL('triggered()'), self.actionsTriggered)
        self.connect(self.actionMaterialize, SIGNAL('triggered()'), self.materializeTriggered)
        self.connect(self.actionShowLocations, SIGNAL('triggered()'), self.showLocationsTriggered)
        self.connect(self.actionShowDetails, SIGNAL('triggered()'), self.showDetailsTriggered)
        self.connect(self.actionShowIgnoreBox, SIGNAL('triggered()'), self.showIgnoreBoxTriggered)
        self.connect(self.actionAddLocation, SIGNAL('triggered()'), self.addLocationTriggered)
        self.connect(self.actionRemoveLocation, SIGNAL('triggered()'), self.removeLocationTriggered)
        self.connect(self.actionUpdateLocation, SIGNAL('triggered()'), self.updateLocationTriggered)
        self.connect(self.actionQuit, SIGNAL('triggered()'), QCoreApplication.instance().quit)
        self.connect(self.actionNewFolder, SIGNAL('triggered()'), self.newFolderTriggered)
        self.connect(self.actionRemoveEmptyFolders, SIGNAL('triggered()'), self.removeEmptyFoldersTriggered)
        self.connect(self.actionRenameSelected, SIGNAL('triggered()'), self.renameSelectedTriggered)
        self.connect(self.actionMoveSelectedToIgnoreBox, SIGNAL('triggered()'), self.moveSelectedToIgnoreBoxTriggered)
        self.connect(self.actionSwitchConflictAndOriginal, SIGNAL('triggered()'), self.switchConflictAndOriginalTriggered)
        self.connect(self.actionMassRename, SIGNAL('triggered()'), self.massRenameTriggered)
        self.connect(self.actionSplit, SIGNAL('triggered()'), self.splitTriggered)
        self.connect(self.actionUndoSplit, SIGNAL('triggered()'), self.undoSplitTriggered)
        self.connect(self.actionMoveConflicts, SIGNAL('triggered()'), self.moveConflictsTriggered)
        self.connect(self.actionMoveConflictsAndOriginals, SIGNAL('triggered()'), self.moveConflictsAndOriginalsTriggered)
        self.connect(self.actionRenameInRespectiveLocations, SIGNAL('triggered()'), self.renameInRespectiveLocationsTriggered)
        self.connect(self.actionCopyToOtherLocation, SIGNAL('triggered()'), self.copyToOtherLocationTriggered)
        self.connect(self.actionMoveToOtherLocation, SIGNAL('triggered()'), self.moveToOtherLocationTriggered)
        self.connect(self.actionShowHelp, SIGNAL('triggered()'), self.showHelpTriggered)
        self.connect(self.actionRegister, SIGNAL('triggered()'), self.registerTrigerred)
        self.connect(self.actionCheckForUpdate, SIGNAL('triggered()'), self.checkForUpdateTriggered)
        self.connect(self.actionOpenDebugLog, SIGNAL('triggered()'), self.openDebugLogTriggered)
        self.connect(self.actionAbout, SIGNAL('triggered()'), self.aboutTriggered)
    
    def _setupUi(self):
        self.setupUi(self)
        self.browserView.setModel(self.boardModel)
        h = self.browserView.header()
        h.setResizeMode(QHeaderView.Fixed)
        h.resizeSection(1, 120)
        h.setResizeMode(0, QHeaderView.Stretch)
        
        # Action menu
        actionMenu = QMenu('Actions', self.toolBar)
        actionMenu.setIcon(QIcon(QPixmap(":/actions")))
        actionMenu.addAction(self.actionNewFolder)
        actionMenu.addAction(self.actionRemoveEmptyFolders)
        actionMenu.addAction(self.actionRenameSelected)
        actionMenu.addAction(self.actionMoveSelectedToIgnoreBox)
        actionMenu.addAction(self.actionSwitchConflictAndOriginal)
        actionMenu.addSeparator()
        actionMenu.addAction(self.actionMassRename)
        actionMenu.addAction(self.actionSplit)
        actionMenu.addAction(self.actionUndoSplit)
        actionMenu.addAction(self.actionMoveConflicts)
        actionMenu.addAction(self.actionMoveConflictsAndOriginals)
        self.actionActions.setMenu(actionMenu)
        button = QToolButton(self.toolBar)
        button.setDefaultAction(actionMenu.menuAction())
        button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        self.actionsButton = button
        self.toolBar.insertWidget(self.actionActions, button) # the action is a placeholder
        self.toolBar.removeAction(self.actionActions)
        
        # Materialize menu
        materializeMenu = QMenu('Materialize', self.toolBar)
        materializeMenu.setIcon(QIcon(QPixmap(":/materialize")))
        materializeMenu.addAction(self.actionRenameInRespectiveLocations)
        materializeMenu.addAction(self.actionCopyToOtherLocation)
        materializeMenu.addAction(self.actionMoveToOtherLocation)
        self.actionMaterialize.setMenu(materializeMenu)
        button = QToolButton(self.toolBar)
        button.setDefaultAction(materializeMenu.menuAction())
        button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        self.materializeButton = button
        self.toolBar.insertWidget(self.actionMaterialize, button) # the action is a placeholder
        self.toolBar.removeAction(self.actionMaterialize)
    
    def _refreshActionsState(self):
        boardEmpty = len(self.app.board) == 0
        hasConflicts = len(self.app.board.allconflicts) > 0
        hasSelection = len(self.app.selectedBoardItems) > 0
        selectedIsConflicted = False
        if hasSelection:
            node = self.app.selectedBoardItems[0]
            selectedIsConflicted = is_conflicted(node.name)
        boardIsSplit = self.app.board.splitted
        for action in [self.actionMassRename, self.actionNewFolder, self.actionRemoveEmptyFolders, 
            self.actionRenameInRespectiveLocations, self.actionCopyToOtherLocation, 
            self.actionMoveToOtherLocation]:
            action.setEnabled(not boardEmpty)
        self.actionMoveConflicts.setEnabled(not boardEmpty and hasConflicts)
        self.actionMoveConflictsAndOriginals.setEnabled(not boardEmpty and hasConflicts)
        self.actionSwitchConflictAndOriginal.setEnabled(not boardEmpty and selectedIsConflicted)
        self.actionRenameSelected.setEnabled(not boardEmpty and hasSelection)
        self.actionMoveSelectedToIgnoreBox.setEnabled(not boardEmpty and hasSelection)
        self.actionSplit.setEnabled(not boardEmpty and not boardIsSplit)
        self.actionUndoSplit.setEnabled(not boardEmpty and boardIsSplit)
    
    #--- Actions
    def aboutTriggered(self):
        self.app.showAboutBox()
    
    def actionsTriggered(self):
        self.actionsButton.showMenu()
    
    def addLocationTriggered(self):
        self.app.addLocationPrompt()
    
    def checkForUpdateTriggered(self):
        QProcess.execute('updater.exe', ['/checknow'])
    
    def copyToOtherLocationTriggered(self):
        self.app.copyOrMove(copy=True)
    
    def massRenameTriggered(self):
        dialog = MassRenameDialog(self.app)
        result = dialog.exec_()
        if result == QDialog.Accepted:
            self.app.massRename(dialog.model, dialog.whitespace)
    
    def materializeTriggered(self):
        self.materializeButton.showMenu()
    
    def moveConflictsTriggered(self):
        self.app.moveConflicts()
    
    def moveConflictsAndOriginalsTriggered(self):
        self.app.moveConflicts(with_original=True)
    
    def moveSelectedToIgnoreBoxTriggered(self):
        self.app.moveSelectedToIgnoreBox()
    
    def moveToOtherLocationTriggered(self):
        self.app.copyOrMove(copy=False)
    
    def newFolderTriggered(self):
        # We're not using browserView.currentIndex as a base index here because it's impossible
        # for the user to set the currentIndex to "None" after a node has been selected (even if
        # you deselect all nodes, the current index will stay on the last selected node).
        selectedIndexes = self.browserView.selectionModel().selectedRows()
        currentIndex = selectedIndexes[0] if selectedIndexes else QModelIndex()
        parent = currentIndex.internalPointer().ref if currentIndex.isValid() else self.app.board
        newname = self.app.new_folder(parent)
        self.boardModel.insertRow(0, currentIndex)
        parentNode = currentIndex.internalPointer() if currentIndex.isValid() else self.boardModel
        for node in parentNode.subnodes:
            if node.ref.name == newname:
                index = node.index
                self.browserView.setCurrentIndex(index)
                self.browserView.edit(index)
                break
    
    def openDebugLogTriggered(self):
        debugLogPath = op.join(self.app.appdata, 'debug.log')
        url = QUrl.fromLocalFile(debugLogPath)
        QDesktopServices.openUrl(url)
    
    def registerTrigerred(self):
        self.app.askForRegCode()
    
    def removeEmptyFoldersTriggered(self):
        self.app.removeEmptyFolders()
    
    def removeLocationTriggered(self):
        self.app.removeLocationPrompt()
    
    def renameInRespectiveLocationsTriggered(self):
        self.app.renameInRespectiveLocations()
    
    def renameSelectedTriggered(self):
        selectedIndexes = self.browserView.selectionModel().selectedRows()
        if not selectedIndexes:
            return
        index = selectedIndexes[0]
        self.browserView.setCurrentIndex(index)
        self.browserView.edit(index)
    
    def showDetailsTriggered(self):
        self.app.showDetailsPanel()
    
    def showHelpTriggered(self):
        self.app.showHelp()
    
    def showIgnoreBoxTriggered(self):
        self.app.showIgnoreBox()
    
    def showLocationsTriggered(self):
        self.app.showLocationPanel()
    
    def splitTriggered(self):
        dialog = SplitDialog(self.app)
        result = dialog.exec_()
        if result == QDialog.Accepted:
            self.app.split(dialog.model, dialog.capacity, dialog.grouping_level)
    
    def switchConflictAndOriginalTriggered(self):
        currentIndex = self.browserView.currentIndex()
        if not currentIndex.isValid():
            return
        currentNode = currentIndex.internalPointer()
        self.app.SwitchConflictAndOriginal(currentNode.ref)
        self.boardModel.refreshNode(currentNode.parent)
        newIndex = self.boardModel.index(currentIndex.row(), currentIndex.column(), currentNode.parent.index)
        self.browserView.setCurrentIndex(newIndex)
    
    def undoSplitTriggered(self):
        self.app.undoSplit()
    
    def updateLocationTriggered(self):
        if self.app.selectedLocation is not None:
            self.app.updateLocation(self.app.selectedLocation)
    
    #--- Events
    def boardChanged(self):
        self.app.selectBoardItems([])
        self._refreshActionsState()
    
    def browserSelectionChanged(self, selected, deselected):
        selectedIndexes = self.browserView.selectionModel().selectedRows()
        nodes = [index.internalPointer() for index in selectedIndexes]
        items = [node.ref for node in nodes]
        self.app.selectBoardItems(items)
        self._refreshActionsState()