def actionThumbnailView_trigger(self, event): log.info("Switch to Thumbnail View") # Get settings app = get_app() s = settings.get_settings() # Files if app.context_menu_object == "files": s.set("file_view", "thumbnail") self.tabFiles.layout().removeWidget(self.filesTreeView) self.filesTreeView.deleteLater() self.filesTreeView = None self.filesTreeView = FilesListView(self) self.tabFiles.layout().addWidget(self.filesTreeView) # Transitions elif app.context_menu_object == "transitions": s.set("transitions_view", "thumbnail") self.tabTransitions.layout().removeWidget(self.transitionsTreeView) self.transitionsTreeView.deleteLater() self.transitionsTreeView = None self.transitionsTreeView = TransitionsListView(self) self.tabTransitions.layout().addWidget(self.transitionsTreeView) # Effects elif app.context_menu_object == "effects": s.set("effects_view", "thumbnail") self.tabEffects.layout().removeWidget(self.effectsTreeView) self.effectsTreeView.deleteLater() self.effectsTreeView = None self.effectsTreeView = EffectsListView(self) self.tabEffects.layout().addWidget(self.effectsTreeView)
class MainWindow(QMainWindow, updates.UpdateWatcher, updates.UpdateInterface): """ This class contains the logic for the main window widget """ # Path to ui file ui_path = os.path.join(info.PATH, 'windows', 'ui', 'main-window.ui') # Save window settings on close def closeEvent(self, event): # Save settings self.save_settings() # Stop threads self.preview_thread.kill() def actionNew_trigger(self, event): # clear data and start new project get_app().project.load("") get_app().updates.reset() self.filesTreeView.refresh_view() log.info("New Project created.") # Set Window title self.SetWindowTitle() def actionAnimatedTitle_trigger(self, event): # show dialog from windows.animated_title import AnimatedTitle win = AnimatedTitle() # Run the dialog event loop - blocking interaction on this window during that time result = win.exec_() if result == QDialog.Accepted: log.info('animated title add confirmed') else: log.info('animated title add cancelled') def actionTitle_trigger(self, event): # show dialog from windows.title_editor import TitleEditor win = TitleEditor() # Run the dialog event loop - blocking interaction on this window during that time result = win.exec_() if result == QDialog.Accepted: log.info('title editor add confirmed') else: log.info('title editor add cancelled') def actionImportImageSequence_trigger(self, event): # show dialog from windows.Import_image_seq import ImportImageSeq win = ImportImageSeq() # Run the dialog event loop - blocking interaction on this window during that time result = win.exec_() if result == QDialog.Accepted: log.info('Import image sequence add confirmed') else: log.info('Import image sequence add cancelled') def actionImportTransition_trigger(self, event): # show dialog from windows.Import_transitions import ImportTransition win = ImportTransition() # Run the dialog event loop -blocking interaction on this window during that time result = win.exec_() if result == QDialog.Accepted: log.info('Import transition add confirmed') else: log.info('Import transition add cancelled') def actionImportTitle_trigger(self, event): # show dialog from windows.Import_titles import ImportTitles win = ImportTitles() # Run the dialog event loop - blocking interaction on this window during that time result = win.exec_() if result == QDialog.Accepted: log.info('Import title add confirmed') else: log.info('Import title add cancelled') def save_project(self, file_path): """ Save a project to a file path, and refresh the screen """ app = get_app() try: # Save project to file app.project.save(file_path) # Set Window title self.SetWindowTitle() # Load recent projects again self.load_recent_menu() log.info("Saved project {}".format(file_path)) except Exception as ex: log.error("Couldn't save project {}".format(file_path)) def open_project(self, file_path): """ Open a project from a file path, and refresh the screen """ app = get_app() try: if os.path.exists(file_path.encode('UTF-8')): # Load project file app.project.load(file_path) # Set Window title self.SetWindowTitle() # Reset undo/redo history app.updates.reset() # Refresh file tree self.filesTreeView.refresh_view() # Load recent projects again self.load_recent_menu() log.info("Loaded project {}".format(file_path)) except Exception as ex: log.error("Couldn't save project {}".format(file_path)) def actionOpen_trigger(self, event): app = get_app() _ = app._tr file_path, file_type = QFileDialog.getOpenFileName(self, _("Open Project...")) # Load project file self.open_project(file_path) def actionSave_trigger(self, event): app = get_app() _ = app._tr # Get current filepath if any, otherwise ask user file_path = app.project.current_filepath if not file_path: file_path, file_type = QFileDialog.getSaveFileName(self, _("Save Project...")) if file_path: # Save project self.save_project(file_path) def actionSaveAs_trigger(self, event): app = get_app() _ = app._tr file_path, file_type = QFileDialog.getSaveFileName(self, _("Save Project As...")) if file_path: # Save project self.save_project(file_path) def actionImportFiles_trigger(self, event): app = get_app() _ = app._tr files = QFileDialog.getOpenFileNames(self, _("Import File..."))[0] for file_path in files: self.filesTreeView.add_file(file_path) self.filesTreeView.refresh_view() log.info("Loaded project {}".format(file_path)) def actionUploadVideo_trigger(self, event): # show window from windows.upload_video import UploadVideo win = UploadVideo() # Run the dialog event loop - blocking interaction on this window during this time result = win.exec_() if result == QDialog.Accepted: log.info('Upload Video add confirmed') else: log.info('Upload Video add cancelled') def actionExportVideo_trigger(self, event): # show window from windows.export import Export win = Export() # Run the dialog event loop - blocking interaction on this window during this time result = win.exec_() if result == QDialog.Accepted: log.info('Export Video add confirmed') else: log.info('Export Video add cancelled') def actionUndo_trigger(self, event): app = get_app() app.updates.undo() # log.info(app.project._data) def actionRedo_trigger(self, event): app = get_app() app.updates.redo() # log.info(app.project._data) def actionPreferences_trigger(self, event): # Show dialog from windows.preferences import Preferences win = Preferences() # Run the dialog event loop - blocking interaction on this window during this time result = win.exec_() if result == QDialog.Accepted: log.info('Preferences add confirmed') else: log.info('Preferences add cancelled') def actionFilesShowAll_trigger(self, event): self.filesTreeView.refresh_view() def actionFilesShowVideo_trigger(self, event): self.filesTreeView.refresh_view() def actionFilesShowAudio_trigger(self, event): self.filesTreeView.refresh_view() def actionFilesShowImage_trigger(self, event): self.filesTreeView.refresh_view() def actionTransitionsShowAll_trigger(self, event): self.transitionsTreeView.refresh_view() def actionTransitionsShowCommon_trigger(self, event): self.transitionsTreeView.refresh_view() def actionEffectsShowAll_trigger(self, event): self.effectsTreeView.refresh_view() def actionEffectsShowVideo_trigger(self, event): self.effectsTreeView.refresh_view() def actionEffectsShowAudio_trigger(self, event): self.effectsTreeView.refresh_view() def actionHelpContents_trigger(self, event): try: webbrowser.open("http://openshotusers.com/") log.info("Help Contents is open") except: QMessageBox.information(self, "Error !", "Unable to open the Help Contents. Please ensure the openshot-doc package is installed.") log.info("Unable to open the Help Contents") def actionAbout_trigger(self, event): """Show about dialog""" from windows.about import About win = About() # Run the dialog event loop - blocking interaction on this window during this time result = win.exec_() if result == QDialog.Accepted: log.info('About Openshot add confirmed') else: log.info('About Openshot add cancelled') def actionReportBug_trigger(self, event): try: webbrowser.open("https://bugs.launchpad.net/openshot/+filebug") log.info("Open the Report Bug Launchpad web page with success") except: QMessageBox.information(self, "Error !", "Unable to open the launchpad web page") log.info("Unable to open the Report Bug launchpad web page") def actionAskQuestion_trigger(self, event): try: webbrowser.open("https://answers.launchpad.net/openshot/+addquestion") log.info("Open the Question launchpad web page with success") except: QMessageBox.information(self, "Error !", "Unable to open the Question web page") log.info("Unable to open the Question web page") def actionTranslate_trigger(self, event): try: webbrowser.open("https://translations.launchpad.net/openshot") log.info("Open the Translate launchpad web page with success") except: QMessageBox.information(self, "Error !", "Unable to open the Translation web page") log.info("Unable to open the Translation web page") def actionDonate_trigger(self, event): try: webbrowser.open("http://openshot.org/donate/") log.info("Open the Donate web page with success") except: QMessageBox.information(self, "Error !", "Unable to open the Donate web page") log.info("Unable to open the Donate web page") def actionPlay_trigger(self, event, force=None): if force == "pause": self.actionPlay.setChecked(False) elif force == "play": self.actionPlay.setChecked(True) if self.actionPlay.isChecked(): ui_util.setup_icon(self, self.actionPlay, "actionPlay", "media-playback-pause") self.preview_thread.Play() else: ui_util.setup_icon(self, self.actionPlay, "actionPlay") # to default self.preview_thread.Pause() def actionPreview_File_trigger(self, event): """ Preview the selected media file """ log.info('actionPreview_File_trigger') if self.selected_files: # Find matching file f = File.get(id=self.selected_files[0]) if f: # Get file path previewPath = f.data["path"] # Load file into player self.preview_thread.LoadFile(previewPath) # Trigger play button self.actionPlay.setChecked(False) self.actionPlay.trigger() def previewFrame(self, position_seconds, position_frames, time_code): """Preview a specific frame""" log.info("previewFrame - position_seconds: %s, position_frames: %s, time_code: %s" % ( position_seconds, position_frames, time_code)) # Notify preview thread self.preview_thread.previewFrame(position_frames) # Notify properties dialog self.propertyTableView.select_frame(position_frames) def movePlayhead(self, position_frames): """Update playhead position""" log.info(position_frames) # Notify preview thread self.timeline.movePlayhead(position_frames) def actionFastForward_trigger(self, event): # Get the video player object player = self.preview_thread.player if player.Speed() + 1 != 0: player.Speed(player.Speed() + 1) else: player.Speed(player.Speed() + 2) if player.Mode() == openshot.PLAYBACK_PAUSED: self.actionPlay.trigger() def actionRewind_trigger(self, event): # Get the video player object player = self.preview_thread.player if player.Speed() - 1 != 0: player.Speed(player.Speed() - 1) else: player.Speed(player.Speed() - 2) if player.Mode() == openshot.PLAYBACK_PAUSED: self.actionPlay.trigger() def actionJumpStart_trigger(self, event): log.info("actionJumpStart_trigger") # Seek to the 1st frame self.preview_thread.player.Seek(1) def actionJumpEnd_trigger(self, event): log.info("actionJumpEnd_trigger") # Determine max frame (based on clips) timeline_length = 0.0 fps = get_app().window.timeline_sync.timeline.info.fps.ToFloat() clips = get_app().window.timeline_sync.timeline.Clips() for clip in clips: clip_last_frame = clip.Position() + clip.Duration() if clip_last_frame > timeline_length: # Set max length of timeline timeline_length = clip_last_frame # Convert to int and round timeline_length_int = round(timeline_length * fps) + 1 # Seek to the 1st frame self.preview_thread.player.Seek(timeline_length_int) def actionAddTrack_trigger(self, event): log.info("actionAddTrack_trigger") # Get # of tracks track_number = len(get_app().project.get(["layers"])) # Look for existing Marker track = Track() track.data = {"number": track_number, "y": 0} track.save() def actionAddTrackAbove_trigger(self, event): log.info("actionAddTrackAbove_trigger") # Get # of tracks track_number = len(get_app().project.get(["layers"])) # Look for existing Marker track = Track() track.data = {"number": track_number, "y": 0} track.save() def actionAddTrackBelow_trigger(self, event): log.info("actionAddTrackAbove_trigger") # Get # of tracks track_number = len(get_app().project.get(["layers"])) # Look for existing Marker track = Track() track.data = {"number": track_number, "y": 0} track.save() def actionArrowTool_trigger(self, event): log.info("actionArrowTool_trigger") def actionSnappingTool_trigger(self, event): log.info("actionSnappingTool_trigger") log.info(self.actionSnappingTool.isChecked()) # Enable / Disable snapping mode self.timeline.SetSnappingMode(self.actionSnappingTool.isChecked()) def actionAddMarker_trigger(self, event): log.info("actionAddMarker_trigger") # Get player object player = self.preview_thread.player # Calculate frames per second fps = get_app().project.get(["fps"]) fps_float = float(fps["num"]) / float(fps["den"]) # Calculate position in seconds position = player.Position() / fps_float # Look for existing Marker marker = Marker() marker.data = {"position": position, "icon": "blue.png"} marker.save() def actionPreviousMarker_trigger(self, event): log.info("actionPreviousMarker_trigger") # Calculate current position (in seconds) fps = get_app().project.get(["fps"]) fps_float = float(fps["num"]) / float(fps["den"]) current_position = self.preview_thread.current_frame / fps_float # Loop through all markers, and find the closest one to the left closest_position = None for marker in Marker.filter(): marker_position = marker.data["position"] # Is marker smaller than position? if marker_position < current_position: # Is marker larger than previous marker if closest_position and marker_position > closest_position: # Set a new closest marker closest_position = marker_position elif not closest_position: # First one found closest_position = marker_position # Seek to marker position (if any) if closest_position: # Seek frame_to_seek = int(closest_position * fps_float) self.preview_thread.player.Seek(frame_to_seek) def actionNextMarker_trigger(self, event): log.info("actionNextMarker_trigger") log.info(self.preview_thread.current_frame) # Calculate current position (in seconds) fps = get_app().project.get(["fps"]) fps_float = float(fps["num"]) / float(fps["den"]) current_position = self.preview_thread.current_frame / fps_float # Loop through all markers, and find the closest one to the right closest_position = None for marker in Marker.filter(): marker_position = marker.data["position"] # Is marker smaller than position? if marker_position > current_position: # Is marker larger than previous marker if closest_position and marker_position < closest_position: # Set a new closest marker closest_position = marker_position elif not closest_position: # First one found closest_position = marker_position # Seek to marker position (if any) if closest_position: # Seek frame_to_seek = int(closest_position * fps_float) self.preview_thread.player.Seek(frame_to_seek) def keyPressEvent(self, event): """ Add some shortkey for Player """ self.key = "" # Get the video player object player = self.preview_thread.player log.info("keyPressEvent: player.Position(): %s" % player.Position()) # Basic shortcuts i.e just a letter if event.key() == Qt.Key_Left: # Pause video self.actionPlay_trigger(event, force="pause") # Set speed to 0 if player.Speed() != 0: player.Speed(0) # Seek to previous frame player.Seek(player.Position() - 1) # Notify properties dialog self.propertyTableView.select_frame(player.Position()) elif event.key() == Qt.Key_Right: # Pause video self.actionPlay_trigger(event, force="pause") # Set speed to 0 if player.Speed() != 0: player.Speed(0) # Seek to next frame player.Seek(player.Position() + 1) # Notify properties dialog self.propertyTableView.select_frame(player.Position()) elif event.key() == Qt.Key_Up: self.actionPlay.trigger() elif event.key() == Qt.Key_Down: self.actionPlay.trigger() elif event.key() == Qt.Key_C: self.actionPlay.trigger() elif event.key() == Qt.Key_J: self.actionRewind.trigger() ui_util.setup_icon(self, self.actionPlay, "actionPlay", "media-playback-pause") self.actionPlay.setChecked(True) elif event.key() == Qt.Key_K or event.key() == Qt.Key_Space: self.actionPlay.trigger() # Notify properties dialog self.propertyTableView.select_frame(player.Position()) elif event.key() == Qt.Key_L: self.actionFastForward.trigger() ui_util.setup_icon(self, self.actionPlay, "actionPlay", "media-playback-pause") self.actionPlay.setChecked(True) elif event.key() == Qt.Key_M: self.actionPlay.trigger() elif event.key() == Qt.Key_D: # Add the Ctrl key if event.modifiers() & Qt.ControlModifier: self.actionFastForward.trigger() elif event.key() == Qt.Key_End: # Add the Ctrl key if event.modifiers() & Qt.ControlModifier: self.actionFastForward.trigger() elif event.key() == Qt.Key_Home: # Add the Ctrl key if event.modifiers() & Qt.ControlModifier: self.actionFastForward.trigger() # Bubble event on event.ignore() def actionProfile_trigger(self, event): # Show dialog from windows.profile import Profile win = Profile() # Run the dialog event loop - blocking interaction on this window during this time result = win.exec_() if result == QDialog.Accepted: log.info('Profile add confirmed') def actionRemove_from_Project_trigger(self, event): log.info("actionRemove_from_Project_trigger") # Loop through selected files for file_id in self.selected_files: # Find matching file f = File.get(id=file_id) if f: # Remove file f.delete() # Find matching clips (if any) clips = Clip.filter(file_id=file_id) for c in clips: # Remove clip c.delete() # Clear selected files self.selected_files = [] def actionRemoveClip_trigger(self, event): log.info('actionRemoveClip_trigger') # Loop through selected clips for clip_id in self.selected_clips: # Find matching file clips = Clip.filter(id=clip_id) for c in clips: # Clear selected clips self.removeSelection(clip_id, "clip") # Remove clip c.delete() def actionRemoveEffect_trigger(self, event): log.info('actionRemoveEffect_trigger') # Loop through selected clips for effect_id in self.selected_effects: log.info("effect id: %s" % effect_id) # Find matching file clips = Clip.filter() found_effect = None for c in clips: found_effect = False log.info("c.data[effects]: %s" % c.data["effects"]) for effect in c.data["effects"]: if effect["id"] == effect_id: found_effect = effect break if found_effect: # Remove found effect from clip data and save clip c.data["effects"].remove(found_effect) c.save() # Clear selected effects self.removeSelection(effect_id, "effect") def actionRemoveTransition_trigger(self, event): log.info('actionRemoveTransition_trigger') # Loop through selected clips for tran_id in self.selected_transitions: # Find matching file transitions = Transition.filter(id=tran_id) for t in transitions: # Clear selected clips self.removeSelection(tran_id, "transition") # Remove transition t.delete() def actionRemoveTrack_trigger(self, event): log.info('actionRemoveTrack_trigger') for track_id in self.selected_tracks: tracks = Track.filter(id=track_id) for t in tracks: # Remove track t.delete() def actionRemoveMarker_trigger(self, event): log.info('actionRemoveMarker_trigger') for marker_id in self.selected_markers: marker = Marker.filter(id=marker_id) for m in marker: # Remove track m.delete() def actionTimelineZoomIn_trigger(self, event): self.sliderZoom.setValue(self.sliderZoom.value() - self.sliderZoom.singleStep()) def actionTimelineZoomOut_trigger(self, event): self.sliderZoom.setValue(self.sliderZoom.value() + self.sliderZoom.singleStep()) def actionFullscreen_trigger(self, event): # Hide fullscreen button, and display exit fullscreen button self.actionFullscreen.setVisible(False) self.actionExit_Fullscreen.setVisible(True) def actionExit_Fullscreen_trigger(self, event): # Hide exit fullscreen button, and display fullscreen button self.actionExit_Fullscreen.setVisible(False) self.actionFullscreen.setVisible(True) def actionDetailsView_trigger(self, event): log.info("Switch to Details View") # Get settings app = get_app() s = settings.get_settings() # Files if app.context_menu_object == "files": s.set("file_view", "details") self.tabFiles.layout().removeWidget(self.filesTreeView) self.filesTreeView.deleteLater() self.filesTreeView = None self.filesTreeView = FilesTreeView(self) self.tabFiles.layout().addWidget(self.filesTreeView) # Transitions elif app.context_menu_object == "transitions": s.set("transitions_view", "details") self.tabTransitions.layout().removeWidget(self.transitionsTreeView) self.transitionsTreeView.deleteLater() self.transitionsTreeView = None self.transitionsTreeView = TransitionsTreeView(self) self.tabTransitions.layout().addWidget(self.transitionsTreeView) # Effects elif app.context_menu_object == "effects": s.set("effects_view", "details") self.tabEffects.layout().removeWidget(self.effectsTreeView) self.effectsTreeView.deleteLater() self.effectsTreeView = None self.effectsTreeView = EffectsTreeView(self) self.tabEffects.layout().addWidget(self.effectsTreeView) def actionThumbnailView_trigger(self, event): log.info("Switch to Thumbnail View") # Get settings app = get_app() s = settings.get_settings() # Files if app.context_menu_object == "files": s.set("file_view", "thumbnail") self.tabFiles.layout().removeWidget(self.filesTreeView) self.filesTreeView.deleteLater() self.filesTreeView = None self.filesTreeView = FilesListView(self) self.tabFiles.layout().addWidget(self.filesTreeView) # Transitions elif app.context_menu_object == "transitions": s.set("transitions_view", "thumbnail") self.tabTransitions.layout().removeWidget(self.transitionsTreeView) self.transitionsTreeView.deleteLater() self.transitionsTreeView = None self.transitionsTreeView = TransitionsListView(self) self.tabTransitions.layout().addWidget(self.transitionsTreeView) # Effects elif app.context_menu_object == "effects": s.set("effects_view", "thumbnail") self.tabEffects.layout().removeWidget(self.effectsTreeView) self.effectsTreeView.deleteLater() self.effectsTreeView = None self.effectsTreeView = EffectsListView(self) self.tabEffects.layout().addWidget(self.effectsTreeView) def resize_contents(self): if self.filesTreeView: self.filesTreeView.resize_contents() def getDocks(self): """ Get a list of all dockable widgets """ return [self.dockFiles, self.dockTransitions, self.dockEffects, self.dockVideo, self.dockProperties, self.dockKeyframe] def removeDocks(self): """ Remove all dockable widgets on main screen """ for dock in self.getDocks(): self.removeDockWidget(dock) def addDocks(self, docks, area): """ Add all dockable widgets to the same dock area on the main screen """ for dock in docks: self.addDockWidget(area, dock) def floatDocks(self, is_floating): """ Float or Un-Float all dockable widgets above main screen """ for dock in self.getDocks(): dock.setFloating(is_floating) def showDocks(self, docks): """ Show all dockable widgets on the main screen """ for dock in docks: if get_app().window.dockWidgetArea(dock) != Qt.NoDockWidgetArea: # Only show correctly docked widgets dock.show() def freezeDocks(self): """ Freeze all dockable widgets on the main screen (no float, moving, or closing) """ for dock in self.getDocks(): dock.setFeatures(QDockWidget.NoDockWidgetFeatures) def unFreezeDocks(self): """ Un-freeze all dockable widgets on the main screen (allow them to be moved, closed, and floated) """ for dock in self.getDocks(): dock.setFeatures(QDockWidget.AllDockWidgetFeatures) def hideDocks(self): """ Hide all dockable widgets on the main screen """ for dock in self.getDocks(): dock.hide() def actionSimple_View_trigger(self, event): """ Switch to the default / simple view """ self.removeDocks() self.addDocks([self.dockFiles, self.dockTransitions, self.dockEffects, self.dockVideo], Qt.TopDockWidgetArea) self.floatDocks(False) self.tabifyDockWidget(self.dockFiles, self.dockTransitions) self.tabifyDockWidget(self.dockTransitions, self.dockEffects) self.showDocks([self.dockFiles, self.dockTransitions, self.dockEffects, self.dockVideo]) def actionAdvanced_View_trigger(self, event): """ Switch to an alternative view """ self.removeDocks() # Add Docks self.addDocks([self.dockFiles, self.dockTransitions, self.dockVideo], Qt.TopDockWidgetArea) self.addDocks([self.dockEffects], Qt.RightDockWidgetArea) self.addDocks([self.dockProperties, self.dockKeyframe], Qt.LeftDockWidgetArea) self.tabifyDockWidget(self.dockProperties, self.dockKeyframe) self.floatDocks(False) self.showDocks([self.dockFiles, self.dockTransitions, self.dockVideo, self.dockEffects, self.dockProperties, self.dockKeyframe]) def actionFreeze_View_trigger(self, event): """ Freeze all dockable widgets on the main screen """ self.freezeDocks() self.actionFreeze_View.setVisible(False) self.actionUn_Freeze_View.setVisible(True) def actionUn_Freeze_View_trigger(self, event): """ Un-Freeze all dockable widgets on the main screen """ self.unFreezeDocks() self.actionFreeze_View.setVisible(True) self.actionUn_Freeze_View.setVisible(False) def actionShow_All_trigger(self, event): """ Show all dockable widgets """ self.showDocks(self.getDocks()) # Init fullscreen menu visibility def init_fullscreen_menu(self): if self.isFullScreen(): self.actionFullscreen_trigger(None) else: self.actionExit_Fullscreen_trigger(None) def SetWindowTitle(self, profile=None): """ Set the window title based on a variety of factors """ # Get translation function _ = get_app()._tr if not profile: profile = get_app().project.get(["profile"]) # Is this a saved project? if not get_app().project.current_filepath: # Not saved yet self.setWindowTitle("%s [%s] - %s" % (_("Untitled Project"), profile, "OpenShot Video Editor")) else: # Yes, project is saved # Get just the filename parent_path, filename = os.path.split(get_app().project.current_filepath) filename, ext = os.path.splitext(filename) filename = filename.replace("_", " ").replace("-", " ").capitalize() self.setWindowTitle("%s [%s] - %s" % (filename, profile, "OpenShot Video Editor")) # Update undo and redo buttons enabled/disabled to available changes def updateStatusChanged(self, undo_status, redo_status): self.actionUndo.setEnabled(undo_status) self.actionRedo.setEnabled(redo_status) # Add to the selected items def addSelection(self, item_id, item_type): if item_type == "clip" and item_id not in self.selected_clips: self.selected_clips.append(item_id) elif item_type == "transition" and item_id not in self.selected_transitions: self.selected_transitions.append(item_id) elif item_type == "effect" and item_id not in self.selected_effects: self.selected_effects.append(item_id) # Change selected item in properties view self.propertyTableView.select_item(item_id, item_type) # Remove from the selected items def removeSelection(self, item_id, item_type): if item_type == "clip" and item_id in self.selected_clips: self.selected_clips.remove(item_id) elif item_type == "transition" and item_id in self.selected_transitions: self.selected_transitions.remove(item_id) elif item_type == "effect" and item_id in self.selected_effects: self.selected_effects.remove(item_id) # Move selection to next selected clip (if any) if item_type == "clip" and self.selected_clips: self.propertyTableView.select_item(self.selected_clips[0], item_type) elif item_type == "transition" and self.selected_transitions: self.propertyTableView.select_item(self.selected_transitions[0], item_type) elif item_type == "effect" and self.selected_effects: self.propertyTableView.select_item(self.selected_effects[0], item_type) else: # Clear selection in properties view self.propertyTableView.select_item("", "") # Update window settings in setting store def save_settings(self): s = settings.get_settings() # Save window state and geometry (saves toolbar and dock locations) s.set('window_state', qt_types.bytes_to_str(self.saveState())) s.set('window_geometry', qt_types.bytes_to_str(self.saveGeometry())) # Get window settings from setting store def load_settings(self): s = settings.get_settings() # Window state and geometry (also toolbar and dock locations) if s.get('window_geometry'): self.restoreGeometry(qt_types.str_to_bytes(s.get('window_geometry'))) if s.get('window_state'): self.restoreState(qt_types.str_to_bytes(s.get('window_state'))) # Load Recent Projects self.load_recent_menu() def load_recent_menu(self): """ Clear and load the list of recent menu items """ s = settings.get_settings() _ = get_app()._tr # Get translation function # Get list of recent projects recent_projects = s.get("recent_projects") # Add Recent Projects menu (after Open File) import functools if not self.recent_menu: # Create a new recent menu self.recent_menu = self.menuFile.addMenu(QIcon.fromTheme("document-open-recent"), _("Recent Projects")) self.menuFile.insertMenu(self.actionRecent_Placeholder, self.recent_menu) else: # Clear the existing children self.recent_menu.clear() # Add recent projects to menu for file_path in reversed(recent_projects): new_action = self.recent_menu.addAction(file_path) new_action.triggered.connect(functools.partial(self.recent_project_clicked, file_path)) def recent_project_clicked(self, file_path): """ Load a recent project when clicked """ # Load project file self.open_project(file_path) def setup_toolbars(self): _ = get_app()._tr # Get translation function # Start undo and redo actions disabled self.actionUndo.setEnabled(False) self.actionRedo.setEnabled(False) # Add files toolbar ================================================================================= self.filesToolbar = QToolBar("Files Toolbar") self.filesActionGroup = QActionGroup(self) self.filesActionGroup.setExclusive(True) self.filesActionGroup.addAction(self.actionFilesShowAll) self.filesActionGroup.addAction(self.actionFilesShowVideo) self.filesActionGroup.addAction(self.actionFilesShowAudio) self.filesActionGroup.addAction(self.actionFilesShowImage) self.actionFilesShowAll.setChecked(True) self.filesToolbar.addAction(self.actionFilesShowAll) self.filesToolbar.addAction(self.actionFilesShowVideo) self.filesToolbar.addAction(self.actionFilesShowAudio) self.filesToolbar.addAction(self.actionFilesShowImage) self.filesFilter = QLineEdit() self.filesFilter.setObjectName("filesFilter") self.filesFilter.setPlaceholderText(_("Filter")) self.filesToolbar.addWidget(self.filesFilter) self.actionFilesClear.setEnabled(False) self.filesToolbar.addAction(self.actionFilesClear) self.tabFiles.layout().addWidget(self.filesToolbar) # Add transitions toolbar ================================================================================= self.transitionsToolbar = QToolBar("Transitions Toolbar") self.transitionsActionGroup = QActionGroup(self) self.transitionsActionGroup.setExclusive(True) self.transitionsActionGroup.addAction(self.actionTransitionsShowAll) self.transitionsActionGroup.addAction(self.actionTransitionsShowCommon) self.actionTransitionsShowAll.setChecked(True) self.transitionsToolbar.addAction(self.actionTransitionsShowAll) self.transitionsToolbar.addAction(self.actionTransitionsShowCommon) self.transitionsFilter = QLineEdit() self.transitionsFilter.setObjectName("transitionsFilter") self.transitionsFilter.setPlaceholderText(_("Filter")) self.transitionsToolbar.addWidget(self.transitionsFilter) self.actionTransitionsClear.setEnabled(False) self.transitionsToolbar.addAction(self.actionTransitionsClear) self.tabTransitions.layout().addWidget(self.transitionsToolbar) # Add effects toolbar ================================================================================= self.effectsToolbar = QToolBar("Effects Toolbar") self.effectsActionGroup = QActionGroup(self) self.effectsActionGroup.setExclusive(True) self.effectsActionGroup.addAction(self.actionEffectsShowAll) self.effectsActionGroup.addAction(self.actionEffectsShowVideo) self.effectsActionGroup.addAction(self.actionEffectsShowAudio) self.actionEffectsShowAll.setChecked(True) self.effectsToolbar.addAction(self.actionEffectsShowAll) self.effectsToolbar.addAction(self.actionEffectsShowVideo) self.effectsToolbar.addAction(self.actionEffectsShowAudio) self.effectsFilter = QLineEdit() self.effectsFilter.setObjectName("effectsFilter") self.effectsFilter.setPlaceholderText(_("Filter")) self.effectsToolbar.addWidget(self.effectsFilter) self.actionEffectsClear.setEnabled(False) self.effectsToolbar.addAction(self.actionEffectsClear) self.tabEffects.layout().addWidget(self.effectsToolbar) # Add Video Preview toolbar ========================================================================== self.videoToolbar = QToolBar("Video Toolbar") # Add left spacer spacer = QWidget(self) spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.videoToolbar.addWidget(spacer) # Playback controls self.videoToolbar.addAction(self.actionJumpStart) self.videoToolbar.addAction(self.actionRewind) self.videoToolbar.addAction(self.actionPlay) self.videoToolbar.addAction(self.actionFastForward) self.videoToolbar.addAction(self.actionJumpEnd) self.actionPlay.setCheckable(True) # Add right spacer spacer = QWidget(self) spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.videoToolbar.addWidget(spacer) self.tabVideo.layout().addWidget(self.videoToolbar) # Add Timeline toolbar ================================================================================ self.timelineToolbar = QToolBar("Timeline Toolbar", self) self.timelineToolbar.addAction(self.actionAddTrack) self.timelineToolbar.addSeparator() # rest of options self.timelineToolbar.addAction(self.actionSnappingTool) self.timelineToolbar.addSeparator() self.timelineToolbar.addAction(self.actionAddMarker) self.timelineToolbar.addAction(self.actionPreviousMarker) self.timelineToolbar.addAction(self.actionNextMarker) self.timelineToolbar.addSeparator() # Setup Zoom slider self.sliderZoom = QSlider(Qt.Horizontal, self) self.sliderZoom.setPageStep(6) self.sliderZoom.setRange(8, 200) self.sliderZoom.setValue(20) self.sliderZoom.setInvertedControls(True) # self.sliderZoom.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self.sliderZoom.resize(100, 16) self.zoomScaleLabel = QLabel(_("{} seconds").format(self.sliderZoom.value())) # add zoom widgets self.timelineToolbar.addAction(self.actionTimelineZoomIn) self.timelineToolbar.addWidget(self.sliderZoom) self.timelineToolbar.addAction(self.actionTimelineZoomOut) self.timelineToolbar.addWidget(self.zoomScaleLabel) # Add timeline toolbar to web frame self.frameWeb.addWidget(self.timelineToolbar) def __init__(self): # Create main window base class QMainWindow.__init__(self) # set window on app for reference during initialization of children get_app().window = self # Load UI from designer ui_util.load_ui(self, self.ui_path) # Load user settings for window s = settings.get_settings() self.recent_menu = None # Init UI ui_util.init_ui(self) # Setup toolbars that aren't on main window, set initial state of items, etc self.setup_toolbars() # Add window as watcher to receive undo/redo status updates get_app().updates.add_watcher(self) # Track the selected file(s) self.selected_files = [] self.selected_clips = [] self.selected_transitions = [] self.selected_markers = [] self.selected_tracks = [] self.selected_effects = [] # Init fullscreen menu visibility self.init_fullscreen_menu() # Setup timeline self.timeline = TimelineWebView(self) self.frameWeb.layout().addWidget(self.timeline) # Set Window title self.SetWindowTitle() # Setup files tree if s.get("file_view") == "details": self.filesTreeView = FilesTreeView(self) else: self.filesTreeView = FilesListView(self) self.tabFiles.layout().addWidget(self.filesTreeView) # Setup transitions tree if s.get("transitions_view") == "details": self.transitionsTreeView = TransitionsTreeView(self) else: self.transitionsTreeView = TransitionsListView(self) self.tabTransitions.layout().addWidget(self.transitionsTreeView) # Setup effects tree if s.get("effects_view") == "details": self.effectsTreeView = EffectsTreeView(self) else: self.effectsTreeView = EffectsListView(self) self.tabEffects.layout().addWidget(self.effectsTreeView) # Setup properties table self.propertyTableView = PropertiesTableView(self) self.dockPropertiesContent.layout().addWidget(self.propertyTableView, 3, 1) # Setup video preview QWidget self.videoPreview = VideoWidget() self.tabVideo.layout().insertWidget(0, self.videoPreview) # Load window state and geometry self.load_settings() # Create the timeline sync object (used for previewing timeline) self.timeline_sync = TimelineSync() # Start the preview thread self.preview_parent = PreviewParent() self.preview_parent.Init(self, self.timeline_sync.timeline) self.preview_thread = self.preview_parent.worker
def __init__(self): # Create main window base class QMainWindow.__init__(self) # set window on app for reference during initialization of children get_app().window = self # Load UI from designer ui_util.load_ui(self, self.ui_path) # Load user settings for window s = settings.get_settings() self.recent_menu = None # Init UI ui_util.init_ui(self) # Setup toolbars that aren't on main window, set initial state of items, etc self.setup_toolbars() # Add window as watcher to receive undo/redo status updates get_app().updates.add_watcher(self) # Track the selected file(s) self.selected_files = [] self.selected_clips = [] self.selected_transitions = [] self.selected_markers = [] self.selected_tracks = [] self.selected_effects = [] # Init fullscreen menu visibility self.init_fullscreen_menu() # Setup timeline self.timeline = TimelineWebView(self) self.frameWeb.layout().addWidget(self.timeline) # Set Window title self.SetWindowTitle() # Setup files tree if s.get("file_view") == "details": self.filesTreeView = FilesTreeView(self) else: self.filesTreeView = FilesListView(self) self.tabFiles.layout().addWidget(self.filesTreeView) # Setup transitions tree if s.get("transitions_view") == "details": self.transitionsTreeView = TransitionsTreeView(self) else: self.transitionsTreeView = TransitionsListView(self) self.tabTransitions.layout().addWidget(self.transitionsTreeView) # Setup effects tree if s.get("effects_view") == "details": self.effectsTreeView = EffectsTreeView(self) else: self.effectsTreeView = EffectsListView(self) self.tabEffects.layout().addWidget(self.effectsTreeView) # Setup properties table self.propertyTableView = PropertiesTableView(self) self.dockPropertiesContent.layout().addWidget(self.propertyTableView, 3, 1) # Setup video preview QWidget self.videoPreview = VideoWidget() self.tabVideo.layout().insertWidget(0, self.videoPreview) # Load window state and geometry self.load_settings() # Create the timeline sync object (used for previewing timeline) self.timeline_sync = TimelineSync() # Start the preview thread self.preview_parent = PreviewParent() self.preview_parent.Init(self, self.timeline_sync.timeline) self.preview_thread = self.preview_parent.worker