OpenShot Video Editor  2.0.0
query.py
Go to the documentation of this file.
1 ##
2 #
3 # @file
4 # @brief This file can easily query Clips, Files, and other project data
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 import copy
31 
32 from classes import info
33 from classes.app import get_app
34 
35 
36 
37 # Get project data reference
38 app = get_app()
39 project = app.project
40 
41 
42 ##
43 # This class allows one or more project data objects to be queried
45 
46  ##
47  # Constructor
48  def __init__(self):
49 
50  self.id = None # Unique ID of object
51  self.key = None # Key path to object in project data
52  self.data = None # Data dictionary of object
53  self.parent = None # Only used with effects (who belong to clips)
54  self.type = "insert" # Type of operation needed to save
55 
56  ##
57  # Save the object back to the project data store
58  def save(self, OBJECT_TYPE):
59 
60  # Insert or Update this data into the project data store
61  if not self.id and self.type == "insert":
62 
63  # Insert record, and Generate id
64  self.id = project.generate_id()
65 
66  # save id in data (if attribute found)
67  self.data["id"] = copy.deepcopy(self.id)
68 
69  # Set key (if needed)
70  if not self.key:
71  self.key = copy.deepcopy(OBJECT_TYPE.object_key)
72  self.key.append({"id": self.id})
73 
74  # Insert into project data
75  app.updates.insert(copy.deepcopy(OBJECT_TYPE.object_key), copy.deepcopy(self.data))
76 
77  # Mark record as 'update' now... so another call to this method won't insert it again
78  self.type = "update"
79 
80  elif self.id and self.type == "update":
81 
82  # Update existing project data
83  app.updates.update(self.key, self.data)
84 
85  ##
86  # Delete the object from the project data store
87  def delete(self, OBJECT_TYPE):
88 
89  # Delete if object found and not pending insert
90  if self.id and self.type == "update":
91  # Delete from project data store
92  app.updates.delete(self.key)
93  self.type = "delete"
94 
95  ##
96  # Get the translated display title of this item
97  def title(self):
98  # Needs to be overwritten in each derived class
99  return None
100 
101  ##
102  # Take any arguments given as filters, and find a list of matching objects
103  def filter(OBJECT_TYPE, **kwargs):
104 
105  # Get a list of all objects of this type
106  parent = project.get(OBJECT_TYPE.object_key)
107  matching_objects = []
108 
109  # Loop through all children objects
110  if parent:
111  for child in parent:
112 
113  # Loop through all kwargs (and look for matches)
114  match = True
115  for key, value in kwargs.items():
116  # Equals
117  if key in child and not child[key] == value:
118  match = False
119  break
120  # Intersection Position
121  elif key == "intersect":
122  if child.get("position", 0) > value or \
123  child.get("position", 0) + (child.get("end", 0) - child.get("start", 0)) < value:
124  match = False
125 
126  # Add matched record
127  if match:
128  object = OBJECT_TYPE()
129  object.id = child["id"]
130  object.key = [OBJECT_TYPE.object_name, {"id": object.id}]
131  object.data = copy.deepcopy(child) # copy of object
132  object.type = "update"
133  matching_objects.append(object)
134 
135  # Return matching objects
136  return matching_objects
137 
138  ##
139  # Take any arguments given as filters, and find the first matching object
140  def get(OBJECT_TYPE, **kwargs):
141 
142  # Look for matching objects
143  matching_objects = QueryObject.filter(OBJECT_TYPE, **kwargs)
144 
145  if matching_objects:
146  return matching_objects[0]
147  else:
148  return None
149 
150 
151 ##
152 # This class allows Clips to be queried, updated, and deleted from the project data.
154  object_name = "clips" # Derived classes should define this
155  object_key = [object_name] # Derived classes should define this also
156 
157  ##
158  # Save the object back to the project data store
159  def save(self):
160  super().save(Clip)
161 
162  ##
163  # Delete the object from the project data store
164  def delete(self):
165  super().delete(Clip)
166 
167  ##
168  # Take any arguments given as filters, and find a list of matching objects
169  def filter(**kwargs):
170  return QueryObject.filter(Clip, **kwargs)
171 
172  ##
173  # Take any arguments given as filters, and find the first matching object
174  def get(**kwargs):
175  return QueryObject.get(Clip, **kwargs)
176 
177  ##
178  # Get the translated display title of this item
179  def title(self):
180  path = self.data.get("reader", {}).get("path")
181  folder_path, filename = os.path.split(path)
182  return filename
183 
184 ##
185 # This class allows Transitions (i.e. timeline effects) to be queried, updated, and deleted from the project data.
187  object_name = "effects" # Derived classes should define this
188  object_key = [object_name] # Derived classes should define this also
189 
190  ##
191  # Save the object back to the project data store
192  def save(self):
193  super().save(Transition)
194 
195  ##
196  # Delete the object from the project data store
197  def delete(self):
198  super().delete(Transition)
199 
200  ##
201  # Take any arguments given as filters, and find a list of matching objects
202  def filter(**kwargs):
203  return QueryObject.filter(Transition, **kwargs)
204 
205  ##
206  # Take any arguments given as filters, and find the first matching object
207  def get(**kwargs):
208  return QueryObject.get(Transition, **kwargs)
209 
210  ##
211  # Get the translated display title of this item
212  def title(self):
213  path = self.data.get("reader", {}).get("path")
214  folder_path, filename = os.path.split(path)
215  fileBaseName, fileExtension = os.path.splitext(filename)
216 
217  # split the name into parts (looking for a number)
218  suffix_number = None
219  name_parts = fileBaseName.split("_")
220  if name_parts[-1].isdigit():
221  suffix_number = name_parts[-1]
222  # get name of transition
223  item_name = fileBaseName.replace("_", " ").capitalize()
224 
225  # replace suffix number with placeholder (if any)
226  if suffix_number:
227  item_name = item_name.replace(suffix_number, "%s")
228  item_name = get_app()._tr(item_name) % suffix_number
229  else:
230  item_name = get_app()._tr(item_name)
231  return item_name
232 
233 
234 ##
235 # This class allows Files to be queried, updated, and deleted from the project data.
237  object_name = "files" # Derived classes should define this
238  object_key = [object_name] # Derived classes should define this also
239 
240  ##
241  # Save the object back to the project data store
242  def save(self):
243  super().save(File)
244 
245  ##
246  # Delete the object from the project data store
247  def delete(self):
248  super().delete(File)
249 
250  ##
251  # Take any arguments given as filters, and find a list of matching objects
252  def filter(**kwargs):
253  return QueryObject.filter(File, **kwargs)
254 
255  ##
256  # Take any arguments given as filters, and find the first matching object
257  def get(**kwargs):
258  return QueryObject.get(File, **kwargs)
259 
260  ##
261  # Get absolute file path of file
262  def absolute_path(self):
263 
264  # Get project folder (if any)
265  project_folder = None
266  if project.current_filepath:
267  project_folder = os.path.dirname(project.current_filepath)
268 
269  # Convert relative file path into absolute (if needed)
270  file_path = self.data["path"]
271  if not os.path.isabs(file_path) and project_folder:
272  file_path = os.path.abspath(os.path.join(project_folder, self.data["path"]))
273 
274  # Return absolute path of file
275  return file_path
276 
277  ##
278  # Get relative path (based on the current working directory)
279  def relative_path(self):
280 
281  # Get absolute file path
282  file_path = self.absolute_path()
283 
284  # Convert path to relative (based on current working directory of Python)
285  file_path = os.path.relpath(file_path, info.CWD)
286 
287  # Return relative path
288  return file_path
289 
290 
291 ##
292 # This class allows Markers to be queried, updated, and deleted from the project data.
294  object_name = "markers" # Derived classes should define this
295  object_key = [object_name] # Derived classes should define this also
296 
297  ##
298  # Save the object back to the project data store
299  def save(self):
300  super().save(Marker)
301 
302  ##
303  # Delete the object from the project data store
304  def delete(self):
305  super().delete(Marker)
306 
307  ##
308  # Take any arguments given as filters, and find a list of matching objects
309  def filter(**kwargs):
310  return QueryObject.filter(Marker, **kwargs)
311 
312  ##
313  # Take any arguments given as filters, and find the first matching object
314  def get(**kwargs):
315  return QueryObject.get(Marker, **kwargs)
316 
317 
318 ##
319 # This class allows Tracks to be queried, updated, and deleted from the project data.
321  object_name = "layers" # Derived classes should define this
322  object_key = [object_name] # Derived classes should define this also
323 
324  ##
325  # Save the object back to the project data store
326  def save(self):
327  super().save(Track)
328 
329  ##
330  # Delete the object from the project data store
331  def delete(self):
332  super().delete(Track)
333 
334  ##
335  # Take any arguments given as filters, and find a list of matching objects
336  def filter(**kwargs):
337  return QueryObject.filter(Track, **kwargs)
338 
339  ##
340  # Take any arguments given as filters, and find the first matching object
341  def get(**kwargs):
342  return QueryObject.get(Track, **kwargs)
343 
344 
345 ##
346 # This class allows Effects to be queried, updated, and deleted from the project data.
348  object_name = "effects" # Derived classes should define this
349  object_key = [object_name] # Derived classes should define this also
350 
351  ##
352  # Save the object back to the project data store
353  def save(self):
354  super().save(Effect)
355 
356  ##
357  # Delete the object from the project data store
358  def delete(self):
359  super().delete(Effect)
360 
361  ##
362  # Take any arguments given as filters, and find a list of matching objects
363  def filter(**kwargs):
364 
365  # Get a list of clips
366  clips = project.get(["clips"])
367  matching_objects = []
368 
369  # Loop through all clips
370  if clips:
371  for clip in clips:
372  # Loop through all effects
373  if "effects" in clip:
374  for child in clip["effects"]:
375 
376  # Loop through all kwargs (and look for matches)
377  match = True
378  for key, value in kwargs.items():
379  if key in child and not child[key] == value:
380  match = False
381  break
382 
383  # Add matched record
384  if match:
385  object = Effect()
386  object.id = child["id"]
387  object.key = ["clips", {"id": clip["id"]}, "effects", {"id": object.id}]
388  object.data = child
389  object.type = "update"
390  object.parent = clip
391  matching_objects.append(object)
392 
393  # Return matching objects
394  return matching_objects
395 
396  ##
397  # Get the translated display title of this item
398  def title(self):
399  return self.data.get("name") or self.data.get("type")
400 
401  ##
402  # Take any arguments given as filters, and find the first matching object
403  def get(**kwargs):
404  # Look for matching objects
405  matching_objects = Effect.filter(**kwargs)
406 
407  if matching_objects:
408  return matching_objects[0]
409  else:
410  return None
def filter
Take any arguments given as filters, and find a list of matching objects.
Definition: query.py:252
def save
Save the object back to the project data store.
Definition: query.py:299
This class allows Tracks to be queried, updated, and deleted from the project data.
Definition: query.py:320
def filter
Take any arguments given as filters, and find a list of matching objects.
Definition: query.py:103
def get_app
Returns the current QApplication instance of OpenShot.
Definition: app.py:55
def delete
Delete the object from the project data store.
Definition: query.py:197
def absolute_path
Get absolute file path of file.
Definition: query.py:262
def save
Save the object back to the project data store.
Definition: query.py:242
def delete
Delete the object from the project data store.
Definition: query.py:247
def relative_path
Get relative path (based on the current working directory)
Definition: query.py:279
def save
Save the object back to the project data store.
Definition: query.py:353
def get
Take any arguments given as filters, and find the first matching object.
Definition: query.py:341
def save
Save the object back to the project data store.
Definition: query.py:159
def delete
Delete the object from the project data store.
Definition: query.py:331
def title
Get the translated display title of this item.
Definition: query.py:179
def get
Take any arguments given as filters, and find the first matching object.
Definition: query.py:140
def get
Take any arguments given as filters, and find the first matching object.
Definition: query.py:403
This class allows Effects to be queried, updated, and deleted from the project data.
Definition: query.py:347
def filter
Take any arguments given as filters, and find a list of matching objects.
Definition: query.py:202
def delete
Delete the object from the project data store.
Definition: query.py:164
def delete
Delete the object from the project data store.
Definition: query.py:87
def filter
Take any arguments given as filters, and find a list of matching objects.
Definition: query.py:169
def filter
Take any arguments given as filters, and find a list of matching objects.
Definition: query.py:336
def get
Take any arguments given as filters, and find the first matching object.
Definition: query.py:257
def title
Get the translated display title of this item.
Definition: query.py:212
This class allows Markers to be queried, updated, and deleted from the project data.
Definition: query.py:293
def save
Save the object back to the project data store.
Definition: query.py:326
def delete
Delete the object from the project data store.
Definition: query.py:304
This class allows Clips to be queried, updated, and deleted from the project data.
Definition: query.py:153
def save
Save the object back to the project data store.
Definition: query.py:58
This class allows Transitions (i.e.
Definition: query.py:186
def get
Take any arguments given as filters, and find the first matching object.
Definition: query.py:174
def filter
Take any arguments given as filters, and find a list of matching objects.
Definition: query.py:309
def title
Get the translated display title of this item.
Definition: query.py:398
This class allows Files to be queried, updated, and deleted from the project data.
Definition: query.py:236
def title
Get the translated display title of this item.
Definition: query.py:97
def get
Take any arguments given as filters, and find the first matching object.
Definition: query.py:314
def __init__
Constructor.
Definition: query.py:48
This class allows one or more project data objects to be queried.
Definition: query.py:44
def save
Save the object back to the project data store.
Definition: query.py:192
def filter
Take any arguments given as filters, and find a list of matching objects.
Definition: query.py:363
def get
Take any arguments given as filters, and find the first matching object.
Definition: query.py:207
def delete
Delete the object from the project data store.
Definition: query.py:358