36 from uuid
import uuid4
37 from copy
import deepcopy
40 from PyQt5.QtGui import QIcon, QCursor, QKeySequence
44 from windows.views.timeline_webview
import TimelineWebView
45 from classes
import info, ui_util, settings, qt_types, updates
46 from classes.app
import get_app
47 from classes.logger
import log
48 from classes.timeline
import TimelineSync
49 from classes.query
import File, Clip, Transition, Marker, Track
52 from classes.conversion
import zoomToSeconds, secondsToZoom
53 from images
import openshot_rc
54 from windows.views.files_treeview
import FilesTreeView
55 from windows.views.files_listview
import FilesListView
56 from windows.views.transitions_treeview
import TransitionsTreeView
57 from windows.views.transitions_listview
import TransitionsListView
58 from windows.views.effects_treeview
import EffectsTreeView
59 from windows.views.effects_listview
import EffectsListView
60 from windows.views.properties_tableview
import PropertiesTableView, SelectionLabel
61 from windows.views.tutorial
import TutorialManager
62 from windows.video_widget
import VideoWidget
63 from windows.preview_thread
import PreviewParent
71 ui_path = os.path.join(info.PATH,
'windows',
'ui',
'main-window.ui')
73 previewFrameSignal = pyqtSignal(int)
74 refreshFrameSignal = pyqtSignal()
75 LoadFileSignal = pyqtSignal(str)
76 PlaySignal = pyqtSignal(int)
77 PauseSignal = pyqtSignal()
78 StopSignal = pyqtSignal()
79 SeekSignal = pyqtSignal(int)
80 SpeedSignal = pyqtSignal(float)
81 RecoverBackup = pyqtSignal()
82 FoundVersionSignal = pyqtSignal(str)
83 WaveformReady = pyqtSignal(str, list)
84 TransformSignal = pyqtSignal(str)
85 ExportStarted = pyqtSignal(str, int, int)
86 ExportFrame = pyqtSignal(str, int, int, int)
87 ExportEnded = pyqtSignal(str)
88 MaxSizeChanged = pyqtSignal(object)
89 InsertKeyframe = pyqtSignal(object)
95 self.tutorial_manager.exit_manager()
98 if get_app().project.needs_save()
and not self.
mode ==
"unittest":
99 log.info(
'Prompt user to save project')
104 ret = QMessageBox.question(self, _(
"Unsaved Changes"), _(
"Save changes to project before closing?"), QMessageBox.Cancel | QMessageBox.No | QMessageBox.Yes)
105 if ret == QMessageBox.Yes:
109 elif ret == QMessageBox.Cancel:
121 self.StopSignal.emit()
124 QCoreApplication.processEvents()
127 self.preview_thread.player.CloseAudioDevice()
128 self.preview_thread.kill()
129 self.preview_parent.background.exit()
130 self.preview_parent.background.wait(5000)
133 openshot.ZmqLogger.Instance().Close()
134 get_app().logger_libopenshot.kill()
142 log.info(
"recover_backup")
144 recovery_path = os.path.join(info.BACKUP_PATH,
"backup.osp")
147 if os.path.exists(recovery_path):
148 log.info(
"Recovering backup file: %s" % recovery_path)
149 self.
open_project(recovery_path, clear_thumbnails=
False)
152 get_app().project.current_filepath =
None
153 get_app().project.has_unsaved_changes =
True
161 msg.setWindowTitle(_(
"Backup Recovered"))
162 msg.setText(_(
"Your most recent unsaved project has been recovered."))
169 self.actionUndo.setEnabled(
False)
170 self.actionRedo.setEnabled(
False)
176 lock_path = os.path.join(info.USER_PATH,
".lock")
177 lock_value = str(uuid4())
180 if os.path.exists(lock_path):
182 log_path = os.path.join(info.USER_PATH,
"libopenshot.log")
184 last_stack_trace =
""
186 log_start_counter = 0
187 if os.path.exists(log_path):
188 with open(log_path,
"rb")
as f:
190 for raw_line
in reversed(self.
tail_file(f, 500)):
191 line = str(raw_line,
'utf-8')
193 if "End of Stack Trace" in line:
196 elif "Unhandled Exception: Stack Trace" in line:
199 elif "libopenshot logging:" in line:
200 log_start_counter += 1
201 if log_start_counter > 1:
207 last_stack_trace = line + last_stack_trace
210 if line.strip()
and "---" not in line
and "libopenshot logging:" not in line
and not last_log_line:
216 last_log_line = last_stack_trace.split(
"\n")[0].strip()
224 if platform.system() ==
"Darwin":
225 last_log_line =
"mac-%s" % last_log_line[58:].strip()
226 elif platform.system() ==
"Windows":
227 last_log_line =
"windows-%s" % last_log_line
228 elif platform.system() ==
"Linux":
229 last_log_line =
"linux-%s" % last_log_line.replace(
"/usr/local/lib/",
"")
232 last_log_line = last_log_line.replace(
"()",
"")
233 log_parts = last_log_line.split(
"(")
234 if len(log_parts) == 2:
235 last_log_line =
"-%s" % log_parts[0].replace(
"logger_libopenshot:INFO ",
"").strip()[:64]
236 elif len(log_parts) >= 3:
237 last_log_line =
"-%s (%s" % (log_parts[0].replace(
"logger_libopenshot:INFO ",
"").strip()[:64], log_parts[1])
242 log.error(
"Unhandled crash detected... will attempt to recover backup project: %s" % info.BACKUP_PATH)
253 with open(lock_path,
'w')
as f:
259 lock_path = os.path.join(info.USER_PATH,
".lock")
262 if os.path.exists(lock_path):
270 to_read = n + (offset
or 0)
275 f.seek(-(avg_line_length * to_read), 2)
280 lines = f.read().splitlines()
281 if len(lines) >= to_read
or pos == 0:
283 return lines[-to_read:offset
and -offset
or None]
292 if get_app().project.needs_save():
293 ret = QMessageBox.question(self, _(
"Unsaved Changes"), _(
"Save changes to project first?"), QMessageBox.Cancel | QMessageBox.No | QMessageBox.Yes)
294 if ret == QMessageBox.Yes:
297 elif ret == QMessageBox.Cancel:
312 self.filesTreeView.refresh_view()
313 log.info(
"New Project created.")
320 from windows.animated_title
import AnimatedTitle
321 win = AnimatedTitle()
324 if result == QDialog.Accepted:
325 log.info(
'animated title add confirmed')
327 log.info(
'animated title add cancelled')
331 from windows.animation
import Animation
335 if result == QDialog.Accepted:
336 log.info(
'animation confirmed')
338 log.info(
'animation cancelled')
342 from windows.title_editor
import TitleEditor
346 if result == QDialog.Accepted:
347 log.info(
'title editor add confirmed')
349 log.info(
'title editor add cancelled')
355 file = File.get(id=selected_file_id)
356 file_path = file.data.get(
"path")
359 thumb_path = os.path.join(info.THUMBNAIL_PATH,
"{}.png".format(file.id))
362 if os.path.exists(thumb_path):
363 os.remove(thumb_path)
366 from windows.title_editor
import TitleEditor
367 win = TitleEditor(file_path)
372 get_app().window.filesTreeView.refresh_view()
378 file = File.get(id=selected_file_id)
379 file_path = file.data.get(
"path")
382 from windows.title_editor
import TitleEditor
383 win = TitleEditor(file_path, duplicate=
True)
389 from windows.Import_image_seq
import ImportImageSeq
390 win = ImportImageSeq()
393 if result == QDialog.Accepted:
394 log.info(
'Import image sequence add confirmed')
396 log.info(
'Import image sequence add cancelled')
403 log.info(
'History cleared')
414 app.updates.save_history(app.project, s.get(
"history-limit"))
417 app.project.save(file_path)
425 log.info(
"Saved project {}".format(file_path))
427 except Exception
as ex:
428 log.error(
"Couldn't save project %s. %s" % (file_path, str(ex)))
429 QMessageBox.warning(self, _(
"Error Saving Project"), str(ex))
439 get_app().setOverrideCursor(QCursor(Qt.WaitCursor))
442 if os.path.exists(file_path):
448 app.project.load(file_path)
455 app.updates.load_history(app.project)
461 self.filesTreeView.refresh_view()
466 log.info(
"Loaded project {}".format(file_path))
468 except Exception
as ex:
469 log.error(
"Couldn't open project {}".format(file_path))
470 QMessageBox.warning(self, _(
"Error Opening Project"), str(ex))
473 get_app().restoreOverrideCursor()
479 if os.path.exists(info.THUMBNAIL_PATH):
480 log.info(
"Clear all thumbnails: %s" % info.THUMBNAIL_PATH)
482 shutil.rmtree(info.THUMBNAIL_PATH)
484 os.mkdir(info.THUMBNAIL_PATH)
487 if os.path.exists(info.BLENDER_PATH):
488 log.info(
"Clear all animations: %s" % info.BLENDER_PATH)
490 shutil.rmtree(info.BLENDER_PATH)
492 os.mkdir(info.BLENDER_PATH)
495 if os.path.exists(info.ASSETS_PATH):
496 log.info(
"Clear all assets: %s" % info.ASSETS_PATH)
498 shutil.rmtree(info.ASSETS_PATH)
500 os.mkdir(info.ASSETS_PATH)
503 if os.path.exists(info.BACKUP_PATH):
504 log.info(
"Clear all backups: %s" % info.BACKUP_PATH)
506 shutil.rmtree(info.BACKUP_PATH)
508 os.mkdir(info.BACKUP_PATH)
510 log.info(
"Failed to clear thumbnails: %s" % info.THUMBNAIL_PATH)
515 recommended_path = app.project.current_filepath
516 if not recommended_path:
517 recommended_path = info.HOME_PATH
520 if get_app().project.needs_save():
521 ret = QMessageBox.question(self, _(
"Unsaved Changes"), _(
"Save changes to project first?"), QMessageBox.Cancel | QMessageBox.No | QMessageBox.Yes)
522 if ret == QMessageBox.Yes:
525 elif ret == QMessageBox.Cancel:
530 file_path, file_type = QFileDialog.getOpenFileName(self, _(
"Open Project..."), recommended_path, _(
"OpenShot Project (*.osp)"))
540 file_path = app.project.current_filepath
542 recommended_path = os.path.join(info.HOME_PATH,
"%s.osp" % _(
"Untitled Project"))
543 file_path, file_type = QFileDialog.getSaveFileName(self, _(
"Save Project..."), recommended_path, _(
"OpenShot Project (*.osp)"))
547 if ".osp" not in file_path:
548 file_path =
"%s.osp" % file_path
556 log.info(
"auto_save_project")
559 file_path =
get_app().project.current_filepath
560 if get_app().project.needs_save():
564 if ".osp" not in file_path:
565 file_path =
"%s.osp" % file_path
568 log.info(
"Auto save project file: %s" % file_path)
573 recovery_path = os.path.join(info.BACKUP_PATH,
"backup.osp")
574 log.info(
"Creating backup of project file: %s" % recovery_path)
575 get_app().project.save(recovery_path, move_temp_files=
False, make_paths_relative=
False)
578 get_app().project.current_filepath =
None
579 get_app().project.has_unsaved_changes =
True
585 recommended_path = app.project.current_filepath
586 if not recommended_path:
587 recommended_path = os.path.join(info.HOME_PATH,
"%s.osp" % _(
"Untitled Project"))
588 file_path, file_type = QFileDialog.getSaveFileName(self, _(
"Save Project As..."), recommended_path, _(
"OpenShot Project (*.osp)"))
591 if ".osp" not in file_path:
592 file_path =
"%s.osp" % file_path
600 recommended_path = app.project.get([
"import_path"])
601 if not recommended_path
or not os.path.exists(recommended_path):
602 recommended_path = os.path.join(info.HOME_PATH)
603 files = QFileDialog.getOpenFileNames(self, _(
"Import File..."), recommended_path)[0]
604 for file_path
in files:
605 self.filesTreeView.add_file(file_path)
606 self.filesTreeView.refresh_view()
607 app.updates.update([
"import_path"], os.path.dirname(file_path))
608 log.info(
"Imported media file {}".format(file_path))
616 files.append(File.get(id=file_id))
619 fps =
get_app().project.get([
"fps"])
620 fps_float = float(fps[
"num"]) / float(fps[
"den"])
621 pos = (self.preview_thread.player.Position() - 1) / fps_float
624 from windows.add_to_timeline
import AddToTimeline
625 win = AddToTimeline(files, pos)
628 if result == QDialog.Accepted:
629 log.info(
'confirmed')
635 from windows.upload_video
import UploadVideo
639 if result == QDialog.Accepted:
640 log.info(
'Upload Video add confirmed')
642 log.info(
'Upload Video add cancelled')
646 from windows.export
import Export
650 if result == QDialog.Accepted:
651 log.info(
'Export Video add confirmed')
653 log.info(
'Export Video add cancelled')
656 log.info(
'actionUndo_trigger')
661 self.refreshFrameSignal.emit()
664 log.info(
'actionRedo_trigger')
669 self.refreshFrameSignal.emit()
673 self.SpeedSignal.emit(0)
675 self.actionPlay.setChecked(
False)
678 from windows.preferences
import Preferences
682 if result == QDialog.Accepted:
683 log.info(
'Preferences add confirmed')
685 log.info(
'Preferences add cancelled')
692 self.filesTreeView.refresh_view()
695 self.filesTreeView.refresh_view()
698 self.filesTreeView.refresh_view()
701 self.filesTreeView.refresh_view()
704 self.transitionsTreeView.refresh_view()
707 self.transitionsTreeView.refresh_view()
712 log.info(
"Help Contents is open")
714 QMessageBox.information(self,
"Error !",
"Unable to open the Help Contents. Please ensure the openshot-doc package is installed.")
715 log.info(
"Unable to open the Help Contents")
720 from windows.about
import About
724 if result == QDialog.Accepted:
725 log.info(
'About Openshot add confirmed')
727 log.info(
'About Openshot add cancelled')
731 webbrowser.open(
"https://github.com/OpenShot/openshot-qt/issues/?app-menu-bug")
732 log.info(
"Open the Bug Report GitHub Issues web page with success")
734 QMessageBox.information(self,
"Error !",
"Unable to open the Bug Report GitHub Issues web page")
735 log.info(
"Unable to open the Bug Report GitHub Issues web page")
739 webbrowser.open(
"https://github.com/OpenShot/openshot-qt/issues/?app-menu-question")
740 log.info(
"Open the Questions GitHub Issues web page with success")
742 QMessageBox.information(self,
"Error !",
"Unable to open the Questions GitHub Issues web page")
743 log.info(
"Unable to open the Questions GitHub Issues web page")
747 webbrowser.open(
"https://translations.launchpad.net/openshot/2.0")
748 log.info(
"Open the Translate launchpad web page with success")
750 QMessageBox.information(self,
"Error !",
"Unable to open the Translation web page")
751 log.info(
"Unable to open the Translation web page")
756 log.info(
"Open the Donate web page with success")
758 QMessageBox.information(self,
"Error !",
"Unable to open the Donate web page")
759 log.info(
"Unable to open the Donate web page")
764 log.info(
"Open the Download web page with success")
766 QMessageBox.information(self,
"Error !",
"Unable to open the Download web page")
767 log.info(
"Unable to open the Download web page")
772 timeline_length = 0.0
773 fps =
get_app().window.timeline_sync.timeline.info.fps.ToFloat()
774 clips =
get_app().window.timeline_sync.timeline.Clips()
776 clip_last_frame = clip.Position() + clip.Duration()
777 if clip_last_frame > timeline_length:
779 timeline_length = clip_last_frame
782 timeline_length_int = round(timeline_length * fps) + 1
785 self.actionPlay.setChecked(
False)
786 elif force ==
"play":
787 self.actionPlay.setChecked(
True)
789 if self.actionPlay.isChecked():
791 self.PlaySignal.emit(timeline_length_int)
795 self.PauseSignal.emit()
800 log.info(
'actionPreview_File_trigger')
806 f = File.get(id=file_id)
814 from windows.cutting
import Cutting
815 win = Cutting(f, preview=
True)
822 self.previewFrameSignal.emit(position_frames)
825 self.propertyTableView.select_frame(position_frames)
830 self.propertyTableView.select_frame(self.preview_thread.player.Position())
836 self.timeline.movePlayhead(position_frames)
841 player = self.preview_thread.player
843 if player.Speed() + 1 != 0:
844 self.SpeedSignal.emit(player.Speed() + 1)
846 self.SpeedSignal.emit(player.Speed() + 2)
848 if player.Mode() == openshot.PLAYBACK_PAUSED:
849 self.actionPlay.trigger()
854 player = self.preview_thread.player
856 if player.Speed() - 1 != 0:
857 self.SpeedSignal.emit(player.Speed() - 1)
859 self.SpeedSignal.emit(player.Speed() - 2)
861 if player.Mode() == openshot.PLAYBACK_PAUSED:
862 self.actionPlay.trigger()
865 log.info(
"actionJumpStart_trigger")
868 self.SeekSignal.emit(1)
871 log.info(
"actionJumpEnd_trigger")
874 timeline_length = 0.0
875 fps =
get_app().window.timeline_sync.timeline.info.fps.ToFloat()
876 clips =
get_app().window.timeline_sync.timeline.Clips()
878 clip_last_frame = clip.Position() + clip.Duration()
879 if clip_last_frame > timeline_length:
881 timeline_length = clip_last_frame
884 timeline_length_int = round(timeline_length * fps) + 1
887 self.SeekSignal.emit(timeline_length_int)
890 log.info(
"actionSaveFrame_trigger")
900 recommended_path = recommended_path = os.path.join(info.HOME_PATH)
901 if get_app().project.current_filepath:
902 recommended_path = os.path.dirname(
get_app().project.current_filepath)
905 if get_app().project.get([
"export_path"]):
906 recommended_path =
get_app().project.get([
"export_path"])
908 framePath = _(
"%s/Frame-%05d.png" % (recommended_path, self.preview_thread.current_frame))
912 framePath, file_type = QFileDialog.getSaveFileName(self, _(
"Save Frame..."), framePath, _(
"Image files (*.png)"))
916 if ".png" not in framePath:
917 framePath =
"%s.osp" % framePath
920 self.statusBar.showMessage(_(
"Save Frame cancelled..."), 5000);
923 get_app().updates.update([
"export_path"], os.path.dirname(framePath))
924 log.info(_(
"Saving frame to %s" % framePath ))
927 get_app().window.actionPlay_trigger(
None, force=
"pause")
932 self.timeline_sync.timeline.SetCache(new_cache_object)
935 self.timeline_sync.timeline.SetMaxSize(
get_app().project.get([
"width"]),
get_app().project.get([
"height"]))
936 self.cache_object.Clear()
939 if os.path.exists(framePath):
940 framePathTime = QFileInfo(framePath).lastModified()
942 framePathTime = QDateTime()
945 openshot.Timeline.GetFrame(self.timeline_sync.timeline,self.preview_thread.current_frame).Save(framePath, 1.0)
951 if os.path.exists(framePath)
and (QFileInfo(framePath).lastModified() > framePathTime):
953 self.statusBar.showMessage(_(
"Saved Frame to %s" % framePath), 5000);
956 self.statusBar.showMessage( _(
"Failed to save image to %s" % framePath), 5000);
959 viewport_rect = self.videoPreview.centeredViewport(self.videoPreview.width(), self.videoPreview.height())
960 self.timeline_sync.timeline.SetMaxSize(viewport_rect.width(), viewport_rect.height())
961 self.cache_object.Clear()
962 self.timeline_sync.timeline.SetCache(old_cache_object)
964 old_cache_object =
None
965 new_cache_object =
None
968 log.info(
"actionAddTrack_trigger")
971 track_number = len(
get_app().project.get([
"layers"]))
975 track.data = {
"number": track_number,
"y": 0,
"label":
"",
"lock":
False}
979 log.info(
"actionAddTrackAbove_trigger")
982 max_track_number = len(
get_app().project.get([
"layers"]))
986 existing_track = Track.get(id=selected_layer_id)
987 selected_layer_number = int(existing_track.data[
"number"])
992 for existing_layer
in list(reversed(range(selected_layer_number+1, max_track_number))):
993 existing_track = Track.get(number=existing_layer)
995 existing_track.data[
"number"] = existing_layer + 1
996 existing_track.save()
999 for clip
in Clip.filter(layer=existing_layer):
1001 clip.data[
"layer"] = int(clip.data[
"layer"]) + 1
1004 for trans
in Transition.filter(layer=existing_layer):
1006 trans.data[
"layer"] = int(trans.data[
"layer"]) + 1
1011 track.data = {
"number": selected_layer_number+1,
"y": 0,
"label":
"",
"lock":
False}
1016 log.info(
"actionAddTrackBelow_trigger")
1019 max_track_number = len(
get_app().project.get([
"layers"]))
1023 existing_track = Track.get(id=selected_layer_id)
1024 selected_layer_number = int(existing_track.data[
"number"])
1029 for existing_layer
in list(reversed(range(selected_layer_number, max_track_number))):
1030 existing_track = Track.get(number=existing_layer)
1032 existing_track.data[
"number"] = existing_layer + 1
1033 existing_track.save()
1036 for clip
in Clip.filter(layer=existing_layer):
1038 clip.data[
"layer"] = int(clip.data[
"layer"]) + 1
1041 for trans
in Transition.filter(layer=existing_layer):
1043 trans.data[
"layer"] = int(trans.data[
"layer"]) + 1
1048 track.data = {
"number": selected_layer_number,
"y": 0,
"label":
"",
"lock":
False}
1053 log.info(
"actionArrowTool_trigger")
1056 log.info(
"actionSnappingTool_trigger")
1057 log.info(self.actionSnappingTool.isChecked())
1060 self.timeline.SetSnappingMode(self.actionSnappingTool.isChecked())
1065 log.info(
'actionRazorTool_trigger')
1068 self.timeline.SetRazorMode(self.actionRazorTool.isChecked())
1071 log.info(
"actionAddMarker_trigger")
1074 player = self.preview_thread.player
1077 fps =
get_app().project.get([
"fps"])
1078 fps_float = float(fps[
"num"]) / float(fps[
"den"])
1081 position = (player.Position() - 1) / fps_float
1085 marker.data = {
"position": position,
"icon":
"blue.png"}
1089 log.info(
"actionPreviousMarker_trigger")
1092 fps =
get_app().project.get([
"fps"])
1093 fps_float = float(fps[
"num"]) / float(fps[
"den"])
1094 current_position = (self.preview_thread.current_frame - 1) / fps_float
1095 all_marker_positions = []
1098 for marker
in Marker.filter():
1099 all_marker_positions.append(marker.data[
"position"])
1104 selected_clip = Clip.get(id=clip_id)
1106 all_marker_positions.append(selected_clip.data[
"position"])
1107 all_marker_positions.append(selected_clip.data[
"position"] + (selected_clip.data[
"end"] - selected_clip.data[
"start"]))
1112 selected_tran = Transition.get(id=tran_id)
1114 all_marker_positions.append(selected_tran.data[
"position"])
1115 all_marker_positions.append(selected_tran.data[
"position"] + (selected_tran.data[
"end"] - selected_tran.data[
"start"]))
1118 closest_position =
None
1119 for marker_position
in sorted(all_marker_positions):
1121 if marker_position < current_position
and (abs(marker_position - current_position) > 0.1):
1123 if closest_position
and marker_position > closest_position:
1125 closest_position = marker_position
1126 elif not closest_position:
1128 closest_position = marker_position
1131 if closest_position !=
None:
1133 frame_to_seek = round(closest_position * fps_float) + 1
1134 self.SeekSignal.emit(frame_to_seek)
1137 get_app().window.refreshFrameSignal.emit()
1138 get_app().window.propertyTableView.select_frame(frame_to_seek)
1141 log.info(
"actionNextMarker_trigger")
1142 log.info(self.preview_thread.current_frame)
1145 fps =
get_app().project.get([
"fps"])
1146 fps_float = float(fps[
"num"]) / float(fps[
"den"])
1147 current_position = (self.preview_thread.current_frame - 1) / fps_float
1148 all_marker_positions = []
1151 for marker
in Marker.filter():
1152 all_marker_positions.append(marker.data[
"position"])
1157 selected_clip = Clip.get(id=clip_id)
1159 all_marker_positions.append(selected_clip.data[
"position"])
1160 all_marker_positions.append(selected_clip.data[
"position"] + (selected_clip.data[
"end"] - selected_clip.data[
"start"]))
1165 selected_tran = Transition.get(id=tran_id)
1167 all_marker_positions.append(selected_tran.data[
"position"])
1168 all_marker_positions.append(selected_tran.data[
"position"] + (selected_tran.data[
"end"] - selected_tran.data[
"start"]))
1171 closest_position =
None
1172 for marker_position
in sorted(all_marker_positions):
1174 if marker_position > current_position
and (abs(marker_position - current_position) > 0.1):
1176 if closest_position
and marker_position < closest_position:
1178 closest_position = marker_position
1179 elif not closest_position:
1181 closest_position = marker_position
1184 if closest_position !=
None:
1186 frame_to_seek = round(closest_position * fps_float) + 1
1187 self.SeekSignal.emit(frame_to_seek)
1190 get_app().window.refreshFrameSignal.emit()
1191 get_app().window.propertyTableView.select_frame(frame_to_seek)
1197 shortcut = QKeySequence(s.get(setting_name))
1203 keyboard_shortcuts = []
1205 for setting
in all_settings:
1206 if setting.get(
'category') ==
'Keyboard':
1207 keyboard_shortcuts.append(setting)
1208 return keyboard_shortcuts
1214 key_value = event.key()
1216 modifiers = int(event.modifiers())
1217 if (key_value > 0
and key_value != Qt.Key_Shift
and key_value != Qt.Key_Alt
and
1218 key_value != Qt.Key_Control
and key_value != Qt.Key_Meta):
1220 key = QKeySequence(modifiers + key_value)
1226 log.info(
"keyPressEvent: %s" % (key.toString()))
1229 player = self.preview_thread.player
1232 fps =
get_app().project.get([
"fps"])
1233 fps_float = float(fps[
"num"]) / float(fps[
"den"])
1234 playhead_position = float(self.preview_thread.current_frame - 1) / fps_float
1237 if key.matches(self.
getShortcutByName(
"seekPreviousFrame")) == QKeySequence.ExactMatch:
1241 if player.Speed() != 0:
1242 self.SpeedSignal.emit(0)
1244 self.SeekSignal.emit(player.Position() - 1)
1247 self.propertyTableView.select_frame(player.Position())
1249 elif key.matches(self.
getShortcutByName(
"seekNextFrame")) == QKeySequence.ExactMatch:
1253 if player.Speed() != 0:
1254 self.SpeedSignal.emit(0)
1256 self.SeekSignal.emit(player.Position() + 1)
1259 self.propertyTableView.select_frame(player.Position())
1261 elif key.matches(self.
getShortcutByName(
"rewindVideo")) == QKeySequence.ExactMatch:
1263 self.actionRewind.trigger()
1265 self.actionPlay.setChecked(
True)
1267 elif key.matches(self.
getShortcutByName(
"fastforwardVideo")) == QKeySequence.ExactMatch:
1269 self.actionFastForward.trigger()
1271 self.actionPlay.setChecked(
True)
1273 elif key.matches(self.
getShortcutByName(
"playToggle")) == QKeySequence.ExactMatch
or \
1274 key.matches(self.
getShortcutByName(
"playToggle1")) == QKeySequence.ExactMatch
or \
1275 key.matches(self.
getShortcutByName(
"playToggle2")) == QKeySequence.ExactMatch
or \
1278 self.actionPlay.trigger()
1279 self.propertyTableView.select_frame(player.Position())
1281 elif key.matches(self.
getShortcutByName(
"deleteItem")) == QKeySequence.ExactMatch
or \
1284 self.actionRemoveClip.trigger()
1285 self.actionRemoveTransition.trigger()
1288 elif key.matches(self.
getShortcutByName(
"actionNew")) == QKeySequence.ExactMatch:
1289 self.actionNew.trigger()
1290 elif key.matches(self.
getShortcutByName(
"actionOpen")) == QKeySequence.ExactMatch:
1291 self.actionOpen.trigger()
1292 elif key.matches(self.
getShortcutByName(
"actionSave")) == QKeySequence.ExactMatch:
1293 self.actionSave.trigger()
1294 elif key.matches(self.
getShortcutByName(
"actionUndo")) == QKeySequence.ExactMatch:
1295 self.actionUndo.trigger()
1296 elif key.matches(self.
getShortcutByName(
"actionSaveAs")) == QKeySequence.ExactMatch:
1297 self.actionSaveAs.trigger()
1298 elif key.matches(self.
getShortcutByName(
"actionImportFiles")) == QKeySequence.ExactMatch:
1299 self.actionImportFiles.trigger()
1300 elif key.matches(self.
getShortcutByName(
"actionRedo")) == QKeySequence.ExactMatch:
1301 self.actionRedo.trigger()
1302 elif key.matches(self.
getShortcutByName(
"actionExportVideo")) == QKeySequence.ExactMatch:
1303 self.actionExportVideo.trigger()
1304 elif key.matches(self.
getShortcutByName(
"actionQuit")) == QKeySequence.ExactMatch:
1305 self.actionQuit.trigger()
1306 elif key.matches(self.
getShortcutByName(
"actionPreferences")) == QKeySequence.ExactMatch:
1307 self.actionPreferences.trigger()
1308 elif key.matches(self.
getShortcutByName(
"actionAddTrack")) == QKeySequence.ExactMatch:
1309 self.actionAddTrack.trigger()
1310 elif key.matches(self.
getShortcutByName(
"actionAddMarker")) == QKeySequence.ExactMatch:
1311 self.actionAddMarker.trigger()
1312 elif key.matches(self.
getShortcutByName(
"actionPreviousMarker")) == QKeySequence.ExactMatch:
1313 self.actionPreviousMarker.trigger()
1314 elif key.matches(self.
getShortcutByName(
"actionNextMarker")) == QKeySequence.ExactMatch:
1315 self.actionNextMarker.trigger()
1316 elif key.matches(self.
getShortcutByName(
"actionTimelineZoomIn")) == QKeySequence.ExactMatch:
1317 self.actionTimelineZoomIn.trigger()
1318 elif key.matches(self.
getShortcutByName(
"actionTimelineZoomOut")) == QKeySequence.ExactMatch:
1319 self.actionTimelineZoomOut.trigger()
1320 elif key.matches(self.
getShortcutByName(
"actionTitle")) == QKeySequence.ExactMatch:
1321 self.actionTitle.trigger()
1322 elif key.matches(self.
getShortcutByName(
"actionAnimatedTitle")) == QKeySequence.ExactMatch:
1323 self.actionAnimatedTitle.trigger()
1324 elif key.matches(self.
getShortcutByName(
"actionFullscreen")) == QKeySequence.ExactMatch:
1325 self.actionFullscreen.trigger()
1326 elif key.matches(self.
getShortcutByName(
"actionAbout")) == QKeySequence.ExactMatch:
1327 self.actionAbout.trigger()
1328 elif key.matches(self.
getShortcutByName(
"actionThumbnailView")) == QKeySequence.ExactMatch:
1329 self.actionThumbnailView.trigger()
1330 elif key.matches(self.
getShortcutByName(
"actionDetailsView")) == QKeySequence.ExactMatch:
1331 self.actionDetailsView.trigger()
1332 elif key.matches(self.
getShortcutByName(
"actionProfile")) == QKeySequence.ExactMatch:
1333 self.actionProfile.trigger()
1334 elif key.matches(self.
getShortcutByName(
"actionAdd_to_Timeline")) == QKeySequence.ExactMatch:
1335 self.actionAdd_to_Timeline.trigger()
1336 elif key.matches(self.
getShortcutByName(
"actionSplitClip")) == QKeySequence.ExactMatch:
1337 self.actionSplitClip.trigger()
1338 elif key.matches(self.
getShortcutByName(
"actionSnappingTool")) == QKeySequence.ExactMatch:
1339 self.actionSnappingTool.trigger()
1340 elif key.matches(self.
getShortcutByName(
"actionJumpStart")) == QKeySequence.ExactMatch:
1341 self.actionJumpStart.trigger()
1342 elif key.matches(self.
getShortcutByName(
"actionJumpEnd")) == QKeySequence.ExactMatch:
1343 self.actionJumpEnd.trigger()
1344 elif key.matches(self.
getShortcutByName(
"actionSaveFrame")) == QKeySequence.ExactMatch:
1345 self.actionSaveFrame.trigger()
1346 elif key.matches(self.
getShortcutByName(
"actionProperties")) == QKeySequence.ExactMatch:
1347 self.actionProperties.trigger()
1348 elif key.matches(self.
getShortcutByName(
"actionTransform")) == QKeySequence.ExactMatch:
1352 self.TransformSignal.emit(
"")
1354 elif key.matches(self.
getShortcutByName(
"actionInsertKeyframe")) == QKeySequence.ExactMatch:
1355 print(
"actionInsertKeyframe")
1357 self.InsertKeyframe.emit(event)
1360 elif key.matches(self.
getShortcutByName(
"sliceAllKeepBothSides")) == QKeySequence.ExactMatch:
1361 intersecting_clips = Clip.filter(intersect=playhead_position)
1362 intersecting_trans = Transition.filter(intersect=playhead_position)
1363 if intersecting_clips
or intersecting_trans:
1365 clip_ids = [c.id
for c
in intersecting_clips]
1366 trans_ids = [t.id
for t
in intersecting_trans]
1367 self.timeline.Slice_Triggered(0, clip_ids, trans_ids, playhead_position)
1368 elif key.matches(self.
getShortcutByName(
"sliceAllKeepLeftSide")) == QKeySequence.ExactMatch:
1369 intersecting_clips = Clip.filter(intersect=playhead_position)
1370 intersecting_trans = Transition.filter(intersect=playhead_position)
1371 if intersecting_clips
or intersecting_trans:
1373 clip_ids = [c.id
for c
in intersecting_clips]
1374 trans_ids = [t.id
for t
in intersecting_trans]
1375 self.timeline.Slice_Triggered(1, clip_ids, trans_ids, playhead_position)
1376 elif key.matches(self.
getShortcutByName(
"sliceAllKeepRightSide")) == QKeySequence.ExactMatch:
1377 intersecting_clips = Clip.filter(intersect=playhead_position)
1378 intersecting_trans = Transition.filter(intersect=playhead_position)
1379 if intersecting_clips
or intersecting_trans:
1381 clip_ids = [c.id
for c
in intersecting_clips]
1382 trans_ids = [t.id
for t
in intersecting_trans]
1383 self.timeline.Slice_Triggered(2, clip_ids, trans_ids, playhead_position)
1386 elif key.matches(self.
getShortcutByName(
"pasteAll")) == QKeySequence.ExactMatch:
1387 self.timeline.Paste_Triggered(9, float(playhead_position), -1, [], [])
1388 elif key.matches(self.
getShortcutByName(
"nudgeLeft")) == QKeySequence.ExactMatch:
1390 elif key.matches(self.
getShortcutByName(
"nudgeRight")) == QKeySequence.ExactMatch:
1394 elif key.matches(self.
getShortcutByName(
"selectAll")) == QKeySequence.ExactMatch:
1395 self.timeline.SelectAll()
1397 elif key.matches(self.
getShortcutByName(
"selectNone")) == QKeySequence.ExactMatch:
1398 self.timeline.ClearAllSelections()
1406 from windows.profile
import Profile
1409 result = win.exec_()
1410 if result == QDialog.Accepted:
1411 log.info(
'Profile add confirmed')
1415 log.info(
"actionSplitClip_trigger")
1421 f = File.get(id=file_id)
1429 from windows.cutting
import Cutting
1432 result = win.exec_()
1433 if result == QDialog.Accepted:
1434 log.info(
'Cutting Finished')
1436 log.info(
'Cutting Cancelled')
1439 log.info(
"actionRemove_from_Project_trigger")
1444 f = File.get(id=file_id)
1450 clips = Clip.filter(file_id=file_id)
1459 log.info(
'actionRemoveClip_trigger')
1464 clips = Clip.filter(id=clip_id)
1473 log.info(
'actionProperties_trigger')
1476 if not self.dockProperties.isVisible():
1477 self.dockProperties.show()
1480 log.info(
'actionRemoveEffect_trigger')
1484 log.info(
"effect id: %s" % effect_id)
1487 clips = Clip.filter()
1490 found_effect =
False
1491 log.info(
"c.data[effects]: %s" % c.data[
"effects"])
1493 for effect
in c.data[
"effects"]:
1494 if effect[
"id"] == effect_id:
1495 found_effect = effect
1500 c.data[
"effects"].remove(found_effect)
1503 c.data.pop(
"reader")
1512 log.info(
'actionRemoveTransition_trigger')
1517 transitions = Transition.filter(id=tran_id)
1518 for t
in transitions:
1526 log.info(
'actionRemoveTrack_trigger')
1532 max_track_number = len(
get_app().project.get([
"layers"]))
1535 selected_track = Track.get(id=track_id)
1536 selected_track_number = int(selected_track.data[
"number"])
1539 if max_track_number == 1:
1541 QMessageBox.warning(self, _(
"Error Removing Track"), _(
"You must keep at least 1 track"))
1545 for clip
in Clip.filter(layer=selected_track_number):
1549 for trans
in Transition.filter(layer=selected_track_number):
1553 selected_track.delete()
1556 for existing_layer
in list(range(selected_track_number + 1, max_track_number)):
1558 track = Track.get(number=existing_layer)
1559 track.data[
"number"] = existing_layer - 1
1562 for clip
in Clip.filter(layer=existing_layer):
1563 clip.data[
"layer"] = int(clip.data[
"layer"]) - 1
1566 for trans
in Transition.filter(layer=existing_layer):
1567 trans.data[
"layer"] = int(trans.data[
"layer"]) - 1
1577 log.info(
'actionLockTrack_trigger')
1581 selected_track = Track.get(id=track_id)
1584 selected_track.data[
'lock'] =
True
1585 selected_track.save()
1590 log.info(
'actionUnlockTrack_trigger')
1594 selected_track = Track.get(id=track_id)
1597 selected_track.data[
'lock'] =
False
1598 selected_track.save()
1603 log.info(
'actionRenameTrack_trigger')
1610 selected_track = Track.get(id=track_id)
1611 track_name = selected_track.data[
"label"]
or _(
"Track %s") % selected_track.data[
"number"]
1613 text, ok = QInputDialog.getText(self, _(
'Rename Track'), _(
'Track Name:'), text=track_name)
1616 selected_track.data[
"label"] = text
1617 selected_track.save()
1620 log.info(
'actionRemoveMarker_trigger')
1623 marker = Marker.filter(id=marker_id)
1629 self.sliderZoom.setValue(self.sliderZoom.value() - self.sliderZoom.singleStep())
1632 self.sliderZoom.setValue(self.sliderZoom.value() + self.sliderZoom.singleStep())
1636 if not self.isFullScreen():
1637 self.showFullScreen()
1642 log.info(
"Show file properties")
1648 f = File.get(id=file_id)
1651 from windows.file_properties
import FileProperties
1652 win = FileProperties(f)
1654 result = win.exec_()
1655 if result == QDialog.Accepted:
1656 log.info(
'File Properties Finished')
1658 log.info(
'File Properties Cancelled')
1661 log.info(
"Switch to Details View")
1669 self.filesTreeView.prepare_for_delete()
1672 if app.context_menu_object ==
"files":
1673 s.set(
"file_view",
"details")
1675 self.filesTreeView.deleteLater()
1681 elif app.context_menu_object ==
"transitions":
1682 s.set(
"transitions_view",
"details")
1684 self.transitionsTreeView.deleteLater()
1690 elif app.context_menu_object ==
"effects":
1691 s.set(
"effects_view",
"details")
1693 self.effectsTreeView.deleteLater()
1699 log.info(
"Switch to Thumbnail View")
1707 self.filesTreeView.prepare_for_delete()
1710 if app.context_menu_object ==
"files":
1711 s.set(
"file_view",
"thumbnail")
1713 self.filesTreeView.deleteLater()
1719 elif app.context_menu_object ==
"transitions":
1720 s.set(
"transitions_view",
"thumbnail")
1722 self.transitionsTreeView.deleteLater()
1728 elif app.context_menu_object ==
"effects":
1729 s.set(
"effects_view",
"thumbnail")
1731 self.effectsTreeView.deleteLater()
1738 self.filesTreeView.resize_contents()
1743 return [self.dockFiles,
1744 self.dockTransitions,
1747 self.dockProperties]
1753 self.removeDockWidget(dock)
1759 self.addDockWidget(area, dock)
1765 dock.setFloating(is_floating)
1771 if get_app().window.dockWidgetArea(dock) != Qt.NoDockWidgetArea:
1779 dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
1785 dock.setFeatures(QDockWidget.AllDockWidgetFeatures)
1797 self.
addDocks([self.dockFiles, self.dockTransitions, self.dockEffects, self.dockVideo], Qt.TopDockWidgetArea)
1799 self.tabifyDockWidget(self.dockFiles, self.dockTransitions)
1800 self.tabifyDockWidget(self.dockTransitions, self.dockEffects)
1801 self.
showDocks([self.dockFiles, self.dockTransitions, self.dockEffects, self.dockVideo])
1804 simple_state =
"AAAA/wAAAAD9AAAAAwAAAAAAAAD8AAAA9PwCAAAAAfwAAAILAAAA9AAAAAAA////+v////8CAAAAAvsAAAAcAGQAbwBjAGsAUAByAG8AcABlAHIAdABpAGUAcwAAAAAA/////wAAAKEA////+wAAABgAZABvAGMAawBLAGUAeQBmAHIAYQBtAGUAAAAAAP////8AAAATAP///wAAAAEAAAEcAAABQPwCAAAAAfsAAAAYAGQAbwBjAGsASwBlAHkAZgByAGEAbQBlAQAAAVgAAAAVAAAAAAAAAAAAAAACAAAEqwAAAdz8AQAAAAL8AAAAAAAAAWQAAAB7AP////oAAAAAAgAAAAP7AAAAEgBkAG8AYwBrAEYAaQBsAGUAcwEAAAAA/////wAAAJgA////+wAAAB4AZABvAGMAawBUAHIAYQBuAHMAaQB0AGkAbwBuAHMBAAAAAP////8AAACYAP////sAAAAWAGQAbwBjAGsARQBmAGYAZQBjAHQAcwEAAAAA/////wAAAJgA////+wAAABIAZABvAGMAawBWAGkAZABlAG8BAAABagAAA0EAAAA6AP///wAABKsAAAD2AAAABAAAAAQAAAAIAAAACPwAAAABAAAAAgAAAAEAAAAOAHQAbwBvAGwAQgBhAHIBAAAAAP////8AAAAAAAAAAA=="
1806 QCoreApplication.processEvents()
1815 self.
addDocks([self.dockFiles, self.dockTransitions, self.dockVideo], Qt.TopDockWidgetArea)
1816 self.
addDocks([self.dockEffects], Qt.RightDockWidgetArea)
1817 self.
addDocks([self.dockProperties], Qt.LeftDockWidgetArea)
1820 self.
showDocks([self.dockFiles, self.dockTransitions, self.dockVideo, self.dockEffects, self.dockProperties])
1823 advanced_state =
"AAAA/wAAAAD9AAAAAwAAAAAAAAD8AAAB5fwCAAAAAfwAAAHVAAAB5QAAAKEA////+gAAAAACAAAAAvsAAAAcAGQAbwBjAGsAUAByAG8AcABlAHIAdABpAGUAcwEAAAAA/////wAAAKEA////+wAAABgAZABvAGMAawBLAGUAeQBmAHIAYQBtAGUAAAAAAP////8AAAAAAAAAAAAAAAEAAAD2AAAB5fwCAAAAAvsAAAAYAGQAbwBjAGsASwBlAHkAZgByAGEAbQBlAQAAAVgAAAAVAAAAAAAAAAD7AAAAFgBkAG8AYwBrAEUAZgBmAGUAYwB0AHMBAAAB1QAAAeUAAACYAP///wAAAAIAAAVmAAABkvwBAAAAA/sAAAASAGQAbwBjAGsARgBpAGwAZQBzAQAAAAAAAAIZAAAAbAD////7AAAAHgBkAG8AYwBrAFQAcgBhAG4AcwBpAHQAaQBvAG4AcwEAAAIfAAABAAAAAGwA////+wAAABIAZABvAGMAawBWAGkAZABlAG8BAAADJQAAAkEAAAA6AP///wAAA2gAAAHlAAAABAAAAAQAAAAIAAAACPwAAAABAAAAAgAAAAEAAAAOAHQAbwBvAGwAQgBhAHIBAAAAAP////8AAAAAAAAAAA=="
1825 QCoreApplication.processEvents()
1831 self.actionFreeze_View.setVisible(
False)
1832 self.actionUn_Freeze_View.setVisible(
True)
1838 self.actionFreeze_View.setVisible(
True)
1839 self.actionUn_Freeze_View.setVisible(
False)
1852 s.set(
"tutorial_enabled",
True)
1853 s.set(
"tutorial_ids",
"")
1857 self.tutorial_manager.exit_manager()
1868 profile =
get_app().project.get([
"profile"])
1872 if get_app().project.needs_save():
1873 save_indicator =
"*"
1874 self.actionSave.setEnabled(
True)
1876 self.actionSave.setEnabled(
False)
1879 if not get_app().project.current_filepath:
1881 self.setWindowTitle(
"%s %s [%s] - %s" % (save_indicator, _(
"Untitled Project"), profile,
"OpenShot Video Editor"))
1885 parent_path, filename = os.path.split(
get_app().project.current_filepath)
1886 filename, ext = os.path.splitext(filename)
1887 filename = filename.replace(
"_",
" ").replace(
"-",
" ").capitalize()
1888 self.setWindowTitle(
"%s %s [%s] - %s" % (save_indicator, filename, profile,
"OpenShot Video Editor"))
1892 log.info(
'updateStatusChanged')
1893 self.actionUndo.setEnabled(undo_status)
1894 self.actionRedo.setEnabled(redo_status)
1899 log.info(
'main::addSelection: item_id: %s, item_type: %s, clear_existing: %s' % (item_id, item_type, clear_existing))
1903 if item_type ==
"clip":
1904 self.selected_clips.clear()
1905 elif item_type ==
"transition":
1906 self.selected_transitions.clear()
1907 elif item_type ==
"effect":
1908 self.selected_effects.clear()
1911 self.TransformSignal.emit(
"")
1916 self.selected_clips.append(item_id)
1918 self.selected_transitions.append(item_id)
1920 self.selected_effects.append(item_id)
1925 self.show_property_timer.start()
1932 self.selected_clips.remove(item_id)
1934 self.selected_transitions.remove(item_id)
1936 self.selected_effects.remove(item_id)
1939 get_app().window.TransformSignal.emit(
"")
1955 self.show_property_timer.start()
1983 recent_projects = s.get(
"recent_projects")
1989 self.
recent_menu = self.menuFile.addMenu(QIcon.fromTheme(
"document-open-recent"), _(
"Recent Projects"))
1990 self.menuFile.insertMenu(self.actionRecent_Placeholder, self.
recent_menu)
1993 self.recent_menu.clear()
1996 for file_path
in reversed(recent_projects):
1997 new_action = self.recent_menu.addAction(file_path)
2011 self.actionUndo.setEnabled(
False)
2012 self.actionRedo.setEnabled(
False)
2017 self.filesActionGroup.setExclusive(
True)
2018 self.filesActionGroup.addAction(self.actionFilesShowAll)
2019 self.filesActionGroup.addAction(self.actionFilesShowVideo)
2020 self.filesActionGroup.addAction(self.actionFilesShowAudio)
2021 self.filesActionGroup.addAction(self.actionFilesShowImage)
2022 self.actionFilesShowAll.setChecked(
True)
2023 self.filesToolbar.addAction(self.actionFilesShowAll)
2024 self.filesToolbar.addAction(self.actionFilesShowVideo)
2025 self.filesToolbar.addAction(self.actionFilesShowAudio)
2026 self.filesToolbar.addAction(self.actionFilesShowImage)
2028 self.filesFilter.setObjectName(
"filesFilter")
2029 self.filesFilter.setPlaceholderText(_(
"Filter"))
2031 self.actionFilesClear.setEnabled(
False)
2032 self.filesToolbar.addAction(self.actionFilesClear)
2038 self.transitionsActionGroup.setExclusive(
True)
2039 self.transitionsActionGroup.addAction(self.actionTransitionsShowAll)
2040 self.transitionsActionGroup.addAction(self.actionTransitionsShowCommon)
2041 self.actionTransitionsShowAll.setChecked(
True)
2042 self.transitionsToolbar.addAction(self.actionTransitionsShowAll)
2043 self.transitionsToolbar.addAction(self.actionTransitionsShowCommon)
2045 self.transitionsFilter.setObjectName(
"transitionsFilter")
2046 self.transitionsFilter.setPlaceholderText(_(
"Filter"))
2048 self.actionTransitionsClear.setEnabled(
False)
2049 self.transitionsToolbar.addAction(self.actionTransitionsClear)
2055 self.effectsFilter.setObjectName(
"effectsFilter")
2056 self.effectsFilter.setPlaceholderText(_(
"Filter"))
2058 self.actionEffectsClear.setEnabled(
False)
2059 self.effectsToolbar.addAction(self.actionEffectsClear)
2066 ospacer1 = QWidget(self)
2067 ospacer1.setMinimumSize(32, 1)
2068 self.videoToolbar.addWidget(ospacer1)
2074 spacer = QWidget(self)
2075 spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
2076 self.videoToolbar.addWidget(spacer)
2079 self.videoToolbar.addAction(self.actionJumpStart)
2080 self.videoToolbar.addAction(self.actionRewind)
2081 self.videoToolbar.addAction(self.actionPlay)
2082 self.videoToolbar.addAction(self.actionFastForward)
2083 self.videoToolbar.addAction(self.actionJumpEnd)
2084 self.actionPlay.setCheckable(
True)
2087 spacer = QWidget(self)
2088 spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
2089 self.videoToolbar.addWidget(spacer)
2092 self.videoToolbar.addAction(self.actionSaveFrame)
2099 self.timelineToolbar.addAction(self.actionAddTrack)
2100 self.timelineToolbar.addSeparator()
2103 self.timelineToolbar.addAction(self.actionSnappingTool)
2104 self.timelineToolbar.addAction(self.actionRazorTool)
2105 self.timelineToolbar.addSeparator()
2106 self.timelineToolbar.addAction(self.actionAddMarker)
2107 self.timelineToolbar.addAction(self.actionPreviousMarker)
2108 self.timelineToolbar.addAction(self.actionNextMarker)
2109 self.timelineToolbar.addSeparator()
2112 initial_scale =
get_app().project.get([
"scale"])
or 15
2118 self.sliderZoom.setPageStep(1)
2119 self.sliderZoom.setRange(0, 30)
2120 self.sliderZoom.setValue(initial_zoom)
2121 self.sliderZoom.setInvertedControls(
True)
2122 self.sliderZoom.resize(100, 16)
2127 self.timelineToolbar.addAction(self.actionTimelineZoomIn)
2128 self.timelineToolbar.addWidget(self.
sliderZoom)
2129 self.timelineToolbar.addAction(self.actionTimelineZoomOut)
2147 self.propertyTableView.loadProperties.emit(
"",
"")
2152 log.info(
'foundCurrentVersion: Found the latest version: %s' % version)
2156 if info.VERSION < version:
2158 spacer = QWidget(self)
2159 spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
2160 self.toolBar.addWidget(spacer)
2163 self.actionUpdate.setVisible(
True)
2164 self.actionUpdate.setText(_(
"Update Available"))
2165 self.actionUpdate.setToolTip(_(
"Update Available: <b>%s</b>") % version)
2168 updateButton = QToolButton()
2169 updateButton.setDefaultAction(self.actionUpdate)
2170 updateButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
2171 self.toolBar.addWidget(updateButton)
2176 QMainWindow.moveEvent(self, event)
2179 self.tutorial_manager.re_position_dialog()
2182 QMainWindow.resizeEvent(self, event)
2185 self.tutorial_manager.re_position_dialog()
2191 QMainWindow.showEvent(self, event)
2192 for child
in self.findChildren(QDockWidget):
2193 if child.isFloating()
and child.isEnabled():
2203 QMainWindow.hideEvent(self, event)
2204 for child
in self.findChildren(QDockWidget):
2205 if child.isFloating()
and child.isVisible():
2215 self.show_property_timer.stop()
2229 for action
in self.findChildren(QAction):
2230 if shortcut.get(
'setting') == action.objectName():
2231 action.setShortcut(QKeySequence(_(shortcut.get(
'value'))))
2238 log.info(
"InitCacheSettings")
2239 log.info(
"cache-mode: %s" % s.get(
"cache-mode"))
2240 log.info(
"cache-limit-mb: %s" % s.get(
"cache-limit-mb"))
2243 cache_limit = s.get(
"cache-limit-mb") * 1024 * 1024
2246 new_cache_object =
None
2247 if s.get(
"cache-mode") ==
"CacheMemory":
2249 log.info(
"Creating CacheMemory object with %s byte limit" % cache_limit)
2250 new_cache_object = openshot.CacheMemory(cache_limit)
2251 self.timeline_sync.timeline.SetCache(new_cache_object)
2253 elif s.get(
"cache-mode") ==
"CacheDisk":
2255 log.info(
"Creating CacheDisk object with %s byte limit at %s" % (cache_limit, info.PREVIEW_CACHE_PATH))
2256 image_format = s.get(
"cache-image-format")
2257 image_quality = s.get(
"cache-quality")
2258 image_scale = s.get(
"cache-scale")
2259 new_cache_object = openshot.CacheDisk(info.PREVIEW_CACHE_PATH, image_format, image_quality, image_scale, cache_limit)
2260 self.timeline_sync.timeline.SetCache(new_cache_object)
2264 self.cache_object.Clear()
2275 from gi.repository
import Unity
2276 self.unity_launchers.append(Unity.LauncherEntry.get_for_desktop_id(
"openshot-qt.desktop"))
2277 self.unity_launchers.append(Unity.LauncherEntry.get_for_desktop_id(
"appimagekit-openshot-qt.desktop"))
2281 launcher.set_property(
"progress", current_frame / (end_frame - start_frame))
2282 launcher.set_property(
"progress_visible",
True)
2295 launcher.set_property(
"progress", 0.0)
2296 launcher.set_property(
"progress_visible",
False)
2312 QMainWindow.__init__(self)
2328 if not s.get(
"unique_install_id"):
2329 s.set(
"unique_install_id", str(uuid4()))
2353 get_app().updates.add_watcher(self)
2362 if not self.
mode ==
"unittest":
2370 self.frameWeb.layout().addWidget(self.
timeline)
2373 if s.get(
"file_view") ==
"details":
2378 self.filesTreeView.setFocus()
2381 if s.get(
"transitions_view") ==
"details":
2388 if s.get(
"effects_view") ==
"details":
2399 self.txtPropertyFilter.setPlaceholderText(_(
"Filter"))
2402 self.dockPropertiesContent.layout().addWidget(self.
selectionLabel, 0, 1)
2414 self.show_property_timer.setInterval(100)
2416 self.show_property_timer.stop()
2420 self.tabVideo.layout().insertWidget(0, self.
videoPreview)
2431 self.preview_parent.Init(self, self.timeline_sync.timeline, self.
videoPreview)
2439 self.auto_save_timer.setInterval(s.get(
"autosave-interval") * 1000 * 60)
2441 if s.get(
"enable-auto-save"):
2442 self.auto_save_timer.start()
2445 if s.get(
"hardware_decode"):
2446 os.environ[
'OS2_DECODE_HW'] =
"1"
2448 os.environ[
'OS2_DECODE_HW'] =
"0"
2451 if s.get(
"omp_threads_enabled"):
2452 os.environ[
'OS2_OMP_THREADS'] =
"1"
2454 os.environ[
'OS2_OMP_THREADS'] =
"0"
2460 if not self.
mode ==
"unittest":
2467 if sys.platform ==
"linux":
2477 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 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.