Example #1
0
 def __init__(self, *args, **kwargs):
     super().__init__(*args, **kwargs)
     __globals__.parent = self
     self.setupFiles()
     settings.reloadSettings()
     Effects()
     self.version = __version__.__version__
     __globals__.refreshMenus = lambda: self.refreshMenus()
     __globals__.serial_thread = QThread()
     # UI initialisation
     self.ui = Ui_Form()
     self.ui.setupUi(self)
     # Setup UI elements
     self.createRightClickMenus()
     self.setupButtons()
     __globals__.colour_picker = QColorDialog(self)
     self.list_menu = CreateMenuContext(parent=self).makeMenu()
     # Initialise first communication
     self.DevicesJson = JsonIO('devices.json')
     try:
         self.comm_name = list(
             self.DevicesJson.readEntry('selected_device')
             ['devices'].keys())[0]
         self.comm_attr = list(
             self.DevicesJson.readEntry('selected_device')
             ['devices'].values())[0]
         __globals__.current_strip = int(
             list(
                 self.DevicesJson.readEntry('selected_device')
                 ['strips'].keys())[0])
     except:
         self.comm_name = None
     if self.comm_name and self.comm_attr:
         ButtonActions.selectDevice((self.comm_name, self.comm_attr))
Example #2
0
 def createRightClickMenus(self):
     self.right_click_json = JsonIO('right_click_menu.json')
     self.right_click_create = CreateMenuEffectEdit(parent=self)
     # Effects right click menu
     self.right_click_menu_effects = self.genRightClickMenu(
         'main_menu_right_click_menu')
     # Devices right click menu
     self.right_click_menu_devices = self.genRightClickMenu(
         'devices_right_click_menu')
Example #3
0
 def setupFiles(self):
     self.init_files = [
         'menus.json', 'settings.json', 'effects.json', 'devices.json'
     ]
     # Copy all files from base dir if they don't already exist
     for file in self.init_files:
         if JsonIO(file).fileExists():
             pass
         else:
             JsonIO(file).copyFromBase()
Example #4
0
 def effectTypeSelect(self):
     # Read entries from JSON
     self.effect_types = JsonIO('effects.json').readEntry('effects')
     # Create new right click menu
     self.menu_effects = CreateMenuContext(parent=self).makeMenu()
     # Add all JSON entries as options to right click menu
     for effect_name, effect_class in self.effect_types.items():
         self.menu_args = (self.ui.btn_effect_types, effect_class)
         CreateMenuContext(parent=self).addOption(self.menu_effects,
                                                  effect_name,
                                                  (self.menu_args))
Example #5
0
class BaseFinder():
    def __init__(self, *args, **kwargs):
        self.json = JsonIO('devices.json')

    def addDevice(self, name, type, port):
        self.command = {'type': type, 'payload': port}
        self.json.writeEntry('discovered_devices',
                             'devices',
                             port,
                             name,
                             self.command,
                             sort_keys=True)
Example #6
0
 def selectStrip(strip, *args, **kwargs):
     from src.rw.jsonio import JsonIO
     __globals__.current_strip = strip
     # Clear existing strip
     JsonIO('devices.json').blankCopy('selected_device',
                                      'strips',
                                      dump=True)
     # Write new strip
     JsonIO('devices.json').writeRaw('selected_device',
                                     'strips',
                                     strip,
                                     None,
                                     sort_keys=True)
Example #7
0
 def findDevices(self):
     # Clear cache
     JsonIO('devices.json').clearLayout('discovered_devices', 'devices')
     # Repopulate cache
     SerialFinder()
     # Remove added devices
     self.json = JsonIO('devices.json')
     self.discovered_devices = list(self.json.readEntry(
         'discovered_devices')['devices'].keys())
     self.known_devices = self.json.readEntry('known_devices')['devices']
     for device in self.known_devices.values():
         self.port = device['command']['payload']
         if self.port in self.discovered_devices:
             self.json.removeSingleEntry('discovered_devices', self.port)
Example #8
0
 def addDevices(self):
     # Imports done here to prevent circular imports
     from src.ui.generators.create_large_button import CreateLargeButton
     self.json = JsonIO('devices.json')
     self.discovered_devices = list(self.json.readEntry(
         'discovered_devices')['devices'].keys())
     self.known_devices = self.json.readEntry('known_devices')['devices']
     for device_name, device_attributes in self.known_devices.items():
         self.attr = {
             'command': {
                 'payload': device_name,
                 'type': 'removeDevice'},
             'text': device_attributes['text']}
         self.btn = CreateLargeButton(self.ui.discovery_button_layout, spacer=True, effect_btn=False).createGenericButton(
             'name', self.attr, self.ui.discovery_scroll_region, 'primary', right_click_menu=None)
Example #9
0
 def findEffects(self):
     # Store effects dict
     self.effects_dict = {'effects': {}}
     # Find all valid python files
     for file in self.effects_files:
         self.file_path = abspath(join(self.effects_path, file))
         if isfile(self.file_path) and file.endswith(
                 '.py') and file != '__init__.py':
             # Format file name
             self.effect = file.split('.py')[0]
             # Import file
             try:
                 self.module = __import__(
                     f'{__globals__.effect_import_path}.{self.effect}',
                     fromlist=[None])
                 self.effect_class = getattr(self.module, self.effect)
                 # Get effect name
                 self.effect_name = getattr(self.effect_class,
                                            'effectData')()
                 self.effects_dict['effects'][
                     self.effect_name] = self.effect
             except:
                 if settings.do_logs:
                     __globals__.logger.error(
                         f'Failed to load effect definitions from {__globals__.effect_import_path}.{self.effect}, '
                         f'does module exist / contain __init__ and effectData methods?'
                     )
     # Write effect data to file
     JsonIO('effects.json').dumpJson(self.effects_dict)
Example #10
0
 def selectDevice(device, *args, **kwargs):
     from src.serial.serialio import SerialIO
     from src.rw.jsonio import JsonIO
     device_name = device[0]
     device_attributes = device[1]
     # Clear existing device
     JsonIO('devices.json').blankCopy('selected_device',
                                      'devices',
                                      dump=True)
     # Write new device
     JsonIO('devices.json').writeRaw('selected_device',
                                     'devices',
                                     device_name,
                                     device_attributes,
                                     sort_keys=True)
     # Set new communcation type
     comm_type = device_attributes['command']['type']
     comm_port = device_attributes['command']['payload']
     # Initialise communication
     comm_objects = {'serial': SerialIO}
     comm_globals = ['serial']
     disable_strips = []
     try:
         # Init device communication
         comm_objects[comm_type](comm_port)
         # Display debugging tools if previously disabled from invalid device
         if settings.advanced_mode:
             settings.setAdvancedModeVisible(override=True)
         # Disable strips menu
         if comm_type in disable_strips:
             __globals__.strips_menu.setVisible(False)
         else:
             __globals__.strips_menu.setVisible(True)
     except:
         if settings.do_logs:
             __globals__.logger.error(
                 f'Failed to initialise {comm_type} communication through {comm_port}'
             )
         # Set all communications to None
         for global_var in comm_globals:
             setattr(__globals__, global_var, None)
         # Clear global board data
         __globals__.board_data = {'name': None, 'type': None, 'port': None}
         # Disable strips menu
         __globals__.strips_menu.setVisible(False)
         # Disable debugging tools
         settings.setAdvancedModeVisible(override=False)
Example #11
0
 def deleteButton(self):
     # Delete button if user confirms in message box
     if CreateMessageBox('Delete Effect',
                         'This action will remove this button. Continue?'
                         ).confirmDelete():
         JsonIO(self.file).removeEntry(self.button.objectName())
     # Refresh menu
     __globals__.refreshMenus()
Example #12
0
 def resetPreferences(self,
                      file,
                      menu=None,
                      layout=None,
                      reset_file=False,
                      reload_settings=False):
     # Get input from user and continue only if input was 'yes'
     if self.getBool():
         if reset_file:
             JsonIO(file).copyFromBase()
         else:
             JsonIO(file).copyLayout(menu, layout)
         # Reload settings
         if reload_settings:
             settings.reloadSettings()
         # Refresh menu button layout using JSON
         __globals__.refreshMenus()
Example #13
0
 def removeDevice(device, *args, **kwargs):
     from src.rw.jsonio import JsonIO
     Json = JsonIO('devices.json')
     Json.removeSingleEntry('known_devices', device)
     # Clear device selection if forgetting currently selected device
     try:
         Json.removeSingleEntry('selected_device', device)
         Json.clearLayout('selected_devices', 'strips')
     except:
         pass
Example #14
0
 def __init__(self, menu, new_entry=True, btn_name=None, *args, **kwargs):
     super().__init__(*args, **kwargs)
     # Setup UI
     self.ui = Ui_Form()
     self.ui.setupUi(self)
     # Initialise variables
     self.effect_name = None
     self.effect_payload = None
     self.menu = menu
     self.new_entry = new_entry
     self.btn_name = btn_name
     # Get buttons from current menu
     self.page_contents = JsonIO('menus.json').readEntry(self.menu)
     # Initialise effect type selection menu
     self.effectTypeSelect()
     # Open effect drop down when 'effects' button clicked
     self.ui.btn_effect_types.clicked.connect(
         lambda: self.contextMenu(self.menu_effects))
     # Add functionality to 'submit' button
     self.ui.btn_submit.clicked.connect(self.getInputs)
     # Create input types
     super().genValidators(button=self.ui.btn_payload_type,
                           entry=self.ui.input_effect_payload)
     # Get existing data from button if editing
     if new_entry:
         # Clear current menu selection
         __globals__.popup_menu_selection = None
     else:
         # Get button data
         self.btn = JsonIO('menus.json').findElement(self.btn_name)
         # Set existing text entry fields
         self.ui.input_effect_name.setText(self.btn[0])
         self.ui.btn_effect_types.setText(self.btn[1])
         self.ui.input_effect_payload.setText(self.btn[2].split(']')[1])
         self.selected_type = self.btn[2].split(']')[0].split('[')[1]
         self.ui.input_effect_payload.setValidator(
             self.input_types[self.selected_type])
         print(self.selected_type)
         self.ui.btn_payload_type.setText(f'Input: {self.selected_type}')
         # Set current menu selection
         __globals__.popup_menu_selection = self.btn[3]
     # Block inputs to application while dialogue active
     self.setWindowModality(Qt.ApplicationModal)
Example #15
0
 def createEffect(self, menu, layout, entry_name):
     self.command = {
         'type': __globals__.popup_menu_selection,
         'payload': f'[{self.selected_type}]{self.effect_payload}'
     }
     JsonIO('menus.json').writeEntry(menu,
                                     layout,
                                     entry_name,
                                     self.effect_name,
                                     self.command,
                                     sort_keys=False)
Example #16
0
 def setBoardInfo(cls):
     __globals__.board_data_buffer += SerialIO.read(__globals__.serial)
     # Finished reading data
     if __globals__.board_data_lines:
         # Disconnect slot
         __globals__.serial.readyRead.disconnect(SerialIO.setBoardInfo)
         # Create list of board data
         serial_data = __globals__.board_data_buffer
         serial_data = serial_data.strip('\r\n').split(',')
         # Ensure received message contains all data
         try:
             # Get relevant data
             if len(serial_data) == int(serial_data[0]) + 1:
                 board_data = {
                     'name': serial_data[1],
                     'type': serial_data[2],
                     'version': serial_data[3],
                     'physical_strips': serial_data[4],
                     'virtual_strips': serial_data[5],
                     'default_brightness': serial_data[6],
                     'port': __globals__.serial.portName()
                 }
                 __globals__.board_data = board_data
                 __globals__.comm_module = [__name__, cls.__name__]
                 command = {
                     'type': 'serial',
                     'payload': __globals__.serial.portName()
                 }
                 JsonIO('devices.json').writeEntry('known_devices',
                                                   'devices',
                                                   serial_data[1],
                                                   serial_data[1],
                                                   command,
                                                   sort_keys=True)
                 # Update brightness slider
                 __globals__.parent.ui.slider_brightness.setValue(
                     int(serial_data[6]))
                 # Show strips menu when clicked
                 __globals__.strips_menu.clicked.connect(
                     lambda: initStripsMenu(int(serial_data[5])))
             else:
                 if settings.do_logs:
                     __globals__.logger.warn(
                         f'Serial input {serial_data[1:]} not of expected size {serial_data[0]}'
                     )
         except:
             if settings.do_logs:
                 __globals__.logger.warn(
                     f'Expected type integer, instead got {serial_data[0]}')
     # Read next line from serial - message sent in two lines
     else:
         __globals__.board_data_lines += 1
Example #17
0
class DeviceDiscovery(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Setup UI
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        # Block inputs to application while dialogue active
        self.setWindowModality(Qt.ApplicationModal)
        # Set style sheet
        with open(getPath('main_ld.qss'), 'r') as style_file:
            self.setStyleSheet(style_file.read())
        # Get devices and save to JSON
        self.findDevices()
        # Add devices to menu
        self.addDevices()

    def findDevices(self):
        # Clear cache
        JsonIO('devices.json').clearLayout('discovered_devices', 'devices')
        # Repopulate cache
        SerialFinder()
        # Remove added devices
        self.json = JsonIO('devices.json')
        self.discovered_devices = list(self.json.readEntry(
            'discovered_devices')['devices'].keys())
        self.known_devices = self.json.readEntry('known_devices')['devices']
        for device in self.known_devices.values():
            self.port = device['command']['payload']
            if self.port in self.discovered_devices:
                self.json.removeSingleEntry('discovered_devices', self.port)

    def addDevices(self):
        # Imports done here to prevent circular imports
        from src.ui.generate_buttons import GenerateButtons
        GenerateButtons('devices.json', 'discovered_devices').generateGenericButtons(
            self.ui.discovery_button_layout, self.ui.discovery_scroll_region, 'primary', spacer=True)
        # Additional spacer below buttons for better separation between border and bottom button
        self.ui.discovery_button_layout.addItem(QSpacerItem(
            20, 40, QSizePolicy.Minimum, QSizePolicy.Fixed))
Example #18
0
class DeviceRemoval(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Setup UI
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        # Block inputs to application while dialogue active
        self.setWindowModality(Qt.ApplicationModal)
        # Set style sheet
        with open(getPath('main_ld.qss'), 'r') as style_file:
            self.setStyleSheet(style_file.read())
        # Get devices and save to JSON
        self.findDevices()
        # Add devices to menu
        self.addDevices()

    def findDevices(self):
        # Clear cache
        JsonIO('devices.json').clearLayout('discovered_devices', 'devices')
        # Repopulate cache
        SerialFinder()

    def addDevices(self):
        # Imports done here to prevent circular imports
        from src.ui.generators.create_large_button import CreateLargeButton
        self.json = JsonIO('devices.json')
        self.discovered_devices = list(self.json.readEntry(
            'discovered_devices')['devices'].keys())
        self.known_devices = self.json.readEntry('known_devices')['devices']
        for device_name, device_attributes in self.known_devices.items():
            self.attr = {
                'command': {
                    'payload': device_name,
                    'type': 'removeDevice'},
                'text': device_attributes['text']}
            self.btn = CreateLargeButton(self.ui.discovery_button_layout, spacer=True, effect_btn=False).createGenericButton(
                'name', self.attr, self.ui.discovery_scroll_region, 'primary', right_click_menu=None)
Example #19
0
def reloadSettings():
    ld_settings = JsonIO('settings.json').readEntry('settings')
    settings = ld_settings['settings_button_layout']
    for option_name, option_contents in settings.items():
        # Ensure option is toggle
        if option_contents['command']['type'] == 'toggleBool':
            # Update each option with value from file
            globals()[option_name] = option_contents['command']['payload']
            options = {
                'advanced_mode': setAdvancedModeVisible,
                'do_logs': initLogs
            }
            # Run function associated with option
            if option_name in list(options.keys()):
                options.get(option_name)()
Example #20
0
 def initListMenu(self, menu):
     self.DevicesJson = JsonIO('devices.json')
     self.ContextMenuGen = CreateMenuContext(parent=self)
     # Clear menu actions
     self.list_menu.clear()
     # Get actions from file
     self.connected_devices = self.DevicesJson.readEntry('known_devices')
     self.device_list = self.connected_devices[menu]
     for device_name, device_attributes in self.device_list.items():
         self.selected_devices = list(
             self.DevicesJson.readEntry('selected_device')
             ['devices'].keys())
         try:
             # Set highlighted entry
             if device_name == list(
                     self.DevicesJson.readEntry('selected_device')
                 ['devices'].keys())[0]:
                 self.ContextMenuGen.addOption(
                     self.list_menu,
                     device_name,
                     (None, ('selectDevice',
                             (device_name, device_attributes))),
                     highlighted=True)
             # Set non-highlighted entry
             else:
                 self.ContextMenuGen.addOption(
                     self.list_menu, device_name,
                     (None, ('selectDevice',
                             (device_name, device_attributes))))
         # Set non-highlighted entry
         except:
             self.ContextMenuGen.addOption(
                 self.list_menu, device_name,
                 (None, ('selectDevice', (device_name, device_attributes))))
     # Place context menu at cursor position
     self.list_menu.exec(QCursor.pos())
Example #21
0
 def checkInputs(self, generated_object_name):
     # Cycle through existing effects to ensure effect does not exist already
     if self.new_entry:
         for menu in self.page_contents:
             for element in self.page_contents[menu]:
                 if element == generated_object_name:
                     # Raise error to user
                     self.ui.label_error.setText('Effect already exists')
                     return False
         # Only runs if effect does not already exist
         self.createEffect('main_menu', 'main_menu_button_layout',
                           generated_object_name)
         self.exitWindow()
     # Edit existing entry
     else:
         # Replace existing button data with new data
         JsonIO('menus.json').replaceEntry(
             self.btn_name, generated_object_name, self.effect_name,
             __globals__.popup_menu_selection,
             f'[{self.selected_type}]{self.effect_payload}')
         self.exitWindow()
Example #22
0
class InputDialogue(QWidget, InputTypes):
    def __init__(self, menu, new_entry=True, btn_name=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Setup UI
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        # Initialise variables
        self.effect_name = None
        self.effect_payload = None
        self.menu = menu
        self.new_entry = new_entry
        self.btn_name = btn_name
        # Get buttons from current menu
        self.page_contents = JsonIO('menus.json').readEntry(self.menu)
        # Initialise effect type selection menu
        self.effectTypeSelect()
        # Open effect drop down when 'effects' button clicked
        self.ui.btn_effect_types.clicked.connect(
            lambda: self.contextMenu(self.menu_effects))
        # Add functionality to 'submit' button
        self.ui.btn_submit.clicked.connect(self.getInputs)
        # Create input types
        super().genValidators(button=self.ui.btn_payload_type,
                              entry=self.ui.input_effect_payload)
        # Get existing data from button if editing
        if new_entry:
            # Clear current menu selection
            __globals__.popup_menu_selection = None
        else:
            # Get button data
            self.btn = JsonIO('menus.json').findElement(self.btn_name)
            # Set existing text entry fields
            self.ui.input_effect_name.setText(self.btn[0])
            self.ui.btn_effect_types.setText(self.btn[1])
            self.ui.input_effect_payload.setText(self.btn[2].split(']')[1])
            self.selected_type = self.btn[2].split(']')[0].split('[')[1]
            self.ui.input_effect_payload.setValidator(
                self.input_types[self.selected_type])
            print(self.selected_type)
            self.ui.btn_payload_type.setText(f'Input: {self.selected_type}')
            # Set current menu selection
            __globals__.popup_menu_selection = self.btn[3]
        # Block inputs to application while dialogue active
        self.setWindowModality(Qt.ApplicationModal)

    def effectTypeSelect(self):
        # Read entries from JSON
        self.effect_types = JsonIO('effects.json').readEntry('effects')
        # Create new right click menu
        self.menu_effects = CreateMenuContext(parent=self).makeMenu()
        # Add all JSON entries as options to right click menu
        for effect_name, effect_class in self.effect_types.items():
            self.menu_args = (self.ui.btn_effect_types, effect_class)
            CreateMenuContext(parent=self).addOption(self.menu_effects,
                                                     effect_name,
                                                     (self.menu_args))

    def contextMenu(self, menu):
        # Place context menu at cursor position
        menu.exec(QCursor.pos())

    def getInputs(self):
        # Reset user presented error
        self.ui.label_error.setText('')
        # Update variables with user input
        self.effect_name = self.ui.input_effect_name.text()
        self.effect_payload = self.ui.input_effect_payload.text()
        # Ensure no input is blank except for payload
        # if not self.effect_name or not self.effect_payload or not __globals__.popup_menu_selection:
        if not self.effect_name or not __globals__.popup_menu_selection:
            # Raise error to user
            self.ui.label_error.setText('Input(s) cannot be left empty')
        else:
            self.genObjectName(self.effect_name)

    def genObjectName(self, user_input):
        self.object_name = 'btn_effect'
        # Create formatted object name
        for word in user_input.split(' '):
            self.object_name += '_' + word
        self.object_name = self.object_name.lower()
        self.checkInputs(self.object_name)

    def checkInputs(self, generated_object_name):
        # Cycle through existing effects to ensure effect does not exist already
        if self.new_entry:
            for menu in self.page_contents:
                for element in self.page_contents[menu]:
                    if element == generated_object_name:
                        # Raise error to user
                        self.ui.label_error.setText('Effect already exists')
                        return False
            # Only runs if effect does not already exist
            self.createEffect('main_menu', 'main_menu_button_layout',
                              generated_object_name)
            self.exitWindow()
        # Edit existing entry
        else:
            # Replace existing button data with new data
            JsonIO('menus.json').replaceEntry(
                self.btn_name, generated_object_name, self.effect_name,
                __globals__.popup_menu_selection,
                f'[{self.selected_type}]{self.effect_payload}')
            self.exitWindow()

    def createEffect(self, menu, layout, entry_name):
        self.command = {
            'type': __globals__.popup_menu_selection,
            'payload': f'[{self.selected_type}]{self.effect_payload}'
        }
        JsonIO('menus.json').writeEntry(menu,
                                        layout,
                                        entry_name,
                                        self.effect_name,
                                        self.command,
                                        sort_keys=False)

    def exitWindow(self):
        # Update menu layout with new JSON
        __globals__.refreshMenus()
        # Close input menu
        self.close()
Example #23
0
 def moveButtonDown(self):
     JsonIO(self.file).shiftEntry(self.button, 1)
     # Refresh menu
     __globals__.refreshMenus()
Example #24
0
 def findDevices(self):
     # Clear cache
     JsonIO('devices.json').clearLayout('discovered_devices', 'devices')
     # Repopulate cache
     SerialFinder()
Example #25
0
 def updateBool(self, text, entry_name, switch):
     # Update settings file
     JsonIO('settings.json').replaceEntry(entry_name, entry_name, text,
                                          'toggleBool', switch.isChecked())
     # Run toggle action
     ButtonActions.toggleBool()
Example #26
0
class GenerateButtons():
    def __init__(self, file, page):
        self.file = file
        self.page_contents = JsonIO(file).readEntry(page)
        self.button = __globals__.current_hovered_btn

    def generateGenericButtons(self,
                               vertical_element,
                               scroll_element,
                               style,
                               right_click_menu=None,
                               spacer=False,
                               effect_btn=False):
        for elements in self.page_contents.values():
            for element_name, element_attributes in elements.items():
                # Create toggle button
                if element_attributes['command']['type'] == 'toggleBool':
                    self.btn = CreateLargeButton(
                        vertical_element, spacer=spacer).createToggleButton(
                            element_name, element_attributes, scroll_element,
                            style)
                # Create pushbutton
                else:
                    self.btn = CreateLargeButton(
                        vertical_element, spacer=spacer,
                        effect_btn=effect_btn).createGenericButton(
                            element_name, element_attributes, scroll_element,
                            style, right_click_menu)

    @staticmethod
    def removeButtons(layout):
        for i in reversed(range(layout.count())):
            try:
                widget = layout.takeAt(i).widget()
                item = layout.itemAt(i)
                # Remove widget
                if widget:
                    widget.deleteLater()
                # Remove spacer item
                elif item:
                    item.removeItem()
            except:
                if settings.do_logs:
                    __globals__.logger.error(
                        f'Failed to remove UI element in layout {layout.objectName()}'
                        f' at UI position {i}')

    @staticmethod
    def editButton():
        button = __globals__.current_hovered_btn
        # Reset input window
        __globals__.popup_view = None
        # Set up input window
        __globals__.popup_view = InputDialogue('main_menu',
                                               new_entry=False,
                                               btn_name=button.objectName())
        __globals__.popup_view.setWindowTitle('Edit Effect')
        __globals__.popup_view.show()

    def deleteButton(self):
        # Delete button if user confirms in message box
        if CreateMessageBox('Delete Effect',
                            'This action will remove this button. Continue?'
                            ).confirmDelete():
            JsonIO(self.file).removeEntry(self.button.objectName())
        # Refresh menu
        __globals__.refreshMenus()

    def moveButtonUp(self):
        JsonIO(self.file).shiftEntry(self.button, -1)
        # Refresh menu
        __globals__.refreshMenus()

    def moveButtonDown(self):
        JsonIO(self.file).shiftEntry(self.button, 1)
        # Refresh menu
        __globals__.refreshMenus()

    @staticmethod
    def deviceDiscovery(*args, **kwargs):
        from src.ui.views.discovery.device_discovery import DeviceDiscovery
        # Reset input window
        __globals__.popup_view = None
        __globals__.popup_view = DeviceDiscovery()
        __globals__.popup_view.setWindowTitle('Device Discovery')
        __globals__.popup_view.show()

    @staticmethod
    def deviceRemoval(*args, **kwargs):
        from src.ui.views.discovery.device_removal import DeviceRemoval
        # Reset input window
        __globals__.popup_view = None
        __globals__.popup_view = DeviceRemoval()
        __globals__.popup_view.setWindowTitle('Forget Devices')
        __globals__.popup_view.show()
Example #27
0
 def __init__(self, file, page):
     self.file = file
     self.page_contents = JsonIO(file).readEntry(page)
     self.button = __globals__.current_hovered_btn
Example #28
0
class MainWindow(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        __globals__.parent = self
        self.setupFiles()
        settings.reloadSettings()
        Effects()
        self.version = __version__.__version__
        __globals__.refreshMenus = lambda: self.refreshMenus()
        __globals__.serial_thread = QThread()
        # UI initialisation
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        # Setup UI elements
        self.createRightClickMenus()
        self.setupButtons()
        __globals__.colour_picker = QColorDialog(self)
        self.list_menu = CreateMenuContext(parent=self).makeMenu()
        # Initialise first communication
        self.DevicesJson = JsonIO('devices.json')
        try:
            self.comm_name = list(
                self.DevicesJson.readEntry('selected_device')
                ['devices'].keys())[0]
            self.comm_attr = list(
                self.DevicesJson.readEntry('selected_device')
                ['devices'].values())[0]
            __globals__.current_strip = int(
                list(
                    self.DevicesJson.readEntry('selected_device')
                    ['strips'].keys())[0])
        except:
            self.comm_name = None
        if self.comm_name and self.comm_attr:
            ButtonActions.selectDevice((self.comm_name, self.comm_attr))

    def setupFiles(self):
        self.init_files = [
            'menus.json', 'settings.json', 'effects.json', 'devices.json'
        ]
        # Copy all files from base dir if they don't already exist
        for file in self.init_files:
            if JsonIO(file).fileExists():
                pass
            else:
                JsonIO(file).copyFromBase()

    def refreshMenus(self):
        try:
            # Reset main menu
            GenerateButtons('menus.json', 'main_menu').removeButtons(
                self.ui.main_menu_button_layout)
            GenerateButtons('menus.json', 'main_menu').generateGenericButtons(
                self.ui.main_menu_button_layout,
                self.ui.effects_scroll_region,
                'primary',
                self.right_click_menu_effects,
                spacer=True,
                effect_btn=True)
            # Reset settings menu
            GenerateButtons('settings.json', 'settings').removeButtons(
                self.ui.settings_button_layout)
            GenerateButtons('settings.json',
                            'settings').generateGenericButtons(
                                self.ui.settings_button_layout,
                                self.ui.settings_scroll_region,
                                'primary',
                                spacer=True)
        except:
            if settings.do_logs:
                __globals__.logger.error(
                    'Failed to reload menu(s), are preferences corrupted?')

    def setupButtons(self):
        # Add elements controlled by advanced mode to global list
        __globals__.advanced_mode_elements.append(self.ui.btn_device_debug)
        __globals__.advanced_mode_elements.append(
            self.ui.btn_device_information)
        # Refresh menus
        self.refreshMenus()
        # Bottom bar
        self.ui.btn_version.setText(f'Version {self.version}')
        self.ui.btn_device_debug.clicked.connect(
            lambda: self.initSerialMonitor())
        self.ui.btn_effect_off.clicked.connect(self.toggleLeds)
        self.ui.btn_device_information.clicked.connect(
            lambda: QMessageBox.information(
                self, 'Device Information',
                f'Device Name: {__globals__.board_data["name"]}\n'
                f'COM Port: {__globals__.board_data["port"]}\n'
                f'Physical Strips: {__globals__.board_data["physical_strips"]}\n'
                f'Virtual Strips: {__globals__.board_data["virtual_strips"]}\n'
                f'ArduRGB Version: {__globals__.board_data["version"]}\n'
                f'Board: {__globals__.board_data["type"]}\n'))
        self.ui.slider_brightness.sliderReleased.connect(self.setBright)
        # Left bar
        self.ui.btn_menu_effects.clicked.connect(
            lambda: self.changePage(self.ui.main_menus, 0))
        self.ui.btn_menu_settings.clicked.connect(
            lambda: self.changePage(self.ui.main_menus, 1))
        self.ui.btn_list_device.clicked.connect(
            lambda: self.initListMenu('devices'))
        self.ui.btn_list_device.setContextMenuPolicy(Qt.CustomContextMenu)
        self.ui.btn_list_device.customContextMenuRequested.connect(
            lambda: self.contextMenu(self.right_click_menu_devices))
        __globals__.strips_menu = self.ui.btn_list_strip
        # Effects menu
        self.ui.btn_menu_effect_new.clicked.connect(
            lambda: self.initDialogue('main_menu', 'Create New Effect'))
        self.ui.btn_menu_effect_reset.clicked.connect(lambda: CreateMessageBox(
            'Reset Effects Menu',
            'This action will erase all custom effects you have specified. Continue?'
        ).resetPreferences(file='menus.json',
                           menu='main_menu',
                           layout='main_menu_button_layout'))
        # Settings menu
        self.ui.btn_settings_reset.clicked.connect(lambda: CreateMessageBox(
            'Reset Settings',
            'This action will revert all settings to their defaults. Continue?'
        ).resetPreferences(
            file='settings.json', reset_file=True, reload_settings=True))

    def changePage(self, widget, index):
        widget.setCurrentIndex(index)

    def createRightClickMenus(self):
        self.right_click_json = JsonIO('right_click_menu.json')
        self.right_click_create = CreateMenuEffectEdit(parent=self)
        # Effects right click menu
        self.right_click_menu_effects = self.genRightClickMenu(
            'main_menu_right_click_menu')
        # Devices right click menu
        self.right_click_menu_devices = self.genRightClickMenu(
            'devices_right_click_menu')

    def genRightClickMenu(self, menu):
        # Get menu options
        options = self.right_click_json.readEntry(menu)
        # Create new right click menu
        r_c_menu = self.right_click_create.makeMenu()
        # Add all JSON entries as options to right click menu
        for entry_name, entry_payload in options.items():
            self.right_click_create.addOption(r_c_menu, entry_name,
                                              entry_payload)
        return r_c_menu

    def setBright(self):
        self.current_brightness = self.ui.slider_brightness.value()
        comm.run('write', f'setbright,{self.current_brightness}', 'ArduRGB')

    def toggleLeds(self):
        comm.run('write', 'toggleleds', 'ArduRGB')

    def setWindowParams(self, window, title, icon=None):
        window.setWindowTitle(title)
        window.show()
        # window.setWindowIcon(icon)

    def initSerialMonitor(self):
        self.serial_monitor = SerialMonitor()
        self.setWindowParams(self.serial_monitor, 'Serial Port Debug View')

    def initDialogue(self, menu, window_title):
        self.input_dialogue = InputDialogue(menu)
        self.setWindowParams(self.input_dialogue, window_title)

    def initListMenu(self, menu):
        self.DevicesJson = JsonIO('devices.json')
        self.ContextMenuGen = CreateMenuContext(parent=self)
        # Clear menu actions
        self.list_menu.clear()
        # Get actions from file
        self.connected_devices = self.DevicesJson.readEntry('known_devices')
        self.device_list = self.connected_devices[menu]
        for device_name, device_attributes in self.device_list.items():
            self.selected_devices = list(
                self.DevicesJson.readEntry('selected_device')
                ['devices'].keys())
            try:
                # Set highlighted entry
                if device_name == list(
                        self.DevicesJson.readEntry('selected_device')
                    ['devices'].keys())[0]:
                    self.ContextMenuGen.addOption(
                        self.list_menu,
                        device_name,
                        (None, ('selectDevice',
                                (device_name, device_attributes))),
                        highlighted=True)
                # Set non-highlighted entry
                else:
                    self.ContextMenuGen.addOption(
                        self.list_menu, device_name,
                        (None, ('selectDevice',
                                (device_name, device_attributes))))
            # Set non-highlighted entry
            except:
                self.ContextMenuGen.addOption(
                    self.list_menu, device_name,
                    (None, ('selectDevice', (device_name, device_attributes))))
        # Place context menu at cursor position
        self.list_menu.exec(QCursor.pos())

    def contextMenu(self, menu):
        menu.exec(QCursor.pos())

    def mousePressEvent(self, event):
        pass
Example #29
0
 def __init__(self, *args, **kwargs):
     self.json = JsonIO('devices.json')