Skip to content

Commit ece947b

Browse files
authored
Merge branch 'emojis' into emojis-mods2
2 parents 57d3229 + 30d1a2a commit ece947b

File tree

8 files changed

+277
-223
lines changed

8 files changed

+277
-223
lines changed

src/classes/info.py

+3
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@
7979
"email": "[email protected]",
8080
"website": "http://openshot.org/developers/jonathan"}
8181

82+
# Desktop launcher ID, for Linux
83+
DESKTOP_ID = "org.openshot.OpenShot.desktop"
84+
8285
# Blender minimum version required (a string value)
8386
BLENDER_MIN_VERSION = "2.80"
8487

src/classes/json_data.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
from classes.app import get_app
4040

4141
# Compiled path regex
42-
path_regex = re.compile(r'\"(image|path)\":.*?\"(.*?)\"')
42+
path_regex = re.compile(r'"(image|path)"\s*:\s*"(.*?)"')
4343
path_context = {}
4444

4545

src/classes/project_data.py

+19-14
Original file line numberDiff line numberDiff line change
@@ -280,21 +280,26 @@ def new(self):
280280
# Loop through profiles
281281
for profile_folder in [info.USER_PROFILES_PATH, info.PROFILES_PATH]:
282282
for file in os.listdir(profile_folder):
283-
# Load Profile and append description
284283
profile_path = os.path.join(profile_folder, file)
285-
profile = openshot.Profile(profile_path)
286-
287-
if default_profile == profile.info.description:
288-
log.info("Setting default profile to %s" % profile.info.description)
289-
290-
# Update default profile
291-
self._data["profile"] = profile.info.description
292-
self._data["width"] = profile.info.width
293-
self._data["height"] = profile.info.height
294-
self._data["fps"] = {"num": profile.info.fps.num, "den": profile.info.fps.den}
295-
self._data["display_ratio"] = {"num": profile.info.display_ratio.num, "den": profile.info.display_ratio.den}
296-
self._data["pixel_ratio"] = {"num": profile.info.pixel_ratio.num, "den": profile.info.pixel_ratio.den}
297-
break
284+
try:
285+
# Load Profile and append description
286+
profile = openshot.Profile(profile_path)
287+
288+
if default_profile == profile.info.description:
289+
log.info("Setting default profile to %s" % profile.info.description)
290+
291+
# Update default profile
292+
self._data["profile"] = profile.info.description
293+
self._data["width"] = profile.info.width
294+
self._data["height"] = profile.info.height
295+
self._data["fps"] = {"num": profile.info.fps.num, "den": profile.info.fps.den}
296+
self._data["display_ratio"] = {"num": profile.info.display_ratio.num, "den": profile.info.display_ratio.den}
297+
self._data["pixel_ratio"] = {"num": profile.info.pixel_ratio.num, "den": profile.info.pixel_ratio.den}
298+
break
299+
300+
except RuntimeError as e:
301+
# This exception occurs when there's a problem parsing the Profile file - display a message and continue
302+
log.error("Failed to parse file '%s' as a profile: %s" % (profile_path, e))
298303

299304
# Get the default audio settings for the timeline (and preview playback)
300305
default_sample_rate = int(s.get("default-samplerate"))

src/windows/export.py

+129-106
Large diffs are not rendered by default.

src/windows/main_window.py

+97-79
Original file line numberDiff line numberDiff line change
@@ -1336,13 +1336,50 @@ def actionAddMarker_trigger(self, event):
13361336
marker.data = {"position": position, "icon": "blue.png"}
13371337
marker.save()
13381338

1339-
def actionPreviousMarker_trigger(self, event):
1340-
log.info("actionPreviousMarker_trigger")
13411339

1342-
# Calculate current position (in seconds)
1343-
fps = get_app().project.get("fps")
1344-
fps_float = float(fps["num"]) / float(fps["den"])
1345-
current_position = (self.preview_thread.current_frame - 1) / fps_float
1340+
def findAllMarkerPositions(self):
1341+
"""Build and return a list of all seekable locations for the currently-selected timeline elements"""
1342+
1343+
def getTimelineObjectPositions(obj):
1344+
""" Add boundaries & all keyframes of a timeline object (clip, transition...) to all_marker_positions """
1345+
positions = []
1346+
1347+
fps = get_app().project.get("fps")
1348+
fps_float = float(fps["num"]) / float(fps["den"])
1349+
1350+
clip_start_time = obj.data["position"]
1351+
clip_orig_time = clip_start_time - obj.data["start"]
1352+
clip_stop_time = clip_orig_time + obj.data["end"]
1353+
1354+
# add clip boundaries
1355+
positions.append(clip_start_time)
1356+
positions.append(clip_stop_time)
1357+
1358+
# add all keyframes
1359+
for property in obj.data :
1360+
try :
1361+
for point in obj.data[property]["Points"] :
1362+
keyframe_time = (point["co"]["X"]-1)/fps_float - obj.data["start"] + obj.data["position"]
1363+
if keyframe_time > clip_start_time and keyframe_time < clip_stop_time :
1364+
positions.append(keyframe_time)
1365+
except (TypeError, KeyError):
1366+
pass
1367+
1368+
1369+
# Add all Effect keyframes
1370+
if "effects" in obj.data:
1371+
for effect_data in obj.data["effects"]:
1372+
for property in effect_data:
1373+
try:
1374+
for point in effect_data[property]["Points"]:
1375+
keyframe_time = (point["co"]["X"]-1)/fps_float + clip_orig_time
1376+
if keyframe_time > clip_start_time and keyframe_time < clip_stop_time:
1377+
positions.append(keyframe_time)
1378+
except (TypeError, KeyError):
1379+
pass
1380+
1381+
return positions
1382+
13461383
all_marker_positions = []
13471384

13481385
# Get list of marker and important positions (like selected clip bounds)
@@ -1354,16 +1391,28 @@ def actionPreviousMarker_trigger(self, event):
13541391
# Get selected object
13551392
selected_clip = Clip.get(id=clip_id)
13561393
if selected_clip:
1357-
all_marker_positions.append(selected_clip.data["position"])
1358-
all_marker_positions.append(selected_clip.data["position"] + (selected_clip.data["end"] - selected_clip.data["start"]))
1394+
all_marker_positions.extend(getTimelineObjectPositions(selected_clip))
13591395

13601396
# Loop through selected transitions (and add key positions)
13611397
for tran_id in self.selected_transitions:
13621398
# Get selected object
13631399
selected_tran = Transition.get(id=tran_id)
13641400
if selected_tran:
1365-
all_marker_positions.append(selected_tran.data["position"])
1366-
all_marker_positions.append(selected_tran.data["position"] + (selected_tran.data["end"] - selected_tran.data["start"]))
1401+
all_marker_positions.extend(getTimelineObjectPositions(selected_tran))
1402+
1403+
# remove duplicates
1404+
all_marker_positions = list(set(all_marker_positions))
1405+
1406+
return all_marker_positions
1407+
1408+
def actionPreviousMarker_trigger(self, event):
1409+
log.info("actionPreviousMarker_trigger")
1410+
1411+
# Calculate current position (in seconds)
1412+
fps = get_app().project.get("fps")
1413+
fps_float = float(fps["num"]) / float(fps["den"])
1414+
current_position = (self.preview_thread.current_frame - 1) / fps_float
1415+
all_marker_positions = self.findAllMarkerPositions()
13671416

13681417
# Loop through all markers, and find the closest one to the left
13691418
closest_position = None
@@ -1395,27 +1444,7 @@ def actionNextMarker_trigger(self, event):
13951444
fps = get_app().project.get("fps")
13961445
fps_float = float(fps["num"]) / float(fps["den"])
13971446
current_position = (self.preview_thread.current_frame - 1) / fps_float
1398-
all_marker_positions = []
1399-
1400-
# Get list of marker and important positions (like selected clip bounds)
1401-
for marker in Marker.filter():
1402-
all_marker_positions.append(marker.data["position"])
1403-
1404-
# Loop through selected clips (and add key positions)
1405-
for clip_id in self.selected_clips:
1406-
# Get selected object
1407-
selected_clip = Clip.get(id=clip_id)
1408-
if selected_clip:
1409-
all_marker_positions.append(selected_clip.data["position"])
1410-
all_marker_positions.append(selected_clip.data["position"] + (selected_clip.data["end"] - selected_clip.data["start"]))
1411-
1412-
# Loop through selected transitions (and add key positions)
1413-
for tran_id in self.selected_transitions:
1414-
# Get selected object
1415-
selected_tran = Transition.get(id=tran_id)
1416-
if selected_tran:
1417-
all_marker_positions.append(selected_tran.data["position"])
1418-
all_marker_positions.append(selected_tran.data["position"] + (selected_tran.data["end"] - selected_tran.data["start"]))
1447+
all_marker_positions = self.findAllMarkerPositions()
14191448

14201449
# Loop through all markers, and find the closest one to the right
14211450
closest_position = None
@@ -2005,18 +2034,13 @@ def resize_contents(self):
20052034

20062035
def getDocks(self):
20072036
""" Get a list of all dockable widgets """
2008-
return [self.dockFiles,
2009-
self.dockTransitions,
2010-
self.dockEffects,
2011-
self.dockEmojis,
2012-
self.dockVideo,
2013-
self.dockProperties,
2014-
self.dockTimeline]
2037+
return self.findChildren(QDockWidget)
20152038

20162039
def removeDocks(self):
20172040
""" Remove all dockable widgets on main screen """
20182041
for dock in self.getDocks():
2019-
self.removeDockWidget(dock)
2042+
if self.dockWidgetArea(dock) != Qt.NoDockWidgetArea:
2043+
self.removeDockWidget(dock)
20202044

20212045
def addDocks(self, docks, area):
20222046
""" Add all dockable widgets to the same dock area on the main screen """
@@ -2026,7 +2050,8 @@ def addDocks(self, docks, area):
20262050
def floatDocks(self, is_floating):
20272051
""" Float or Un-Float all dockable widgets above main screen """
20282052
for dock in self.getDocks():
2029-
dock.setFloating(is_floating)
2053+
if self.dockWidgetArea(dock) != Qt.NoDockWidgetArea:
2054+
dock.setFloating(is_floating)
20302055

20312056
def showDocks(self, docks):
20322057
""" Show all dockable widgets on the main screen """
@@ -2038,20 +2063,17 @@ def showDocks(self, docks):
20382063
def freezeDocks(self):
20392064
""" Freeze all dockable widgets on the main screen (prevent them being closed, floated, or moved) """
20402065
for dock in self.getDocks():
2041-
dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
2066+
if self.dockWidgetArea(dock) != Qt.NoDockWidgetArea:
2067+
dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
20422068

20432069
def unFreezeDocks(self):
20442070
""" Un-freeze all dockable widgets on the main screen (allow them to be closed, floated, or moved, as appropriate) """
20452071
for dock in self.getDocks():
2046-
if dock is self.dockTimeline:
2047-
dock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable)
2048-
else:
2049-
dock.setFeatures(QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable)
2050-
2051-
def hideDocks(self):
2052-
""" Hide all dockable widgets on the main screen """
2053-
for dock in self.getDocks():
2054-
dock.hide()
2072+
if self.dockWidgetArea(dock) != Qt.NoDockWidgetArea:
2073+
if dock is self.dockTimeline:
2074+
dock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable)
2075+
else:
2076+
dock.setFeatures(QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable)
20552077

20562078
def actionSimple_View_trigger(self, event):
20572079
""" Switch to the default / simple view """
@@ -2490,15 +2512,15 @@ def resizeEvent(self, event):
24902512
def showEvent(self, event):
24912513
""" Have any child windows follow main-window state """
24922514
QMainWindow.showEvent(self, event)
2493-
for child in self.findChildren(QDockWidget):
2515+
for child in self.getDocks():
24942516
if child.isFloating() and child.isEnabled():
24952517
child.raise_()
24962518
child.show()
24972519

24982520
def hideEvent(self, event):
24992521
""" Have any child windows hide with main window """
25002522
QMainWindow.hideEvent(self, event)
2501-
for child in self.findChildren(QDockWidget):
2523+
for child in self.getDocks():
25022524
if child.isFloating() and child.isVisible():
25032525
child.hide()
25042526

@@ -2558,34 +2580,21 @@ def InitCacheSettings(self):
25582580
self.cache_object = new_cache_object
25592581

25602582
def FrameExported(self, title_message, start_frame, end_frame, current_frame):
2561-
"""Connect to Unity launcher (for Linux)"""
2583+
"""Update progress in Unity Launcher (if connected)"""
25622584
try:
2563-
if sys.platform == "linux" and self.has_launcher:
2564-
if not self.unity_launchers:
2565-
# Get launcher only once
2566-
import gi
2567-
gi.require_version('Unity', '7.0')
2568-
from gi.repository import Unity
2569-
self.unity_launchers.append(Unity.LauncherEntry.get_for_desktop_id("openshot-qt.desktop"))
2570-
self.unity_launchers.append(Unity.LauncherEntry.get_for_desktop_id("appimagekit-openshot-qt.desktop"))
2571-
2572-
# Set progress and show progress bar
2573-
for launcher in self.unity_launchers:
2574-
launcher.set_property("progress", current_frame / (end_frame - start_frame))
2575-
launcher.set_property("progress_visible", True)
2576-
2585+
# Set progress and show progress bar
2586+
self.unity_launcher.set_property("progress", current_frame / (end_frame - start_frame))
2587+
self.unity_launcher.set_property("progress_visible", True)
25772588
except Exception:
25782589
# Just ignore
2579-
self.has_launcher = False
2590+
pass
25802591

25812592
def ExportFinished(self, path):
2582-
"""Export has completed"""
2593+
"""Show completion in Unity Launcher (if connected)"""
25832594
try:
2584-
if sys.platform == "linux" and self.has_launcher:
2585-
for launcher in self.unity_launchers:
2586-
# Set progress on Unity launcher and hide progress bar
2587-
launcher.set_property("progress", 0.0)
2588-
launcher.set_property("progress_visible", False)
2595+
# Set progress on Unity launcher and hide progress bar
2596+
self.unity_launcher.set_property("progress", 0.0)
2597+
self.unity_launcher.set_property("progress_visible", False)
25892598
except Exception:
25902599
pass
25912600

@@ -2843,11 +2852,20 @@ def __init__(self, mode=None):
28432852
self.tutorial_manager = TutorialManager(self)
28442853

28452854
# Connect to Unity DBus signal (if linux)
2846-
if sys.platform == "linux":
2847-
self.unity_launchers = []
2848-
self.has_launcher = True
2849-
self.ExportFrame.connect(self.FrameExported)
2850-
self.ExportEnded.connect(self.ExportFinished)
2855+
self.unity_launcher = None
2856+
if "linux" in sys.platform:
2857+
try:
2858+
# Get connection to Unity Launcher
2859+
import gi
2860+
gi.require_version('Unity', '7.0')
2861+
from gi.repository import Unity
2862+
self.unity_launcher = Unity.LauncherEntry.get_for_desktop_id(info.DESKTOP_ID)
2863+
except Exception:
2864+
# Guess we're not on Ubuntu
2865+
pass
2866+
else:
2867+
self.ExportFrame.connect(self.FrameExported)
2868+
self.ExportEnded.connect(self.ExportFinished)
28512869

28522870
# Save settings
28532871
s.save()

src/windows/profile.py

+13-8
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,20 @@ def __init__(self):
7272
self.profile_paths = {}
7373
for profile_folder in [info.USER_PROFILES_PATH, info.PROFILES_PATH]:
7474
for file in os.listdir(profile_folder):
75-
# Load Profile
7675
profile_path = os.path.join(profile_folder, file)
77-
profile = openshot.Profile(profile_path)
78-
79-
# Add description of Profile to list
80-
profile_name = "%s (%sx%s)" % (profile.info.description, profile.info.width, profile.info.height)
81-
self.profile_names.append(profile_name)
82-
self.profile_paths[profile_name] = profile_path
83-
76+
try:
77+
# Load Profile
78+
profile = openshot.Profile(profile_path)
79+
80+
# Add description of Profile to list
81+
profile_name = "%s (%sx%s)" % (profile.info.description, profile.info.width, profile.info.height)
82+
self.profile_names.append(profile_name)
83+
self.profile_paths[profile_name] = profile_path
84+
85+
except RuntimeError as e:
86+
# This exception occurs when there's a problem parsing the Profile file - display a message and continue
87+
log.error("Failed to parse file '%s' as a profile: %s" % (profile_path, e))
88+
8489
# Sort list
8590
self.profile_names.sort()
8691

src/windows/ui/main-window.ui

+4-4
Original file line numberDiff line numberDiff line change
@@ -894,10 +894,10 @@
894894
<normaloff>:/icons/Humanity/actions/16/go-first.svg</normaloff>:/icons/Humanity/actions/16/go-first.svg</iconset>
895895
</property>
896896
<property name="text">
897-
<string>Previous Marker</string>
897+
<string>Previous Key Point</string>
898898
</property>
899899
<property name="toolTip">
900-
<string>Previous Marker</string>
900+
<string>Previous Key Point</string>
901901
</property>
902902
</action>
903903
<action name="actionNextMarker">
@@ -906,10 +906,10 @@
906906
<normaloff>:/icons/Humanity/actions/16/go-last.svg</normaloff>:/icons/Humanity/actions/16/go-last.svg</iconset>
907907
</property>
908908
<property name="text">
909-
<string>Next Marker</string>
909+
<string>Next Key Point</string>
910910
</property>
911911
<property name="toolTip">
912-
<string>Next Marker</string>
912+
<string>Next Key Point</string>
913913
</property>
914914
</action>
915915
<action name="actionCenterOnPlayhead">

0 commit comments

Comments
 (0)