36 from operator
import itemgetter
37 from uuid
import uuid4
38 from copy
import deepcopy
39 from time
import sleep
42 from PyQt5.QtGui import QIcon, QCursor, QKeySequence
46 from windows.views.timeline_webview
import TimelineWebView
47 from classes
import info, ui_util, settings, qt_types, updates
48 from classes.app
import get_app
49 from classes.logger
import log
50 from classes.timeline
import TimelineSync
51 from classes.query
import File, Clip, Transition, Marker, Track
54 from classes.conversion
import zoomToSeconds, secondsToZoom
55 from images
import openshot_rc
56 from windows.views.files_treeview
import FilesTreeView
57 from windows.views.files_listview
import FilesListView
58 from windows.views.transitions_treeview
import TransitionsTreeView
59 from windows.views.transitions_listview
import TransitionsListView
60 from windows.views.effects_treeview
import EffectsTreeView
61 from windows.views.effects_listview
import EffectsListView
62 from windows.views.properties_tableview
import PropertiesTableView, SelectionLabel
63 from windows.views.tutorial
import TutorialManager
64 from windows.video_widget
import VideoWidget
65 from windows.preview_thread
import PreviewParent
73 ui_path = os.path.join(info.PATH,
'windows',
'ui',
'main-window.ui')
75 previewFrameSignal = pyqtSignal(int)
76 refreshFrameSignal = pyqtSignal()
77 LoadFileSignal = pyqtSignal(str)
78 PlaySignal = pyqtSignal(int)
79 PauseSignal = pyqtSignal()
80 StopSignal = pyqtSignal()
81 SeekSignal = pyqtSignal(int)
82 SpeedSignal = pyqtSignal(float)
83 RecoverBackup = pyqtSignal()
84 FoundVersionSignal = pyqtSignal(str)
85 WaveformReady = pyqtSignal(str, list)
86 TransformSignal = pyqtSignal(str)
87 ExportStarted = pyqtSignal(str, int, int)
88 ExportFrame = pyqtSignal(str, int, int, int)
89 ExportEnded = pyqtSignal(str)
90 MaxSizeChanged = pyqtSignal(object)
91 InsertKeyframe = pyqtSignal(object)
92 OpenProjectSignal = pyqtSignal(str)
93 ThumbnailUpdated = pyqtSignal(str)
99 self.tutorial_manager.exit_manager()
102 if get_app().project.needs_save()
and not self.
mode ==
"unittest":
103 log.info(
'Prompt user to save project')
108 ret = QMessageBox.question(self, _(
"Unsaved Changes"), _(
"Save changes to project before closing?"), QMessageBox.Cancel | QMessageBox.No | QMessageBox.Yes)
109 if ret == QMessageBox.Yes:
113 elif ret == QMessageBox.Cancel:
125 self.StopSignal.emit()
128 QCoreApplication.processEvents()
131 self.preview_thread.player.CloseAudioDevice()
132 self.preview_thread.kill()
133 self.preview_parent.background.exit()
134 self.preview_parent.background.wait(5000)
137 openshot.ZmqLogger.Instance().Close()
138 get_app().logger_libopenshot.kill()
146 log.info(
"recover_backup")
148 recovery_path = os.path.join(info.BACKUP_PATH,
"backup.osp")
151 if os.path.exists(recovery_path):
152 log.info(
"Recovering backup file: %s" % recovery_path)
153 self.
open_project(recovery_path, clear_thumbnails=
False)
156 get_app().project.current_filepath =
None
157 get_app().project.has_unsaved_changes =
True
165 msg.setWindowTitle(_(
"Backup Recovered"))
166 msg.setText(_(
"Your most recent unsaved project has been recovered."))
173 self.actionUndo.setEnabled(
False)
174 self.actionRedo.setEnabled(
False)
180 lock_path = os.path.join(info.USER_PATH,
".lock")
181 lock_value = str(uuid4())
184 if os.path.exists(lock_path):
186 log_path = os.path.join(info.USER_PATH,
"libopenshot.log")
188 last_stack_trace =
""
190 log_start_counter = 0
191 if os.path.exists(log_path):
192 with open(log_path,
"rb")
as f:
194 for raw_line
in reversed(self.
tail_file(f, 500)):
195 line = str(raw_line,
'utf-8')
197 if "End of Stack Trace" in line:
200 elif "Unhandled Exception: Stack Trace" in line:
203 elif "libopenshot logging:" in line:
204 log_start_counter += 1
205 if log_start_counter > 1:
211 last_stack_trace = line + last_stack_trace
214 if line.strip()
and "---" not in line
and "libopenshot logging:" not in line
and not last_log_line:
220 last_log_line = last_stack_trace.split(
"\n")[0].strip()
228 if platform.system() ==
"Darwin":
229 last_log_line =
"mac-%s" % last_log_line[58:].strip()
230 elif platform.system() ==
"Windows":
231 last_log_line =
"windows-%s" % last_log_line
232 elif platform.system() ==
"Linux":
233 last_log_line =
"linux-%s" % last_log_line.replace(
"/usr/local/lib/",
"")
236 last_log_line = last_log_line.replace(
"()",
"")
237 log_parts = last_log_line.split(
"(")
238 if len(log_parts) == 2:
239 last_log_line =
"-%s" % log_parts[0].replace(
"logger_libopenshot:INFO ",
"").strip()[:64]
240 elif len(log_parts) >= 3:
241 last_log_line =
"-%s (%s" % (log_parts[0].replace(
"logger_libopenshot:INFO ",
"").strip()[:64], log_parts[1])
246 log.error(
"Unhandled crash detected... will attempt to recover backup project: %s" % info.BACKUP_PATH)
261 with open(lock_path,
'w')
as f:
271 lock_path = os.path.join(info.USER_PATH,
".lock")
287 to_read = n + (offset
or 0)
292 f.seek(-(avg_line_length * to_read), 2)
297 lines = f.read().splitlines()
298 if len(lines) >= to_read
or pos == 0:
300 return lines[-to_read:offset
and -offset
or None]
309 if get_app().project.needs_save():
310 ret = QMessageBox.question(self, _(
"Unsaved Changes"), _(
"Save changes to project first?"), QMessageBox.Cancel | QMessageBox.No | QMessageBox.Yes)
311 if ret == QMessageBox.Yes:
314 elif ret == QMessageBox.Cancel:
329 self.filesTreeView.refresh_view()
330 log.info(
"New Project created.")
336 self.SeekSignal.emit(1)
340 from windows.animated_title
import AnimatedTitle
341 win = AnimatedTitle()
344 if result == QDialog.Accepted:
345 log.info(
'animated title add confirmed')
347 log.info(
'animated title add cancelled')
351 from windows.animation
import Animation
355 if result == QDialog.Accepted:
356 log.info(
'animation confirmed')
358 log.info(
'animation cancelled')
362 from windows.title_editor
import TitleEditor
366 if result == QDialog.Accepted:
367 log.info(
'title editor add confirmed')
369 log.info(
'title editor add cancelled')
375 file = File.get(id=selected_file_id)
376 file_path = file.data.get(
"path")
379 thumb_path = os.path.join(info.THUMBNAIL_PATH,
"{}.png".format(file.id))
382 if os.path.exists(thumb_path):
383 os.remove(thumb_path)
386 from windows.title_editor
import TitleEditor
387 win = TitleEditor(file_path)
392 get_app().window.filesTreeView.refresh_view()
395 clips = Clip.filter(file_id=selected_file_id)
398 c.data[
"reader"][
"path"] = file_path
402 self.ThumbnailUpdated.emit(c.id)
408 file = File.get(id=selected_file_id)
409 file_path = file.data.get(
"path")
412 from windows.title_editor
import TitleEditor
413 win = TitleEditor(file_path, duplicate=
True)
419 from windows.Import_image_seq
import ImportImageSeq
420 win = ImportImageSeq()
423 if result == QDialog.Accepted:
424 log.info(
'Import image sequence add confirmed')
426 log.info(
'Import image sequence add cancelled')
433 log.info(
'History cleared')
444 app.updates.save_history(app.project, s.get(
"history-limit"))
447 app.project.save(file_path)
455 log.info(
"Saved project {}".format(file_path))
457 except Exception
as ex:
458 log.error(
"Couldn't save project %s. %s" % (file_path, str(ex)))
459 QMessageBox.warning(self, _(
"Error Saving Project"), str(ex))
469 if get_app().project.needs_save():
470 ret = QMessageBox.question(self, _(
"Unsaved Changes"), _(
"Save changes to project first?"), QMessageBox.Cancel | QMessageBox.No | QMessageBox.Yes)
471 if ret == QMessageBox.Yes:
473 self.actionSave.trigger()
474 elif ret == QMessageBox.Cancel:
479 get_app().setOverrideCursor(QCursor(Qt.WaitCursor))
482 if os.path.exists(file_path):
488 app.project.load(file_path)
495 app.updates.load_history(app.project)
501 self.filesTreeView.refresh_view()
506 log.info(
"Loaded project {}".format(file_path))
517 log.info(
"File not found at {}".format(file_path))
518 self.statusBar.showMessage(_(
"Project {} is missing (it may have been moved or deleted). It has been removed from the Recent Projects menu.".format(file_path)), 5000)
522 except Exception
as ex:
523 log.error(
"Couldn't open project {}".format(file_path))
524 QMessageBox.warning(self, _(
"Error Opening Project"), str(ex))
527 get_app().restoreOverrideCursor()
533 if os.path.exists(info.THUMBNAIL_PATH):
534 log.info(
"Clear all thumbnails: %s" % info.THUMBNAIL_PATH)
536 shutil.rmtree(info.THUMBNAIL_PATH)
538 os.mkdir(info.THUMBNAIL_PATH)
541 if os.path.exists(info.BLENDER_PATH):
542 log.info(
"Clear all animations: %s" % info.BLENDER_PATH)
544 shutil.rmtree(info.BLENDER_PATH)
546 os.mkdir(info.BLENDER_PATH)
549 if os.path.exists(info.ASSETS_PATH):
550 log.info(
"Clear all assets: %s" % info.ASSETS_PATH)
552 shutil.rmtree(info.ASSETS_PATH)
554 os.mkdir(info.ASSETS_PATH)
557 if os.path.exists(info.BACKUP_PATH):
558 log.info(
"Clear all backups: %s" % info.BACKUP_PATH)
560 shutil.rmtree(info.BACKUP_PATH)
562 os.mkdir(info.BACKUP_PATH)
564 log.info(
"Failed to clear thumbnails: %s" % info.THUMBNAIL_PATH)
569 recommended_path = app.project.current_filepath
570 if not recommended_path:
571 recommended_path = info.HOME_PATH
574 if get_app().project.needs_save():
575 ret = QMessageBox.question(self, _(
"Unsaved Changes"), _(
"Save changes to project first?"), QMessageBox.Cancel | QMessageBox.No | QMessageBox.Yes)
576 if ret == QMessageBox.Yes:
579 elif ret == QMessageBox.Cancel:
584 file_path, file_type = QFileDialog.getOpenFileName(self, _(
"Open Project..."), recommended_path, _(
"OpenShot Project (*.osp)"))
587 self.OpenProjectSignal.emit(file_path)
594 file_path = app.project.current_filepath
596 recommended_path = os.path.join(info.HOME_PATH,
"%s.osp" % _(
"Untitled Project"))
597 file_path, file_type = QFileDialog.getSaveFileName(self, _(
"Save Project..."), recommended_path, _(
"OpenShot Project (*.osp)"))
601 if ".osp" not in file_path:
602 file_path =
"%s.osp" % file_path
610 log.info(
"auto_save_project")
613 file_path =
get_app().project.current_filepath
614 if get_app().project.needs_save():
618 if ".osp" not in file_path:
619 file_path =
"%s.osp" % file_path
622 log.info(
"Auto save project file: %s" % file_path)
627 recovery_path = os.path.join(info.BACKUP_PATH,
"backup.osp")
628 log.info(
"Creating backup of project file: %s" % recovery_path)
629 get_app().project.save(recovery_path, move_temp_files=
False, make_paths_relative=
False)
632 get_app().project.current_filepath =
None
633 get_app().project.has_unsaved_changes =
True
639 recommended_path = app.project.current_filepath
640 if not recommended_path:
641 recommended_path = os.path.join(info.HOME_PATH,
"%s.osp" % _(
"Untitled Project"))
642 file_path, file_type = QFileDialog.getSaveFileName(self, _(
"Save Project As..."), recommended_path, _(
"OpenShot Project (*.osp)"))
645 if ".osp" not in file_path:
646 file_path =
"%s.osp" % file_path
654 recommended_path = app.project.get([
"import_path"])
655 if not recommended_path
or not os.path.exists(recommended_path):
656 recommended_path = os.path.join(info.HOME_PATH)
657 files = QFileDialog.getOpenFileNames(self, _(
"Import File..."), recommended_path)[0]
658 for file_path
in files:
659 self.filesTreeView.add_file(file_path)
660 self.filesTreeView.refresh_view()
661 app.updates.update([
"import_path"], os.path.dirname(file_path))
662 log.info(
"Imported media file {}".format(file_path))
670 files.append(File.get(id=file_id))
673 fps =
get_app().project.get([
"fps"])
674 fps_float = float(fps[
"num"]) / float(fps[
"den"])
675 pos = (self.preview_thread.player.Position() - 1) / fps_float
678 from windows.add_to_timeline
import AddToTimeline
679 win = AddToTimeline(files, pos)
682 if result == QDialog.Accepted:
683 log.info(
'confirmed')
689 from windows.upload_video
import UploadVideo
693 if result == QDialog.Accepted:
694 log.info(
'Upload Video add confirmed')
696 log.info(
'Upload Video add cancelled')
700 from windows.export
import Export
704 if result == QDialog.Accepted:
705 log.info(
'Export Video add confirmed')
707 log.info(
'Export Video add cancelled')
710 log.info(
'actionUndo_trigger')
715 self.refreshFrameSignal.emit()
718 log.info(
'actionRedo_trigger')
723 self.refreshFrameSignal.emit()
727 self.SpeedSignal.emit(0)
729 self.actionPlay.setChecked(
False)
732 from windows.preferences
import Preferences
736 if result == QDialog.Accepted:
737 log.info(
'Preferences add confirmed')
739 log.info(
'Preferences add cancelled')
746 self.filesTreeView.refresh_view()
749 self.filesTreeView.refresh_view()
752 self.filesTreeView.refresh_view()
755 self.filesTreeView.refresh_view()
758 self.transitionsTreeView.refresh_view()
761 self.transitionsTreeView.refresh_view()
766 log.info(
"Help Contents is open")
768 QMessageBox.information(self,
"Error !",
"Unable to open the Help Contents. Please ensure the openshot-doc package is installed.")
769 log.info(
"Unable to open the Help Contents")
774 from windows.about
import About
778 if result == QDialog.Accepted:
779 log.info(
'About Openshot add confirmed')
781 log.info(
'About Openshot add cancelled')
786 log.info(
"Open the Bug Report GitHub Issues web page with success")
788 QMessageBox.information(self,
"Error !",
"Unable to open the Bug Report GitHub Issues web page")
792 webbrowser.open(
"https://www.reddit.com/r/OpenShot/")
793 log.info(
"Open the official OpenShot subreddit web page with success")
795 QMessageBox.information(self,
"Error !",
"Unable to open the official OpenShot subreddit web page")
799 webbrowser.open(
"https://translations.launchpad.net/openshot/2.0")
800 log.info(
"Open the Translate launchpad web page with success")
802 QMessageBox.information(self,
"Error !",
"Unable to open the Translation web page")
807 log.info(
"Open the Donate web page with success")
809 QMessageBox.information(self,
"Error !",
"Unable to open the Donate web page")
814 log.info(
"Open the Download web page with success")
816 QMessageBox.information(self,
"Error !",
"Unable to open the Download web page")
821 timeline_length = 0.0
822 fps =
get_app().window.timeline_sync.timeline.info.fps.ToFloat()
823 clips =
get_app().window.timeline_sync.timeline.Clips()
825 clip_last_frame = clip.Position() + clip.Duration()
826 if clip_last_frame > timeline_length:
828 timeline_length = clip_last_frame
831 timeline_length_int = round(timeline_length * fps) + 1
834 self.actionPlay.setChecked(
False)
835 elif force ==
"play":
836 self.actionPlay.setChecked(
True)
838 if self.actionPlay.isChecked():
840 self.PlaySignal.emit(timeline_length_int)
844 self.PauseSignal.emit()
849 log.info(
'actionPreview_File_trigger')
855 f = File.get(id=file_id)
863 from windows.cutting
import Cutting
864 win = Cutting(f, preview=
True)
871 self.previewFrameSignal.emit(position_frames)
874 self.propertyTableView.select_frame(position_frames)
879 self.propertyTableView.select_frame(self.preview_thread.player.Position())
885 self.timeline.movePlayhead(position_frames)
890 player = self.preview_thread.player
892 if player.Speed() + 1 != 0:
893 self.SpeedSignal.emit(player.Speed() + 1)
895 self.SpeedSignal.emit(player.Speed() + 2)
897 if player.Mode() == openshot.PLAYBACK_PAUSED:
898 self.actionPlay.trigger()
903 player = self.preview_thread.player
905 if player.Speed() - 1 != 0:
906 self.SpeedSignal.emit(player.Speed() - 1)
908 self.SpeedSignal.emit(player.Speed() - 2)
910 if player.Mode() == openshot.PLAYBACK_PAUSED:
911 self.actionPlay.trigger()
914 log.info(
"actionJumpStart_trigger")
917 self.SeekSignal.emit(1)
920 log.info(
"actionJumpEnd_trigger")
923 timeline_length = 0.0
924 fps =
get_app().window.timeline_sync.timeline.info.fps.ToFloat()
925 clips =
get_app().window.timeline_sync.timeline.Clips()
927 clip_last_frame = clip.Position() + clip.Duration()
928 if clip_last_frame > timeline_length:
930 timeline_length = clip_last_frame
933 timeline_length_int = round(timeline_length * fps) + 1
936 self.SeekSignal.emit(timeline_length_int)
939 log.info(
"actionSaveFrame_trigger")
949 recommended_path = recommended_path = os.path.join(info.HOME_PATH)
950 if get_app().project.current_filepath:
951 recommended_path = os.path.dirname(
get_app().project.current_filepath)
954 if get_app().project.get([
"export_path"]):
955 recommended_path =
get_app().project.get([
"export_path"])
957 framePath =
"%s/Frame-%05d.png" % (recommended_path, self.preview_thread.current_frame)
960 framePath, file_type = QFileDialog.getSaveFileName(self, _(
"Save Frame..."), framePath, _(
"Image files (*.png)"))
964 if ".png" not in framePath:
965 framePath =
"%s.png" % framePath
968 self.statusBar.showMessage(_(
"Save Frame cancelled..."), 5000)
971 get_app().updates.update([
"export_path"], os.path.dirname(framePath))
972 log.info(_(
"Saving frame to %s" % framePath ))
975 get_app().window.actionPlay_trigger(
None, force=
"pause")
980 self.timeline_sync.timeline.SetCache(new_cache_object)
983 self.timeline_sync.timeline.SetMaxSize(
get_app().project.get([
"width"]),
get_app().project.get([
"height"]))
984 self.cache_object.Clear()
987 if os.path.exists(framePath):
988 framePathTime = QFileInfo(framePath).lastModified()
990 framePathTime = QDateTime()
993 openshot.Timeline.GetFrame(self.timeline_sync.timeline,self.preview_thread.current_frame).Save(framePath, 1.0)
996 if os.path.exists(framePath)
and (QFileInfo(framePath).lastModified() > framePathTime):
997 self.statusBar.showMessage(_(
"Saved Frame to %s" % framePath), 5000)
999 self.statusBar.showMessage( _(
"Failed to save image to %s" % framePath), 5000)
1002 viewport_rect = self.videoPreview.centeredViewport(self.videoPreview.width(), self.videoPreview.height())
1003 self.timeline_sync.timeline.SetMaxSize(viewport_rect.width(), viewport_rect.height())
1004 self.cache_object.Clear()
1005 self.timeline_sync.timeline.SetCache(old_cache_object)
1007 old_cache_object =
None
1008 new_cache_object =
None
1011 log.info(
"actionAddTrack_trigger")
1014 all_tracks =
get_app().project.get([
"layers"])
1015 track_number = list(reversed(sorted(all_tracks, key=itemgetter(
'number'))))[0].get(
"number") + 1000000
1019 track.data = {
"number": track_number,
"y": 0,
"label":
"",
"lock":
False}
1023 log.info(
"actionAddTrackAbove_trigger")
1026 all_tracks =
get_app().project.get([
"layers"])
1030 existing_track = Track.get(id=selected_layer_id)
1031 if not existing_track:
1033 log.error(
'No track object found with id: %s' % selected_layer_id)
1035 selected_layer_number = int(existing_track.data[
"number"])
1038 previous_track_number = 0
1039 track_number_delta = 0
1040 for track
in reversed(sorted(all_tracks, key=itemgetter(
'number'))):
1041 if track.get(
"number") == selected_layer_number:
1042 track_number_delta = previous_track_number - selected_layer_number
1044 previous_track_number = track.get(
"number")
1047 new_track_number = selected_layer_number + 1000000
1048 if track_number_delta > 2:
1050 new_track_number = selected_layer_number + int(round(track_number_delta / 2.0))
1053 for track
in reversed(sorted(all_tracks, key=itemgetter(
'number'))):
1054 if track.get(
"number") > selected_layer_number:
1055 existing_track = Track.get(number=track.get(
"number"))
1056 if not existing_track:
1058 log.error(
'No track object found with number: %s' % track.get(
"number"))
1060 existing_layer = existing_track.data[
"number"]
1061 existing_track.data[
"number"] = existing_layer + 1000000
1062 existing_track.save()
1065 for clip
in Clip.filter(layer=existing_layer):
1066 clip.data[
"layer"] = int(clip.data[
"layer"]) + 1000000
1069 for trans
in Transition.filter(layer=existing_layer):
1070 trans.data[
"layer"] = int(trans.data[
"layer"]) + 1000000
1075 track.data = {
"number": new_track_number,
"y": 0,
"label":
"",
"lock":
False}
1079 log.info(
"actionAddTrackBelow_trigger")
1082 all_tracks =
get_app().project.get([
"layers"])
1086 existing_track = Track.get(id=selected_layer_id)
1087 if not existing_track:
1089 log.error(
'No track object found with id: %s' % selected_layer_id)
1091 selected_layer_number = int(existing_track.data[
"number"])
1094 next_track_number = 0
1095 track_number_delta = 0
1097 for track
in reversed(sorted(all_tracks, key=itemgetter(
'number'))):
1099 next_track_number = track.get(
"number")
1100 track_number_delta = selected_layer_number - next_track_number
1102 if track.get(
"number") == selected_layer_number:
1107 new_track_number = selected_layer_number
1108 if track_number_delta > 2:
1110 new_track_number = selected_layer_number - int(round(track_number_delta / 2.0))
1113 for track
in reversed(sorted(all_tracks, key=itemgetter(
'number'))):
1114 if track.get(
"number") >= selected_layer_number:
1115 existing_track = Track.get(number=track.get(
"number"))
1116 if not existing_track:
1118 log.error(
'No track object found with number: %s' % track.get(
"number"))
1120 existing_layer = existing_track.data[
"number"]
1121 existing_track.data[
"number"] = existing_layer + 1000000
1122 existing_track.save()
1125 for clip
in Clip.filter(layer=existing_layer):
1126 clip.data[
"layer"] = int(clip.data[
"layer"]) + 1000000
1129 for trans
in Transition.filter(layer=existing_layer):
1130 trans.data[
"layer"] = int(trans.data[
"layer"]) + 1000000
1135 track.data = {
"number": new_track_number,
"y": 0,
"label":
"",
"lock":
False}
1139 log.info(
"actionArrowTool_trigger")
1142 log.info(
"actionSnappingTool_trigger")
1143 log.info(self.actionSnappingTool.isChecked())
1146 self.timeline.SetSnappingMode(self.actionSnappingTool.isChecked())
1151 log.info(
'actionRazorTool_trigger')
1154 self.timeline.SetRazorMode(self.actionRazorTool.isChecked())
1157 log.info(
"actionAddMarker_trigger")
1160 player = self.preview_thread.player
1163 fps =
get_app().project.get([
"fps"])
1164 fps_float = float(fps[
"num"]) / float(fps[
"den"])
1167 position = (player.Position() - 1) / fps_float
1171 marker.data = {
"position": position,
"icon":
"blue.png"}
1175 log.info(
"actionPreviousMarker_trigger")
1178 fps =
get_app().project.get([
"fps"])
1179 fps_float = float(fps[
"num"]) / float(fps[
"den"])
1180 current_position = (self.preview_thread.current_frame - 1) / fps_float
1181 all_marker_positions = []
1184 for marker
in Marker.filter():
1185 all_marker_positions.append(marker.data[
"position"])
1190 selected_clip = Clip.get(id=clip_id)
1192 all_marker_positions.append(selected_clip.data[
"position"])
1193 all_marker_positions.append(selected_clip.data[
"position"] + (selected_clip.data[
"end"] - selected_clip.data[
"start"]))
1198 selected_tran = Transition.get(id=tran_id)
1200 all_marker_positions.append(selected_tran.data[
"position"])
1201 all_marker_positions.append(selected_tran.data[
"position"] + (selected_tran.data[
"end"] - selected_tran.data[
"start"]))
1204 closest_position =
None
1205 for marker_position
in sorted(all_marker_positions):
1207 if marker_position < current_position
and (abs(marker_position - current_position) > 0.1):
1209 if closest_position
and marker_position > closest_position:
1211 closest_position = marker_position
1212 elif not closest_position:
1214 closest_position = marker_position
1217 if closest_position !=
None:
1219 frame_to_seek = round(closest_position * fps_float) + 1
1220 self.SeekSignal.emit(frame_to_seek)
1223 get_app().window.refreshFrameSignal.emit()
1224 get_app().window.propertyTableView.select_frame(frame_to_seek)
1227 log.info(
"actionNextMarker_trigger")
1228 log.info(self.preview_thread.current_frame)
1231 fps =
get_app().project.get([
"fps"])
1232 fps_float = float(fps[
"num"]) / float(fps[
"den"])
1233 current_position = (self.preview_thread.current_frame - 1) / fps_float
1234 all_marker_positions = []
1237 for marker
in Marker.filter():
1238 all_marker_positions.append(marker.data[
"position"])
1243 selected_clip = Clip.get(id=clip_id)
1245 all_marker_positions.append(selected_clip.data[
"position"])
1246 all_marker_positions.append(selected_clip.data[
"position"] + (selected_clip.data[
"end"] - selected_clip.data[
"start"]))
1251 selected_tran = Transition.get(id=tran_id)
1253 all_marker_positions.append(selected_tran.data[
"position"])
1254 all_marker_positions.append(selected_tran.data[
"position"] + (selected_tran.data[
"end"] - selected_tran.data[
"start"]))
1257 closest_position =
None
1258 for marker_position
in sorted(all_marker_positions):
1260 if marker_position > current_position
and (abs(marker_position - current_position) > 0.1):
1262 if closest_position
and marker_position < closest_position:
1264 closest_position = marker_position
1265 elif not closest_position:
1267 closest_position = marker_position
1270 if closest_position !=
None:
1272 frame_to_seek = round(closest_position * fps_float) + 1
1273 self.SeekSignal.emit(frame_to_seek)
1276 get_app().window.refreshFrameSignal.emit()
1277 get_app().window.propertyTableView.select_frame(frame_to_seek)
1283 shortcut = QKeySequence(s.get(setting_name))
1289 keyboard_shortcuts = []
1291 for setting
in all_settings:
1292 if setting.get(
'category') ==
'Keyboard':
1293 keyboard_shortcuts.append(setting)
1294 return keyboard_shortcuts
1300 key_value = event.key()
1302 modifiers = int(event.modifiers())
1303 if (key_value > 0
and key_value != Qt.Key_Shift
and key_value != Qt.Key_Alt
and
1304 key_value != Qt.Key_Control
and key_value != Qt.Key_Meta):
1306 key = QKeySequence(modifiers + key_value)
1312 log.info(
"keyPressEvent: %s" % (key.toString()))
1315 player = self.preview_thread.player
1318 fps =
get_app().project.get([
"fps"])
1319 fps_float = float(fps[
"num"]) / float(fps[
"den"])
1320 playhead_position = float(self.preview_thread.current_frame - 1) / fps_float
1323 if key.matches(self.
getShortcutByName(
"seekPreviousFrame")) == QKeySequence.ExactMatch:
1327 if player.Speed() != 0:
1328 self.SpeedSignal.emit(0)
1330 self.SeekSignal.emit(player.Position() - 1)
1333 self.propertyTableView.select_frame(player.Position())
1335 elif key.matches(self.
getShortcutByName(
"seekNextFrame")) == QKeySequence.ExactMatch:
1339 if player.Speed() != 0:
1340 self.SpeedSignal.emit(0)
1342 self.SeekSignal.emit(player.Position() + 1)
1345 self.propertyTableView.select_frame(player.Position())
1347 elif key.matches(self.
getShortcutByName(
"rewindVideo")) == QKeySequence.ExactMatch:
1349 self.actionRewind.trigger()
1351 self.actionPlay.setChecked(
True)
1353 elif key.matches(self.
getShortcutByName(
"fastforwardVideo")) == QKeySequence.ExactMatch:
1355 self.actionFastForward.trigger()
1357 self.actionPlay.setChecked(
True)
1359 elif key.matches(self.
getShortcutByName(
"playToggle")) == QKeySequence.ExactMatch
or \
1360 key.matches(self.
getShortcutByName(
"playToggle1")) == QKeySequence.ExactMatch
or \
1361 key.matches(self.
getShortcutByName(
"playToggle2")) == QKeySequence.ExactMatch
or \
1364 self.actionPlay.trigger()
1365 self.propertyTableView.select_frame(player.Position())
1367 elif key.matches(self.
getShortcutByName(
"deleteItem")) == QKeySequence.ExactMatch
or \
1370 self.actionRemoveClip.trigger()
1371 self.actionRemoveTransition.trigger()
1374 elif key.matches(self.
getShortcutByName(
"actionNew")) == QKeySequence.ExactMatch:
1375 self.actionNew.trigger()
1376 elif key.matches(self.
getShortcutByName(
"actionOpen")) == QKeySequence.ExactMatch:
1377 self.actionOpen.trigger()
1378 elif key.matches(self.
getShortcutByName(
"actionSave")) == QKeySequence.ExactMatch:
1379 self.actionSave.trigger()
1380 elif key.matches(self.
getShortcutByName(
"actionUndo")) == QKeySequence.ExactMatch:
1381 self.actionUndo.trigger()
1382 elif key.matches(self.
getShortcutByName(
"actionSaveAs")) == QKeySequence.ExactMatch:
1383 self.actionSaveAs.trigger()
1384 elif key.matches(self.
getShortcutByName(
"actionImportFiles")) == QKeySequence.ExactMatch:
1385 self.actionImportFiles.trigger()
1386 elif key.matches(self.
getShortcutByName(
"actionRedo")) == QKeySequence.ExactMatch:
1387 self.actionRedo.trigger()
1388 elif key.matches(self.
getShortcutByName(
"actionExportVideo")) == QKeySequence.ExactMatch:
1389 self.actionExportVideo.trigger()
1390 elif key.matches(self.
getShortcutByName(
"actionQuit")) == QKeySequence.ExactMatch:
1391 self.actionQuit.trigger()
1392 elif key.matches(self.
getShortcutByName(
"actionPreferences")) == QKeySequence.ExactMatch:
1393 self.actionPreferences.trigger()
1394 elif key.matches(self.
getShortcutByName(
"actionAddTrack")) == QKeySequence.ExactMatch:
1395 self.actionAddTrack.trigger()
1396 elif key.matches(self.
getShortcutByName(
"actionAddMarker")) == QKeySequence.ExactMatch:
1397 self.actionAddMarker.trigger()
1398 elif key.matches(self.
getShortcutByName(
"actionPreviousMarker")) == QKeySequence.ExactMatch:
1399 self.actionPreviousMarker.trigger()
1400 elif key.matches(self.
getShortcutByName(
"actionNextMarker")) == QKeySequence.ExactMatch:
1401 self.actionNextMarker.trigger()
1402 elif key.matches(self.
getShortcutByName(
"actionTimelineZoomIn")) == QKeySequence.ExactMatch:
1403 self.actionTimelineZoomIn.trigger()
1404 elif key.matches(self.
getShortcutByName(
"actionTimelineZoomOut")) == QKeySequence.ExactMatch:
1405 self.actionTimelineZoomOut.trigger()
1406 elif key.matches(self.
getShortcutByName(
"actionTitle")) == QKeySequence.ExactMatch:
1407 self.actionTitle.trigger()
1408 elif key.matches(self.
getShortcutByName(
"actionAnimatedTitle")) == QKeySequence.ExactMatch:
1409 self.actionAnimatedTitle.trigger()
1410 elif key.matches(self.
getShortcutByName(
"actionFullscreen")) == QKeySequence.ExactMatch:
1411 self.actionFullscreen.trigger()
1412 elif key.matches(self.
getShortcutByName(
"actionAbout")) == QKeySequence.ExactMatch:
1413 self.actionAbout.trigger()
1414 elif key.matches(self.
getShortcutByName(
"actionThumbnailView")) == QKeySequence.ExactMatch:
1415 self.actionThumbnailView.trigger()
1416 elif key.matches(self.
getShortcutByName(
"actionDetailsView")) == QKeySequence.ExactMatch:
1417 self.actionDetailsView.trigger()
1418 elif key.matches(self.
getShortcutByName(
"actionProfile")) == QKeySequence.ExactMatch:
1419 self.actionProfile.trigger()
1420 elif key.matches(self.
getShortcutByName(
"actionAdd_to_Timeline")) == QKeySequence.ExactMatch:
1421 self.actionAdd_to_Timeline.trigger()
1422 elif key.matches(self.
getShortcutByName(
"actionSplitClip")) == QKeySequence.ExactMatch:
1423 self.actionSplitClip.trigger()
1424 elif key.matches(self.
getShortcutByName(
"actionSnappingTool")) == QKeySequence.ExactMatch:
1425 self.actionSnappingTool.trigger()
1426 elif key.matches(self.
getShortcutByName(
"actionJumpStart")) == QKeySequence.ExactMatch:
1427 self.actionJumpStart.trigger()
1428 elif key.matches(self.
getShortcutByName(
"actionJumpEnd")) == QKeySequence.ExactMatch:
1429 self.actionJumpEnd.trigger()
1430 elif key.matches(self.
getShortcutByName(
"actionSaveFrame")) == QKeySequence.ExactMatch:
1431 self.actionSaveFrame.trigger()
1432 elif key.matches(self.
getShortcutByName(
"actionProperties")) == QKeySequence.ExactMatch:
1433 self.actionProperties.trigger()
1434 elif key.matches(self.
getShortcutByName(
"actionTransform")) == QKeySequence.ExactMatch:
1438 self.TransformSignal.emit(
"")
1440 elif key.matches(self.
getShortcutByName(
"actionInsertKeyframe")) == QKeySequence.ExactMatch:
1441 print(
"actionInsertKeyframe")
1443 self.InsertKeyframe.emit(event)
1446 elif key.matches(self.
getShortcutByName(
"sliceAllKeepBothSides")) == QKeySequence.ExactMatch:
1447 intersecting_clips = Clip.filter(intersect=playhead_position)
1448 intersecting_trans = Transition.filter(intersect=playhead_position)
1449 if intersecting_clips
or intersecting_trans:
1451 clip_ids = [c.id
for c
in intersecting_clips]
1452 trans_ids = [t.id
for t
in intersecting_trans]
1453 self.timeline.Slice_Triggered(0, clip_ids, trans_ids, playhead_position)
1454 elif key.matches(self.
getShortcutByName(
"sliceAllKeepLeftSide")) == QKeySequence.ExactMatch:
1455 intersecting_clips = Clip.filter(intersect=playhead_position)
1456 intersecting_trans = Transition.filter(intersect=playhead_position)
1457 if intersecting_clips
or intersecting_trans:
1459 clip_ids = [c.id
for c
in intersecting_clips]
1460 trans_ids = [t.id
for t
in intersecting_trans]
1461 self.timeline.Slice_Triggered(1, clip_ids, trans_ids, playhead_position)
1462 elif key.matches(self.
getShortcutByName(
"sliceAllKeepRightSide")) == QKeySequence.ExactMatch:
1463 intersecting_clips = Clip.filter(intersect=playhead_position)
1464 intersecting_trans = Transition.filter(intersect=playhead_position)
1465 if intersecting_clips
or intersecting_trans:
1467 clip_ids = [c.id
for c
in intersecting_clips]
1468 trans_ids = [t.id
for t
in intersecting_trans]
1469 self.timeline.Slice_Triggered(2, clip_ids, trans_ids, playhead_position)
1472 elif key.matches(self.
getShortcutByName(
"pasteAll")) == QKeySequence.ExactMatch:
1473 self.timeline.Paste_Triggered(9, float(playhead_position), -1, [], [])
1474 elif key.matches(self.
getShortcutByName(
"nudgeLeft")) == QKeySequence.ExactMatch:
1476 elif key.matches(self.
getShortcutByName(
"nudgeRight")) == QKeySequence.ExactMatch:
1480 elif key.matches(self.
getShortcutByName(
"selectAll")) == QKeySequence.ExactMatch:
1481 self.timeline.SelectAll()
1483 elif key.matches(self.
getShortcutByName(
"selectNone")) == QKeySequence.ExactMatch:
1484 self.timeline.ClearAllSelections()
1492 from windows.profile
import Profile
1495 result = win.exec_()
1496 if result == QDialog.Accepted:
1497 log.info(
'Profile add confirmed')
1501 log.info(
"actionSplitClip_trigger")
1507 f = File.get(id=file_id)
1515 from windows.cutting
import Cutting
1518 result = win.exec_()
1519 if result == QDialog.Accepted:
1520 log.info(
'Cutting Finished')
1522 log.info(
'Cutting Cancelled')
1525 log.info(
"actionRemove_from_Project_trigger")
1530 f = File.get(id=file_id)
1536 clips = Clip.filter(file_id=file_id)
1545 get_app().window.refreshFrameSignal.emit()
1548 log.info(
'actionRemoveClip_trigger')
1553 clips = Clip.filter(id=clip_id)
1562 get_app().window.refreshFrameSignal.emit()
1565 log.info(
'actionProperties_trigger')
1568 if not self.dockProperties.isVisible():
1569 self.dockProperties.show()
1572 log.info(
'actionRemoveEffect_trigger')
1576 log.info(
"effect id: %s" % effect_id)
1579 clips = Clip.filter()
1582 found_effect =
False
1583 log.info(
"c.data[effects]: %s" % c.data[
"effects"])
1585 for effect
in c.data[
"effects"]:
1586 if effect[
"id"] == effect_id:
1587 found_effect = effect
1592 c.data[
"effects"].remove(found_effect)
1595 c.data.pop(
"reader")
1604 get_app().window.refreshFrameSignal.emit()
1607 log.info(
'actionRemoveTransition_trigger')
1612 transitions = Transition.filter(id=tran_id)
1613 for t
in transitions:
1621 get_app().window.refreshFrameSignal.emit()
1624 log.info(
'actionRemoveTrack_trigger')
1630 max_track_number = len(
get_app().project.get([
"layers"]))
1633 selected_track = Track.get(id=track_id)
1634 selected_track_number = int(selected_track.data[
"number"])
1637 if max_track_number == 1:
1639 QMessageBox.warning(self, _(
"Error Removing Track"), _(
"You must keep at least 1 track"))
1643 for clip
in Clip.filter(layer=selected_track_number):
1647 for trans
in Transition.filter(layer=selected_track_number):
1651 selected_track.delete()
1657 get_app().window.refreshFrameSignal.emit()
1662 log.info(
'actionLockTrack_trigger')
1666 selected_track = Track.get(id=track_id)
1669 selected_track.data[
'lock'] =
True
1670 selected_track.save()
1675 log.info(
'actionUnlockTrack_trigger')
1679 selected_track = Track.get(id=track_id)
1682 selected_track.data[
'lock'] =
False
1683 selected_track.save()
1688 log.info(
'actionRenameTrack_trigger')
1695 selected_track = Track.get(id=track_id)
1698 all_tracks =
get_app().project.get([
"layers"])
1699 display_count = len(all_tracks)
1700 for track
in reversed(sorted(all_tracks, key=itemgetter(
'number'))):
1701 if track.get(
"id") == track_id:
1705 track_name = selected_track.data[
"label"]
or _(
"Track %s") % display_count
1707 text, ok = QInputDialog.getText(self, _(
'Rename Track'), _(
'Track Name:'), text=track_name)
1710 selected_track.data[
"label"] = text
1711 selected_track.save()
1714 log.info(
'actionRemoveMarker_trigger')
1717 marker = Marker.filter(id=marker_id)
1723 self.sliderZoom.setValue(self.sliderZoom.value() - self.sliderZoom.singleStep())
1726 self.sliderZoom.setValue(self.sliderZoom.value() + self.sliderZoom.singleStep())
1730 if not self.isFullScreen():
1731 self.showFullScreen()
1736 log.info(
"Show file properties")
1742 f = File.get(id=file_id)
1745 from windows.file_properties
import FileProperties
1746 win = FileProperties(f)
1748 result = win.exec_()
1749 if result == QDialog.Accepted:
1752 clips = Clip.filter(file_id=file_id)
1755 c.data[
"reader"][
"path"] = f.data[
"path"]
1758 log.info(
'File Properties Finished')
1760 log.info(
'File Properties Cancelled')
1763 log.info(
"Switch to Details View")
1771 self.filesTreeView.prepare_for_delete()
1774 if app.context_menu_object ==
"files":
1775 s.set(
"file_view",
"details")
1777 self.filesTreeView.deleteLater()
1783 elif app.context_menu_object ==
"transitions":
1784 s.set(
"transitions_view",
"details")
1786 self.transitionsTreeView.deleteLater()
1792 elif app.context_menu_object ==
"effects":
1793 s.set(
"effects_view",
"details")
1795 self.effectsTreeView.deleteLater()
1801 log.info(
"Switch to Thumbnail View")
1809 self.filesTreeView.prepare_for_delete()
1812 if app.context_menu_object ==
"files":
1813 s.set(
"file_view",
"thumbnail")
1815 self.filesTreeView.deleteLater()
1821 elif app.context_menu_object ==
"transitions":
1822 s.set(
"transitions_view",
"thumbnail")
1824 self.transitionsTreeView.deleteLater()
1830 elif app.context_menu_object ==
"effects":
1831 s.set(
"effects_view",
"thumbnail")
1833 self.effectsTreeView.deleteLater()
1840 self.filesTreeView.resize_contents()
1845 return [self.dockFiles,
1846 self.dockTransitions,
1849 self.dockProperties,
1856 self.removeDockWidget(dock)
1862 self.addDockWidget(area, dock)
1868 dock.setFloating(is_floating)
1874 if get_app().window.dockWidgetArea(dock) != Qt.NoDockWidgetArea:
1882 dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
1888 dock.setFeatures(QDockWidget.AllDockWidgetFeatures)
1902 self.
addDocks([self.dockFiles, self.dockTransitions, self.dockEffects, self.dockVideo], Qt.TopDockWidgetArea)
1905 self.tabifyDockWidget(self.dockFiles, self.dockTransitions)
1906 self.tabifyDockWidget(self.dockTransitions, self.dockEffects)
1907 self.
showDocks([self.dockFiles, self.dockTransitions, self.dockEffects, self.dockVideo])
1910 simple_state =
"AAAA/wAAAAD9AAAAAwAAAAAAAAEnAAAC3/wCAAAAAvwAAAJeAAAApwAAAAAA////+gAAAAACAAAAAfsAAAAYAGQAbwBjAGsASwBlAHkAZgByAGEAbQBlAAAAAAD/////AAAAAAAAAAD7AAAAHABkAG8AYwBrAFAAcgBvAHAAZQByAHQAaQBlAHMAAAAAJwAAAt8AAACnAP///wAAAAEAAAEcAAABQPwCAAAAAfsAAAAYAGQAbwBjAGsASwBlAHkAZgByAGEAbQBlAQAAAVgAAAAVAAAAAAAAAAAAAAACAAAERgAAAtj8AQAAAAH8AAAAAAAABEYAAAD6AP////wCAAAAAvwAAAAnAAABwAAAALQA/////AEAAAAC/AAAAAAAAAFcAAAAewD////6AAAAAAIAAAAD+wAAABIAZABvAGMAawBGAGkAbABlAHMBAAAAAP////8AAACYAP////sAAAAeAGQAbwBjAGsAVAByAGEAbgBzAGkAdABpAG8AbgBzAQAAAAD/////AAAAmAD////7AAAAFgBkAG8AYwBrAEUAZgBmAGUAYwB0AHMBAAAAAP////8AAACYAP////sAAAASAGQAbwBjAGsAVgBpAGQAZQBvAQAAAWIAAALkAAAARwD////7AAAAGABkAG8AYwBrAFQAaQBtAGUAbABpAG4AZQEAAAHtAAABEgAAAJYA////AAAERgAAAAEAAAABAAAAAgAAAAEAAAAC/AAAAAEAAAACAAAAAQAAAA4AdABvAG8AbABCAGEAcgEAAAAA/////wAAAAAAAAAA"
1912 QCoreApplication.processEvents()
1921 self.
addDocks([self.dockFiles, self.dockTransitions, self.dockVideo], Qt.TopDockWidgetArea)
1922 self.
addDocks([self.dockEffects], Qt.RightDockWidgetArea)
1923 self.
addDocks([self.dockProperties], Qt.LeftDockWidgetArea)
1926 self.tabifyDockWidget(self.dockTransitions, self.dockEffects)
1927 self.
showDocks([self.dockFiles, self.dockTransitions, self.dockVideo, self.dockEffects, self.dockProperties])
1930 advanced_state =
"AAAA/wAAAAD9AAAAAwAAAAAAAACCAAAC3/wCAAAAAvsAAAASAGQAbwBjAGsARgBpAGwAZQBzAQAAACcAAALfAAAAmAD////8AAACXgAAAKcAAAAAAP////oAAAAAAgAAAAH7AAAAGABkAG8AYwBrAEsAZQB5AGYAcgBhAG0AZQAAAAAA/////wAAAAAAAAAAAAAAAQAAANUAAALf/AIAAAAC+wAAABwAZABvAGMAawBQAHIAbwBwAGUAcgB0AGkAZQBzAQAAACcAAALfAAAAnwD////7AAAAGABkAG8AYwBrAEsAZQB5AGYAcgBhAG0AZQEAAAFYAAAAFQAAAAAAAAAAAAAAAgAAAuMAAALY/AEAAAAB/AAAAIgAAALjAAABWgD////8AgAAAAL8AAAAJwAAAe8AAACYAP////wBAAAAAvsAAAAeAGQAbwBjAGsAVAByAGEAbgBzAGkAdABpAG8AbgBzAQAAAIgAAACKAAAAbAD////7AAAAEgBkAG8AYwBrAFYAaQBkAGUAbwEAAAEYAAACUwAAAEcA/////AAAAhwAAADjAAAAmAD////8AQAAAAL7AAAAGABkAG8AYwBrAFQAaQBtAGUAbABpAG4AZQEAAACIAAACUgAAAPoA////+wAAABYAZABvAGMAawBFAGYAZgBlAGMAdABzAQAAAuAAAACLAAAAWgD///8AAALjAAAAAQAAAAEAAAACAAAAAQAAAAL8AAAAAQAAAAIAAAABAAAADgB0AG8AbwBsAEIAYQByAQAAAAD/////AAAAAAAAAAA="
1932 QCoreApplication.processEvents()
1938 self.actionFreeze_View.setVisible(
False)
1939 self.actionUn_Freeze_View.setVisible(
True)
1945 self.actionFreeze_View.setVisible(
True)
1946 self.actionUn_Freeze_View.setVisible(
False)
1959 s.set(
"tutorial_enabled",
True)
1960 s.set(
"tutorial_ids",
"")
1964 self.tutorial_manager.exit_manager()
1975 profile =
get_app().project.get([
"profile"])
1979 if get_app().project.needs_save():
1980 save_indicator =
"*"
1981 self.actionSave.setEnabled(
True)
1983 self.actionSave.setEnabled(
False)
1986 if not get_app().project.current_filepath:
1988 self.setWindowTitle(
"%s %s [%s] - %s" % (save_indicator, _(
"Untitled Project"), profile,
"OpenShot Video Editor"))
1992 parent_path, filename = os.path.split(
get_app().project.current_filepath)
1993 filename, ext = os.path.splitext(filename)
1994 filename = filename.replace(
"_",
" ").replace(
"-",
" ").capitalize()
1995 self.setWindowTitle(
"%s %s [%s] - %s" % (save_indicator, filename, profile,
"OpenShot Video Editor"))
1999 log.info(
'updateStatusChanged')
2000 self.actionUndo.setEnabled(undo_status)
2001 self.actionRedo.setEnabled(redo_status)
2006 log.info(
'main::addSelection: item_id: %s, item_type: %s, clear_existing: %s' % (item_id, item_type, clear_existing))
2010 if item_type ==
"clip":
2011 self.selected_clips.clear()
2012 elif item_type ==
"transition":
2013 self.selected_transitions.clear()
2014 elif item_type ==
"effect":
2015 self.selected_effects.clear()
2018 self.TransformSignal.emit(
"")
2023 self.selected_clips.append(item_id)
2025 self.selected_transitions.append(item_id)
2027 self.selected_effects.append(item_id)
2032 self.show_property_timer.start()
2039 self.selected_clips.remove(item_id)
2041 self.selected_transitions.remove(item_id)
2043 self.selected_effects.remove(item_id)
2046 get_app().window.TransformSignal.emit(
"")
2062 self.show_property_timer.start()
2078 if s.get(
'window_geometry_v2'): self.restoreGeometry(
qt_types.str_to_bytes(s.get(
'window_geometry_v2')))
2090 recent_projects = s.get(
"recent_projects")
2096 self.
recent_menu = self.menuFile.addMenu(QIcon.fromTheme(
"document-open-recent"), _(
"Recent Projects"))
2097 self.menuFile.insertMenu(self.actionRecent_Placeholder, self.
recent_menu)
2100 self.recent_menu.clear()
2103 for file_path
in reversed(recent_projects):
2104 new_action = self.recent_menu.addAction(file_path)
2110 recent_projects = s.get(
"recent_projects")
2111 if file_path
in recent_projects:
2112 recent_projects.remove(file_path)
2113 s.set(
"recent_projects", recent_projects)
2121 self.OpenProjectSignal.emit(file_path)
2127 self.actionUndo.setEnabled(
False)
2128 self.actionRedo.setEnabled(
False)
2133 self.filesActionGroup.setExclusive(
True)
2134 self.filesActionGroup.addAction(self.actionFilesShowAll)
2135 self.filesActionGroup.addAction(self.actionFilesShowVideo)
2136 self.filesActionGroup.addAction(self.actionFilesShowAudio)
2137 self.filesActionGroup.addAction(self.actionFilesShowImage)
2138 self.actionFilesShowAll.setChecked(
True)
2139 self.filesToolbar.addAction(self.actionFilesShowAll)
2140 self.filesToolbar.addAction(self.actionFilesShowVideo)
2141 self.filesToolbar.addAction(self.actionFilesShowAudio)
2142 self.filesToolbar.addAction(self.actionFilesShowImage)
2144 self.filesFilter.setObjectName(
"filesFilter")
2145 self.filesFilter.setPlaceholderText(_(
"Filter"))
2147 self.actionFilesClear.setEnabled(
False)
2148 self.filesToolbar.addAction(self.actionFilesClear)
2154 self.transitionsActionGroup.setExclusive(
True)
2155 self.transitionsActionGroup.addAction(self.actionTransitionsShowAll)
2156 self.transitionsActionGroup.addAction(self.actionTransitionsShowCommon)
2157 self.actionTransitionsShowAll.setChecked(
True)
2158 self.transitionsToolbar.addAction(self.actionTransitionsShowAll)
2159 self.transitionsToolbar.addAction(self.actionTransitionsShowCommon)
2161 self.transitionsFilter.setObjectName(
"transitionsFilter")
2162 self.transitionsFilter.setPlaceholderText(_(
"Filter"))
2164 self.actionTransitionsClear.setEnabled(
False)
2165 self.transitionsToolbar.addAction(self.actionTransitionsClear)
2171 self.effectsFilter.setObjectName(
"effectsFilter")
2172 self.effectsFilter.setPlaceholderText(_(
"Filter"))
2174 self.actionEffectsClear.setEnabled(
False)
2175 self.effectsToolbar.addAction(self.actionEffectsClear)
2182 ospacer1 = QWidget(self)
2183 ospacer1.setMinimumSize(32, 1)
2184 self.videoToolbar.addWidget(ospacer1)
2190 spacer = QWidget(self)
2191 spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
2192 self.videoToolbar.addWidget(spacer)
2195 self.videoToolbar.addAction(self.actionJumpStart)
2196 self.videoToolbar.addAction(self.actionRewind)
2197 self.videoToolbar.addAction(self.actionPlay)
2198 self.videoToolbar.addAction(self.actionFastForward)
2199 self.videoToolbar.addAction(self.actionJumpEnd)
2200 self.actionPlay.setCheckable(
True)
2203 spacer = QWidget(self)
2204 spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
2205 self.videoToolbar.addWidget(spacer)
2208 self.videoToolbar.addAction(self.actionSaveFrame)
2215 self.timelineToolbar.addAction(self.actionAddTrack)
2216 self.timelineToolbar.addSeparator()
2219 self.timelineToolbar.addAction(self.actionSnappingTool)
2220 self.timelineToolbar.addAction(self.actionRazorTool)
2221 self.timelineToolbar.addSeparator()
2222 self.timelineToolbar.addAction(self.actionAddMarker)
2223 self.timelineToolbar.addAction(self.actionPreviousMarker)
2224 self.timelineToolbar.addAction(self.actionNextMarker)
2225 self.timelineToolbar.addSeparator()
2228 initial_scale =
get_app().project.get([
"scale"])
or 15
2234 self.sliderZoom.setPageStep(1)
2235 self.sliderZoom.setRange(0, 30)
2236 self.sliderZoom.setValue(initial_zoom)
2237 self.sliderZoom.setInvertedControls(
True)
2238 self.sliderZoom.resize(100, 16)
2243 self.timelineToolbar.addAction(self.actionTimelineZoomIn)
2244 self.timelineToolbar.addWidget(self.
sliderZoom)
2245 self.timelineToolbar.addAction(self.actionTimelineZoomOut)
2263 self.propertyTableView.loadProperties.emit(
"",
"")
2268 log.info(
'foundCurrentVersion: Found the latest version: %s' % version)
2272 if info.VERSION < version:
2274 spacer = QWidget(self)
2275 spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
2276 self.toolBar.addWidget(spacer)
2279 self.actionUpdate.setVisible(
True)
2280 self.actionUpdate.setText(_(
"Update Available"))
2281 self.actionUpdate.setToolTip(_(
"Update Available: <b>%s</b>") % version)
2284 updateButton = QToolButton()
2285 updateButton.setDefaultAction(self.actionUpdate)
2286 updateButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
2287 self.toolBar.addWidget(updateButton)
2292 QMainWindow.moveEvent(self, event)
2294 self.tutorial_manager.re_position_dialog()
2297 QMainWindow.resizeEvent(self, event)
2299 self.tutorial_manager.re_position_dialog()
2304 QMainWindow.showEvent(self, event)
2305 for child
in self.findChildren(QDockWidget):
2306 if child.isFloating()
and child.isEnabled():
2313 QMainWindow.hideEvent(self, event)
2314 for child
in self.findChildren(QDockWidget):
2315 if child.isFloating()
and child.isVisible():
2323 self.show_property_timer.stop()
2337 for action
in self.findChildren(QAction):
2338 if shortcut.get(
'setting') == action.objectName():
2339 action.setShortcut(QKeySequence(_(shortcut.get(
'value'))))
2346 log.info(
"InitCacheSettings")
2347 log.info(
"cache-mode: %s" % s.get(
"cache-mode"))
2348 log.info(
"cache-limit-mb: %s" % s.get(
"cache-limit-mb"))
2351 cache_limit = s.get(
"cache-limit-mb") * 1024 * 1024
2354 new_cache_object =
None
2355 if s.get(
"cache-mode") ==
"CacheMemory":
2357 log.info(
"Creating CacheMemory object with %s byte limit" % cache_limit)
2358 new_cache_object = openshot.CacheMemory(cache_limit)
2359 self.timeline_sync.timeline.SetCache(new_cache_object)
2361 elif s.get(
"cache-mode") ==
"CacheDisk":
2363 log.info(
"Creating CacheDisk object with %s byte limit at %s" % (cache_limit, info.PREVIEW_CACHE_PATH))
2364 image_format = s.get(
"cache-image-format")
2365 image_quality = s.get(
"cache-quality")
2366 image_scale = s.get(
"cache-scale")
2367 new_cache_object = openshot.CacheDisk(info.PREVIEW_CACHE_PATH, image_format, image_quality, image_scale, cache_limit)
2368 self.timeline_sync.timeline.SetCache(new_cache_object)
2372 self.cache_object.Clear()
2383 from gi.repository
import Unity
2384 self.unity_launchers.append(Unity.LauncherEntry.get_for_desktop_id(
"openshot-qt.desktop"))
2385 self.unity_launchers.append(Unity.LauncherEntry.get_for_desktop_id(
"appimagekit-openshot-qt.desktop"))
2389 launcher.set_property(
"progress", current_frame / (end_frame - start_frame))
2390 launcher.set_property(
"progress_visible",
True)
2403 launcher.set_property(
"progress", 0.0)
2404 launcher.set_property(
"progress_visible",
False)
2420 QMainWindow.__init__(self)
2436 if not s.get(
"unique_install_id"):
2437 s.set(
"unique_install_id", str(uuid4()))
2461 get_app().updates.add_watcher(self)
2470 if not self.
mode ==
"unittest":
2478 self.frameWeb.layout().addWidget(self.
timeline)
2481 self.setCorner(Qt.TopLeftCorner, Qt.LeftDockWidgetArea)
2482 self.setCorner(Qt.BottomLeftCorner, Qt.LeftDockWidgetArea)
2483 self.setCorner(Qt.TopRightCorner, Qt.RightDockWidgetArea)
2484 self.setCorner(Qt.BottomRightCorner, Qt.RightDockWidgetArea)
2487 if s.get(
"file_view") ==
"details":
2492 self.filesTreeView.setFocus()
2495 if s.get(
"transitions_view") ==
"details":
2502 if s.get(
"effects_view") ==
"details":
2513 self.txtPropertyFilter.setPlaceholderText(_(
"Filter"))
2516 self.dockPropertiesContent.layout().addWidget(self.
selectionLabel, 0, 1)
2528 self.show_property_timer.setInterval(100)
2530 self.show_property_timer.stop()
2534 self.tabVideo.layout().insertWidget(0, self.
videoPreview)
2545 self.preview_parent.Init(self, self.timeline_sync.timeline, self.
videoPreview)
2553 self.auto_save_timer.setInterval(s.get(
"autosave-interval") * 1000 * 60)
2555 if s.get(
"enable-auto-save"):
2556 self.auto_save_timer.start()
2559 if s.get(
"hardware_decode"):
2560 openshot.Settings.Instance().HARDWARE_DECODE =
True
2562 openshot.Settings.Instance().HARDWARE_DECODE =
False
2565 if s.get(
"hardware_encode"):
2566 openshot.Settings.Instance().HARDWARE_ENCODE =
True
2568 openshot.Settings.Instance().HARDWARE_ENCODE =
False
2571 if s.get(
"omp_threads_enabled"):
2572 openshot.Settings.Instance().WAIT_FOR_VIDEO_PROCESSING_TASK =
False
2574 openshot.Settings.Instance().WAIT_FOR_VIDEO_PROCESSING_TASK =
True
2577 openshot.Settings.Instance().HIGH_QUALITY_SCALING =
False
2586 if not self.
mode ==
"unittest":
2593 if sys.platform ==
"linux":
2603 QTimer.singleShot(100, self.refreshFrameSignal.emit)
def actionLockTrack_trigger
Callback for locking a track.
def actionAdvanced_View_trigger
Switch to an alternative view.
def actionExportVideo_trigger
def InitCacheSettings
Set the correct cache settings for the timeline.
def actionRemoveTrack_trigger
def actionImportImageSequence_trigger
def secondsToZoom
Convert a number of seconds to a timeline zoom factor.
def save_project
Save a project to a file path, and refresh the screen.
def recent_project_clicked
Load a recent project when clicked.
def actionDuplicateTitle_trigger
def actionImportFiles_trigger
def actionRemove_from_Project_trigger
def actionAddMarker_trigger
def track_metric_screen
Track a GUI screen being shown.
def actionAbout_trigger
Show about dialog.
def open_project
Open a project from a file path, and refresh the screen.
def actionFile_Properties_trigger
def get_app
Returns the current QApplication instance of OpenShot.
def actionArrowTool_trigger
def actionAnimatedTitle_trigger
def actionSimple_View_trigger
Switch to the default / simple view.
def str_to_bytes
This is required to save Qt byte arrays into a base64 string (to save screen preferences) ...
def setup_icon
Using the window xml, set the icon on the given element, or if theme_name passed load that icon...
def getDocks
Get a list of all dockable widgets.
def freezeDocks
Freeze all dockable widgets on the main screen (no float, moving, or closing)
def actionDetailsView_trigger
def floatDocks
Float or Un-Float all dockable widgets above main screen.
def foundCurrentVersion
Handle the callback for detecting the current version on openshot.org.
def actionRazorTool_trigger
Toggle razor tool on and off.
def actionRenameTrack_trigger
Callback for renaming track.
def actionUnlockTrack_trigger
Callback for unlocking a track.
def actionSnappingTool_trigger
def actionEditTitle_trigger
def getShortcutByName
Get a key sequence back from the setting name.
def actionUn_Freeze_View_trigger
Un-Freeze all dockable widgets on the main screen.
def actionAddTrackBelow_trigger
def actionFilesShowAll_trigger
def actionTimelineZoomOut_trigger
def previewFrame
Preview a specific frame.
def actionAddTrack_trigger
def actionTranslate_trigger
def track_metric_error
Track an error has occurred.
def actionAnimation_trigger
def actionJumpStart_trigger
def clear_all_thumbnails
Clear all user thumbnails.
def actionRemoveMarker_trigger
def actionReportBug_trigger
def InitKeyboardShortcuts
Initialize all keyboard shortcuts from the settings file.
def FrameExported
Connect to Unity launcher (for Linux)
def transformTriggered
Handle transform signal (to keep track of whether a transform is happening or not) ...
def keyPressEvent
Process key press events and match with known shortcuts.
def removeDocks
Remove all dockable widgets on main screen.
def actionRemoveTransition_trigger
def actionShow_All_trigger
Show all dockable widgets.
def actionThumbnailView_trigger
def actionNextMarker_trigger
def load_ui
Load a Qt *.ui file, and also load an XML parsed version.
def recover_backup
Recover the backup file (if any)
def showDocks
Show all dockable widgets on the main screen.
def show_property_timeout
Callback for show property timer.
def tail_file
Read the end of a file (n number of lines)
def actionPreferences_trigger
def getAllKeyboardShortcuts
Get a key sequence back from the setting name.
def actionSplitClip_trigger
def showEvent
Have any child windows follow main-window state.
def actionPreview_File_trigger
Preview the selected media file.
def actionTransitionsShowAll_trigger
def website_language
Get the current website language code for URLs.
def moveEvent
Move tutorial dialogs also (if any)
def actionProfile_trigger
def actionPreviousMarker_trigger
def unFreezeDocks
Un-freeze all dockable widgets on the main screen (allow them to be moved, closed, and floated)
def destroy_lock_file
Destroy the lock file.
def actionProperties_trigger
def actionRemoveEffect_trigger
def actionHelpContents_trigger
def zoomToSeconds
Convert zoom factor (slider position) into scale-seconds.
def SetWindowTitle
Set the window title based on a variety of factors.
def actionRemoveClip_trigger
def auto_save_project
Auto save the project.
def actionAskQuestion_trigger
def clearSelections
Clear all selection containers.
def actionFastForward_trigger
def actionFilesShowImage_trigger
def actionFilesShowVideo_trigger
def get_current_Version
Get the current version.
def track_exception_stacktrace
Track an exception/stacktrace has occurred.
Interface for classes that listen for 'undo' and 'redo' events.
def handlePausedVideo
Handle the pause signal, by refreshing the properties dialog.
def actionUploadVideo_trigger
def actionFilesShowAudio_trigger
def load_recent_menu
Clear and load the list of recent menu items.
def actionFullscreen_trigger
def init_ui
Initialize all child widgets and action of a window or dialog.
def actionTransitionsShowCommon_trigger
def actionJumpEnd_trigger
This class contains the logic for the main window widget.
def updateStatusChanged
Easily be notified each time there are 'undo' or 'redo' actions available in the UpdateManager.
def actionTutorial_trigger
Show tutorial again.
def actionAddTrackAbove_trigger
def hideDocks
Hide all dockable widgets on the main screen.
def actionTimelineZoomIn_trigger
def addDocks
Add all dockable widgets to the same dock area on the main screen.
def hideEvent
Have any child windows hide with main window.
def remove_recent_project
def track_metric_session
Track a GUI screen being shown.
def actionSaveFrame_trigger
def bytes_to_str
This is required to load base64 Qt byte array strings into a Qt byte array (to load screen preference...
def movePlayhead
Update playhead position.
def actionAdd_to_Timeline_trigger
def ExportFinished
Export has completed.
def create_lock_file
Create a lock file.
def actionFreeze_View_trigger
Freeze all dockable widgets on the main screen.
def get_settings
Get the current QApplication's settings instance.
def actionClearHistory_trigger
Clear history for current project.