def add_uri_audio_media_cue(): """Add audio MediaCue(s) form user-selected files""" if get_backend() is None: QMessageBox.critical(MainWindow(), 'Error', 'Backend not loaded') return # Default path to system "music" folder path = QStandardPaths.writableLocation(QStandardPaths.MusicLocation) # Get the backend extensions and create a filter for the Qt file-dialog extensions = get_backend().supported_extensions() filters = qfile_filters(extensions, anyfile=False) # Display a file-dialog for the user to choose the media-files files, _ = QFileDialog.getOpenFileNames( MainWindow(), translate('MediaCueMenus', 'Select media files'), path, filters) QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) # Create media cues, and add them to the Application cue_model for file in files: cue = CueFactory.create_cue('URIAudioCue', uri='file://' + file) # Use the filename without extension as cue name cue.name = os.path.splitext(os.path.basename(file))[0] Application().cue_model.add(cue) QApplication.restoreOverrideCursor()
def __init__(self): super().__init__() if not os.path.exists(PRESETS_DIR): os.makedirs(PRESETS_DIR, exist_ok=True) # Entry in mainWindow menu self.manageAction = QAction(MainWindow()) self.manageAction.triggered.connect(self.__edit_presets) self.manageAction.setText(translate('Presets', 'Presets')) self.menu_action = MainWindow().menuTools.addAction(self.manageAction) self.loadOnCueAction = QAction(None) self.loadOnCueAction.triggered.connect(self.__load_on_cue) self.loadOnCueAction.setText(translate('Presets', 'Load preset')) self.createFromCueAction = QAction(None) self.createFromCueAction.triggered.connect(self.__create_from_cue) self.createFromCueAction.setText(translate('Presets', 'Save as preset')) CueLayout.cm_registry.add_separator() CueLayout.cm_registry.add_item(self.loadOnCueAction) CueLayout.cm_registry.add_item(self.createFromCueAction) CueLayout.cm_registry.add_separator()
def select_preset_dialog(): try: presets = tuple(sorted(scan_presets(), key=natural_keys)) if presets: item, confirm = QInputDialog.getItem( MainWindow(), translate('Presets', 'Select Preset'), '', presets) if confirm: return item except OSError as e: scan_presets_error(e, parent=MainWindow())
def show_info(self, clicked): media_uri = Application().layout.get_context_cue().media.input_uri() if not media_uri: QMessageBox.critical(MainWindow(), translate('MediaInfo', 'Error'), translate('MediaInfo', 'No info to display')) else: gst_info = gst_uri_metadata(media_uri) info = {'URI': unquote(gst_info.get_uri())} # Audio streams info for stream in gst_info.get_audio_streams(): name = stream.get_stream_type_nick().capitalize() info[name] = { 'Bitrate': str(stream.get_bitrate() // 1000) + ' Kb/s', 'Channels': str(stream.get_channels()), 'Sample rate': str(stream.get_sample_rate()) + ' Hz', 'Sample size': str(stream.get_depth()) + ' bit' } # Video streams info for stream in gst_info.get_video_streams(): name = stream.get_stream_type_nick().capitalize() info[name] = { 'Height': str(stream.get_height()) + ' px', 'Width': str(stream.get_width()) + ' px', 'Framerate': str( round(stream.get_framerate_num() / stream.get_framerate_denom())) } # Media tags info['Tags'] = {} tags = gst_info.get_tags() if tags is not None: tags = gst_parse_tags_list(tags) for tag in tags: if type(tags[tag]).__str__ is not object.__str__: info['Tags'][tag.capitalize()] = str(tags[tag]) if not info['Tags']: info.pop('Tags') # Show the dialog dialog = InfoDialog(MainWindow(), info, Application().layout.get_context_cue().name) dialog.exec_()
def __init__(self): QtGui.QIcon.setThemeSearchPaths(styles.QLiSPIconsThemePaths) QtGui.QIcon.setThemeName(styles.QLiSPIconsThemeName) self.mainWindow = MainWindow() self.collector = Collector() self.collectorUi = None self.programConf = {} try: midi.initialize() self.midiHandler = midi.MidiEventHandler(int(cfg.config['MIDI']['DeviceID'])) self.midiHandler.start() except: self.midiHandler = None QtGui.QMessageBox.critical(self.mainWindow, 'Error', 'MIDI event handler cannot be started!') self.mainWindow.newProgramAction.connect(self.newProgram) self.mainWindow.saveProgramAction.connect(self.saveProgram) self.mainWindow.openProgramAction.connect(self.openProgram) self.mainWindow.addMediaAction.connect(self.addMedia, QtCore.Qt.QueuedConnection) if(cfg.config['Layout']['UseDefault'] == 'True'): self.createLayout(cfg.config['Layout']['Default']) else: self.mainWindow.setEnabled(False) while(not self.layoutDialog()): pass self.mainWindow.setEnabled(True) try: self.plugins = plugin.initPlugins(self) except Exception as e: QtGui.QMessageBox.critical(None, 'Error Message', ' '.join([str(i) for i in e.args]))
def show_ip(self): ip = translate('Synchronizer', 'Your IP is:') + ' ' try: ip += socket.gethostbyname(socket.gethostname()) except OSError: ip = '127.0.0.1' QMessageBox.information(MainWindow(), ' ', ip)
def gain(self): gainUi = GainUi(MainWindow()) gainUi.exec_() if gainUi.result() == QDialog.Accepted: files = {} if gainUi.only_selected(): cues = Application().layout.get_selected_cues(MediaCue) else: cues = Application().cue_model.filter(MediaCue) for cue in cues: media = cue.media uri = media.input_uri() if uri is not None: if uri not in files: files[uri] = [media] else: files[uri].append(media) # Gain (main) thread self._gain_thread = GainMainThread(files, gainUi.threads(), gainUi.mode(), gainUi.ref_level(), gainUi.norm_level()) # Progress dialog self._progress = GainProgressDialog(len(files)) self._gain_thread.on_progress.connect(self._progress.on_progress, mode=Connection.QtQueued) self._progress.show() self._gain_thread.start()
def finalize(self): MainWindow().menuLayout.clear() # Disconnect menu-actions signals self.edit_action.triggered.disconnect() self.remove_action.triggered.disconnect() self.select_action.triggered.disconnect() self.play_action.triggered.disconnect() self.pause_action.triggered.disconnect() self.stop_action.triggered.disconnect() self.reset_volume_action.disconnect() # Remove context-items self.cm_registry.remove_item(self.edit_action) self.cm_registry.remove_item(self.sep1) self.cm_registry.remove_item(self.remove_action) self.cm_registry.remove_item(self.select_action) self.cm_registry.remove_item(self.sep2) self.cm_registry.remove_item(self.play_action) self.cm_registry.remove_item(self.pause_action) self.cm_registry.remove_item(self.stop_action) self.cm_registry.remove_item(self.reset_volume_action) # Delete the layout self.deleteLater()
def __init__(self): self.syncMenu = QMenu(translate('Synchronizer', 'Synchronization')) self.menu_action = MainWindow().menuTools.addMenu(self.syncMenu) self.addPeerAction = QAction( translate('Synchronizer', 'Manage connected peers'), MainWindow()) self.addPeerAction.triggered.connect(self.manage_peers) self.syncMenu.addAction(self.addPeerAction) self.showIpAction = QAction( translate('Synchronizer', 'Show your IP'), MainWindow()) self.showIpAction.triggered.connect(self.show_ip) self.syncMenu.addAction(self.showIpAction) self.peers = [] self.cue_media = {}
def __load_on_cue(): preset_name = select_preset_dialog() if preset_name is not None: try: load_on_cue(preset_name, Application().layout.get_context_cue()) except OSError as e: load_preset_error(e, preset_name, parent=MainWindow())
def save_preset_dialog(base_name=''): name, confirm = QInputDialog.getText(MainWindow(), translate('Presets', 'Presets'), translate('Presets', 'Preset name'), text=base_name) if confirm: return name
def check_override_dialog(preset_name): answer = QMessageBox.question(MainWindow(), translate('Presets', 'Presets'), translate( 'Presets', 'Preset already exists, overwrite?'), buttons=QMessageBox.Yes | QMessageBox.Cancel) return answer == QMessageBox.Yes
def edit_cue(self, cue): edit_ui = CueSettings(cue, parent=MainWindow()) def on_apply(settings): action = UpdateCueAction(settings, cue) MainActionsHandler.do_action(action) edit_ui.on_apply.connect(on_apply) edit_ui.exec_()
def __init__(self): self._mainWindow = MainWindow() self._app_conf = {} self._layout = None self._memento_model = None self._cue_model = CueModel() # Connect mainWindow actions self._mainWindow.new_session.connect(self.new_session_dialog) self._mainWindow.save_session.connect(self._save_to_file) self._mainWindow.open_session.connect(self._load_from_file) # Register general settings widget AppSettings.register_settings_widget(AppGeneral) AppSettings.register_settings_widget(CueAppSettings) # Show the mainWindow maximized self._mainWindow.showMaximized()
def __load_on_selected(self): item = self.presetsList.currentItem() if item is not None: preset_name = item.text() try: cues = Application().layout.get_selected_cues() if cues: load_on_cues(preset_name, cues) except OSError as e: load_preset_error(e, preset_name, parent=MainWindow())
def testOla(self): if self.activateBox.isChecked(): try: client = OlaClient() del client except OLADNotRunningException: QMessageBox.warning( MainWindow(), translate('TimecodeSettings', 'OLA status'), translate('TimecodeSettings', 'OLA is not running - start the OLA daemon.'))
def __init__(self): for name, cue in load_classes(__package__, path.dirname(__file__)): # Register the action-cue in the cue-factory CueFactory.register_factory(cue.__name__, cue) # Register the menu action for adding the action-cue add_function = ActionCues.create_add_action_cue_method(cue) MainWindow().register_cue_menu_action( translate('CueName', cue.Name), add_function, 'Action cues') logging.debug('ACTION-CUES: Loaded "' + name + '"')
def __init__(self): self._gain_thread = None # Entry in mainWindow menu self.menu = QMenu(translate('ReplayGain', 'ReplayGain / Normalization')) self.menu_action = MainWindow().menuTools.addMenu(self.menu) self.actionGain = QAction(MainWindow()) self.actionGain.triggered.connect(self.gain) self.actionGain.setText(translate('ReplayGain', 'Calculate')) self.menu.addAction(self.actionGain) self.actionReset = QAction(MainWindow()) self.actionReset.triggered.connect(self._reset_all) self.actionReset.setText(translate('ReplayGain', 'Reset all')) self.menu.addAction(self.actionReset) self.actionResetSelected = QAction(MainWindow()) self.actionResetSelected.triggered.connect(self._reset_selected) self.actionResetSelected.setText( translate('ReplayGain', 'Reset selected')) self.menu.addAction(self.actionResetSelected)
def __create_from_cue(): cue = Application().layout.get_context_cue() name = save_preset_dialog(cue.name) if name is not None: if not (preset_exists(name) and not check_override_dialog(name)): preset = cue.properties(only_changed=True) # Discard id and index preset.pop('id') preset.pop('index') try: write_preset(name, preset) except OSError as e: write_preset_error(e, name, parent=MainWindow())
def __init__(self): self._mainWindow = MainWindow() self._app_conf = {} self._layout = None self._memento_model = None self._cue_model = CueModel() # Connect mainWindow actions self._mainWindow.new_session.connect(self.new_session_dialog) self._mainWindow.save_session.connect(self._save_to_file) self._mainWindow.open_session.connect(self._load_from_file) # Register general settings widget AppSettings.register_settings_widget(General) # Show the mainWindow maximized self._mainWindow.showMaximized()
def __init__(self): # Create the mainWindow self.mainWindow = MainWindow() # Create a layout 'reference' and set to None self.layout = None # Create an empty configuration self.app_conf = {} # Initialize modules failed = modules.init_modules() for err in failed: msg = 'Module "' + err[0] + '" loading failed' QDetailedMessageBox.dcritical('Module error', msg, str(err[1])) # Connect mainWindow actions self.mainWindow.new_session.connect(self._startup) self.mainWindow.save_session.connect(self._save_to_file) self.mainWindow.open_session.connect(self._load_from_file) # Register general settings widget AppSettings.register_settings_widget(General) # Show the mainWindow maximized self.mainWindow.showMaximized()
def show_ip(self): ip = translate('Synchronizer', 'Your IP is:') + ' ' + str(get_lan_ip()) QMessageBox.information(MainWindow(), ' ', ip)
class Application(metaclass=Singleton): def __init__(self): self._mainWindow = MainWindow() self._app_conf = {} self._layout = None self._memento_model = None self._cue_model = CueModel() # Connect mainWindow actions self._mainWindow.new_session.connect(self.new_session_dialog) self._mainWindow.save_session.connect(self._save_to_file) self._mainWindow.open_session.connect(self._load_from_file) # Register general settings widget AppSettings.register_settings_widget(AppGeneral) AppSettings.register_settings_widget(CueAppSettings) # Show the mainWindow maximized self._mainWindow.showMaximized() @property def layout(self): """:rtype: lisp.layouts.cue_layout.CueLayout""" return self._layout @property def cue_model(self): """:rtype: lisp.cues.cue_model.CueModel""" return self._cue_model def start(self, session_file=''): if exists(session_file): self._load_from_file(session_file) elif cfg.config['Layout']['Default'].lower() != 'nodefault': layout = layouts.get_layout(cfg.config['Layout']['Default']) self._new_session(layout) else: self.new_session_dialog() def new_session_dialog(self): """Show the layout-selection dialog""" try: # Prompt the user for a new layout dialog = LayoutSelect() if dialog.exec_() != QDialog.Accepted: if self._layout is None: # If the user close the dialog, and no layout exists # the application is closed self.finalize() qApp.quit() exit() else: return # If a valid file is selected load it, otherwise load the layout if exists(dialog.filepath): self._load_from_file(dialog.filepath) else: self._new_session(dialog.selected()) except Exception as e: elogging.exception('Startup error', e) qApp.quit() exit(-1) def _new_session(self, layout): self._delete_session() self._layout = layout(self._cue_model) self._memento_model = AdapterMementoModel(self.layout.model_adapter) self._mainWindow.set_layout(self._layout) self._app_conf['layout'] = layout.NAME plugins.init_plugins() def _delete_session(self): if self._layout is not None: MainActionsHandler.clear() plugins.reset_plugins() self._app_conf.clear() self._cue_model.reset() self._layout.finalize() self._layout = None self._memento_model = None self._cue_model.reset() def finalize(self): modules.terminate_modules() self._delete_session() self._mainWindow.deleteLater() def _save_to_file(self, session_file): """Save the current session into a file.""" session = {"cues": [], "plugins": {}, "application": []} # Add the cues for cue in self._cue_model: session['cues'].append(cue.properties(only_changed=True)) # Sort cues by index, allow sorted-models to load properly session['cues'].sort(key=lambda cue: cue['index']) session['plugins'] = plugins.get_plugin_settings() session['application'] = self._app_conf # Write to a file the json-encoded dictionary with open(session_file, mode='w', encoding='utf-8') as file: file.write(json.dumps(session, sort_keys=True, indent=4)) MainActionsHandler.set_saved() self._mainWindow.update_window_title() def _load_from_file(self, session_file): """ Load a saved session from file """ try: with open(session_file, mode='r', encoding='utf-8') as file: session = json.load(file) # New session self._new_session( layouts.get_layout(session['application']['layout'])) # Get the application settings self._app_conf = session['application'] # Load cues for cue_conf in session['cues']: cue_type = cue_conf.pop('_type_', 'Undefined') cue_id = cue_conf.pop('id') try: cue = CueFactory.create_cue(cue_type, cue_id=cue_id) cue.update_properties(cue_conf) self._cue_model.add(cue) except Exception as e: elogging.exception('Unable to create the cue', e) MainActionsHandler.set_saved() self._mainWindow.update_window_title() # Load plugins settings plugins.set_plugins_settings(session['plugins']) # Update the main-window self._mainWindow.filename = session_file self._mainWindow.update() except Exception as e: elogging.exception('Error during file reading', e) self.new_session_dialog()
class Application(metaclass=Singleton): def __init__(self): # Create the mainWindow self.mainWindow = MainWindow() # Create a layout 'reference' and set to None self.layout = None # Create an empty configuration self.app_conf = {} # Initialize modules failed = modules.init_modules() for err in failed: msg = 'Module "' + err[0] + '" loading failed' QDetailedMessageBox.dcritical('Module error', msg, str(err[1])) # Connect mainWindow actions self.mainWindow.new_session.connect(self._startup) self.mainWindow.save_session.connect(self._save_to_file) self.mainWindow.open_session.connect(self._load_from_file) # Register general settings widget AppSettings.register_settings_widget(General) # Show the mainWindow maximized self.mainWindow.showMaximized() def start(self, filepath=''): if exists(filepath): # Load the file self.mainWindow.file = filepath self._load_from_file(filepath) else: # Create the layout self._startup(first=True) def finalize(self): self.layout.destroy_layout() # Terminate the loaded modules modules.terminate_modules() def _create_layout(self, layout): ''' Clear ActionHandler session; Reset plugins; Creates a new layout; Init plugins. ''' ActionsHandler().clear() plugins.reset_plugins() if self.layout is not None: self.layout.destroy_layout() self.layout = None try: self.layout = layout(self) self.mainWindow.set_layout(self.layout) self.app_conf['layout'] = layout.NAME self._init_plugins() except Exception: QMessageBox.critical(None, 'Error', 'Layout init failed') print(traceback.format_exc(), file=sys.stderr) def _layout_dialog(self): ''' Show the layout-selection dialog ''' try: select = LayoutSelect() select.exec_() except Exception as e: QMessageBox.critical(None, 'Fatal error', str(e)) qApp.quit() exit(-1) if select.result() != QDialog.Accepted: qApp.quit() exit() if exists(select.filepath): self._load_from_file(select.filepath) else: self._create_layout(select.slected()) def _startup(self, first=False): ''' Initializes the basic components ''' self.mainWindow.file = '' self.app_conf = {} if first and cfg.config['Layout']['Default'].lower() != 'nodefault': layout = layouts.get_layout(cfg.config['Layout']['Default']) self._create_layout(layout) else: self._layout_dialog() def _save_to_file(self, filepath): ''' Save the current program into "filepath" ''' # Empty structure program = {"cues": [], "plugins": {}, "application": []} # Add the cues for cue in self.layout.get_cues(): if cue is not None: program['cues'].append(cue.properties()) # Add the plugins failed = program['plugins'] = plugins.get_plugin_settings() for err in failed: msg = 'Plugin "' + err[0] + '" saving failed' QDetailedMessageBox.dcritical('Plugin error', msg, str(err[1])) # Add the app settings program['application'] = self.app_conf # Write to a file the json-encoded dictionary with open(filepath, mode='w', encoding='utf-8') as file: file.write(json.dumps(program, sort_keys=True, indent=4)) ActionsHandler().set_saved() self.mainWindow.update_window_title() def _load_from_file(self, filepath): ''' Loads a saved program from "filepath" ''' try: # Read the file with open(filepath, mode='r', encoding='utf-8') as file: program = json.load(file) # Get the application settings self.app_conf = program['application'] # Create the layout self._create_layout(layouts.get_layout(self.app_conf['layout'])) # Load cues for cue_conf in program['cues']: cue = CueFactory.create_cue(cue_conf) if cue is not None: self.layout.add_cue(cue, cue['index']) ActionsHandler().set_saved() self.mainWindow.update_window_title() # Load plugins settings self._load_plugins_settings(program['plugins']) # Update the main-window self.mainWindow.file = filepath self.mainWindow.update() except Exception: QMessageBox.critical(None, 'Error', 'Error during file reading') print(traceback.format_exc(), file=sys.stderr) self._startup() def _init_plugins(self): ''' Initialize all the plugins ''' failed = plugins.init_plugins() for err in failed: msg = 'Plugin "' + err[0] + '" initialization failed' QDetailedMessageBox.dcritical('Plugin error', msg, str(err[1])) def _load_plugins_settings(self, settings): ''' Loads all the plugins settings ''' failed = plugins.set_plugins_settings(settings) for err in failed: msg = 'Plugin "' + err[0] + '" loading failed' QDetailedMessageBox.dcritical('Plugin error', msg, str(err[1]))
def __init__(self, cue_model, **kwargs): super().__init__(cue_model=cue_model, **kwargs) self.tabBar().setObjectName('CartTabBar') self.__columns = int(config['CartLayout']['GridColumns']) self.__rows = int(config['CartLayout']['GridRows']) self.__pages = [] self.__context_widget = None self._show_seek = config['CartLayout'].getboolean('ShowSeek') self._show_dbmeter = config['CartLayout'].getboolean('ShowDbMeters') self._show_volume = config['CartLayout'].getboolean('ShowVolume') self._accurate_timing = config['CartLayout'].getboolean('ShowAccurate') self._countdown_mode = config['CartLayout'].getboolean('CountDown') self._auto_add_page = config['CartLayout'].getboolean('AutoAddPage') self._model_adapter = CueCartModel(cue_model, self.__rows, self.__columns) self._model_adapter.item_added.connect(self.__cue_added, Connection.QtQueued) self._model_adapter.item_removed.connect(self.__cue_removed, Connection.QtQueued) self._model_adapter.item_moved.connect(self.__cue_moved, Connection.QtQueued) self._model_adapter.model_reset.connect(self.__model_reset) # Add layout-specific menus self.new_page_action = QAction(self) self.new_page_action.triggered.connect(self.add_page) self.new_pages_action = QAction(self) self.new_pages_action.triggered.connect(self.add_pages) self.rm_current_page_action = QAction(self) self.rm_current_page_action.triggered.connect(self.remove_current_page) self.countdown_mode = QAction(self) self.countdown_mode.setCheckable(True) self.countdown_mode.setChecked(self._countdown_mode) self.countdown_mode.triggered.connect(self.set_countdown_mode) self.show_seek_action = QAction(self) self.show_seek_action.setCheckable(True) self.show_seek_action.setChecked(self._show_seek) self.show_seek_action.triggered.connect(self.set_seek_visible) self.show_dbmeter_action = QAction(self) self.show_dbmeter_action.setCheckable(True) self.show_dbmeter_action.setChecked(self._show_dbmeter) self.show_dbmeter_action.triggered.connect(self.set_dbmeter_visible) self.show_volume_action = QAction(self) self.show_volume_action.setCheckable(True) self.show_volume_action.setChecked(self._show_volume) self.show_volume_action.triggered.connect(self.set_volume_visible) self.show_accurate_action = QAction(self) self.show_accurate_action.setCheckable(True) self.show_accurate_action.setChecked(self._accurate_timing) self.show_accurate_action.triggered.connect(self.set_accurate) layoutMenu = MainWindow().menuLayout layoutMenu.addAction(self.new_page_action) layoutMenu.addAction(self.new_pages_action) layoutMenu.addAction(self.rm_current_page_action) layoutMenu.addSeparator() layoutMenu.addAction(self.countdown_mode) layoutMenu.addAction(self.show_seek_action) layoutMenu.addAction(self.show_dbmeter_action) layoutMenu.addAction(self.show_volume_action) layoutMenu.addAction(self.show_accurate_action) # TODO: maybe can be moved outside the layout # Add cue preferences widgets CueSettingsRegistry().add_item(CueGeneralSettings, Cue) CueSettingsRegistry().add_item(MediaCueSettings, MediaCue) CueSettingsRegistry().add_item(Appearance) # Cue(s) context-menu actions self.edit_action = QAction(self) self.edit_action.triggered.connect(self._edit_cue_action) self.cm_registry.add_item(self.edit_action) self.sep1 = self.cm_registry.add_separator() self.remove_action = QAction(self) self.remove_action.triggered.connect(self._remove_cue_action) self.cm_registry.add_item(self.remove_action) self.select_action = QAction(self) self.select_action.triggered.connect(self.select_context_cue) self.cm_registry.add_item(self.select_action) self.sep2 = self.cm_registry.add_separator(MediaCue) # MediaCue(s) context-menu actions self.play_action = QAction(self) self.play_action.triggered.connect(self._play_context_cue) self.cm_registry.add_item(self.play_action, MediaCue) self.pause_action = QAction(self) self.pause_action.triggered.connect(self._pause_context_cue) self.cm_registry.add_item(self.pause_action, MediaCue) self.stop_action = QAction(self) self.stop_action.triggered.connect(self._stop_context_cue) self.cm_registry.add_item(self.stop_action, MediaCue) self.reset_volume_action = QAction(self) self.reset_volume_action.triggered.connect(self._reset_cue_volume) self.cm_registry.add_item(self.reset_volume_action, MediaCue) self.setAcceptDrops(True) self.retranslateUi() self.add_page()
def terminate(self): self.stop() MainWindow().menuTools.removeAction(self.menu_action)
def show_context_menu(position): menu_edit = MainWindow().menuEdit menu_edit.move(position) menu_edit.show() # Adjust the menu position desktop = qApp.desktop().availableGeometry() menu_rect = menu_edit.geometry() if menu_rect.bottom() > desktop.bottom(): menu_edit.move(menu_edit.x(), menu_edit.y() - menu_edit.height()) if menu_rect.right() > desktop.right(): menu_edit.move(menu_edit.x() - menu_edit.width(), menu_edit.y())
def __edit_presets(): ui = PresetsDialog(parent=MainWindow()) ui.show()
class Application(metaclass=Singleton): def __init__(self): self._mainWindow = MainWindow() self._app_conf = {} self._layout = None self._memento_model = None self._cue_model = CueModel() # Connect mainWindow actions self._mainWindow.new_session.connect(self.new_session_dialog) self._mainWindow.save_session.connect(self._save_to_file) self._mainWindow.open_session.connect(self._load_from_file) # Register general settings widget AppSettings.register_settings_widget(General) # Show the mainWindow maximized self._mainWindow.showMaximized() @property def layout(self): """:rtype: lisp.layouts.cue_layout.CueLayout""" return self._layout @property def cue_model(self): """:rtype: lisp.model_view.cue_model.CueModel""" return self._cue_model def start(self, session_file=''): if exists(session_file): self._load_from_file(session_file) elif cfg.config['Layout']['Default'].lower() != 'nodefault': layout = layouts.get_layout(cfg.config['Layout']['Default']) self._new_session(layout) else: self.new_session_dialog() def new_session_dialog(self): """Show the layout-selection dialog""" try: # Prompt the user for a new layout dialog = LayoutSelect() if dialog.exec_() != QDialog.Accepted: if self._layout is None: # If the user close the dialog, and no layout exists # the application is closed self.finalize() qApp.quit() exit() else: return # If a valid file is selected load it, otherwise load the layout if exists(dialog.filepath): self._load_from_file(dialog.filepath) else: self._new_session(dialog.selected()) except Exception as e: logging.exception('Startup error', e) qApp.quit() exit(-1) def _new_session(self, layout): self._delete_session() self._layout = layout(self._cue_model) self._memento_model = AdapterMementoModel(self.layout.model_adapter) self._mainWindow.set_layout(self._layout) self._app_conf['layout'] = layout.NAME plugins.init_plugins() def _delete_session(self): if self._layout is not None: MainActionsHandler().clear() plugins.reset_plugins() self._app_conf.clear() self._cue_model.reset() self._layout.finalize() self._layout = None self._memento_model = None def finalize(self): self._delete_session() modules.terminate_modules() def _save_to_file(self, session_file): """ Save the current session into a file """ session = {"cues": [], "plugins": {}, "application": []} # Add the cues for cue in self._cue_model: session['cues'].append(cue.properties()) # Sort cues by index, allow sorted-models to load properly session['cues'].sort(key=lambda cue: cue['index']) session['plugins'] = plugins.get_plugin_settings() session['application'] = self._app_conf # Write to a file the json-encoded dictionary with open(session_file, mode='w', encoding='utf-8') as file: file.write(json.dumps(session, sort_keys=True, indent=4)) MainActionsHandler().set_saved() self._mainWindow.update_window_title() def _load_from_file(self, session_file): """ Load a saved session from file """ try: with open(session_file, mode='r', encoding='utf-8') as file: session = json.load(file) # New session self._new_session( layouts.get_layout(session['application']['layout'])) # Get the application settings self._app_conf = session['application'] # Load cues for cue_conf in session['cues']: cue_type = cue_conf.pop('_type_', 'Undefined') try: cue = CueFactory.create_cue(cue_type) cue.update_properties(cue_conf) self._cue_model.add(cue) except Exception as e: logging.exception('Unable to create the cue', e) MainActionsHandler().set_saved() self._mainWindow.update_window_title() # Load plugins settings plugins.set_plugins_settings(session['plugins']) # Update the main-window self._mainWindow.filename = session_file self._mainWindow.update() except Exception as e: logging.exception('Error during file reading', e) self.new_session_dialog()
def manage_peers(self): manager = PeersDialog(self.peers, parent=MainWindow()) manager.exec_()
def __init__(self): MainWindow().register_cue_menu_action(translate( 'MediaCueMenus', 'Audio cue (from file)'), self.add_uri_audio_media_cue, category='Media cues', shortcut='CTRL+M')
def terminate(self): MainWindow().menuTools.removeAction(self.menuAction)
def show_dialog(self): dialog = UriChangerDialog(parent=MainWindow()) dialog.exec_()
class Main: def __init__(self): QtGui.QIcon.setThemeSearchPaths(styles.QLiSPIconsThemePaths) QtGui.QIcon.setThemeName(styles.QLiSPIconsThemeName) self.mainWindow = MainWindow() self.collector = Collector() self.collectorUi = None self.programConf = {} try: midi.initialize() self.midiHandler = midi.MidiEventHandler(int(cfg.config['MIDI']['DeviceID'])) self.midiHandler.start() except: self.midiHandler = None QtGui.QMessageBox.critical(self.mainWindow, 'Error', 'MIDI event handler cannot be started!') self.mainWindow.newProgramAction.connect(self.newProgram) self.mainWindow.saveProgramAction.connect(self.saveProgram) self.mainWindow.openProgramAction.connect(self.openProgram) self.mainWindow.addMediaAction.connect(self.addMedia, QtCore.Qt.QueuedConnection) if(cfg.config['Layout']['UseDefault'] == 'True'): self.createLayout(cfg.config['Layout']['Default']) else: self.mainWindow.setEnabled(False) while(not self.layoutDialog()): pass self.mainWindow.setEnabled(True) try: self.plugins = plugin.initPlugins(self) except Exception as e: QtGui.QMessageBox.critical(None, 'Error Message', ' '.join([str(i) for i in e.args])) def layoutDialog(self): select = LayoutSelect() select.exec_() if(select.result() == QtGui.QDialog.Accepted): self.createLayout(select.getSlected()) return True else: return False def createLayout(self, lay): self.mainWindow.menuLayout.clear() if(self.collectorUi is not None): self.collectorUi.destroyLayout() self.mainWindow.multiEditAction.disconnect() self.mainWindow.selectAllAction.disconnect() self.mainWindow.deselectAllAction.disconnect() self.mainWindow.invertSelectionAction.disconnect() self.collectorUi = layout.buildLayout(lay, self, parent=self.mainWindow.centralwidget) self.mainWindow.multiEditAction.connect(self.collectorUi.editSelectedMedia) self.mainWindow.selectAllAction.connect(self.collectorUi.selectAll) self.mainWindow.deselectAllAction.connect(self.collectorUi.deselectAll) self.mainWindow.invertSelectionAction.connect(self.collectorUi.invertSelection) self.mainWindow.setProgramLayout(self.collectorUi) self.programConf['layout'] = lay def addMedia(self, files): try: for file in files: conf = {} conf['location'] = file conf['name'] = file.split('/')[len(file.split('/')) - 1] media = self.collectorUi.getMediaClass()(conf) self.collectorUi.addMedia(media) except Exception as e: QtGui.QMessageBox.critical(None, 'Error Message', ' '.join([str(i) for i in e.args])) def playByPos(self, pos): media = self.collectorUi.mediaAt(pos) if(media is not None): media.play() def stopByPos(self, pos): media = self.collectorUi.mediaAt(pos) if(media is not None): media.stop() def pauseByPos(self, pos): media = self.collectorUi.mediaAt(pos) if(media is not None): media.pause() def seekByPos(self, pos, time_ms): media = self.collectorUi.mediaAt(pos) if(media is not None): media.seek(time_ms) def newProgram(self): self.collectorUi.destroyLayout() self.collector.resetCollector() self.collectorUi = None self.mainWindow.file = '' while(not self.layoutDialog()): pass self.resetPlugin() def saveProgram(self, filepath): writer = xml_writer.XmlWriter(filepath) for media in self.collectorUi.mediaList(): if(media is not None): if(media.state != Media.NONE): writer.appendMedia(media.conf, media.uuid) writer.appendProgramSettings(self.programConf) for plug in self.plugins: data = self.getPluginData(plug) if(data is not None): writer.appendPluginSettings(plug.PLUGIN_NAME, data) writer.writeFile() def openProgram(self, filepath): progress = Progress(title='Loading ' + filepath) progress.show() try: progress.setLabelText('Reading file ...') reader = xml_reader.XmlReader(filepath) conf = reader.readMediaList() progress.setMaximum(len(conf) + 10) pluginsConf = reader.readPluginsSettings() self.programConf = reader.readProgramSettings() progress.setLabelText('Creating layout ...') self.createLayout(self.programConf['layout']) self.mainWindow.update() progress.setValue(progress.value() + 5) progress.setLabelText('Loading media ...') pfunc = lambda w: progress.setValue(progress.value() + 1) self.collector.onMediaAdded.connect(pfunc) self.collectorUi.readProgramConf(conf) self.collector.onMediaAdded.disconnect(pfunc) progress.setLabelText('Loading plugins ...') self.resetPlugin() self.reloadPlugins() self.setPluginsData(pluginsConf) progress.hide() except Exception as e: progress.hide() QtGui.QMessageBox.critical(None, 'Error Message', 'Error during file reading: ' + ' '.join([str(i) for i in e.args])) self.newProgram() def setPluginsData(self, conf, debug=False): for plug in self.plugins: if(plug.PLUGIN_NAME in conf): if(debug): plug.setData(conf[plug.PLUGIN_NAME]) else: try: plug.setData(conf[plug.PLUGIN_NAME]) except: raise Exception('Plugin data read failed: ' + plug.PLUGIN_NAME) def reloadPlugins(self, debug=False): for plug in self.plugins: if(debug): plug.reload() else: try: plug.reload() except: raise Exception('Plugin load failed: ' + plug.PLUGIN_NAME) def resetPlugin(self, debug=False): for plug in self.plugins: if(debug): plug.reset() else: try: plug.reset() except: raise Exception('Plugin reset failed: ' + plug.PLUGIN_NAME) def getPluginData(self, plugin, debug=False): if(debug): return plugin.getData() else: try: return plugin.getData() except: raise Exception('Plugin data save failed: ' + plugin.PLUGIN_NAME)
def __init__(self): self.menuAction = QAction( translate('UriChanger', 'Session URI change'), MainWindow()) self.menuAction.triggered.connect(self.show_dialog) MainWindow().menuTools.addAction(self.menuAction)
def __init__(self, cue_model, **kwargs): super().__init__(cue_model=cue_model, **kwargs) self.setLayout(QGridLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self._model_adapter = CueListModel(self._cue_model) self._model_adapter.item_added.connect(self.__cue_added) self._model_adapter.item_removed.connect(self.__cue_removed) self._playing_model = RunningCueModel(self._cue_model) self._context_item = None self._next_cue_index = 0 self._show_dbmeter = config['ListLayout'].getboolean('ShowDbMeters') self._seek_visible = config['ListLayout'].getboolean('ShowSeek') self._accurate_time = config['ListLayout'].getboolean('ShowAccurate') self._auto_continue = config['ListLayout'].getboolean('AutoContinue') self._show_playing = config['ListLayout'].getboolean('ShowPlaying') self._go_key = config['ListLayout']['GoKey'] self._go_key_sequence = QKeySequence(self._go_key, QKeySequence.NativeText) try: self._end_list = EndListBehavior(config['ListLayout']['EndList']) except ValueError: self._end_list = EndListBehavior.Stop # Add layout-specific menus self.showPlayingAction = QAction(self) self.showPlayingAction.setCheckable(True) self.showPlayingAction.setChecked(self._show_playing) self.showPlayingAction.triggered.connect(self.set_playing_visible) self.showDbMeterAction = QAction(self) self.showDbMeterAction.setCheckable(True) self.showDbMeterAction.setChecked(self._show_dbmeter) self.showDbMeterAction.triggered.connect(self.set_dbmeter_visible) self.showSeekAction = QAction(self) self.showSeekAction.setCheckable(True) self.showSeekAction.setChecked(self._seek_visible) self.showSeekAction.triggered.connect(self.set_seek_visible) self.accurateTimingAction = QAction(self) self.accurateTimingAction.setCheckable(True) self.accurateTimingAction.setChecked(self._accurate_time) self.accurateTimingAction.triggered.connect(self.set_accurate_time) self.autoNextAction = QAction(self) self.autoNextAction.setCheckable(True) self.autoNextAction.setChecked(self._auto_continue) self.autoNextAction.triggered.connect(self.set_auto_next) MainWindow().menuLayout.addAction(self.showPlayingAction) MainWindow().menuLayout.addAction(self.showDbMeterAction) MainWindow().menuLayout.addAction(self.showSeekAction) MainWindow().menuLayout.addAction(self.accurateTimingAction) MainWindow().menuLayout.addAction(self.autoNextAction) # GO-BUTTON (top-left) self.goButton = QPushButton('GO', self) self.goButton.setFocusPolicy(Qt.NoFocus) self.goButton.setFixedWidth(120) self.goButton.setFixedHeight(100) self.goButton.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) self.goButton.setStyleSheet('font-size: 48pt;') self.goButton.clicked.connect(self.__go_slot) self.layout().addWidget(self.goButton, 0, 0) # INFO PANEL (top center) self.infoPanel = InfoPanel() self.infoPanel.setFixedHeight(100) self.layout().addWidget(self.infoPanel, 0, 1) # CONTROL-BUTTONS (top-right) self.controlButtons = ShowControlButtons(parent=self) self.controlButtons.setFixedHeight(100) self.controlButtons.stopButton.clicked.connect(self.stop_all) self.controlButtons.pauseButton.clicked.connect(self.pause_all) self.controlButtons.fadeInButton.clicked.connect(self.fadein_all) self.controlButtons.fadeOutButton.clicked.connect(self.fadeout_all) self.controlButtons.resumeButton.clicked.connect(self.restart_all) self.controlButtons.interruptButton.clicked.connect(self.interrupt_all) self.layout().addWidget(self.controlButtons, 0, 2) # CUE VIEW (center left) self.listView = CueListView(self._model_adapter, self) self.listView.itemDoubleClicked.connect(self.double_clicked) self.listView.currentItemChanged.connect(self.__current_changed) self.listView.context_event.connect(self.context_event) self.listView.key_event.connect(self.onKeyPressEvent) self.listView.select_cue_event.connect(self.select_event) self.layout().addWidget(self.listView, 1, 0, 1, 2) # PLAYING VIEW (center right) self.playView = RunningCuesListWidget(self._playing_model, parent=self) self.playView.dbmeter_visible = self._show_dbmeter self.playView.accurate_time = self._accurate_time self.playView.seek_visible = self._seek_visible self.playView.setMinimumWidth(300) self.playView.setMaximumWidth(300) self.layout().addWidget(self.playView, 1, 2) self.set_playing_visible(self._show_playing) # TODO: maybe can be moved outside the layout # Add cue preferences widgets CueSettingsRegistry().add_item(CueGeneralSettings, Cue) CueSettingsRegistry().add_item(MediaCueSettings, MediaCue) CueSettingsRegistry().add_item(Appearance) # Context menu actions self.edit_action = QAction(self) self.edit_action.triggered.connect(self.edit_context_cue) self.remove_action = QAction(self) self.remove_action.triggered.connect(self.remove_context_cue) self.select_action = QAction(self) self.select_action.triggered.connect(self.select_context_cue) self.cm_registry.add_item(self.edit_action) self.sep1 = self.cm_registry.add_separator() self.cm_registry.add_item(self.remove_action) self.cm_registry.add_item(self.select_action) self.retranslateUi()
def __init__(self, cue_model, **kwargs): super().__init__(cue_model=cue_model, **kwargs) self.tabBar().setObjectName('CartTabBar') self.__columns = int(config['CartLayout']['GridColumns']) self.__rows = int(config['CartLayout']['GridRows']) self.__pages = [] self.__context_widget = None self._show_seek = config['CartLayout']['ShowSeek'] == 'True' self._show_dbmeter = config['CartLayout']['ShowDbMeters'] == 'True' self._accurate_timing = config['CartLayout']['ShowAccurate'] == 'True' self._countdown_mode = config['CartLayout']['countDown'] == 'True' self._auto_add_page = config['CartLayout']['autoAddPage'] == 'True' self._model_adapter = CueCartModel(cue_model, self.__rows, self.__columns) self._model_adapter.item_added.connect(self.__cue_added,Connection.QtQueued) self._model_adapter.item_removed.connect(self.__cue_removed, Connection.QtQueued) self._model_adapter.item_moved.connect(self.__cue_moved, Connection.QtQueued) # Add layout-specific menus self.new_page_action = QAction(self) self.new_page_action.triggered.connect(self.add_page) self.new_pages_action = QAction(self) self.new_pages_action.triggered.connect(self.add_pages) self.rm_current_page_action = QAction(self) self.rm_current_page_action.triggered.connect(self.remove_current_page) self.countdown_mode = QAction(self) self.countdown_mode.setCheckable(True) self.countdown_mode.setChecked(self._countdown_mode) self.countdown_mode.triggered.connect(self.set_countdown_mode) self.show_sliders_action = QAction(self) self.show_sliders_action.setCheckable(True) self.show_sliders_action.setChecked(self._show_seek) self.show_sliders_action.triggered.connect(self.set_seek_visible) self.show_vumeter_action = QAction(self) self.show_vumeter_action.setCheckable(True) self.show_vumeter_action.setChecked(self._show_dbmeter) self.show_vumeter_action.triggered.connect(self.set_dbmeter_visible) self.show_accurate_action = QAction(self) self.show_accurate_action.setCheckable(True) self.show_accurate_action.setChecked(self._accurate_timing) self.show_accurate_action.triggered.connect(self.set_accurate) layoutMenu = MainWindow().menuLayout layoutMenu.addAction(self.new_page_action) layoutMenu.addAction(self.new_pages_action) layoutMenu.addAction(self.rm_current_page_action) layoutMenu.addSeparator() layoutMenu.addAction(self.countdown_mode) layoutMenu.addAction(self.show_sliders_action) layoutMenu.addAction(self.show_vumeter_action) layoutMenu.addAction(self.show_accurate_action) # TODO: maybe can be moved outside the layout # Add cue preferences widgets CueSettingsRegistry().add_item(CueGeneralSettings, Cue) CueSettingsRegistry().add_item(MediaCueSettings, MediaCue) CueSettingsRegistry().add_item(Appearance) # Cue(s) context-menu actions self.edit_action = QAction(self) self.edit_action.triggered.connect(self._edit_cue_action) self.cm_registry.add_item(self.edit_action) self.sep1 = self.cm_registry.add_separator() self.remove_action = QAction(self) self.remove_action.triggered.connect(self._remove_cue_action) self.cm_registry.add_item(self.remove_action) self.select_action = QAction(self) self.select_action.triggered.connect(self.select_context_cue) self.cm_registry.add_item(self.select_action) self.sep2 = self.cm_registry.add_separator(MediaCue) # MediaCue(s) context-menu actions self.play_action = QAction(self) self.play_action.triggered.connect(self._play_context_cue) self.cm_registry.add_item(self.play_action, MediaCue) self.pause_action = QAction(self) self.pause_action.triggered.connect(self._pause_context_cue) self.cm_registry.add_item(self.pause_action, MediaCue) self.stop_action = QAction(self) self.stop_action.triggered.connect(self._stop_context_cue) self.cm_registry.add_item(self.stop_action, MediaCue) self.setAcceptDrops(True) self.retranslateUi() self.add_page()