OpenShot Video Editor  2.0.0
effects_model.py
Go to the documentation of this file.
1 ##
2 #
3 # @file
4 # @brief This file contains the effects model, used by the main window
5 # @author Jonathan Thomas <jonathan@openshot.org>
6 #
7 # @section LICENSE
8 #
9 # Copyright (c) 2008-2018 OpenShot Studios, LLC
10 # (http://www.openshotstudios.com). This file is part of
11 # OpenShot Video Editor (http://www.openshot.org), an open-source project
12 # dedicated to delivering high quality video editing and animation solutions
13 # to the world.
14 #
15 # OpenShot Video Editor is free software: you can redistribute it and/or modify
16 # it under the terms of the GNU General Public License as published by
17 # the Free Software Foundation, either version 3 of the License, or
18 # (at your option) any later version.
19 #
20 # OpenShot Video Editor is distributed in the hope that it will be useful,
21 # but WITHOUT ANY WARRANTY; without even the implied warranty of
22 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 # GNU General Public License for more details.
24 #
25 # You should have received a copy of the GNU General Public License
26 # along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
27 #
28 
29 import os
30 
31 from PyQt5.QtCore import QMimeData, Qt
32 from PyQt5.QtGui import *
33 from PyQt5.QtWidgets import QMessageBox
34 import openshot # Python module for libopenshot (required video editing module installed separately)
35 
36 from classes import info
37 from classes.logger import log
38 from classes.app import get_app
39 
40 try:
41  import json
42 except ImportError:
43  import simplejson as json
44 
45 
46 class EffectsStandardItemModel(QStandardItemModel):
47  def __init__(self, parent=None):
48  QStandardItemModel.__init__(self)
49 
50  def mimeData(self, indexes):
51  # Create MimeData for drag operation
52  data = QMimeData()
53 
54  # Get list of all selected file ids
55  files = []
56  for item in indexes:
57  selected_row = self.itemFromIndex(item).row()
58  files.append(self.item(selected_row, 4).text())
59  data.setText(json.dumps(files))
60  data.setHtml("effect")
61 
62  # Return Mimedata
63  return data
64 
65 
66 class EffectsModel():
67  def update_model(self, clear=True):
68  log.info("updating effects model.")
69  app = get_app()
70 
71  # Get window to check filters
72  win = app.window
73  _ = app._tr
74 
75  # Clear all items
76  if clear:
77  self.model_names = {}
78  self.model.clear()
79 
80  # Add Headers
81  self.model.setHorizontalHeaderLabels([_("Thumb"), _("Name"), _("Description")])
82 
83  # Get the folder path of effects
84  effects_dir = os.path.join(info.PATH, "effects")
85  icons_dir = os.path.join(effects_dir, "icons")
86 
87  # Get a JSON list of all supported effects in libopenshot
88  raw_effects_list = json.loads(openshot.EffectInfo.Json())
89 
90  # Loop through each effect
91  for effect_info in raw_effects_list:
92  # Get basic properties about each effect
93  effect_name = effect_info["class_name"]
94  title = effect_info["name"]
95  description = effect_info["description"]
96  icon_name = "%s.png" % effect_name.lower()
97  icon_path = os.path.join(icons_dir, icon_name)
98 
99  # Determine the category of effect (audio, video, both)
100  category = None
101  if effect_info["has_video"] and effect_info["has_audio"]:
102  category = "Audio & Video"
103  elif not effect_info["has_video"] and effect_info["has_audio"]:
104  category = "Audio"
105  icon_path = os.path.join(icons_dir, "audio.png")
106  elif effect_info["has_video"] and not effect_info["has_audio"]:
107  category = "Video"
108 
109  log.info("category: %s" % category)
110 
111  # Filter out effect (if needed)
112  if not win.actionEffectsShowAll.isChecked():
113  if win.actionEffectsShowVideo.isChecked():
114  if not category == "Video":
115  continue # to next file, didn't match filter
116  elif win.actionEffectsShowAudio.isChecked():
117  if not category == "Audio":
118  continue # to next file, didn't match filter
119 
120  if win.effectsFilter.text() != "":
121  if not win.effectsFilter.text().lower() in self.app._tr(title).lower() and not win.effectsFilter.text().lower() in self.app._tr(description).lower():
122  continue
123 
124  # Check for thumbnail path (in build-in cache)
125  thumb_path = os.path.join(info.IMAGES_PATH, "cache", icon_name)
126 
127  # Check built-in cache (if not found)
128  if not os.path.exists(thumb_path):
129  # Check user folder cache
130  thumb_path = os.path.join(info.CACHE_PATH, icon_name)
131 
132  # Generate thumbnail (if needed)
133  if not os.path.exists(thumb_path):
134 
135  try:
136  # Reload this reader
137  clip = openshot.Clip(icon_path)
138  reader = clip.Reader()
139 
140  # Open reader
141  reader.Open()
142 
143  # Save thumbnail
144  reader.GetFrame(0).Thumbnail(thumb_path, 98, 64, os.path.join(info.IMAGES_PATH, "mask.png"), "",
145  "#000", True)
146  reader.Close()
147 
148  except:
149  # Handle exception
150  msg = QMessageBox()
151  msg.setText(_("{} is not a valid image file.".format(icon_path)))
152  msg.exec_()
153  continue
154 
155  row = []
156 
157  # Append thumbnail
158  col = QStandardItem()
159  col.setIcon(QIcon(thumb_path))
160  col.setText(self.app._tr(title))
161  col.setToolTip(self.app._tr(title))
162  col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsDragEnabled)
163  row.append(col)
164 
165  # Append Name
166  col = QStandardItem("Name")
167  col.setData(self.app._tr(title), Qt.DisplayRole)
168  col.setText(self.app._tr(title))
169  col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsDragEnabled)
170  row.append(col)
171 
172  # Append Description
173  col = QStandardItem("Description")
174  col.setData(self.app._tr(description), Qt.DisplayRole)
175  col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsDragEnabled)
176  row.append(col)
177 
178  # Append Category
179  col = QStandardItem("Category")
180  col.setData(category, Qt.DisplayRole)
181  col.setText(category)
182  col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsDragEnabled)
183  row.append(col)
184 
185  # Append Path
186  col = QStandardItem("Effect")
187  col.setData(effect_name, Qt.DisplayRole)
188  col.setText(effect_name)
189  col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsDragEnabled)
190  row.append(col)
191 
192  # Append ROW to MODEL (if does not already exist in model)
193  if not effect_name in self.model_names:
194  self.model.appendRow(row)
195  self.model_names[effect_name] = effect_name
196 
197  def __init__(self, *args):
198 
199  # Create standard model
200  self.app = get_app()
202  self.model.setColumnCount(5)
203  self.model_names = {}
def get_app
Returns the current QApplication instance of OpenShot.
Definition: app.py:55