def __init__(self, *args):
		# Invoke parent init
		QTableView.__init__(self, *args)
		
		# Get a reference to the window object
		self.win = get_app().window
		
		# Get Model data
		self.clip_properties_model = PropertiesModel(self)
		
		# Keep track of mouse press start position to determine when to start drag
		self.selected = []
		self.selected_item = None

		# Setup header columns
		self.setModel(self.clip_properties_model.model)
		self.setSelectionBehavior(QAbstractItemView.SelectRows)
		self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
		self.setWordWrap(True)

		# Get table header
		horizontal_header = self.horizontalHeader()
		horizontal_header.setSectionResizeMode(QHeaderView.Stretch)
		vertical_header = self.verticalHeader()
		vertical_header.setVisible(False)
		
		# Refresh view
		self.clip_properties_model.update_model()
		
		# Resize columns
		self.resizeColumnToContents(0)
		self.resizeColumnToContents(1)

		# Connect filter signals
		get_app().window.txtPropertyFilter.textChanged.connect(self.filter_changed)
Example #2
0
    def updateProperty(self, id, frame_number, property_key, new_value):
        """Update a keyframe property to a new value, adding or updating keyframes as needed"""
        found_point = False
        clip_updated = False

        c = Clip.get(id=id)
        if not c:
            # No clip found
            return

        for point in c.data[property_key]["Points"]:
            log.info("looping points: co.X = %s" % point["co"]["X"])

            if point["co"]["X"] == frame_number:
                found_point = True
                clip_updated = True
                point["interpolation"] = openshot.BEZIER
                point["co"]["Y"] = float(new_value)

        if not found_point and new_value != None:
            clip_updated = True
            log.info("Created new point at X=%s" % frame_number)
            c.data[property_key]["Points"].append({'co': {'X': frame_number, 'Y': new_value}, 'interpolation': openshot.BEZIER})

        # Reduce # of clip properties we are saving (performance boost)
        c.data = {property_key: c.data.get(property_key)}

        # Save changes
        if clip_updated:
            # Save
            c.save()

            # Update the preview
            get_app().window.refreshFrameSignal.emit()
Example #3
0
    def __init__(self, parent, *args):

        # Keep track of the selected items (clips, transitions, etc...)
        self.selected = []
        self.current_item_id = None
        self.frame_number = 1
        self.previous_hash = ""
        self.new_item = True
        self.items = {}
        self.ignore_update_signal = False
        self.parent = parent
        self.previous_filter = None
        self.filter_base_properties = []

        # Create standard model
        self.model = ClipStandardItemModel()
        self.model.setColumnCount(2)

        # Timer to use a delay before showing properties (to prevent a mass selection from trying
        # to update the property model hundreds of times)
        self.update_timer = QTimer()
        self.update_timer.setInterval(100)
        self.update_timer.timeout.connect(self.update_item_timeout)
        self.update_timer.stop()
        self.next_item_id = None
        self.next_item_type = None

        # Connect data changed signal
        self.model.itemChanged.connect(self.value_updated)

        # Add self as listener to project data updates (used to update the timeline)
        get_app().updates.add_listener(self)
Example #4
0
    def accept(self):
        app = get_app()
        _ = app._tr

        # Get current project folder (if any)
        project_path = get_app().project.current_filepath
        default_folder = info.HOME_PATH
        if project_path:
            default_folder = os.path.dirname(project_path)

        # Init file path for new title
        title_path = os.path.join(default_folder, "%s.svg" % _("New Title"))

        # Get file path for SVG title
        file_path, file_type = QFileDialog.getSaveFileName(self, _("Save Title As..."), title_path, _("Scalable Vector Graphics (*.svg)"))

        if file_path:
            # Append .svg (if not already there)
            if not file_path.endswith("svg"):
                file_path = file_path + ".svg"

            # Update filename
            self.filename = file_path

            # Save title
            self.writeToFile(self.xmldoc)

            # Add file to project
            self.add_file(self.filename)

            # Close window
            super(TitleEditor, self).accept()
Example #5
0
    def bool_value_changed(self, widget, param, state):
        # Save setting
        if state == Qt.Checked:
            self.s.set(param["setting"], True)
        else:
            self.s.set(param["setting"], False)

        # Trigger specific actions
        if param["setting"] == "debug-mode":
            # Update debug setting of timeline
            log.info("Setting debug-mode to %s" % (state == Qt.Checked))
            debug_enabled = (state == Qt.Checked)

            # Enable / Disable logger
            openshot.ZmqLogger.Instance().Enable(debug_enabled)

        elif param["setting"] == "enable-auto-save":
            # Toggle autosave
            if (state == Qt.Checked):
                # Start/Restart autosave timer
                get_app().window.auto_save_timer.start()
            else:
                # Stop autosave timer
                get_app().window.auto_save_timer.stop()

        # Check for restart
        self.check_for_restart(param)
    def __init__(self, *args):
        # Invoke parent init
        QFrame.__init__(self, *args)
        self.item_id = None
        self.item_type = None

        # Get translation object
        _ = get_app()._tr

        # Widgets
        self.lblSelection = QLabel()
        self.lblSelection.setText("<strong>%s</strong>" % _("No Selection"))
        self.btnSelectionName = QPushButton()
        self.btnSelectionName.setVisible(False)
        self.btnSelectionName.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)

        # Support rich text
        self.lblSelection.setTextFormat(Qt.RichText)

        hbox = QHBoxLayout()
        hbox.setContentsMargins(0,0,0,0)
        hbox.addWidget(self.lblSelection)
        hbox.addWidget(self.btnSelectionName)
        self.setLayout(hbox)

        # Connect signals
        get_app().window.propertyTableView.loadProperties.connect(self.select_item)
    def Action_Triggered(self, event):
        # Switch selection
        item_id = self.sender().data()['item_id']
        item_type = self.sender().data()['item_type']
        log.info('switch selection to %s:%s' % (item_id, item_type))

        # Set the property tableview to the new item
        get_app().window.propertyTableView.loadProperties.emit(item_id, item_type)
Example #8
0
    def eventFilter(self, object, e):
        if e.type() == QEvent.WindowActivate:
            # Raise parent window, and then this tutorial
            get_app().window.showNormal()
            get_app().window.raise_()
            self.raise_()

        return False
Example #9
0
    def actionNew_trigger(self, event):
        # clear data and start new project
        get_app().project.load("")
        get_app().updates.reset()
        self.filesTreeView.refresh_view()
        log.info("New Project created.")

        # Set Window title
        self.SetWindowTitle()
Example #10
0
    def update_item_timeout(self):
        # Get the next item id, and type
        item_id = self.next_item_id
        item_type = self.next_item_type

        # Clear previous selection
        self.selected = []
        self.filter_base_properties = []

        log.info("Update item: %s" % item_type)

        if item_type == "clip":
            c = None
            clips = get_app().window.timeline_sync.timeline.Clips()
            for clip in clips:
                if clip.Id() == item_id:
                    c = clip
                    break

            # Append to selected clips
            self.selected.append((c, item_type))

        if item_type == "transition":
            t = None
            trans = get_app().window.timeline_sync.timeline.Effects()
            for tran in trans:
                if tran.Id() == item_id:
                    t = tran
                    break

            # Append to selected clips
            self.selected.append((t, item_type))

        if item_type == "effect":
            e = None
            clips = get_app().window.timeline_sync.timeline.Clips()
            for clip in clips:
                for effect in clip.Effects():
                    if effect.Id() == item_id:
                        e = effect
                        break

            # Filter out basic properties, since this is an effect on a clip
            self.filter_base_properties = ["position", "layer", "start", "end", "duration"]

            # Append to selected items
            self.selected.append((e, item_type))


        # Update frame # from timeline
        self.update_frame(get_app().window.preview_thread.player.Position(), reload_model=False)

        # Get ID of item
        self.new_item = True

        # Update the model data
        self.update_model(get_app().window.txtPropertyFilter.text())
    def mouseReleaseEvent(self, event):
        # Inform UpdateManager to accept updates, and only store our final update
        get_app().updates.ignore_history = False

        # Add final update to undo/redo history
        get_app().updates.apply_last_action_to_history(self.original_data)

        # Clear original data
        self.original_data = None
    def getMenu(self):
        # Build menu for selection button
        menu = QMenu(self)

        # Get translation object
        _ = get_app()._tr

        # Look up item for more info
        if self.item_type == "clip":
            self.item_name = Clip.get(id=self.item_id).title()
        elif self.item_type == "transition":
            self.item_name = Transition.get(id=self.item_id).title()
        elif self.item_type == "effect":
            self.item_name = Effect.get(id=self.item_id).title()

        # Add selected clips
        for item_id in get_app().window.selected_clips:
            clip = Clip.get(id=item_id)
            item_name = clip.title()
            item_icon = QIcon(QPixmap(clip.data.get('image')))
            action = menu.addAction(item_name)
            action.setIcon(item_icon)
            action.setData({'item_id':item_id, 'item_type':'clip'})
            action.triggered.connect(self.Action_Triggered)

            # Add effects for these clips (if any)
            for effect in clip.data.get('effects'):
                item_name = Effect.get(id=effect.get('id')).title()
                item_icon = QIcon(QPixmap(os.path.join(info.PATH, "effects", "icons", "%s.png" % effect.get('class_name').lower())))
                action = menu.addAction('  >  %s' % _(item_name))
                action.setIcon(item_icon)
                action.setData({'item_id': effect.get('id'), 'item_type': 'effect'})
                action.triggered.connect(self.Action_Triggered)

        # Add selected transitions
        for item_id in get_app().window.selected_transitions:
            trans = Transition.get(id=item_id)
            item_name = _(trans.title())
            item_icon = QIcon(QPixmap(trans.data.get('reader',{}).get('path')))
            action = menu.addAction(_(item_name))
            action.setIcon(item_icon)
            action.setData({'item_id': item_id, 'item_type': 'transition'})
            action.triggered.connect(self.Action_Triggered)

        # Add selected effects
        for item_id in get_app().window.selected_effects:
            effect = Effect.get(id=item_id)
            item_name = _(effect.title())
            item_icon = QIcon(QPixmap(os.path.join(info.PATH, "effects", "icons", "%s.png" % effect.data.get('class_name').lower())))
            action = menu.addAction(_(item_name))
            action.setIcon(item_icon)
            action.setData({'item_id': item_id, 'item_type': 'effect'})
            action.triggered.connect(self.Action_Triggered)

        # Return the menu object
        return menu
Example #13
0
    def load(self, file_path):
        """ Load project from file """

        self.new()

        if file_path:
            log.info("Loading project file: {}".format(file_path))

            # Default project data
            default_project = self._data

            try:
                # Attempt to load v2.X project file
                project_data = self.read_from_file(file_path, path_mode="absolute")

            except Exception as ex:
                try:
                    # Attempt to load legacy project file (v1.X version)
                    project_data = self.read_legacy_project_file(file_path)

                except Exception as ex:
                    # Project file not recognized as v1.X or v2.X, bubble up error
                    raise ex

            # Merge default and project settings, excluding settings not in default.
            self._data = self.merge_settings(default_project, project_data)

            # On success, save current filepath
            self.current_filepath = file_path

            # Check if paths are all valid
            self.check_if_paths_are_valid()

            # Copy any project thumbnails to main THUMBNAILS folder
            loaded_project_folder = os.path.dirname(self.current_filepath)
            project_thumbnails_folder = os.path.join(loaded_project_folder, "thumbnail")
            if os.path.exists(project_thumbnails_folder):
                # Remove thumbnail path
                shutil.rmtree(info.THUMBNAIL_PATH, True)

                # Copy project thumbnails folder
                shutil.copytree(project_thumbnails_folder, info.THUMBNAIL_PATH)

            # Add to recent files setting
            self.add_to_recent_files(file_path)

            # Upgrade any data structures
            self.upgrade_project_data_structures()

        # Get app, and distribute all project data through update manager
        from classes.app import get_app
        get_app().updates.load(self._data)

        # Clear needs save flag
        self.has_unsaved_changes = False
Example #14
0
    def update_frame(self, frame_number, reload_model=True):

        # Check for a selected clip
        if self.selected:
            clip, item_type = self.selected[0]

            if not clip:
                # Ignore null clip
                return

            # If effect, find the position of the parent clip
            if item_type == "effect":
                # find parent clip
                effect = Effect.get(id=clip.Id())
                if not effect:
                    # Invalid effect
                    return

                parent_clip_id = effect.parent["id"]

                # Find this clip object
                clips = get_app().window.timeline_sync.timeline.Clips()
                for c in clips:
                    if c.Id() == parent_clip_id:
                        # Override the selected clip object (so the effect gets the correct starting position)
                        clip = c
                        break

            # Get FPS from project
            fps = get_app().project.get(["fps"])
            fps_float = float(fps["num"]) / float(fps["den"])

            # Requested time
            requested_time = float(frame_number - 1) / fps_float

            # Determine the frame needed for this clip (based on the position on the timeline)
            time_diff = (requested_time - clip.Position()) + clip.Start()
            self.frame_number = round(time_diff * fps_float) + 1

            # Calculate biggest and smallest possible frames
            min_frame_number = round((clip.Start() * fps_float)) + 1
            max_frame_number = round((clip.End() * fps_float)) + 1

            # Adjust frame number if out of range
            if self.frame_number < min_frame_number:
                self.frame_number = min_frame_number
            if self.frame_number > max_frame_number:
                self.frame_number = max_frame_number

            log.info("Update frame to %s" % self.frame_number)

            # Update the model data
            if reload_model:
                self.update_model(get_app().window.txtPropertyFilter.text())
Example #15
0
    def spinner_value_changed(self, param, value):
        # Save setting
        self.s.set(param["setting"], value)
        log.info(value)

        if param["setting"] == "autosave-interval":
            # Update autosave interval (# of minutes)
            get_app().window.auto_save_timer.setInterval(value * 1000 * 60)

        # Check for restart
        self.check_for_restart(param)
Example #16
0
    def dropdown_index_changed(self, widget, param, index):
        # Save setting
        value = widget.itemData(index)
        self.s.set(param["setting"], value)
        log.info(value)

        # Apply cache settings (if needed)
        if param["setting"] in ["cache-mode", "cache-image-format"]:
            get_app().window.InitCacheSettings()

        # Check for restart
        self.check_for_restart(param)
Example #17
0
    def bool_value_changed(self, widget, param, state):
        # Save setting
        if state == Qt.Checked:
            self.s.set(param["setting"], True)
        else:
            self.s.set(param["setting"], False)

        # Trigger specific actions
        if param["setting"] == "debug-mode":
            # Update debug setting of timeline
            log.info("Setting debug-mode to %s" % (state == Qt.Checked))
            debug_enabled = (state == Qt.Checked)

            # Enable / Disable logger
            openshot.ZmqLogger.Instance().Enable(debug_enabled)

        elif param["setting"] == "enable-auto-save":
            # Toggle autosave
            if (state == Qt.Checked):
                # Start/Restart autosave timer
                get_app().window.auto_save_timer.start()
            else:
                # Stop autosave timer
                get_app().window.auto_save_timer.stop()

        elif param["setting"] == "hardware_decode":
            if (state == Qt.Checked):
                # Enable hardware decode
                openshot.Settings.Instance().HARDWARE_DECODE = True
            else:
                # Disable hardware decode
                openshot.Settings.Instance().HARDWARE_DECODE = False

        elif param["setting"] == "hardware_encode":
            if (state == Qt.Checked):
                # Enable hardware encode
                openshot.Settings.Instance().HARDWARE_ENCODE = True
            else:
                # Disable hardware encode
                openshot.Settings.Instance().HARDWARE_ENCODE = False

        elif param["setting"] == "omp_threads_enabled":
            if (state == Qt.Checked):
                # Enable OMP multi-threading
                openshot.Settings.Instance().WAIT_FOR_VIDEO_PROCESSING_TASK = False
            else:
                # Disable OMP multi-threading
                openshot.Settings.Instance().WAIT_FOR_VIDEO_PROCESSING_TASK = True

        # Check for restart
        self.check_for_restart(param)
	def select_item(self, item_id, item_type):
		""" Update the selected item in the properties window """

		# Get translation object
		_ = get_app()._tr
		
		# Set label
		if item_id:
			get_app().window.lblSelectedItem.setText(_("Selection: %s") % item_id)
		else:
			get_app().window.lblSelectedItem.setText(_("No Selection"))
			
		# Update item
		self.clip_properties_model.update_item(item_id, item_type)
    def __init__(self, *args):
        # Invoke parent init
        QTableView.__init__(self, *args)

        # Get a reference to the window object
        self.win = get_app().window

        # Get Model data
        self.clip_properties_model = PropertiesModel(self)
        self.transition_model = TransitionsModel(self)
        self.files_model = FilesModel(self)

        # Keep track of mouse press start position to determine when to start drag
        self.selected = []
        self.selected_label = None
        self.selected_item = None
        self.new_value = None
        self.original_data = None

        # Setup header columns
        self.setModel(self.clip_properties_model.model)
        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.setWordWrap(True)

        # Set delegate
        delegate = PropertyDelegate()
        self.setItemDelegateForColumn(1, delegate)
        self.previous_x = -1

        # Get table header
        horizontal_header = self.horizontalHeader()
        horizontal_header.setSectionResizeMode(QHeaderView.Stretch)
        vertical_header = self.verticalHeader()
        vertical_header.setVisible(False)

        # Refresh view
        self.clip_properties_model.update_model()
        self.transition_model.update_model()
        self.files_model.update_model()

        # Resize columns
        self.resizeColumnToContents(0)
        self.resizeColumnToContents(1)

        # Connect filter signals
        get_app().window.txtPropertyFilter.textChanged.connect(self.filter_changed)
        get_app().window.InsertKeyframe.connect(self.Insert_Action_Triggered)
        self.doubleClicked.connect(self.doubleClickedCB)
        self.loadProperties.connect(self.select_item)
Example #20
0
    def btnBrowse_clicked(self):
        log.info("btnBrowse_clicked")

        # get translations
        app = get_app()
        _ = app._tr

        # update export folder path
        file_path = QFileDialog.getExistingDirectory(self, _("Choose a Folder..."), self.txtExportFolder.text())
        if os.path.exists(file_path):
            self.txtExportFolder.setText(file_path)

            # update export folder path in project file
            get_app().updates.update(["export_path"], file_path)
Example #21
0
    def spinner_value_changed(self, param, value):
        # Save setting
        self.s.set(param["setting"], value)
        log.info(value)

        if param["setting"] == "autosave-interval":
            # Update autosave interval (# of minutes)
            get_app().window.auto_save_timer.setInterval(value * 1000 * 60)

        # Apply cache settings (if needed)
        if param["setting"] in ["cache-limit-mb", "cache-scale", "cache-quality"]:
            get_app().window.InitCacheSettings()

        # Check for restart
        self.check_for_restart(param)
Example #22
0
    def mouseReleaseEvent(self, event):
        """Capture mouse release event on video preview window"""
        self.mouse_pressed = False
        self.mouse_dragging = False
        self.transform_mode = None

        # Inform UpdateManager to accept updates, and only store our final update
        get_app().updates.ignore_history = False

        # Add final update to undo/redo history
        if self.original_clip_data:
            get_app().updates.apply_last_action_to_history(self.original_clip_data)

        # Clear original data
        self.original_clip_data = None
Example #23
0
    def cboProfile_index_changed(self, widget, index):
        selected_profile_path = widget.itemData(index)
        log.info(selected_profile_path)

        # get translations
        app = get_app()
        _ = app._tr

        # Load profile
        profile = openshot.Profile(selected_profile_path)

        # Load profile settings into advanced editor
        self.txtWidth.setValue(profile.info.width)
        self.txtHeight.setValue(profile.info.height)
        self.txtFrameRateNum.setValue(profile.info.fps.num)
        self.txtFrameRateDen.setValue(profile.info.fps.den)
        self.txtAspectRatioNum.setValue(profile.info.display_ratio.num)
        self.txtAspectRatioDen.setValue(profile.info.display_ratio.den)
        self.txtPixelRatioNum.setValue(profile.info.pixel_ratio.num)
        self.txtPixelRatioDen.setValue(profile.info.pixel_ratio.den)

        # Load the interlaced options
        self.cboInterlaced.clear()
        self.cboInterlaced.addItem(_("Yes"), "Yes")
        self.cboInterlaced.addItem(_("No"), "No")
        if profile.info.interlaced_frame:
            self.cboInterlaced.setCurrentIndex(0)
        else:
            self.cboInterlaced.setCurrentIndex(1)
Example #24
0
    def cboSimpleProjectType_index_changed(self, widget, index):
        selected_project = widget.itemData(index)

        # set the target dropdown based on the selected project type
        # first clear the combo
        self.cboSimpleTarget.clear()

        # get translations
        app = get_app()
        _ = app._tr

        # parse the xml files and get targets that match the project type
        project_types = []
        for file in os.listdir(info.EXPORT_PRESETS_DIR):
            xmldoc = xml.parse(os.path.join(info.EXPORT_PRESETS_DIR, file))
            type = xmldoc.getElementsByTagName("type")

            if _(type[0].childNodes[0].data) == selected_project:
                titles = xmldoc.getElementsByTagName("title")
                for title in titles:
                    project_types.append(_(title.childNodes[0].data))

        # Add all targets for selected project type
        for item in sorted(project_types):
            self.cboSimpleTarget.addItem(item, item)
Example #25
0
    def contextMenuEvent(self, event):
        # Update selection
        self.updateSelection()

        # Set context menu mode
        app = get_app()
        app.context_menu_object = "files"

        menu = QMenu(self)

        menu.addAction(self.win.actionImportFiles)
        menu.addSeparator()
        if self.selected:
            # If file selected, show file related options
            menu.addAction(self.win.actionPreview_File)
            menu.addAction(self.win.actionSplitClip)
            menu.addAction(self.win.actionAdd_to_Timeline)
            menu.addSeparator()
            #menu.addAction(self.win.actionFile_Properties)
            menu.addAction(self.win.actionRemove_from_Project)
            menu.addSeparator()
        menu.addAction(self.win.actionThumbnailView)

        # Show menu
        menu.exec_(QCursor.pos())
Example #26
0
    def __init__(self):
        # Create dialog class
        QDialog.__init__(self)

        # Load UI from designer
        ui_util.load_ui(self, self.ui_path)

        # Init Ui
        ui_util.init_ui(self)

        # get translations
        self.app = get_app()
        _ = self.app._tr

        # Init license
        #license_path = os.path.join(path_xdg, 'COPYING')
        #license_path = os.path.join(info.PATH, 'COPYING')
        #my_license = open('license_path', "r")
        #content = my_license.read()
        #for text in license_path:
            #self.textBrowser.append(text)
        #self.textBrowser.append(content)
        with open("(os.path.join(info.PATH, 'COPYING'))", 'r') as my_license:
            text = my_license.read()
            self.textBrowser.append(text)
Example #27
0
    def get_thumb_path(
            self, file_id, thumbnail_frame, clear_cache=False):
        """Get thumbnail path by invoking HTTP thumbnail request"""

        # Clear thumb cache (if requested)
        thumb_cache = ""
        if clear_cache:
            thumb_cache = "no-cache/"

        # Connect to thumbnail server and get image
        thumb_server_details = get_app().window.http_server_thread.server_address
        thumb_address = "http://%s:%s/thumbnails/%s/%s/path/%s" % (
            thumb_server_details[0],
            thumb_server_details[1],
            file_id,
            thumbnail_frame,
            thumb_cache)
        r = get(thumb_address)
        if r.ok:
            # Update thumbnail path to real one
            return r.text
        else:
            return ''
Example #28
0
    def filterAcceptsRow(self, sourceRow, sourceParent):
        """Filter for common transitions and text filter"""

        if get_app().window.actionTransitionsShowCommon.isChecked():
            # Fetch the group name
            index = self.sourceModel().index(sourceRow, 2,
                                             sourceParent)  # group name column
            group_name = self.sourceModel().data(
                index)  # group name (i.e. common)

            # Fetch the transitions name
            index = self.sourceModel().index(
                sourceRow, 0, sourceParent)  # transition name column
            trans_name = self.sourceModel().data(
                index)  # transition name (i.e. Fade In)

            # Return, if regExp match in displayed format.
            return group_name == "common" and self.filterRegExp().indexIn(
                trans_name) >= 0

        # Continue running built-in parent filter logic
        return super(TransitionFilterProxyModel,
                     self).filterAcceptsRow(sourceRow, sourceParent)
Example #29
0
    def __init__(self):
        # Create dialog class
        QDialog.__init__(self)

        # Load UI from designer
        ui_util.load_ui(self, self.ui_path)

        # Init Ui
        ui_util.init_ui(self)

        # get translations
        self.app = get_app()
        _ = self.app._tr

        # Init license
        with open(os.path.join(info.RESOURCES_PATH, 'license.txt'), 'r') as my_license:
            text = my_license.read()
            self.textBrowser.append(text)

        # Scroll to top
        cursor = self.textBrowser.textCursor()
        cursor.setPosition(0)
        self.textBrowser.setTextCursor(cursor)
Example #30
0
    def __init__(self, *args):
        # Invoke parent init
        QListView.__init__(self, *args)

        # Get a reference to the window object
        self.app = get_app()
        self.win = args[0]

        # Get Model data
        self.title_model = TitlesModel()

        # Setup header columns
        self.setModel(self.title_model.model)
        self.setIconSize(QSize(131, 108))
        self.setGridSize(QSize(102, 92))
        self.setViewMode(QListView.IconMode)
        self.setResizeMode(QListView.Adjust)
        self.setUniformItemSizes(True)
        self.setWordWrap(True)
        self.setTextElideMode(Qt.ElideRight)

        # Refresh view
        self.refresh_view()
Example #31
0
    def __init__(self):
        # Create dialog class
        QDialog.__init__(self)

        # Load UI from designer
        ui_util.load_ui(self, self.ui_path)

        # Init Ui
        ui_util.init_ui(self)

        # get translations
        self.app = get_app()
        _ = self.app._tr

        #create_text = _('Your X-Factor for composing amazing videos')
        description_text = _(
            'Magic VideoX Pro is simple, intuitive and amazing video editing software. Your X-Factor for composing amazing videos'
        )
        #learnmore_text = _('Learn more')
        #copyright_text = _('Copyright &copy; %(begin_year)s-%(current_year)s') % {'begin_year': '2008', 'current_year': str(datetime.datetime.today().year) }
        #about_html = '<html><head/><body><hr/><p align="center"><span style=" font-size:10pt; font-weight:600;">%s</span></p><p align="center"><span style=" font-size:10pt;">%s </span><a href="http://%s.openshot.org?r=about-us"><span style=" font-size:10pt; text-decoration: none; color:#55aaff;">%s</span></a><span style=" font-size:10pt;">.</span></p></body></html>' % (create_text, description_text, info.website_language(), learnmore_text)
        #company_html = '<html><head/><body style="font-size:11pt; font-weight:400; font-style:normal;">\n<hr />\n<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">%s </span><a href="http://%s.openshotstudios.com?r=about-us"><span style=" font-size:10pt; font-weight:600; text-decoration: none; color:#55aaff;">OpenShot Studios, LLC<br /></span></a></p></body></html>' % (copyright_text, info.website_language())

        # Set description and company labels
        self.lblAboutDescription.setText(description_text)
        #self.lblAboutCompany.setText(company_html)

        # set events handlers
        #self.btncredit.clicked.connect(self.load_credit)
        #self.btnlicense.clicked.connect(self.load_license)

        # Init some variables
        #self.txtversion.setText(_("Version: %s") % info.VERSION)
        self.txtversion.setAlignment(Qt.AlignCenter)

        # Track metrics
        track_metric_screen("about-screen")
Example #32
0
    def __init__(self, *args):
        # Init QObject superclass
        super().__init__(*args)

        # Create standard model
        self.app = get_app()
        self.model = QStandardItemModel()
        self.model.setColumnCount(4)
        self.model_paths = {}

        # Create proxy model (for sorting and filtering)
        self.proxy_model = TransitionFilterProxyModel()
        self.proxy_model.setDynamicSortFilter(True)
        self.proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.proxy_model.setSortCaseSensitivity(Qt.CaseSensitive)
        self.proxy_model.setSourceModel(self.model)
        self.proxy_model.setSortLocaleAware(True)

        # Create selection model to share between views
        self.selection_model = QItemSelectionModel(self.proxy_model)

        # Attempt to load model testing interface, if requested
        # (will only succeed with Qt 5.11+)
        if info.MODEL_TEST:
            try:
                # Create model tester objects
                from PyQt5.QtTest import QAbstractItemModelTester
                self.model_tests = []
                for m in [self.proxy_model, self.model]:
                    self.model_tests.append(
                        QAbstractItemModelTester(
                            m, QAbstractItemModelTester.FailureReportingMode.
                            Warning))
                log.info("Enabled {} model tests for transition data".format(
                    len(self.model_tests)))
            except ImportError:
                pass
Example #33
0
    def accept(self):
        app = get_app()
        _ = app._tr

        # If editing file, just update the existing file
        if self.edit_file_path and not self.duplicate:
            # Update filename
            self.filename = self.edit_file_path

            # Overwrite title svg file
            self.writeToFile(self.xmldoc)

        else:
            # Create new title (with unique name)
            file_name = "%s.svg" % self.txtFileName.toPlainText().strip()
            file_path = os.path.join(info.TITLE_PATH, file_name)

            if self.txtFileName.toPlainText().strip():
                # Do we have unsaved changes?
                if os.path.exists(file_path) and not self.edit_file_path:
                    ret = QMessageBox.question(self, _("Title Editor"), _("%s already exists.\nDo you want to replace it?") % file_name,
                                               QMessageBox.No | QMessageBox.Yes)
                    if ret == QMessageBox.No:
                        # Do nothing
                        return

                # Update filename
                self.filename = file_path

                # Save title
                self.writeToFile(self.xmldoc)

                # Add file to project
                self.add_file(self.filename)

        # Close window
        super(TitleEditor, self).accept()
    def cboSimpleProjectType_index_changed(self, widget, index):
        selected_project = widget.itemData(index)

        # set the target dropdown based on the selected project type
        # first clear the combo
        self.cboSimpleTarget.clear()

        # get translations
        app = get_app()
        _ = app._tr

        # parse the xml files and get targets that match the project type
        project_types = []
        for preset_path in [info.EXPORT_PRESETS_PATH, info.USER_PRESETS_PATH]:
            for file in os.listdir(preset_path):
                xmldoc = xml.parse(os.path.join(preset_path, file))
                type = xmldoc.getElementsByTagName("type")

                if _(type[0].childNodes[0].data) == selected_project:
                    titles = xmldoc.getElementsByTagName("title")
                    for title in titles:
                        project_types.append(_(title.childNodes[0].data))

        # Add all targets for selected project type
        preset_index = 0
        selected_preset = 0
        for item in sorted(project_types):
            self.cboSimpleTarget.addItem(item, item)

            # Find index of MP4/H.264
            if item == _("MP4 (h.264)"):
                selected_preset = preset_index

            preset_index += 1

        # Select MP4/H.264 as default
        self.cboSimpleTarget.setCurrentIndex(selected_preset)
Example #35
0
    def add_file(self, filepath):
        filename = os.path.basename(filepath)

        # Add file into project
        _ = get_app()._tr

        # Check for this path in our existing project data
        file = File.get(path=filepath)

        # If this file is already found, exit
        if file:
            return

        # Load filepath in libopenshot clip object (which will try multiple readers to open it)
        clip = openshot.Clip(filepath)

        # Get the JSON for the clip's internal reader
        try:
            reader = clip.Reader()
            file_data = json.loads(reader.Json())

            # Set media type
            file_data["media_type"] = "image"

            # Save new file to the project data
            file = File()
            file.data = file_data
            file.save()
            return True

        except Exception as ex:
            # Handle exception
            log.error('Could not import {}: {}'.format(filename, str(ex)))
            msg = QMessageBox()
            msg.setText(_("{} is not a valid video, audio, or image file.".format(filename)))
            msg.exec_()
            return False
Example #36
0
    def btnEnd_clicked(self):
        """End of clip button was clicked"""
        _ = get_app()._tr

        # Pause video
        self.btnPlay_clicked(force="pause")

        # Get the current frame
        current_frame = self.sliderVideo.value()

        # Check if ending frame greater than start frame
        if current_frame <= self.start_frame:
            # Handle exception
            msg = QMessageBox()
            msg.setText(
                _("Please choose valid 'start' and 'end' values for your clip."
                  ))
            msg.exec_()
            return

        # remember frame #
        self.end_frame = current_frame

        # Save thumbnail image
        self.end_image = os.path.join(info.USER_PATH, 'thumbnail',
                                      '%s.png' % self.end_frame)
        self.r.GetFrame(self.end_frame).Thumbnail(self.end_image, 160, 90, '',
                                                  '', '#000000', True)

        # Set CSS on button
        self.btnEnd.setStyleSheet('background-image: url(%s);' %
                                  self.end_image.replace('\\', '/'))

        # Enable create button
        self.btnAddClip.setEnabled(True)

        log.info('btnEnd_clicked, current frame: %s' % self.end_frame)
Example #37
0
    def __init__(self, window):
        self.app = get_app()
        # window 是我 timeline_sync 的爸爸
        self.window = window
        project = self.app.project
        s = settings.get_settings()

        # Get some settings from the project
        fps = project.get("fps")
        width = project.get("width")
        height = project.get("height")
        sample_rate = project.get("sample_rate")
        channels = project.get("channels")
        channel_layout = project.get("channel_layout")

        # Create an instance of a libopenshot Timeline object
        self.timeline = openshot.Timeline(
            width, height, openshot.Fraction(fps["num"], fps["den"]),
            sample_rate, channels, channel_layout)
        self.timeline.info.channel_layout = channel_layout
        self.timeline.info.has_audio = True
        self.timeline.info.has_video = True
        self.timeline.info.video_length = 99999
        self.timeline.info.duration = 999.99
        self.timeline.info.sample_rate = sample_rate
        self.timeline.info.channels = channels

        # Open the timeline reader
        self.timeline.Open()

        # Add self as listener to project data updates (at the beginning of the list)
        # This listener will receive events before others.
        self.app.updates.add_listener(self, 0)

        # Connect to signal
        self.window.MaxSizeChanged.connect(self.MaxSizeChangedCB)
Example #38
0
    def __init__(self, *args):
        # Invoke parent init
        QWidget.__init__(self, *args)

        # Init aspect ratio settings (default values)
        self.aspect_ratio = openshot.Fraction()
        self.pixel_ratio = openshot.Fraction()
        self.aspect_ratio.num = 16
        self.aspect_ratio.den = 9
        self.pixel_ratio.num = 1
        self.pixel_ratio.den = 1

        # Init Qt style properties (black background, ect...)
        p = QPalette()
        p.setColor(QPalette.Window, Qt.black)
        super().setPalette(p)
        super().setAttribute(Qt.WA_OpaquePaintEvent)
        super().setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)

        # Init current frame's QImage
        self.current_image = None

        # Get a reference to the window object
        self.win = get_app().window
Example #39
0
    def btnFont_clicked(self):
        app = get_app()
        _ = app._tr

        # Default to previously-selected font
        oldfont = self.qfont

        # Get font from user
        font, ok = QFontDialog.getFont(oldfont, caption=("Change Font"))

        # Update SVG font
        if ok and font is not oldfont:
            self.qfont = font
            fontinfo = QtGui.QFontInfo(font)
            self.font_family = fontinfo.family()
            self.font_style = fontinfo.styleName()
            self.font_weight = fontinfo.weight()
            self.set_font_style()

            # Something changed, so update temp SVG
            self.writeToFile(self.xmldoc)

            # Display SVG again
            self.display_svg()
Example #40
0
    def currentChanged(self, selected, deselected):
        # Get selected item
        self.selected = selected
        self.deselected = deselected

        # Get translation object
        _ = get_app()._tr

        # Get all selected rows items
        if self.title_model.model.itemFromIndex(self.selected):
            ItemRow = self.title_model.model.itemFromIndex(self.selected).row()
            title_path = self.title_model.model.item(ItemRow, 2).text()

            # Display title in graphicsView
            self.win.filename = title_path

            # Create temp version of title
            self.win.create_temp_title(title_path)

            # Add all widgets for editing
            self.win.load_svg_template()

            # Display temp image (slight delay to allow screen to be shown first)
            QTimer.singleShot(50, self.win.display_svg)
Example #41
0
    def hide_tips(self, tid, user_clicked=False):
        """ Hide the current tip, and don't show anymore """
        s = get_app().get_settings()

        # Loop through and find current tid
        for tutorial_object in self.tutorial_objects:
            # Get details
            tutorial_id = tutorial_object["id"]
            if tutorial_id == tid:
                # Hide dialog
                self.close_dialogs()
                # Update settings that this tutorial is completed
                if tid not in self.tutorial_ids:
                    self.tutorial_ids.append(str(tid))
                    s.set("tutorial_ids", ",".join(self.tutorial_ids))

        # Mark tutorial as completed (if settings)
        if user_clicked:
            # Disable all tutorials
            self.tutorial_enabled = False
            s.set("tutorial_enabled", False)

        # Forgot current tutorial
        self.current_dialog = None
Example #42
0
    def __init__(self):
        # Create dialog class
        QDialog.__init__(self)

        # Load UI from designer
        ui_util.load_ui(self, self.ui_path)

        # Init Ui
        ui_util.init_ui(self)

        # get translations
        self.app = get_app()
        _ = self.app._tr

        # set events handlers
        self.btncredit.clicked.connect(self.load_credit)
        self.btnlicense.clicked.connect(self.load_license)

        # Init some variables
        self.txtversion.setText(_("Version: %s") % info.VERSION)
        self.txtversion.setAlignment(Qt.AlignCenter)

        # Track metrics
        track_metric_screen("about-screen")
    def addTrack(self, name):
        log.info("add track %s", name)
        # Get # of tracks
        all_tracks = get_app().project.get(["layers"])
        track_number = 1000000
        if len(list(reversed(sorted(all_tracks,
                                    key=itemgetter('number'))))) > 0:
            track_number = list(
                reversed(sorted(
                    all_tracks,
                    key=itemgetter('number'))))[0].get("number") + 1000000

        # Create new track above existing layer(s)
        track = Track()
        track.data = {
            "number": track_number,
            id: str(len(all_tracks)),
            "y": 0,
            "label": "",
            "lock": False,
            "name": name
        }
        track.save()
        return track
Example #44
0
    def value_updated(self, item):
        """ Name or tags updated """
        if self.files_model.ignore_updates:
            return

        # Get translation method
        _ = get_app()._tr

        # Determine what was changed
        file_id = self.files_model.model.item(item.row(), 5).text()
        name = self.files_model.model.item(item.row(), 1).text()
        tags = self.files_model.model.item(item.row(), 2).text()

        # Get file object and update friendly name and tags attribute
        f = File.get(id=file_id)
        f.data.update({"name": name or os.path.basename(f.data.get("path"))})
        if "tags" in f.data or tags:
            f.data.update({"tags": tags})

        # Save File
        f.save()

        # Update file thumbnail
        self.win.FileUpdated.emit(file_id)
Example #45
0
    def updateTotal(self):
        """Calculate the total length of what's about to be added to the timeline"""
        fade_value = self.cmbFade.currentData()
        fade_length = self.txtFadeLength.value()
        transition_path = self.cmbTransition.currentData()
        transition_length = self.txtTransitionLength.value()

        total = 0.0
        for file in self.treeFiles.timeline_model.files:
            # Adjust clip duration, start, and end
            duration = file.data["duration"]
            if file.data["media_type"] == "image":
                duration = self.txtImageLength.value()

            if total != 0.0:
                # Don't subtract time from initial clip
                if not transition_path:
                    # No transitions
                    if fade_value != None:
                        # Fade clip - subtract the fade length
                        duration -= fade_length
                else:
                    # Transition
                    duration -= transition_length

            # Append duration to total
            total += duration

        # Get frames per second
        fps = get_app().project.get(["fps"])

        # Update label
        total_parts = self.secondsToTime(total, fps["num"], fps["den"])
        timestamp = "%s:%s:%s:%s" % (total_parts["hour"], total_parts["min"],
                                     total_parts["sec"], total_parts["frame"])
        self.lblTotalLengthValue.setText(timestamp)
Example #46
0
    def transformTriggered(self, clip_id):
        """Handle the transform signal when it's emitted"""
        # Disable Transform UI
        if self.transforming_clip:
            # Is this the same clip_id already being transformed?
            if clip_id == self.transforming_clip.id:
                # Clear transform
                self.transforming_clip = None

        # Get new clip for transform
        self.transforming_clip = Clip.get(id=clip_id)

        if self.transforming_clip:
            self.transforming_clip_object = None
            clips = get_app().window.timeline_sync.timeline.Clips()
            for clip in clips:
                if clip.Id() == self.transforming_clip.id:
                    self.transforming_clip_object = clip
                    break

        # Update the preview and reselct current frame in properties
        get_app().window.refreshFrameSignal.emit()
        get_app().window.propertyTableView.select_frame(
            get_app().window.preview_thread.player.Position())
Example #47
0
    def Render(self, blend_file_path, target_script, preview_mode=False):
        """ Worker's Render method which invokes the Blender rendering commands """
        log.info("QThread Render Method Invoked")

        # Init regex expression used to determine blender's render progress
        s = settings.get_settings()

        # get the blender executable path
        self.blender_exec_path = s.get("blender_command")
        self.blender_frame_expression = re.compile(
            r"Fra:([0-9,]*).*Mem:(.*?) .*Part ([0-9,]*)-([0-9,]*)")
        self.blender_saved_expression = re.compile(r"Saved: '(.*.png)(.*)'")
        self.blender_version = re.compile(r"Blender (.*?) ")
        self.blend_file_path = blend_file_path
        self.target_script = target_script
        self.preview_mode = preview_mode
        self.frame_detected = False
        self.version = None
        self.command_output = ""
        self.process = None
        self.is_running = True
        _ = get_app()._tr

        try:
            # Shell the blender command to create the image sequence
            command_get_version = [self.blender_exec_path, '-v']
            command_render = [
                self.blender_exec_path, '-b', self.blend_file_path, '-P',
                self.target_script
            ]
            self.process = subprocess.Popen(command_get_version,
                                            stdout=subprocess.PIPE)

            # Check the version of Blender
            self.version = self.blender_version.findall(
                str(self.process.stdout.readline()))

            if self.version:
                if float(self.version[0]) < 2.78:
                    # change cursor to "default" and stop running blender command
                    self.is_running = False

                    # Wrong version of Blender.  Must be 2.62+:
                    self.blender_version_error.emit(float(self.version[0]))
                    return

            # debug info
            log.info("Blender command: {} {} '{}' {} '{}'".format(
                command_render[0], command_render[1], command_render[2],
                command_render[3], command_render[4]))

            # Run real command to render Blender project
            self.process = subprocess.Popen(command_render,
                                            stdout=subprocess.PIPE)

        except:
            # Error running command.  Most likely the blender executable path in the settings
            # is not correct, or is not the correct version of Blender (i.e. 2.62+)
            self.is_running = False
            self.blender_error_nodata.emit()
            return

        while self.is_running and self.process.poll() is None:

            # Look for progress info in the Blender Output
            line = str(self.process.stdout.readline())
            self.command_output = self.command_output + line + "\n"  # append all output into a variable
            output_frame = self.blender_frame_expression.findall(line)

            # Does it have a match?
            if output_frame:
                # Yes, we have a match
                self.frame_detected = True
                current_frame = output_frame[0][0]
                memory = output_frame[0][1]
                current_part = output_frame[0][2]
                max_parts = output_frame[0][3]

                # Update progress bar
                if not self.preview_mode:
                    # only update progress if in 'render' mode
                    self.progress.emit(float(current_frame),
                                       float(current_part), float(max_parts))

            # Look for progress info in the Blender Output
            output_saved = self.blender_saved_expression.findall(str(line))
            log.info("Image detected from blender regex: %s" % output_saved)

            # Does it have a match?
            if output_saved:
                # Yes, we have a match
                self.frame_detected = True
                image_path = output_saved[0][0]
                time_saved = output_saved[0][1]

                # Update preview image
                self.image_updated.emit(image_path)

        # Re-enable the interface
        self.enable_interface.emit()

        # Check if NO FRAMES are detected
        if not self.frame_detected:
            # Show Error that no frames are detected.  This is likely caused by
            # the wrong command being executed... or an error in Blender.
            self.blender_error_with_data.emit(
                _("No frame was found in the output from Blender"))

        # Done with render (i.e. close window)
        elif not self.preview_mode:
            # only close window if in 'render' mode
            self.finished.emit()

        # Thread finished
        log.info("Blender render thread finished")
        if self.is_running == False:
            # close window if thread was killed
            self.closed.emit()

        # mark thread as finished
        self.is_running = False
    def __init__(self, cuts_json, clips_json, preview=False):
        _ = get_app()._tr

        # Create dialog class
        QDialog.__init__(self)

        # Load UI from designer
        ui_util.load_ui(self, self.ui_path)

        # Init UI
        ui_util.init_ui(self)

        # Track metrics
        track_metric_screen("cutting-screen")

        # If preview, hide cutting controls
        if preview:
            self.lblInstructions.setVisible(False)
            self.widgetControls.setVisible(False)
            self.setWindowTitle(_("Preview"))

        self.start_frame = 1
        self.start_image = None
        self.end_frame = 1
        self.end_image = None

        project = get_app().project

        # Keep track of file object
        #self.file = file
        self.file_path = file.absolute_path()
        self.video_length = int(file.data['video_length'])
        self.fps_num = int(file.data['fps']['num'])
        self.fps_den = int(file.data['fps']['den'])
        self.fps = float(self.fps_num) / float(self.fps_den)
        self.width = int(file.data['width'])
        self.height = int(file.data['height'])
        self.sample_rate = int(file.data['sample_rate'])
        self.channels = int(file.data['channels'])
        self.channel_layout = int(file.data['channel_layout'])

        # Open video file with Reader
        log.info(self.file_path)

        # Create an instance of a libopenshot Timeline object
        self.r = openshot.Timeline(
            self.width, self.height,
            openshot.Fraction(self.fps_num, self.fps_den), self.sample_rate,
            self.channels, self.channel_layout)
        self.r.info.channel_layout = self.channel_layout

        try:
            # Add clip for current preview file
            self.clip = openshot.Clip(self.file_path)

            # Show waveform for audio files
            if not self.clip.Reader().info.has_video and self.clip.Reader(
            ).info.has_audio:
                self.clip.Waveform(True)

            # Set has_audio property
            self.r.info.has_audio = self.clip.Reader().info.has_audio

            if preview:
                # Display frame #'s during preview
                self.clip.display = openshot.FRAME_DISPLAY_CLIP

            self.r.AddClip(self.clip)
        except:
            log.error('Failed to load media file into preview player: %s' %
                      self.file_path)
            return

        # Add Video Widget
        self.videoPreview = VideoWidget()
        self.videoPreview.setSizePolicy(QSizePolicy.Preferred,
                                        QSizePolicy.Expanding)
        self.verticalLayout.insertWidget(0, self.videoPreview)

        # Set max size of video preview (for speed)
        viewport_rect = self.videoPreview.centeredViewport(
            self.videoPreview.width(), self.videoPreview.height())
        self.r.SetMaxSize(viewport_rect.width(), viewport_rect.height())

        # Open reader
        self.r.Open()

        # Start the preview thread
        self.initialized = False
        self.transforming_clip = False
        self.preview_parent = PreviewParent()
        self.preview_parent.Init(self, self.r, self.videoPreview)
        self.preview_thread = self.preview_parent.worker

        # Set slider constraints
        self.sliderIgnoreSignal = False
        self.sliderVideo.setMinimum(1)
        self.sliderVideo.setMaximum(self.video_length)
        self.sliderVideo.setSingleStep(1)
        self.sliderVideo.setSingleStep(1)
        self.sliderVideo.setPageStep(24)

        # Determine if a start or end attribute is in this file
        start_frame = 1
        if 'start' in self.file.data.keys():
            start_frame = (float(self.file.data['start']) * self.fps) + 1

        # Display start frame (and then the previous frame)
        QTimer.singleShot(
            500, functools.partial(self.sliderVideo.setValue, start_frame + 1))
        QTimer.singleShot(
            600, functools.partial(self.sliderVideo.setValue, start_frame))

        # Connect signals
        self.actionPlay.triggered.connect(self.actionPlay_Triggered)
        self.btnPlay.clicked.connect(self.btnPlay_clicked)
        self.sliderVideo.valueChanged.connect(self.sliderVideo_valueChanged)
        self.btnStart.clicked.connect(self.btnStart_clicked)
        self.btnEnd.clicked.connect(self.btnEnd_clicked)
        self.btnClear.clicked.connect(self.btnClear_clicked)
        self.btnAddClip.clicked.connect(self.btnAddClip_clicked)
        self.initialized = True
    def value_updated(self,
                      item,
                      interpolation=-1,
                      value=None,
                      interpolation_details=[]):
        """ Table cell change event - also handles context menu to update interpolation value """

        if self.ignore_update_signal:
            return

        # Get translation method
        _ = get_app()._tr

        # Determine what was changed
        property = self.model.item(item.row(), 0).data()
        property_name = property[1]["name"]
        closest_point_x = property[1]["closest_point_x"]
        previous_point_x = property[1]["previous_point_x"]
        property_type = property[1]["type"]
        property_key = property[0]
        clip_id, item_type = item.data()

        # Get value (if any)
        if item.text():
            # Set and format value based on property type
            if value != None:
                # Override value
                new_value = value
            elif property_type == "string":
                # Use string value
                new_value = item.text()
            elif property_type == "bool":
                # Use boolean value
                if item.text() == _("False"):
                    new_value = False
                else:
                    new_value = True
            elif property_type == "int":
                # Use int value
                new_value = QLocale().system().toInt(item.text())[0]
            else:
                # Use decimal value
                new_value = QLocale().system().toFloat(item.text())[0]
        else:
            new_value = None

        log.info(
            "%s for %s changed to %s at frame %s with interpolation: %s at closest x: %s"
            % (property_key, clip_id, new_value, self.frame_number,
               interpolation, closest_point_x))

        # Find this clip
        c = None
        clip_updated = False

        if item_type == "clip":
            # Get clip object
            c = Clip.get(id=clip_id)
        elif item_type == "transition":
            # Get transition object
            c = Transition.get(id=clip_id)
        elif item_type == "effect":
            # Get effect object
            c = Effect.get(id=clip_id)

        if c:
            # Update clip attribute
            if property_key in c.data:
                log.info("value updated: %s" % c.data)

                # Check the type of property (some are keyframe, and some are not)
                if type(c.data[property_key]) == dict:
                    # Keyframe
                    # Loop through points, find a matching points on this frame
                    found_point = False
                    point_to_delete = None
                    for point in c.data[property_key]["Points"]:
                        log.info("looping points: co.X = %s" %
                                 point["co"]["X"])
                        if interpolation == -1 and point["co"][
                                "X"] == self.frame_number:
                            # Found point, Update value
                            found_point = True
                            clip_updated = True
                            # Update or delete point
                            if new_value != None:
                                point["co"]["Y"] = float(new_value)
                                log.info(
                                    "updating point: co.X = %s to value: %s" %
                                    (point["co"]["X"], float(new_value)))
                            else:
                                point_to_delete = point
                            break

                        elif interpolation > -1 and point["co"][
                                "X"] == previous_point_x:
                            # Only update interpolation type (and the LEFT side of the curve)
                            found_point = True
                            clip_updated = True
                            point["interpolation"] = interpolation
                            if interpolation == 0:
                                point["handle_right"] = point.get(
                                    "handle_right") or {
                                        "Y": 0.0,
                                        "X": 0.0
                                    }
                                point["handle_right"][
                                    "X"] = interpolation_details[0]
                                point["handle_right"][
                                    "Y"] = interpolation_details[1]

                            log.info(
                                "updating interpolation mode point: co.X = %s to %s"
                                % (point["co"]["X"], interpolation))
                            log.info("use interpolation preset: %s" %
                                     str(interpolation_details))

                        elif interpolation > -1 and point["co"][
                                "X"] == closest_point_x:
                            # Only update interpolation type (and the RIGHT side of the curve)
                            found_point = True
                            clip_updated = True
                            point["interpolation"] = interpolation
                            if interpolation == 0:
                                point["handle_left"] = point.get(
                                    "handle_left") or {
                                        "Y": 0.0,
                                        "X": 0.0
                                    }
                                point["handle_left"][
                                    "X"] = interpolation_details[2]
                                point["handle_left"][
                                    "Y"] = interpolation_details[3]

                            log.info(
                                "updating interpolation mode point: co.X = %s to %s"
                                % (point["co"]["X"], interpolation))
                            log.info("use interpolation preset: %s" %
                                     str(interpolation_details))

                    # Delete point (if needed)
                    if point_to_delete:
                        clip_updated = True
                        log.info("Found point to delete at X=%s" %
                                 point_to_delete["co"]["X"])
                        c.data[property_key]["Points"].remove(point_to_delete)

                    # Create new point (if needed)
                    elif not found_point and new_value != None:
                        clip_updated = True
                        log.info("Created new point at X=%s" %
                                 self.frame_number)
                        c.data[property_key]["Points"].append({
                            'co': {
                                'X': self.frame_number,
                                'Y': new_value
                            },
                            'interpolation':
                            1
                        })

                elif property_type == "int":
                    # Integer
                    clip_updated = True
                    c.data[property_key] = int(new_value)

                elif property_type == "float":
                    # Float
                    clip_updated = True
                    c.data[property_key] = new_value

                elif property_type == "bool":
                    # Boolean
                    clip_updated = True
                    c.data[property_key] = bool(new_value)

                elif property_type == "string":
                    # String
                    clip_updated = True
                    c.data[property_key] = str(new_value)

            # Reduce # of clip properties we are saving (performance boost)
            c.data = {property_key: c.data.get(property_key)}

            # Save changes
            if clip_updated:
                # Save
                c.save()

                # Update the preview
                get_app().window.refreshFrameSignal.emit()

            # Clear selection
            self.parent.clearSelection()
    def update_model(self, filter=""):
        log.info("updating clip properties model.")
        app = get_app()
        _ = app._tr

        # Stop QTimer
        self.update_timer.stop()

        # Check for a selected clip
        if self.selected and self.selected[0]:
            c, item_type = self.selected[0]

            # Skip blank clips
            # TODO: Determine why c is occasional = None
            if not c:
                return

            # Get raw unordered JSON properties
            raw_properties = json.loads(c.PropertiesJSON(self.frame_number))
            all_properties = OrderedDict(
                sorted(raw_properties.items(), key=lambda x: x[1]['name']))
            log.info("Getting properties for frame %s: %s" %
                     (self.frame_number, str(all_properties)))

            # Check if filter was changed (if so, wipe previous model data)
            if self.previous_filter != filter:
                self.previous_filter = filter
                self.new_item = True  # filter changed, so we need to regenerate the entire model

            # Ignore any events from this method
            self.ignore_update_signal = True

            # Clear previous model data (if item is different)
            if self.new_item:
                # Prepare for new properties
                self.items = {}
                self.model.clear()

                # Add Headers
                self.model.setHorizontalHeaderLabels(
                    [_("Property"), _("Value")])

            # Loop through properties, and build a model
            for property in all_properties.items():
                label = property[1]["name"]
                name = property[0]
                value = property[1]["value"]
                type = property[1]["type"]
                memo = property[1]["memo"]
                readonly = property[1]["readonly"]
                keyframe = property[1]["keyframe"]
                points = property[1]["points"]
                interpolation = property[1]["interpolation"]
                closest_point_x = property[1]["closest_point_x"]
                choices = property[1]["choices"]

                # Adding Transparency to translation file
                transparency_label = _("Transparency")

                selected_choice = None
                if choices:
                    selected_choice = [
                        c for c in choices if c["selected"] == True
                    ][0]["name"]

                # Hide filtered out properties
                if filter and filter.lower() not in name.lower():
                    continue

                # Hide unused base properties (if any)
                if name in self.filter_base_properties:
                    continue

                # Insert new data into model, or update existing values
                row = []
                if self.new_item:

                    # Append Property Name
                    col = QStandardItem("Property")
                    col.setText(_(label))
                    col.setData(property)
                    if keyframe and points > 1:
                        col.setBackground(
                            QColor("green"))  # Highlight keyframe background
                    elif points > 1:
                        col.setBackground(QColor(
                            42, 130,
                            218))  # Highlight interpolated value background
                    if readonly:
                        col.setFlags(Qt.ItemIsEnabled)
                    else:
                        col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled
                                     | Qt.ItemIsUserCheckable)
                    row.append(col)

                    # Append Value
                    col = QStandardItem("Value")
                    if selected_choice:
                        col.setText(_(selected_choice))
                    elif type == "string":
                        # Use string value
                        col.setText(memo)
                    elif type == "bool":
                        # Use boolean value
                        if value:
                            col.setText(_("True"))
                        else:
                            col.setText(_("False"))
                    elif type == "color":
                        # Don't output a value for colors
                        col.setText("")
                    elif type == "int":
                        col.setText("%d" % value)
                    else:
                        # Use numeric value
                        col.setText(QLocale().system().toString(float(value),
                                                                "f",
                                                                precision=2))
                    col.setData((c.Id(), item_type))
                    if points > 1:
                        # Apply icon to cell
                        my_icon = QPixmap(
                            os.path.join(info.IMAGES_PATH,
                                         "keyframe-%s.png" % interpolation))
                        col.setData(my_icon, Qt.DecorationRole)

                        # Set the background color of the cell
                        if keyframe:
                            col.setBackground(QColor(
                                "green"))  # Highlight keyframe background
                        else:
                            col.setBackground(
                                QColor(42, 130, 218)
                            )  # Highlight interpolated value background

                    if type == "color":
                        # Color needs to be handled special
                        red = property[1]["red"]["value"]
                        green = property[1]["green"]["value"]
                        blue = property[1]["blue"]["value"]
                        col.setBackground(QColor(red, green, blue))

                    if readonly or type == "color" or choices:
                        col.setFlags(Qt.ItemIsEnabled)
                    else:
                        col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled
                                     | Qt.ItemIsUserCheckable
                                     | Qt.ItemIsEditable)
                    row.append(col)

                    # Append ROW to MODEL (if does not already exist in model)
                    self.model.appendRow(row)

                else:
                    # Update the value of the existing model
                    # Get 1st Column
                    col = self.items[name]["row"][0]
                    col.setData(property)

                    # For non-color types, update the background color
                    if keyframe and points > 1:
                        col.setBackground(
                            QColor("green"))  # Highlight keyframe background
                    elif points > 1:
                        col.setBackground(QColor(
                            42, 130,
                            218))  # Highlight interpolated value background
                    else:
                        col.setBackground(QStandardItem("Empty").background())

                    # Update helper dictionary
                    row.append(col)

                    # Get 2nd Column
                    col = self.items[name]["row"][1]
                    if selected_choice:
                        col.setText(_(selected_choice))
                    elif type == "string":
                        # Use string value
                        col.setText(memo)
                    elif type == "bool":
                        # Use boolean value
                        if value:
                            col.setText(_("True"))
                        else:
                            col.setText(_("False"))
                    elif type == "color":
                        # Don't output a value for colors
                        col.setText("")
                    elif type == "int":
                        col.setText("%d" % value)
                    else:
                        # Use numeric value
                        col.setText(QLocale().system().toString(float(value),
                                                                "f",
                                                                precision=2))

                    if points > 1:
                        # Apply icon to cell
                        my_icon = QPixmap(
                            os.path.join(info.IMAGES_PATH,
                                         "keyframe-%s.png" % interpolation))
                        col.setData(my_icon, Qt.DecorationRole)

                        # Set the background color of the cell
                        if keyframe:
                            col.setBackground(QColor(
                                "green"))  # Highlight keyframe background
                        else:
                            col.setBackground(
                                QColor(42, 130, 218)
                            )  # Highlight interpolated value background

                    else:
                        # clear background color
                        col.setBackground(QStandardItem("Empty").background())

                        # clear icon
                        my_icon = QPixmap()
                        col.setData(my_icon, Qt.DecorationRole)

                    if type == "color":
                        # Update the color based on the color curves
                        red = property[1]["red"]["value"]
                        green = property[1]["green"]["value"]
                        blue = property[1]["blue"]["value"]
                        col.setBackground(QColor(red, green, blue))

                    # Update helper dictionary
                    row.append(col)

                # Keep track of items in a dictionary (for quick look up)
                self.items[name] = {"row": row, "property": property}

            # Update the values on the next call to this method (instead of adding rows)
            self.new_item = False

        else:
            # Clear previous properties hash
            self.previous_hash = ""

            # Clear previous model data (if any)
            self.model.clear()

            # Add Headers
            self.model.setHorizontalHeaderLabels([_("Property"), _("Value")])

        # Done updating model
        self.ignore_update_signal = False
    def remove_keyframe(self, item):
        """Remove an existing keyframe (if any)"""

        # Determine what was changed
        property = self.model.item(item.row(), 0).data()
        property_name = property[1]["name"]
        property_type = property[1]["type"]
        closest_point_x = property[1]["closest_point_x"]
        property_type = property[1]["type"]
        property_key = property[0]
        clip_id, item_type = item.data()

        # Find this clip
        c = None
        clip_updated = False

        if item_type == "clip":
            # Get clip object
            c = Clip.get(id=clip_id)
        elif item_type == "transition":
            # Get transition object
            c = Transition.get(id=clip_id)
        elif item_type == "effect":
            # Get effect object
            c = Effect.get(id=clip_id)

        if c:
            # Update clip attribute
            if property_key in c.data:
                log.info("remove keyframe: %s" % c.data)

                # Determine type of keyframe (normal or color)
                keyframe_list = []
                if property_type == "color":
                    keyframe_list = [
                        c.data[property_key]["red"],
                        c.data[property_key]["blue"],
                        c.data[property_key]["green"]
                    ]
                else:
                    keyframe_list = [c.data[property_key]]

                # Loop through each keyframe (red, blue, and green)
                for keyframe in keyframe_list:

                    # Keyframe
                    # Loop through points, find a matching points on this frame
                    closest_point = None
                    point_to_delete = None
                    for point in keyframe["Points"]:
                        if point["co"]["X"] == self.frame_number:
                            # Found point, Update value
                            clip_updated = True
                            point_to_delete = point
                            break
                        if point["co"]["X"] == closest_point_x:
                            closest_point = point

                    # If no point found, use closest point x
                    if not point_to_delete:
                        point_to_delete = closest_point

                    # Delete point (if needed)
                    if point_to_delete:
                        clip_updated = True
                        log.info("Found point to delete at X=%s" %
                                 point_to_delete["co"]["X"])
                        keyframe["Points"].remove(point_to_delete)

                # Reduce # of clip properties we are saving (performance boost)
                c.data = {property_key: c.data[property_key]}

                # Save changes
                if clip_updated:
                    # Save
                    c.save()

                    # Update the preview
                    get_app().window.refreshFrameSignal.emit()

                # Clear selection
                self.parent.clearSelection()
    def color_update(self,
                     item,
                     new_color,
                     interpolation=-1,
                     interpolation_details=[]):
        """Insert/Update a color keyframe for the selected row"""

        # Determine what was changed
        property = self.model.item(item.row(), 0).data()
        property_type = property[1]["type"]
        closest_point_x = property[1]["closest_point_x"]
        previous_point_x = property[1]["previous_point_x"]
        property_key = property[0]
        clip_id, item_type = item.data()

        if property_type == "color":
            # Find this clip
            c = None
            clip_updated = False

            if item_type == "clip":
                # Get clip object
                c = Clip.get(id=clip_id)
            elif item_type == "transition":
                # Get transition object
                c = Transition.get(id=clip_id)
            elif item_type == "effect":
                # Get effect object
                c = Effect.get(id=clip_id)

            if c:
                # Update clip attribute
                if property_key in c.data:
                    log.info("color update: %s" % c.data)

                    # Loop through each keyframe (red, blue, and green)
                    for color, new_value in [("red", new_color.red()),
                                             ("blue", new_color.blue()),
                                             ("green", new_color.green())]:

                        # Keyframe
                        # Loop through points, find a matching points on this frame
                        found_point = False
                        for point in c.data[property_key][color]["Points"]:
                            log.info("looping points: co.X = %s" %
                                     point["co"]["X"])
                            if interpolation == -1 and point["co"][
                                    "X"] == self.frame_number:
                                # Found point, Update value
                                found_point = True
                                clip_updated = True
                                # Update point
                                point["co"]["Y"] = new_value
                                log.info(
                                    "updating point: co.X = %s to value: %s" %
                                    (point["co"]["X"], float(new_value)))
                                break

                            elif interpolation > -1 and point["co"][
                                    "X"] == previous_point_x:
                                # Only update interpolation type (and the LEFT side of the curve)
                                found_point = True
                                clip_updated = True
                                point["interpolation"] = interpolation
                                if interpolation == 0:
                                    point["handle_right"] = point.get(
                                        "handle_right") or {
                                            "Y": 0.0,
                                            "X": 0.0
                                        }
                                    point["handle_right"][
                                        "X"] = interpolation_details[0]
                                    point["handle_right"][
                                        "Y"] = interpolation_details[1]

                                log.info(
                                    "updating interpolation mode point: co.X = %s to %s"
                                    % (point["co"]["X"], interpolation))
                                log.info("use interpolation preset: %s" %
                                         str(interpolation_details))

                            elif interpolation > -1 and point["co"][
                                    "X"] == closest_point_x:
                                # Only update interpolation type (and the RIGHT side of the curve)
                                found_point = True
                                clip_updated = True
                                point["interpolation"] = interpolation
                                if interpolation == 0:
                                    point["handle_left"] = point.get(
                                        "handle_left") or {
                                            "Y": 0.0,
                                            "X": 0.0
                                        }
                                    point["handle_left"][
                                        "X"] = interpolation_details[2]
                                    point["handle_left"][
                                        "Y"] = interpolation_details[3]

                                log.info(
                                    "updating interpolation mode point: co.X = %s to %s"
                                    % (point["co"]["X"], interpolation))
                                log.info("use interpolation preset: %s" %
                                         str(interpolation_details))

                        # Create new point (if needed)
                        if not found_point:
                            clip_updated = True
                            log.info("Created new point at X=%s" %
                                     self.frame_number)
                            c.data[property_key][color]["Points"].append({
                                'co': {
                                    'X': self.frame_number,
                                    'Y': new_value
                                },
                                'interpolation':
                                1
                            })

                # Reduce # of clip properties we are saving (performance boost)
                c.data = {property_key: c.data[property_key]}

                # Save changes
                if clip_updated:
                    # Save
                    c.save()

                    # Update the preview
                    get_app().window.refreshFrameSignal.emit()

                # Clear selection
                self.parent.clearSelection()
Example #53
0
    def add_file(self, filepath):
        path, filename = os.path.split(filepath)

        # Add file into project
        app = get_app()
        _ = get_app()._tr

        # Check for this path in our existing project data
        file = File.get(path=filepath)

        # If this file is already found, exit
        if file:
            return

        # Load filepath in libopenshot clip object (which will try multiple readers to open it)
        clip = openshot.Clip(filepath)

        # Get the JSON for the clip's internal reader
        try:
            reader = clip.Reader()
            file_data = json.loads(reader.Json())

            # Determine media type
            if file_data["has_video"] and not self.is_image(file_data):
                file_data["media_type"] = "video"
            elif file_data["has_video"] and self.is_image(file_data):
                file_data["media_type"] = "image"
            elif file_data["has_audio"] and not file_data["has_video"]:
                file_data["media_type"] = "audio"

            # Save new file to the project data
            file = File()
            file.data = file_data

            # Is this file an image sequence / animation?
            image_seq_details = self.get_image_sequence_details(filepath)
            if image_seq_details:
                # Update file with correct path
                folder_path = image_seq_details["folder_path"]
                file_name = image_seq_details["file_path"]
                base_name = image_seq_details["base_name"]
                fixlen = image_seq_details["fixlen"]
                digits = image_seq_details["digits"]
                extension = image_seq_details["extension"]

                if not fixlen:
                    zero_pattern = "%d"
                else:
                    zero_pattern = "%%0%sd" % digits

                # Generate the regex pattern for this image sequence
                pattern = "%s%s.%s" % (base_name, zero_pattern, extension)

                # Split folder name
                (parentPath, folderName) = os.path.split(folder_path)
                if not base_name:
                    # Give alternate name
                    file.data["name"] = "%s (%s)" % (folderName, pattern)

                # Load image sequence (to determine duration and video_length)
                image_seq = openshot.Clip(os.path.join(folder_path, pattern))

                # Update file details
                file.data["path"] = os.path.join(folder_path, pattern)
                file.data["media_type"] = "video"
                file.data["duration"] = image_seq.Reader().info.duration
                file.data["video_length"] = image_seq.Reader(
                ).info.video_length

            # Save file
            file.save()
            return True

        except:
            # Handle exception
            msg = QMessageBox()
            msg.setText(
                _("{} is not a valid video, audio, or image file.".format(
                    filename)))
            msg.exec_()
            return False
Example #54
0
    def get_image_sequence_details(self, file_path):
        """Inspect a file path and determine if this is an image sequence"""

        # Get just the file name
        (dirName, fileName) = os.path.split(file_path)
        extensions = ["png", "jpg", "jpeg", "gif", "tif"]
        match = re.findall(r"(.*[^\d])?(0*)(\d+)\.(%s)" % "|".join(extensions),
                           fileName, re.I)

        if not match:
            # File name does not match an image sequence
            return None
        else:
            # Get the parts of image name
            base_name = match[0][0]
            fixlen = match[0][1] > ""
            number = int(match[0][2])
            digits = len(match[0][1] + match[0][2])
            extension = match[0][3]

            full_base_name = os.path.join(dirName, base_name)

            # Check for images which the file names have the different length
            fixlen = fixlen or not (
                glob.glob("%s%s.%s" % (full_base_name, "[0-9]" *
                                       (digits + 1), extension))
                or glob.glob("%s%s.%s" %
                             (full_base_name, "[0-9]" *
                              ((digits - 1) if digits > 1 else 3), extension)))

            # Check for previous or next image
            for x in range(max(0, number - 100), min(number + 101, 50000)):
                if x != number and os.path.exists(
                        "%s%s.%s" % (full_base_name, str(x).rjust(digits, "0")
                                     if fixlen else str(x), extension)):
                    is_sequence = True
                    break
            else:
                is_sequence = False

            if is_sequence and dirName not in self.ignore_image_sequence_paths:
                log.info('Prompt user to import image sequence')
                # Ignore this path (temporarily)
                self.ignore_image_sequence_paths.append(dirName)

                # Translate object
                _ = get_app()._tr

                # Handle exception
                ret = QMessageBox.question(
                    self, _("Import Image Sequence"),
                    _("Would you like to import %s as an image sequence?") %
                    fileName, QMessageBox.No | QMessageBox.Yes)
                if ret == QMessageBox.Yes:
                    # Yes, import image sequence
                    parameters = {
                        "file_path": file_path,
                        "folder_path": dirName,
                        "base_name": base_name,
                        "fixlen": fixlen,
                        "digits": digits,
                        "extension": extension
                    }
                    return parameters
                else:
                    return None
            else:
                return None
Example #55
0
def import_xml():
    """Import final cut pro XML file"""
    app = get_app()
    _ = app._tr

    # Get FPS info
    fps_num = app.project.get("fps").get("num", 24)
    fps_den = app.project.get("fps").get("den", 1)
    fps_float = float(fps_num / fps_den)

    # Get XML path
    recommended_path = app.project.current_filepath or ""
    if not recommended_path:
        recommended_path = info.HOME_PATH
    else:
        recommended_path = os.path.dirname(recommended_path)
    file_path = QFileDialog.getOpenFileName(app.window, _("Import XML..."),
                                            recommended_path,
                                            _("Final Cut Pro (*.xml)"),
                                            _("Final Cut Pro (*.xml)"))[0]

    if not file_path or not os.path.exists(file_path):
        # User canceled dialog
        return

    # Parse XML file
    xmldoc = minidom.parse(file_path)

    # Get video tracks
    video_tracks = []
    for video_element in xmldoc.getElementsByTagName("video"):
        for video_track in video_element.getElementsByTagName("track"):
            video_tracks.append(video_track)
    audio_tracks = []
    for audio_element in xmldoc.getElementsByTagName("audio"):
        for audio_track in audio_element.getElementsByTagName("track"):
            audio_tracks.append(audio_track)

    # Loop through tracks
    track_index = 0
    for tracks in [audio_tracks, video_tracks]:
        for track_element in tracks:
            # Get clipitems on this track (if any)
            clips_on_track = track_element.getElementsByTagName("clipitem")
            if not clips_on_track:
                continue

            # Get # of tracks
            track_index += 1
            all_tracks = app.project.get("layers")
            track_number = list(
                reversed(sorted(
                    all_tracks,
                    key=itemgetter('number'))))[0].get("number") + 1000000

            # Create new track above existing layer(s)
            track = Track()
            is_locked = False
            if track_element.getElementsByTagName(
                    "locked")[0].childNodes[0].nodeValue == "TRUE":
                is_locked = True
            track.data = {
                "number": track_number,
                "y": 0,
                "label": "XML Import %s" % track_index,
                "lock": is_locked
            }
            track.save()

            # Loop through clips
            for clip_element in clips_on_track:
                # Get clip path
                xml_file_id = clip_element.getElementsByTagName(
                    "file")[0].getAttribute("id")
                clip_path = ""
                if clip_element.getElementsByTagName("pathurl"):
                    clip_path = clip_element.getElementsByTagName(
                        "pathurl")[0].childNodes[0].nodeValue
                else:
                    # Skip clipitem if no clippath node found
                    # This usually happens for linked audio clips (which OpenShot combines audio and thus ignores this)
                    continue

                clip_path, is_modified, is_skipped = find_missing_file(
                    clip_path)
                if is_skipped:
                    continue

                # Check for this path in our existing project data
                file = File.get(path=clip_path)

                # Load filepath in libopenshot clip object (which will try multiple readers to open it)
                clip_obj = openshot.Clip(clip_path)

                if not file:
                    # Get the JSON for the clip's internal reader
                    try:
                        reader = clip_obj.Reader()
                        file_data = json.loads(reader.Json())

                        # Determine media type
                        if file_data["has_video"] and not is_image(file_data):
                            file_data["media_type"] = "video"
                        elif file_data["has_video"] and is_image(file_data):
                            file_data["media_type"] = "image"
                        elif file_data[
                                "has_audio"] and not file_data["has_video"]:
                            file_data["media_type"] = "audio"

                        # Save new file to the project data
                        file = File()
                        file.data = file_data

                        # Save file
                        file.save()
                    except Exception:
                        # Ignore errors for now
                        pass

                if (file.data["media_type"] == "video"
                        or file.data["media_type"] == "image"):
                    # Determine thumb path
                    thumb_path = os.path.join(info.THUMBNAIL_PATH,
                                              "%s.png" % file.data["id"])
                else:
                    # Audio file
                    thumb_path = os.path.join(info.PATH, "images",
                                              "AudioThumbnail.png")

                # Create Clip object
                clip = Clip()
                clip.data = json.loads(clip_obj.Json())
                clip.data["file_id"] = file.id
                clip.data["title"] = clip_element.getElementsByTagName(
                    "name")[0].childNodes[0].nodeValue
                clip.data["layer"] = track.data.get("number", 1000000)
                clip.data["image"] = thumb_path
                clip.data["position"] = float(
                    clip_element.getElementsByTagName("start")
                    [0].childNodes[0].nodeValue) / fps_float
                clip.data["start"] = float(
                    clip_element.getElementsByTagName("in")
                    [0].childNodes[0].nodeValue) / fps_float
                clip.data["end"] = float(
                    clip_element.getElementsByTagName("out")
                    [0].childNodes[0].nodeValue) / fps_float

                # Loop through clip's effects
                for effect_element in clip_element.getElementsByTagName(
                        "effect"):
                    effectid = effect_element.getElementsByTagName(
                        "effectid")[0].childNodes[0].nodeValue
                    keyframes = effect_element.getElementsByTagName("keyframe")
                    if effectid == "opacity":
                        clip.data["alpha"] = {"Points": []}
                        for keyframe_element in keyframes:
                            keyframe_time = float(
                                keyframe_element.getElementsByTagName("when")
                                [0].childNodes[0].nodeValue)
                            keyframe_value = float(
                                keyframe_element.getElementsByTagName("value")
                                [0].childNodes[0].nodeValue) / 100.0
                            clip.data["alpha"]["Points"].append({
                                "co": {
                                    "X": round(keyframe_time),
                                    "Y": keyframe_value
                                },
                                "interpolation":
                                1  # linear
                            })
                    elif effectid == "audiolevels":
                        clip.data["volume"] = {"Points": []}
                        for keyframe_element in keyframes:
                            keyframe_time = float(
                                keyframe_element.getElementsByTagName("when")
                                [0].childNodes[0].nodeValue)
                            keyframe_value = float(
                                keyframe_element.getElementsByTagName("value")
                                [0].childNodes[0].nodeValue) / 100.0
                            clip.data["volume"]["Points"].append({
                                "co": {
                                    "X": round(keyframe_time),
                                    "Y": keyframe_value
                                },
                                "interpolation":
                                1  # linear
                            })

                # Save clip
                clip.save()

            # Update the preview and reselect current frame in properties
            app.window.refreshFrameSignal.emit()
            app.window.propertyTableView.select_frame(
                app.window.preview_thread.player.Position())
Example #56
0
    def __init__(self, *args):
        # Invoke parent init
        QTreeView.__init__(self, *args)

        # Get a reference to the window object
        self.app = get_app()
        self.win = args[0]

        # Get Model data
        self.blender_model = BlenderModel()

        # Keep track of mouse press start position to determine when to start drag
        self.selected = None
        self.deselected = None

        # Preview render timer
        self.preview_timer = QTimer(self)
        self.preview_timer.setInterval(300)
        self.preview_timer.timeout.connect(self.preview_timer_onTimeout)

        # Init dictionary which holds the values to the template parameters
        self.params = {}

        # Assign a new unique id for each template selected
        self.unique_folder_name = None

        # Disable interface
        self.disable_interface(cursor=False)
        self.selected_template = ""

        # Setup header columns
        self.setModel(self.blender_model.model)
        self.setIconSize(QSize(131, 108))
        self.setGridSize(QSize(102, 92))
        self.setViewMode(QListView.IconMode)
        self.setResizeMode(QListView.Adjust)
        self.setUniformItemSizes(False)
        self.setWordWrap(True)
        self.setTextElideMode(Qt.ElideRight)
        self.setStyleSheet('QTreeView::item { padding-top: 2px; }')

        # Hook up button
        self.win.btnRefresh.clicked.connect(
            functools.partial(self.btnRefresh_clicked))
        self.win.sliderPreview.valueChanged.connect(
            functools.partial(self.sliderPreview_valueChanged))

        # Refresh view
        self.refresh_view()

        # Background Worker Thread (for Blender process)
        self.background = QThread(self)
        self.worker = Worker()  # no parent!

        # Hook up signals to Background Worker
        self.worker.closed.connect(self.onCloseWindow)
        self.worker.finished.connect(self.onRenderFinish)
        self.worker.blender_version_error.connect(self.onBlenderVersionError)
        self.worker.blender_error_nodata.connect(self.onBlenderErrorNoData)
        self.worker.progress.connect(self.onUpdateProgress)
        self.worker.image_updated.connect(self.onUpdateImage)
        self.worker.blender_error_with_data.connect(self.onBlenderErrorMessage)
        self.worker.enable_interface.connect(self.onRenableInterface)

        # Move Worker to new thread, and Start
        self.worker.moveToThread(self.background)
        self.background.start()
Example #57
-1
    def __init__(self, *args):
        # Invoke parent init
        QListView.__init__(self, *args)

        # Get a reference to the window object
        self.win = get_app().window

        # Get Model data
        self.files_model = FilesModel()
        self.setAcceptDrops(True)
        self.setDragEnabled(True)
        self.setDropIndicatorShown(True)
        self.selected = []
        self.ignore_image_sequence_paths = []

        # Setup header columns
        self.setModel(self.files_model.model)
        self.setIconSize(QSize(131, 108))
        self.setViewMode(QListView.IconMode)
        self.setResizeMode(QListView.Adjust)
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setUniformItemSizes(True)
        self.setWordWrap(True)
        self.setStyleSheet('QListView::item { padding-top: 2px; }')

        # Refresh view
        self.refresh_view()

        # setup filter events
        app = get_app()
        app.window.filesFilter.textChanged.connect(self.filter_changed)
        app.window.actionFilesClear.triggered.connect(self.clear_filter)
Example #58
-1
    def __init__(self, *args):
        # Invoke parent init
        QTreeView.__init__(self, *args)

        # Get a reference to the window object
        self.win = get_app().window

        # Get Model data
        self.files_model = FilesModel()

        # Keep track of mouse press start position to determine when to start drag
        self.setAcceptDrops(True)
        self.setDragEnabled(True)
        self.setDropIndicatorShown(True)
        self.selected = []

        # Setup header columns
        self.setModel(self.files_model.model)
        self.setIconSize(QSize(75, 62))
        self.setIndentation(0)
        self.setSelectionBehavior(QTreeView.SelectRows)
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.setWordWrap(True)
        self.setStyleSheet('QTreeView::item { padding-top: 2px; }')

        # Refresh view
        self.refresh_view()

        # setup filter events
        app = get_app()
        app.window.filesFilter.textChanged.connect(self.filter_changed)
        app.window.actionFilesClear.triggered.connect(self.clear_filter)
        self.files_model.model.itemChanged.connect(self.value_updated)
Example #59
-1
	def __init__(self, *args):
		# Invoke parent init
		QListView.__init__(self, *args)
		
		# Get a reference to the window object
		self.win = get_app().window
		
		# Get Model data
		self.effects_model = EffectsModel()
		
		# Keep track of mouse press start position to determine when to start drag
		self.setAcceptDrops(True)
		self.setDragEnabled(True)
		self.setDropIndicatorShown(True)

		# Setup header columns
		self.setModel(self.effects_model.model)
		self.setIconSize(QSize(131, 108))
		self.setViewMode(QListView.IconMode)
		self.setResizeMode(QListView.Adjust)
		self.setUniformItemSizes(True)
		self.setWordWrap(True)
		self.setStyleSheet('QListView::item { padding-top: 2px; }')
		
		# Refresh view
		self.refresh_view()

		# setup filter events
		app = get_app()
		app.window.effectsFilter.textChanged.connect(self.filter_changed)
		app.window.actionEffectsClear.triggered.connect(self.clear_filter)
Example #60
-1
    def __init__(self, commits, commit_url, *args):
        # Invoke parent init
        QListView.__init__(self, *args)

        # Get a reference to the window object
        self.win = get_app().window

        # Get Model data
        self.changelog_model = ChangelogModel(commits)
        self.selected = []

        # Setup header columns
        self.setModel(self.changelog_model.model)
        self.setIndentation(0)
        self.setSelectionBehavior(QTreeView.SelectRows)
        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.setWordWrap(True)
        self.setStyleSheet('QTreeView::item { padding-top: 2px; }')
        self.commit_url = commit_url

        # Refresh view
        self.refresh_view()

        # setup filter events
        app = get_app()