forked from OpenShot/openshot-qt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfiles_treeview.py
229 lines (177 loc) · 7.75 KB
/
files_treeview.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
"""
@file
@brief This file contains the project file treeview, used by the main window
@author Noah Figg <[email protected]>
@author Jonathan Thomas <[email protected]>
@author Olivier Girard <[email protected]>
@section LICENSE
Copyright (c) 2008-2018 OpenShot Studios, LLC
(http://www.openshotstudios.com). This file is part of
OpenShot Video Editor (http://www.openshot.org), an open-source project
dedicated to delivering high quality video editing and animation solutions
to the world.
OpenShot Video Editor is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenShot Video Editor is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
"""
import os
from PyQt5.QtCore import QSize, Qt, QPoint
from PyQt5.QtGui import QDrag, QCursor
from PyQt5.QtWidgets import QTreeView, QAbstractItemView, QMenu, QSizePolicy, QHeaderView
from classes.app import get_app
from classes.logger import log
from classes.query import File
class FilesTreeView(QTreeView):
""" A TreeView QWidget used on the main window """
drag_item_size = 48
def contextMenuEvent(self, event):
# Set context menu mode
app = get_app()
app.context_menu_object = "files"
event.accept()
index = self.indexAt(event.pos())
# Build menu
menu = QMenu(self)
menu.addAction(self.win.actionImportFiles)
menu.addAction(self.win.actionThumbnailView)
if index.isValid():
# Look up the model item and our unique ID
model = index.model()
# Look up file_id from 5th column of row
id_index = index.sibling(index.row(), 5)
file_id = model.data(id_index, Qt.DisplayRole)
# If a valid file selected, show file related options
menu.addSeparator()
# Add edit title option (if svg file)
file = File.get(id=file_id)
if file and file.data.get("path").endswith(".svg"):
menu.addAction(self.win.actionEditTitle)
menu.addAction(self.win.actionDuplicateTitle)
menu.addSeparator()
menu.addAction(self.win.actionPreview_File)
menu.addAction(self.win.actionSplitClip)
menu.addAction(self.win.actionAdd_to_Timeline)
menu.addAction(self.win.actionFile_Properties)
menu.addSeparator()
menu.addAction(self.win.actionRemove_from_Project)
menu.addSeparator()
# Show menu
menu.popup(event.globalPos())
def dragEnterEvent(self, event):
# If dragging urls onto widget, accept
if event.mimeData().hasUrls():
event.setDropAction(Qt.CopyAction)
event.accept()
def startDrag(self, supportedActions):
""" Override startDrag method to display custom icon """
# Get first column indexes for all selected rows
selected = self.selectionModel().selectedRows(0)
# Get image of current item
current = self.selectionModel().currentIndex()
if not current.isValid() and selected:
current = selected[0]
if not current.isValid():
log.warning("No draggable items found in model!")
return False
# Get icon from column 0 on same row as current item
icon = current.sibling(current.row(), 0).data(Qt.DecorationRole)
# Start drag operation
drag = QDrag(self)
drag.setMimeData(self.model().mimeData(selected))
drag.setPixmap(icon.pixmap(QSize(self.drag_item_size, self.drag_item_size)))
drag.setHotSpot(QPoint(self.drag_item_size / 2, self.drag_item_size / 2))
drag.exec_()
# Without defining this method, the 'copy' action doesn't show with cursor
def dragMoveEvent(self, event):
event.accept()
# Handle a drag and drop being dropped on widget
def dropEvent(self, event):
if not event.mimeData().hasUrls():
# Nothing we're interested in
event.ignore()
return
event.accept()
# Use try/finally so we always reset the cursor
try:
# Set cursor to waiting
get_app().setOverrideCursor(QCursor(Qt.WaitCursor))
qurl_list = event.mimeData().urls()
log.info("Processing drop event for {} urls".format(len(qurl_list)))
self.files_model.process_urls(qurl_list)
finally:
# Restore cursor
get_app().restoreOverrideCursor()
# Forward file-add requests to the model, for legacy code (previous API)
def add_file(self, filepath):
self.files_model.add_files(filepath)
def filter_changed(self):
self.refresh_view()
def refresh_view(self):
"""Resize and hide certain columns"""
self.hideColumn(3)
self.hideColumn(4)
self.hideColumn(5)
self.resize_contents()
def resize_contents(self):
# Get size of widget
thumbnail_width = 78
tags_width = 75
# Resize thumbnail and tags column
self.header().resizeSection(0, thumbnail_width)
self.header().resizeSection(2, tags_width)
# Set stretch mode on certain columns
self.header().setStretchLastSection(False)
self.header().setSectionResizeMode(1, QHeaderView.Stretch)
self.header().setSectionResizeMode(2, QHeaderView.Interactive)
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)
def __init__(self, model, *args):
# Invoke parent init
super().__init__(*args)
# Get a reference to the window object
self.win = get_app().window
# Get Model data
self.files_model = model
self.setModel(self.files_model.proxy_model)
# Remove the default selection model and wire up to the shared one
self.selectionModel().deleteLater()
self.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.setSelectionBehavior(QAbstractItemView.SelectRows)
self.setSelectionModel(self.files_model.selection_model)
self.setAcceptDrops(True)
self.setDragEnabled(True)
self.setDropIndicatorShown(True)
# Setup header columns and layout
self.setIconSize(QSize(75, 62))
self.setIndentation(0)
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.setStyleSheet('QTreeView::item { padding-top: 2px; }')
self.setWordWrap(False)
self.setTextElideMode(Qt.ElideRight)
self.files_model.ModelRefreshed.connect(self.refresh_view)
# setup filter events
# self.files_model.model.itemChanged.connect(self.value_updated)