提交 b2ad5b36 编写于 作者: J Jonathan Thomas

Merge branch 'master' into merge-master-into-develop

# Conflicts:
#	src/classes/info.py
......@@ -19,7 +19,7 @@ linux-builder:
- cp -r "$CI_PROJECT_DIR/build/install-x64/python/." "$CI_PROJECT_DIR"
- export LD_LIBRARY_PATH=$CI_PROJECT_DIR/build/install-x64/lib:$LD_LIBRARY_PATH
- echo -e "CI_PROJECT_NAME:$CI_PROJECT_NAME\nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME\nCI_COMMIT_SHA:$CI_COMMIT_SHA\nCI_JOB_ID:$CI_JOB_ID" > "build/install-x64/share/$CI_PROJECT_NAME"
- git log $(git describe --tags --abbrev=0)..HEAD --oneline --pretty=format:"%C(auto,yellow)%h%C(auto,magenta)% %C(auto,blue)%>(12,trunc)%ad %C(auto,green)%<(25,trunc)%aN%C(auto,reset)%s%C(auto,red)% gD% D" --date=short > "build/install-x64/share/$CI_PROJECT_NAME.log"
- git log $(git describe --tags --abbrev=0 @^)..@ --oneline --pretty=format:"%C(auto,yellow)%h%C(auto,magenta)% %C(auto,blue)%>(12,trunc)%ad %C(auto,green)%<(25,trunc)%aN%C(auto,reset)%s%C(auto,red)% gD% D" --date=short > "build/install-x64/share/$CI_PROJECT_NAME.log"
- python3 freeze.py build
- python3 installer/build-server.py "$SLACK_TOKEN" "$S3_ACCESS_KEY" "$S3_SECRET_KEY" "$WINDOWS_KEY" "$WINDOWS_PASSWORD" "$GITHUB_USER" "$GITHUB_PASS" "False" "$CI_COMMIT_REF_NAME"
when: always
......@@ -59,7 +59,7 @@ mac-builder:
- export LD_LIBRARY_PATH=$CI_PROJECT_DIR/build/install-x64/lib:$LD_LIBRARY_PATH
- export DYLD_LIBRARY_PATH=$CI_PROJECT_DIR/build/install-x64/lib:DYLD_LIBRARY_PATH
- echo -e "CI_PROJECT_NAME:$CI_PROJECT_NAME\nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME\nCI_COMMIT_SHA:$CI_COMMIT_SHA\nCI_JOB_ID:$CI_JOB_ID" > "build/install-x64/share/$CI_PROJECT_NAME"
- git log $(git describe --tags --abbrev=0)..HEAD --oneline --pretty=format:"%C(auto,yellow)%h%C(auto,magenta)% %C(auto,blue)%>(12,trunc)%ad %C(auto,green)%<(25,trunc)%aN%C(auto,reset)%s%C(auto,red)% gD% D" --date=short > "build/install-x64/share/$CI_PROJECT_NAME.log"
- git log $(git describe --tags --abbrev=0 @^)..@ --oneline --pretty=format:"%C(auto,yellow)%h%C(auto,magenta)% %C(auto,blue)%>(12,trunc)%ad %C(auto,green)%<(25,trunc)%aN%C(auto,reset)%s%C(auto,red)% gD% D" --date=short > "build/install-x64/share/$CI_PROJECT_NAME.log"
- /Library/Frameworks/Python.Framework/Versions/3.6/bin/python3.6 freeze.py bdist_mac --iconfile=installer/openshot.icns --custom-info-plist=installer/Info.plist --bundle-name="OpenShot Video Editor"
- /Library/Frameworks/Python.Framework/Versions/3.6/bin/python3.6 installer/build-server.py "$SLACK_TOKEN" "$S3_ACCESS_KEY" "$S3_SECRET_KEY" "$WINDOWS_KEY" "$WINDOWS_PASSWORD" "$GITHUB_USER" "$GITHUB_PASS" "False" "$CI_COMMIT_REF_NAME"
when: always
......@@ -85,8 +85,8 @@ windows-builder-x64:
- $env:Path = "$CI_PROJECT_DIR\build\install-x64\lib;$CI_PROJECT_DIR\build\install-x64\lib\python3.7\site-packages\;C:\msys64\mingw64\bin;C:\msys64\mingw64\lib;C:\msys64\mingw64\lib\python3.7\;C:\msys64\mingw64\lib\python3.7\site-packages\;C:\msys64\mingw64\lib\python3.7\site-packages\PyQt5;C:\msys64\usr\lib\cmake\UnitTest++;C:\msys64\usr;C:\msys64\usr\lib;" + $env:Path;
- $env:PYTHONPATH = "$CI_PROJECT_DIR\build\install-x64\lib\python3.7\site-packages\;C:\msys64\usr\lib;C:\msys64\usr\lib\site-packages\;C:\msys64\mingw64\lib\python3.7\;C:\msys64\mingw64\lib\python3.7\site-packages\;C:\msys64\mingw64\lib\python3.7\site-packages\PyQt5;";
- New-Item -path "build/install-x64/share/" -Name "$CI_PROJECT_NAME" -Value "CI_PROJECT_NAME:$CI_PROJECT_NAME`nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME`nCI_COMMIT_SHA:$CI_COMMIT_SHA`nCI_JOB_ID:$CI_JOB_ID" -ItemType file -force
- $PREV_GIT_LABEL=(git describe --tags --abbrev=0)
- git log "$PREV_GIT_LABEL..HEAD" --oneline --pretty=format:"%C(auto,yellow)%h%C(auto,magenta)% %C(auto,blue)%>(12,trunc)%ad %C(auto,green)%<(25,trunc)%aN%C(auto,reset)%s%C(auto,red)% gD% D" --date=short > "build/install-x64/share/$CI_PROJECT_NAME.log"
- $PREV_GIT_LABEL=(git describe --tags --abbrev=0 '@^')
- git log "$PREV_GIT_LABEL..@" --oneline --pretty=format:"%C(auto,yellow)%h%C(auto,magenta)% %C(auto,blue)%>(12,trunc)%ad %C(auto,green)%<(25,trunc)%aN%C(auto,reset)%s%C(auto,red)% gD% D" --date=short > "build/install-x64/share/$CI_PROJECT_NAME.log"
- python3 freeze.py build
- python3 installer/build-server.py "$SLACK_TOKEN" "$S3_ACCESS_KEY" "$S3_SECRET_KEY" "$WINDOWS_KEY" "$WINDOWS_PASSWORD" "$GITHUB_USER" "$GITHUB_PASS" "False" "$CI_COMMIT_REF_NAME"
when: always
......@@ -112,8 +112,8 @@ windows-builder-x86:
- $env:Path = "$CI_PROJECT_DIR\build\install-x86\lib;$CI_PROJECT_DIR\build\install-x86\lib\python3.7\site-packages\;C:\msys32\mingw32\bin;C:\msys32\mingw32\lib;C:\msys32\mingw32\lib\python3.7\;C:\msys32\mingw32\lib\python3.7\site-packages\;C:\msys32\mingw32\lib\python3.7\site-packages\PyQt5;C:\msys32\usr\lib\cmake\UnitTest++;C:\msys32\usr;C:\msys32\usr\lib;" + $env:Path;
- $env:PYTHONPATH = "$CI_PROJECT_DIR\build\install-x86\lib\python3.7\site-packages\;C:\msys32\usr\lib;C:\msys32\usr\lib\site-packages\;C:\msys32\mingw32\lib\python3.7\;C:\msys32\mingw32\lib\python3.7\site-packages\;C:\msys32\mingw32\lib\python3.7\site-packages\PyQt5;";
- New-Item -path "build/install-x86/share/" -Name "$CI_PROJECT_NAME" -Value "CI_PROJECT_NAME:$CI_PROJECT_NAME`nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME`nCI_COMMIT_SHA:$CI_COMMIT_SHA`nCI_JOB_ID:$CI_JOB_ID" -ItemType file -force
- $PREV_GIT_LABEL=(git describe --tags --abbrev=0)
- git log "$PREV_GIT_LABEL..HEAD" --oneline --pretty=format:"%C(auto,yellow)%h%C(auto,magenta)% %C(auto,blue)%>(12,trunc)%ad %C(auto,green)%<(25,trunc)%aN%C(auto,reset)%s%C(auto,red)% gD% D" --date=short > "build/install-x86/share/$CI_PROJECT_NAME.log"
- $PREV_GIT_LABEL=(git describe --tags --abbrev=0 '@^')
- git log "$PREV_GIT_LABEL..@" --oneline --pretty=format:"%C(auto,yellow)%h%C(auto,magenta)% %C(auto,blue)%>(12,trunc)%ad %C(auto,green)%<(25,trunc)%aN%C(auto,reset)%s%C(auto,red)% gD% D" --date=short > "build/install-x86/share/$CI_PROJECT_NAME.log"
- python3 freeze.py build
- editbin /LARGEADDRESSAWARE "$CI_PROJECT_DIR\build\exe.mingw-3.7\openshot-qt.exe"
- python3 installer/build-server.py "$SLACK_TOKEN" "$S3_ACCESS_KEY" "$S3_SECRET_KEY" "$WINDOWS_KEY" "$WINDOWS_PASSWORD" "$GITHUB_USER" "$GITHUB_PASS" "True" "$CI_COMMIT_REF_NAME"
......
......@@ -292,8 +292,8 @@ elif sys.platform == "linux":
# for certain distros (like Fedora, openSUSE, Debian, etc...)
# Also add Glib related files (required for some distros)
for added_lib in [ARCHLIB + "libssl.so.1.0.0",
ARCHLIB + "libcrypto.so.1.0.0",
for added_lib in [ARCHLIB + "libssl.so",
ARCHLIB + "libcrypto.so",
ARCHLIB + "libglib-2.0.so",
ARCHLIB + "libgio-2.0.so",
ARCHLIB + "libgmodule-2.0.so",
......
......@@ -34,6 +34,7 @@ mv "$OS_PATH/MacOS/images" "$OS_PATH/Resources/images"; ln -s "../Resources/imag
mv "$OS_PATH/MacOS/language" "$OS_PATH/Resources/language"; ln -s "../Resources/language" "$OS_PATH/MacOS/language";
mv "$OS_PATH/MacOS/presets" "$OS_PATH/Resources/presets"; ln -s "../Resources/presets" "$OS_PATH/MacOS/presets";
mv "$OS_PATH/MacOS/profiles" "$OS_PATH/Resources/profiles"; ln -s "../Resources/profiles" "$OS_PATH/MacOS/profiles";
mv "$OS_PATH/MacOS/resources" "$OS_PATH/Resources/resources"; ln -s "../Resources/resources" "$OS_PATH/MacOS/resources";
mv "$OS_PATH/MacOS/settings" "$OS_PATH/Resources/settings"; ln -s "../Resources/settings" "$OS_PATH/MacOS/settings";
mv "$OS_PATH/MacOS/tests" "$OS_PATH/Resources/tests"; ln -s "../Resources/tests" "$OS_PATH/MacOS/tests";
mv "$OS_PATH/MacOS/timeline" "$OS_PATH/Resources/timeline"; ln -s "../Resources/timeline" "$OS_PATH/MacOS/timeline";
......
......@@ -30,6 +30,7 @@ import encodings.idna
import requests
import platform
import threading
import time
import urllib.parse
from copy import deepcopy
from classes import info
......@@ -86,6 +87,9 @@ params = {
"cd5": linux_distro
}
# Queue for metrics (incase things are disabled... just queue it up
# incase the user enables metrics later
metric_queue = []
def track_metric_screen(screen_name):
"""Track a GUI screen being shown"""
......@@ -148,19 +152,31 @@ def track_metric_session(is_start=True):
def send_metric(params):
"""Send anonymous metric over HTTP for tracking"""
# Add to queue and *maybe* send if the user allows it
metric_queue.append(params)
# Check if the user wants to send metrics and errors
if s.get("send_metrics"):
url_params = urllib.parse.urlencode(params)
url = "http://www.google-analytics.com/collect?%s" % url_params
for metric_params in metric_queue:
url_params = urllib.parse.urlencode(metric_params)
url = "http://www.google-analytics.com/collect?%s" % url_params
# Send metric HTTP data
try:
r = requests.get(url, headers={"user-agent": user_agent}, verify=False)
log.info("Track metric: [%s] %s | (%s bytes)" % (r.status_code, r.url, len(r.content)))
# Send metric HTTP data
try:
r = requests.get(url, headers={"user-agent": user_agent}, verify=False)
log.info("Track metric: [%s] %s | (%s bytes)" % (r.status_code, r.url, len(r.content)))
except Exception as Ex:
log.error("Failed to Track metric: %s" % (Ex))
except Exception as Ex:
log.error("Failed to Track metric: %s" % (Ex))
# Wait a moment, so we don't spam the requests
time.sleep(0.25)
# All metrics have been sent (or attempted to send)
# Clear the queue
metric_queue.clear()
def send_exception(stacktrace, source):
......
......@@ -399,12 +399,17 @@ class ProjectDataStore(JsonDataStore, UpdateInterface):
return round(original_value * scale_factor)
def rescale_keyframes(self, scale_factor):
"""Adjust all keyframe coordinates from previous FPS to new FPS (using a scale factor)"""
"""Adjust all keyframe coordinates from previous FPS to new FPS (using a scale factor)
and return scaled project data without modifing the current project."""
log.info('Scale all keyframes by a factor of %s' % scale_factor)
# Create copy of active project data
data = copy.deepcopy(self._data)
# Rescale the the copied project data
# Loop through all clips (and look for Keyframe objects)
# Scale the X coordinate by factor (which represents the frame #)
for clip in self._data.get('clips', []):
for clip in data.get('clips', []):
for attribute in clip:
if type(clip.get(attribute)) == dict and "Points" in clip.get(attribute):
for point in clip.get(attribute).get("Points"):
......@@ -429,7 +434,7 @@ class ProjectDataStore(JsonDataStore, UpdateInterface):
# Loop through all effects/transitions (and look for Keyframe objects)
# Scale the X coordinate by factor (which represents the frame #)
for effect in self._data.get('effects', []):
for effect in data.get('effects', []):
for attribute in effect:
if type(effect.get(attribute)) == dict and "Points" in effect.get(attribute):
for point in effect.get(attribute).get("Points"):
......@@ -441,9 +446,8 @@ class ProjectDataStore(JsonDataStore, UpdateInterface):
if "co" in point:
point["co"]["X"] = self.scale_keyframe_value(point["co"].get("X", 0.0), scale_factor)
# Get app, and distribute all project data through update manager
from classes.app import get_app
get_app().updates.load(self._data)
# return the copied and scaled project data
return data
def read_legacy_project_file(self, file_path):
"""Attempt to read a legacy version 1.x openshot project file"""
......
......@@ -333,7 +333,7 @@
"restart": true
},
{
"value": true,
"value": false,
"title": "Send Anonymous Metrics and Errors",
"type": "bool",
"category": "Debug",
......
......@@ -95,7 +95,9 @@ class About(QDialog):
self.btnchangelog.clicked.connect(self.load_changelog)
# Init some variables
self.txtversion.setText(_("Version: %s") % info.VERSION)
openshot_qt_version = _("Version: %s") % info.VERSION
libopenshot_version = "libopenshot: %s" % openshot.OPENSHOT_VERSION_FULL
self.txtversion.setText("<b>%s</b><br/>%s" % (openshot_qt_version, libopenshot_version))
self.txtversion.setAlignment(Qt.AlignCenter)
# Track metrics
......@@ -266,6 +268,7 @@ class Changelog(QDialog):
'date': line[9:20].strip(),
'author': line[20:45].strip(),
'subject': line[45:].strip() })
break
except:
# Ignore decoding errors
pass
......
......@@ -62,8 +62,7 @@ class Export(QDialog):
ui_util.init_ui(self)
# get translations
app = get_app()
_ = app._tr
_ = get_app()._tr
# Get settings
self.s = settings.get_settings()
......@@ -93,10 +92,10 @@ class Export(QDialog):
self.delayed_fps_timer.stop()
# Pause playback (to prevent crash since we are fixing to change the timeline's max size)
app.window.actionPlay_trigger(None, force="pause")
get_app().window.actionPlay_trigger(None, force="pause")
# Clear timeline preview cache (to get more available memory)
app.window.timeline_sync.timeline.ClearAllCache()
get_app().window.timeline_sync.timeline.ClearAllCache()
# Hide audio channels
self.lblChannels.setVisible(False)
......@@ -107,30 +106,27 @@ class Export(QDialog):
openshot.Settings.Instance().HIGH_QUALITY_SCALING = True
# Get the original timeline settings
width = app.window.timeline_sync.timeline.info.width
height = app.window.timeline_sync.timeline.info.height
fps = app.window.timeline_sync.timeline.info.fps
sample_rate = app.window.timeline_sync.timeline.info.sample_rate
channels = app.window.timeline_sync.timeline.info.channels
channel_layout = app.window.timeline_sync.timeline.info.channel_layout
# No keyframe rescaling has happened yet (due to differences in FPS)
self.keyframes_rescaled = False
width = get_app().window.timeline_sync.timeline.info.width
height = get_app().window.timeline_sync.timeline.info.height
fps = get_app().window.timeline_sync.timeline.info.fps
sample_rate = get_app().window.timeline_sync.timeline.info.sample_rate
channels = get_app().window.timeline_sync.timeline.info.channels
channel_layout = get_app().window.timeline_sync.timeline.info.channel_layout
# Create new "export" openshot.Timeline object
self.timeline = openshot.Timeline(width, height, openshot.Fraction(fps.num, fps.den),
sample_rate, channels, channel_layout)
# Init various properties
self.timeline.info.channel_layout = app.window.timeline_sync.timeline.info.channel_layout
self.timeline.info.has_audio = app.window.timeline_sync.timeline.info.has_audio
self.timeline.info.has_video = app.window.timeline_sync.timeline.info.has_video
self.timeline.info.video_length = app.window.timeline_sync.timeline.info.video_length
self.timeline.info.duration = app.window.timeline_sync.timeline.info.duration
self.timeline.info.sample_rate = app.window.timeline_sync.timeline.info.sample_rate
self.timeline.info.channels = app.window.timeline_sync.timeline.info.channels
self.timeline.info.channel_layout = get_app().window.timeline_sync.timeline.info.channel_layout
self.timeline.info.has_audio = get_app().window.timeline_sync.timeline.info.has_audio
self.timeline.info.has_video = get_app().window.timeline_sync.timeline.info.has_video
self.timeline.info.video_length = get_app().window.timeline_sync.timeline.info.video_length
self.timeline.info.duration = get_app().window.timeline_sync.timeline.info.duration
self.timeline.info.sample_rate = get_app().window.timeline_sync.timeline.info.sample_rate
self.timeline.info.channels = get_app().window.timeline_sync.timeline.info.channels
# Load the "export" Timeline reader with the JSON from the real timeline
json_timeline = json.dumps(app.project._data)
json_timeline = json.dumps(get_app().project._data)
self.timeline.SetJson(json_timeline)
# Open the "export" Timeline reader
......@@ -138,10 +134,10 @@ class Export(QDialog):
# Default export path
recommended_path = os.path.join(info.HOME_PATH)
if app.project.current_filepath:
recommended_path = os.path.dirname(app.project.current_filepath)
if get_app().project.current_filepath:
recommended_path = os.path.dirname(get_app().project.current_filepath)
export_path = app.project.get("export_path")
export_path = get_app().project.get("export_path")
if export_path and os.path.exists(export_path):
# Use last selected export path
self.txtExportFolder.setText(export_path)
......@@ -150,13 +146,13 @@ class Export(QDialog):
self.txtExportFolder.setText(recommended_path)
# Is this a saved project?
if not app.project.current_filepath:
if not get_app().project.current_filepath:
# Not saved yet
self.txtFileName.setText(_("Untitled Project"))
else:
# Yes, project is saved
# Get just the filename
filename = os.path.basename(app.project.current_filepath)
filename = os.path.basename(get_app().project.current_filepath)
filename = os.path.splitext(filename)[0]
self.txtFileName.setText(filename)
......@@ -192,7 +188,7 @@ class Export(QDialog):
self.cboSimpleQuality.currentIndexChanged.connect(
functools.partial(self.cboSimpleQuality_index_changed, self.cboSimpleQuality))
self.cboChannelLayout.currentIndexChanged.connect(self.updateChannels)
app.window.ExportFrame.connect(self.updateProgressBar)
get_app().window.ExportFrame.connect(self.updateProgressBar)
# ********* Advanced Profile List **********
# Loop through profiles
......@@ -221,7 +217,7 @@ class Export(QDialog):
self.cboProfile.addItem(self.getProfileName(self.getProfilePath(profile_name)), self.getProfilePath(profile_name))
# Set default (if it matches the project)
if app.project.get(['profile']) in profile_name:
if get_app().project.get(['profile']) in profile_name:
self.selected_profile_index = box_index
# increment item counter
......@@ -252,7 +248,7 @@ class Export(QDialog):
# Populate all profiles
self.populateAllProfiles(app.project.get(['profile']))
self.populateAllProfiles(get_app().project.get(['profile']))
# Connect framerate signals
self.txtFrameRateNum.valueChanged.connect(self.updateFrameRate)
......@@ -369,8 +365,7 @@ class Export(QDialog):
self.cboSimpleTarget.clear()
# get translations
app = get_app()
_ = app._tr
_ = get_app()._tr
# parse the xml files and get targets that match the project type
project_types = []
......@@ -425,8 +420,7 @@ class Export(QDialog):
log.info(selected_profile_path)
# get translations
app = get_app()
_ = app._tr
_ = get_app()._tr
# Load profile
profile = openshot.Profile(selected_profile_path)
......@@ -455,8 +449,7 @@ class Export(QDialog):
log.info(selected_target)
# get translations
app = get_app()
_ = app._tr
_ = get_app()._tr
# don't do anything if the combo has been cleared
if selected_target:
......@@ -595,8 +588,7 @@ class Export(QDialog):
log.info(selected_quality)
# get translations
app = get_app()
_ = app._tr
_ = get_app()._tr
# Set the video and audio bitrates
if selected_quality:
......@@ -607,8 +599,7 @@ class Export(QDialog):
log.info("btnBrowse_clicked")
# get translations
app = get_app()
_ = app._tr
_ = get_app()._tr
# update export folder path
file_path = QFileDialog.getExistingDirectory(self, _("Choose a Folder..."), self.txtExportFolder.text())
......@@ -678,8 +669,7 @@ class Export(QDialog):
""" Start exporting video """
# get translations
app = get_app()
_ = app._tr
_ = get_app()._tr
# Init progress bar
self.progressExportVideo.setMinimum(self.txtStartFrame.value())
......@@ -783,9 +773,9 @@ class Export(QDialog):
video_settings["vcodec"] = image_ext
# Store updated export folder path in project file
app.updates.update_untracked(["export_path"], os.path.dirname(export_file_path))
get_app().updates.update_untracked(["export_path"], os.path.dirname(export_file_path))
# Mark project file as unsaved
app.project.has_unsaved_changes = True
get_app().project.has_unsaved_changes = True
# Set MaxSize (so we don't have any downsampling)
self.timeline.SetMaxSize(video_settings.get("width"), video_settings.get("height"))
......@@ -794,14 +784,13 @@ class Export(QDialog):
export_cache_object = openshot.CacheMemory(500)
self.timeline.SetCache(export_cache_object)
# Rescale all keyframes and reload project
# Rescale all keyframes (if needed)
if self.export_fps_factor != 1.0:
self.keyframes_rescaled = True
app.project.rescale_keyframes(self.export_fps_factor)
# Get a copy of rescaled project data (this does not modify the active project)
rescaled_app_data = get_app().project.rescale_keyframes(self.export_fps_factor)
# Load the "export" Timeline reader with the JSON from the real timeline
json_timeline = json.dumps(app.project._data)
self.timeline.SetJson(json_timeline)
self.timeline.SetJson(json.dumps(rescaled_app_data))
# Re-update the timeline FPS again (since the timeline just got clobbered)
self.updateFrameRate()
......@@ -854,7 +843,7 @@ class Export(QDialog):
# Notify window of export started
title_message = ""
app.window.ExportStarted.emit(export_file_path, video_settings.get("start_frame"), video_settings.get("end_frame"))
get_app().window.ExportStarted.emit(export_file_path, video_settings.get("start_frame"), video_settings.get("end_frame"))
progressstep = max(1 , round(( video_settings.get("end_frame") - video_settings.get("start_frame") ) / 1000))
start_time_export = time.time()
......@@ -875,7 +864,7 @@ class Export(QDialog):
'fps': fps_encode}
# Emit frame exported
app.window.ExportFrame.emit(title_message, video_settings.get("start_frame"), video_settings.get("end_frame"), frame)
get_app().window.ExportFrame.emit(title_message, video_settings.get("start_frame"), video_settings.get("end_frame"), frame)
# Process events (to show the progress bar moving)
QCoreApplication.processEvents()
......@@ -898,7 +887,7 @@ class Export(QDialog):
'seconds': seconds_run % 60,
'fps': fps_encode}
app.window.ExportFrame.emit(title_message, video_settings.get("start_frame"),
get_app().window.ExportFrame.emit(title_message, video_settings.get("start_frame"),
video_settings.get("end_frame"), frame)
except Exception as e:
......@@ -937,7 +926,7 @@ class Export(QDialog):
msg.exec_()
# Notify window of export started
app.window.ExportEnded.emit(export_file_path)
get_app().window.ExportEnded.emit(export_file_path)
# Close timeline object
self.timeline.Close()
......@@ -954,10 +943,6 @@ class Export(QDialog):
# Return scale mode to lower quality scaling (for faster previews)
openshot.Settings.Instance().HIGH_QUALITY_SCALING = False
# Return keyframes to preview scaling
if self.keyframes_rescaled:
app.project.rescale_keyframes(self.original_fps_factor)
# Handle end of export (for non-canceled exports)
if self.s.get("show_finished_window") and self.exporting:
# Hide cancel and export buttons
......@@ -992,6 +977,8 @@ class Export(QDialog):
return
# Re-set OMP thread enabled flag
# NOTE: This is always called when closing the export modal, and thus
# the keyframes are always scaled back to the original FPS if needed.
if self.s.get("omp_threads_enabled"):
openshot.Settings.Instance().WAIT_FOR_VIDEO_PROCESSING_TASK = False
else:
......@@ -1000,10 +987,6 @@ class Export(QDialog):
# Return scale mode to lower quality scaling (for faster previews)
openshot.Settings.Instance().HIGH_QUALITY_SCALING = False
# Return keyframes to preview scaling
if self.keyframes_rescaled:
get_app().project.rescale_keyframes(self.original_fps_factor)
# Cancel dialog
self.exporting = False
super(Export, self).reject()
......@@ -486,6 +486,12 @@ class MainWindow(QMainWindow, updates.UpdateWatcher):
# Ignore the request
return
# Stop preview thread
self.SpeedSignal.emit(0)
ui_util.setup_icon(self, self.actionPlay, "actionPlay", "media-playback-start")
self.actionPlay.setChecked(False)
QCoreApplication.processEvents()
# Do we have unsaved changes?
if app.project.needs_save():
ret = QMessageBox.question(self, _("Unsaved Changes"), _("Save changes to project first?"), QMessageBox.Cancel | QMessageBox.No | QMessageBox.Yes)
......@@ -545,25 +551,25 @@ class MainWindow(QMainWindow, updates.UpdateWatcher):
def clear_all_thumbnails(self):
"""Clear all user thumbnails"""
try:
openshot_thumbnail_path = os.path.join(info.USER_PATH, "thumbnail")
if os.path.exists(openshot_thumbnail_path):
log.info("Clear all thumbnails: %s" % openshot_thumbnail_path)
shutil.rmtree(openshot_thumbnail_path)
os.mkdir(openshot_thumbnail_path)
clear_path = os.path.join(info.USER_PATH, "thumbnail")
if os.path.exists(clear_path):
log.info("Clear all thumbnails: %s" % clear_path)
shutil.rmtree(clear_path)
os.mkdir(clear_path)
# Clear any blender animations
openshot_blender_path = os.path.join(info.USER_PATH, "blender")
if os.path.exists(openshot_blender_path):
log.info("Clear all animations: %s" % openshot_blender_path)
shutil.rmtree(openshot_blender_path)
os.mkdir(openshot_blender_path)
clear_path = os.path.join(info.USER_PATH, "blender")
if os.path.exists(clear_path):
log.info("Clear all animations: %s" % clear_path)
shutil.rmtree(clear_path)
os.mkdir(clear_path)
# Clear any title animations
openshot_title_path = os.path.join(info.USER_PATH, "title")
if os.path.exists(openshot_title_path):
log.info("Clear all titles: %s" % openshot_title_path)
shutil.rmtree(openshot_title_path)
os.mkdir(openshot_title_path)
clear_path = os.path.join(info.USER_PATH, "title")
if os.path.exists(clear_path):
log.info("Clear all titles: %s" % clear_path)
shutil.rmtree(clear_path)
os.mkdir(clear_path)
# Clear any backups
if os.path.exists(info.BACKUP_FILE):
......@@ -571,8 +577,8 @@ class MainWindow(QMainWindow, updates.UpdateWatcher):
# Remove backup file
os.unlink(info.BACKUP_FILE)
except:
log.info("Failed to clear thumbnails: %s" % info.THUMBNAIL_PATH)
except Exception as ex:
log.info("Failed to clear {}: {}".format(clear_path, ex))
def actionOpen_trigger(self, event):
app = get_app()
......@@ -1043,13 +1049,13 @@ class MainWindow(QMainWindow, updates.UpdateWatcher):
framePathTime = QDateTime()
# Get and Save the frame (return is void, so we cannot check for success/fail here - must use file modification timestamp)
openshot.Timeline.GetFrame(self.timeline_sync.timeline,self.preview_thread.current_frame).Save(framePath, 1.0)
openshot.Timeline.GetFrame(self.timeline_sync.timeline, self.preview_thread.current_frame).Save(framePath, 1.0)
# Show message to user
if os.path.exists(framePath) and (QFileInfo(framePath).lastModified() > framePathTime):
self.statusBar.showMessage(_("Saved Frame to %s" % framePath), 5000)
else:
self.statusBar.showMessage( _("Failed to save image to %s" % framePath), 5000)
self.statusBar.showMessage(_("Failed to save image to %s" % framePath), 5000)
# Reset the MaxSize to match the preview and reset the preview cache
viewport_rect = self.videoPreview.centeredViewport(self.videoPreview.width(), self.videoPreview.height())
......@@ -1266,7 +1272,7 @@ class MainWindow(QMainWindow, updates.UpdateWatcher):
closest_position = marker_position
# Seek to marker position (if any)
if closest_position != None:
if closest_position is not None:
# Seek
frame_to_seek = round(closest_position * fps_float) + 1
self.SeekSignal.emit(frame_to_seek)
......@@ -1319,7 +1325,7 @@ class MainWindow(QMainWindow, updates.UpdateWatcher):
closest_position = marker_position
# Seek to marker position (if any)
if closest_position != None:
if closest_position is not None:
# Seek
frame_to_seek = round(closest_position * fps_float) + 1
self.SeekSignal.emit(frame_to_seek)
......@@ -1406,16 +1412,16 @@ class MainWindow(QMainWindow, updates.UpdateWatcher):
ui_util.setup_icon(self, self.actionPlay, "actionPlay", "media-playback-pause")
self.actionPlay.setChecked(True)
elif key.matches(self.getShortcutByName("playToggle")) == QKeySequence.ExactMatch or \
key.matches(self.getShortcutByName("playToggle1")) == QKeySequence.ExactMatch or \
key.matches(self.getShortcutByName("playToggle2")) == QKeySequence.ExactMatch or \
key.matches(self.getShortcutByName("playToggle3")) == QKeySequence.ExactMatch:
elif (key.matches(self.getShortcutByName("playToggle")) == QKeySequence.ExactMatch or
key.matches(self.getShortcutByName("playToggle1")) == QKeySequence.ExactMatch or
key.matches(self.getShortcutByName("playToggle2")) == QKeySequence.ExactMatch or
key.matches(self.getShortcutByName("playToggle3")) == QKeySequence.ExactMatch):
# Toggle playbutton and show properties
self.actionPlay.trigger()
self.propertyTableView.select_frame(player.Position())
elif key.matches(self.getShortcutByName("deleteItem")) == QKeySequence.ExactMatch or \
key.matches(self.getShortcutByName("deleteItem1")) == QKeySequence.ExactMatch:
elif (key.matches(self.getShortcutByName("deleteItem")) == QKeySequence.ExactMatch or
key.matches(self.getShortcutByName("deleteItem1")) == QKeySequence.ExactMatch):
# Delete selected clip / transition
self.actionRemoveClip.trigger()
self.actionRemoveTransition.trigger()
......@@ -2227,11 +2233,8 @@ class MainWindow(QMainWindow, updates.UpdateWatcher):
# Add fixed spacer(s) (one for each "Other control" to keep playback controls centered)
ospacer1 = QWidget(self)
ospacer1.setMinimumSize(32, 1) # actionSaveFrame
ospacer1.setMinimumSize(32, 1) # actionSaveFrame
self.videoToolbar.addWidget(ospacer1)
#ospacer2 = QWidget(self)
#ospacer2.setMinimumSize(32, 1) # ???
#self.videoToolbar.addWidget(ospacer2)
# Add left spacer
spacer = QWidget(self)
......@@ -2285,7 +2288,9 @@ class MainWindow(QMainWindow, updates.UpdateWatcher):
self.sliderZoom.setInvertedControls(True)
self.sliderZoom.resize(100, 16)
self.zoomScaleLabel = QLabel( _("{} seconds").format(zoomToSeconds(self.sliderZoom.value())) )
self.zoomScaleLabel = QLabel(
_("{} seconds").format(zoomToSeconds(self.sliderZoom.value()))
)
# add zoom widgets
self.timelineToolbar.addAction(self.actionTimelineZoomIn)
......@@ -2388,7 +2393,7 @@ class MainWindow(QMainWindow, updates.UpdateWatcher):
log.info("cache-limit-mb: %s" % s.get("cache-limit-mb"))
# Get MB limit of cache (and convert to bytes)
cache_limit = s.get("cache-limit-mb") * 1024 * 1024 # Convert MB to Bytes
cache_limit = s.get("cache-limit-mb") * 1024 * 1024 # Convert MB to Bytes
# Clear old cache
new_cache_object = None
......@@ -2419,6 +2424,8 @@ class MainWindow(QMainWindow, updates.UpdateWatcher):
if sys.platform == "linux" and self.has_launcher:
if not self.unity_launchers:
# Get launcher only once
import gi
gi.require_version('Unity', '7.0')
from gi.repository import Unity
self.unity_launchers.append(Unity.LauncherEntry.get_for_desktop_id("openshot-qt.desktop"))
self.unity_launchers.append(Unity.LauncherEntry.get_for_desktop_id("appimagekit-openshot-qt.desktop"))
......@@ -2428,7 +2435,7 @@ class MainWindow(QMainWindow, updates.UpdateWatcher):
launcher.set_property("progress", current_frame / (end_frame - start_frame))
launcher.set_property("progress_visible", True)
except:
except Exception:
# Just ignore
self.has_launcher = False
......@@ -2440,7 +2447,7 @@ class MainWindow(QMainWindow, updates.UpdateWatcher):
# Set progress on Unity launcher and hide progress bar
launcher.set_property("progress", 0.0)
launcher.set_property("progress_visible", False)
except:
except Exception:
pass
def transformTriggered(self, clip_id):
......@@ -2598,9 +2605,9 @@ class MainWindow(QMainWindow, updates.UpdateWatcher):
# Set encoding method
if s.get("hw-decoder"):
openshot.Settings.Instance().HARDWARE_DECODER = int(str(s.get("hw-decoder")))
openshot.Settings.Instance().HARDWARE_DECODER = int(str(s.get("hw-decoder")))
else:
openshot.Settings.Instance().HARDWARE_DECODER = 0
openshot.Settings.Instance().HARDWARE_DECODER = 0
# Set graphics card for decoding
if s.get("graca_number_de"):
......@@ -2622,9 +2629,9 @@ class MainWindow(QMainWindow, updates.UpdateWatcher):
# Set audio playback settings
if s.get("playback-audio-device"):
openshot.Settings.Instance().PLAYBACK_AUDIO_DEVICE_NAME = str(s.get("playback-audio-device"))
openshot.Settings.Instance().PLAYBACK_AUDIO_DEVICE_NAME = str(s.get("playback-audio-device"))
else:
openshot.Settings.Instance().PLAYBACK_AUDIO_DEVICE_NAME = ""
openshot.Settings.Instance().PLAYBACK_AUDIO_DEVICE_NAME = ""
# Set OMP thread enabled flag (for stability)
if s.get("omp_threads_enabled"):
......@@ -2637,13 +2644,13 @@ class MainWindow(QMainWindow, updates.UpdateWatcher):
# Set use omp threads number environment variable
if s.get("omp_threads_number"):
openshot.Settings.Instance().OMP_THREADS = max(2,int(str(s.get("omp_threads_number"))))
openshot.Settings.Instance().OMP_THREADS = max(2, int(str(s.get("omp_threads_number"))))
else:
openshot.Settings.Instance().OMP_THREADS = 12
# Set use ffmpeg threads number environment variable
if s.get("ff_threads_number"):
openshot.Settings.Instance().FF_THREADS = max(1,int(str(s.get("ff_threads_number"))))
openshot.Settings.Instance().FF_THREADS = max(1, int(str(s.get("ff_threads_number"))))
else:
openshot.Settings.Instance().FF_THREADS = 8
......
......@@ -410,6 +410,16 @@ class Preferences(QDialog):
fileName = QFileDialog.getOpenFileName(self, _("Select executable file"), startpath, _("All Files (*)"))[0]
if fileName:
if platform.system() == "Darwin":
# Check for Mac specific app-bundle executable file (if any)
appBundlePath = os.path.join(fileName, 'Contents', 'MacOS')
if os.path.exists(os.path.join(appBundlePath, 'blender')):
fileName = os.path.join(appBundlePath, 'blender')
elif os.path.exists(os.path.join(appBundlePath, 'Blender')):
fileName = os.path.join(appBundlePath, 'Blender')
elif os.path.exists(os.path.join(appBundlePath, 'Inkscape')):
fileName = os.path.join(appBundlePath, 'Inkscape')
self.s.set(param["setting"], fileName)
widget.setText(fileName)
......
......@@ -56,11 +56,10 @@ class Profile(QDialog):
ui_util.init_ui(self)
# get translations
app = get_app()
_ = app._tr
_ = get_app()._tr
# Pause playback (to prevent crash since we are fixing to change the timeline's max size)
app.window.actionPlay_trigger(None, force="pause")
get_app().window.actionPlay_trigger(None, force="pause")
# Track metrics
track_metric_screen("profile-screen")
......@@ -93,7 +92,7 @@ class Profile(QDialog):
self.cboProfile.addItem(profile_name, self.profile_paths[profile_name])
# Set default (if it matches the project)
if app.project.get(['profile']) in profile_name:
if get_app().project.get(['profile']) in profile_name:
self.initial_index = box_index
# increment item counter
......@@ -145,7 +144,14 @@ class Profile(QDialog):
# Rescale all keyframes and reload project
if fps_factor != 1.0:
get_app().project.rescale_keyframes(fps_factor)
# Get a copy of rescaled project data (this does not modify the active project... yet)
rescaled_app_data = get_app().project.rescale_keyframes(fps_factor)
# Apply rescaled data to active project
get_app().project._data = rescaled_app_data
# Distribute all project data through update manager
get_app().updates.load(rescaled_app_data)
# Force ApplyMapperToClips to apply these changes
get_app().window.timeline_sync.timeline.ApplyMapperToClips()
......
......@@ -41,7 +41,7 @@
</sizepolicy>
</property>
<property name="pixmap">
<pixmap resource="../../images/openshot.qrc">:/about/AboutLogo.png</pixmap>
<pixmap resource="../../images/openshot.qrc">:/about/AboutLogo.png</pixmap>
</property>
</widget>
</item>
......@@ -51,13 +51,16 @@
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true">font-size: 4em; font-weight: bold;</string>
<string notr="true">font-size: 4em;</string>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="text">
<string/>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
<enum>Qt::RichText</enum>
</property>
</widget>
</item>
......
......@@ -46,8 +46,6 @@ class VideoWidget(QWidget, updates.UpdateInterface):
display_ratio_changed = False
pixel_ratio_changed = False
if action.key and action.key[0] in ["display_ratio", "pixel_ratio"] or action.type in ["load"]:
self.mutex.lock()
# Update display ratio (if found)
if action.type == "load" and action.values.get("display_ratio"):
display_ratio_changed = True
......@@ -72,8 +70,6 @@ class VideoWidget(QWidget, updates.UpdateInterface):
if display_ratio_changed or pixel_ratio_changed:
get_app().window.timeline_sync.timeline.SetMaxSize(round(self.width() * self.pixel_ratio.ToFloat()), round(self.height() * self.pixel_ratio.ToFloat()))
self.mutex.unlock()
def paintEvent(self, event, *args):
""" Custom paint event """
self.mutex.lock()
......
......@@ -69,6 +69,7 @@
<content_attribute id="money-gambling">none</content_attribute>
</content_rating>
<releases>
<release version="2.5.0" date="2020-02-07"/>
<release version="2.4.4" date="2019-03-20"/>
<release version="2.4.3" date="2018-09-22"/>
<release version="2.4.2" date="2018-06-30"/>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册