Skip to content
This repository was archived by the owner on Oct 10, 2024. It is now read-only.

Commit ff6d4c8

Browse files
authored
Merge pull request #100 from pypeclub/feature/PYPE-603_show_date_workfile
[PYPE-603] #close show date workfile
2 parents d38371f + 7f02bc9 commit ff6d4c8

File tree

3 files changed

+178
-27
lines changed

3 files changed

+178
-27
lines changed

avalon/tools/models.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,17 @@ class TreeModel(QtCore.QAbstractItemModel):
1414

1515
Columns = list()
1616
ItemRole = QtCore.Qt.UserRole + 1
17+
item_class = None
1718

1819
def __init__(self, parent=None):
1920
super(TreeModel, self).__init__(parent)
20-
self._root_item = Item()
21+
self._root_item = self.ItemClass()
22+
23+
@property
24+
def ItemClass(self):
25+
if self.item_class is not None:
26+
return self.item_class
27+
return Item
2128

2229
def rowCount(self, parent):
2330
if parent.isValid():
@@ -129,7 +136,7 @@ def column_name(self, column):
129136

130137
def clear(self):
131138
self.beginResetModel()
132-
self._root_item = Item()
139+
self._root_item = self.ItemClass()
133140
self.endResetModel()
134141

135142

avalon/tools/workfiles/app.py

Lines changed: 71 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
import getpass
44
import re
55
import shutil
6+
from datetime import datetime
67

78
from ...vendor.Qt import QtWidgets, QtCore
89
from ... import style, io, api
910

11+
from .model import WorkFileModel
12+
1013
from .. import lib as tools_lib
1114

1215
module = sys.modules[__name__]
@@ -260,8 +263,19 @@ def __init__(self, root=None, parent=None):
260263
separator.setFrameShadow(QtWidgets.QFrame.Plain)
261264
self.layout.addWidget(separator)
262265

263-
self.list = QtWidgets.QListWidget()
264-
self.layout.addWidget(self.list)
266+
# View
267+
view = QtWidgets.QTreeView()
268+
view.setTextElideMode(QtCore.Qt.ElideLeft)
269+
view.setSortingEnabled(True)
270+
view.setRootIsDecorated(False)
271+
view.setAlternatingRowColors(True)
272+
273+
model = WorkFileModel(view)
274+
view.setModel(model)
275+
276+
self.layout.addWidget(view)
277+
self.view = view
278+
self.model = model
265279

266280
buttons_layout = QtWidgets.QHBoxLayout()
267281
self.duplicate_button = QtWidgets.QPushButton("Duplicate")
@@ -292,7 +306,7 @@ def __init__(self, root=None, parent=None):
292306

293307
self.duplicate_button.pressed.connect(self.on_duplicate_pressed)
294308
self.open_button.pressed.connect(self.on_open_pressed)
295-
self.list.doubleClicked.connect(self.on_open_pressed)
309+
self.view.doubleClicked.connect(self.on_open_pressed)
296310
self.browse_button.pressed.connect(self.on_browse_pressed)
297311
self.save_as_button.pressed.connect(self.on_save_as_pressed)
298312

@@ -302,7 +316,7 @@ def __init__(self, root=None, parent=None):
302316
self.open_button.setFocus()
303317

304318
self.refresh()
305-
self.resize(400, 550)
319+
self.resize(550, 550)
306320

307321
def get_name(self):
308322

@@ -313,9 +327,11 @@ def get_name(self):
313327
return self._name_window.get_result()
314328

315329
def refresh(self):
316-
self.list.clear()
330+
self.model.clear()
317331

318-
modified = []
332+
last_modified = None
333+
last_modified_idx = None
334+
parent_idx = QtCore.QModelIndex()
319335
extensions = set(self.host.file_extensions())
320336
for f in reversed(os.listdir(self.root)):
321337
path = os.path.join(self.root, f)
@@ -325,23 +341,42 @@ def refresh(self):
325341
if extensions and os.path.splitext(f)[1] not in extensions:
326342
continue
327343

328-
self.list.addItem(f)
329-
modified.append(os.path.getmtime(path))
344+
_modified = os.path.getmtime(path)
345+
if not last_modified or last_modified < _modified:
346+
last_modified = _modified
347+
last_modified_idx = self.model.rowCount(parent_idx)
330348

331-
# Select last modified file
332-
if self.list.count():
333-
item = self.list.item(modified.index(max(modified)))
334-
item.setSelected(True)
349+
modified = (
350+
datetime.fromtimestamp(_modified)
351+
.strftime("%Y/%m/%d %H:%M:%S")
352+
)
353+
self.model.add_file(f, modified)
335354

355+
self.view.header().resizeSection(
356+
0, self.view.sizeHintForColumn(0) + 40
357+
)
358+
self.view.sortByColumn(0, QtCore.Qt.DescendingOrder)
359+
360+
# Select last modified file
361+
if self.model.rowCount(parent_idx):
362+
index = self.model.index(last_modified_idx, 0, parent_idx)
363+
self.view.selectionModel().select(
364+
index,
365+
(
366+
QtCore.QItemSelectionModel.SelectCurrent |
367+
QtCore.QItemSelectionModel.Rows
368+
)
369+
)
336370
# Scroll list so item is visible
337-
QtCore.QTimer.singleShot(100, lambda: self.list.scrollToItem(item))
371+
self.view.scrollTo(
372+
index,
373+
QtWidgets.QAbstractItemView.EnsureVisible
374+
)
338375

339376
self.duplicate_button.setEnabled(True)
340377
else:
341378
self.duplicate_button.setEnabled(False)
342379

343-
self.list.setMinimumWidth(self.list.sizeHintForColumn(0) + 30)
344-
345380
def save_changes_prompt(self):
346381
self._messagebox = QtWidgets.QMessageBox()
347382
self._messagebox.setWindowFlags(QtCore.Qt.FramelessWindowHint)
@@ -389,24 +424,35 @@ def on_duplicate_pressed(self):
389424
if not work_file:
390425
return
391426

392-
src = os.path.join(
393-
self.root, self.list.selectedItems()[0].text()
394-
)
395-
dst = os.path.join(
396-
self.root, work_file
397-
)
398-
shutil.copy(src, dst)
427+
selection = self.view.selectionModel()
428+
rows = selection.selectedRows(column=0)
429+
for row_index in rows:
430+
filename = row_index.data(self.model.FilenameRole)
431+
432+
src = os.path.join(
433+
self.root, filename
434+
)
435+
dst = os.path.join(
436+
self.root, work_file
437+
)
438+
shutil.copy(src, dst)
399439

400440
self.refresh()
401441

402442
def on_open_pressed(self):
443+
selection = self.view.selectionModel()
444+
rows = selection.selectedRows(column=0)
403445

404-
selection = self.list.selectedItems()
405-
if not selection:
446+
if len(rows) == 0:
406447
print("No file selected to open..")
407448
return
408449

409-
work_file = os.path.join(self.root, selection[0].text())
450+
elif len(rows) > 1:
451+
print("More than one file selected to open..")
452+
return
453+
454+
filename = rows[0].data(self.model.FilenameRole)
455+
work_file = os.path.join(self.root, filename)
410456

411457
result = self.open(work_file)
412458
if result:

avalon/tools/workfiles/model.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
from ...vendor.Qt import QtCore
2+
3+
from ..models import TreeModel, Item
4+
5+
6+
class WorkFileItem(Item):
7+
def sort(self, key, order):
8+
children = sorted(self.children(), key=lambda item: item[key])
9+
if order == QtCore.Qt.DescendingOrder:
10+
children = reversed(children)
11+
12+
self._children = list(children)
13+
for child in self._children:
14+
child.sort(key, order)
15+
16+
17+
class WorkFileModel(TreeModel):
18+
"""A model listing the tasks combined for a list of assets"""
19+
20+
Columns = ["Filename", "Modified"]
21+
FilenameRole = QtCore.Qt.UserRole + 2
22+
ModifiedRole = QtCore.Qt.UserRole + 3
23+
item_class = WorkFileItem
24+
25+
def parent(self, index):
26+
item = index.internalPointer()
27+
if isinstance(item, int):
28+
index = self.createIndex(item, 0, self._root_item)
29+
return super(WorkFileModel, self).parent(index)
30+
31+
def sort(self, column, order):
32+
# Use super of QAbstractItemModel because in PySide `parent` method
33+
# does not return parent QObject but tries to find Item parent
34+
parent = super(QtCore.QAbstractItemModel, self).parent()
35+
selection = []
36+
if parent and hasattr(parent, "selectionModel"):
37+
selection_model = parent.selectionModel()
38+
for row in selection_model.selectedRows():
39+
selection.append(row.data(self.ItemRole))
40+
41+
self.beginResetModel()
42+
43+
key = self.Columns[column]
44+
self._root_item.sort(key, order)
45+
46+
self.endResetModel()
47+
48+
if not parent or not selection:
49+
return
50+
51+
item_selection = QtCore.QItemSelection()
52+
for idx, item in enumerate(self._root_item.children()):
53+
if item not in selection:
54+
continue
55+
56+
index = self.createIndex(idx, 0, idx)
57+
item_selection.append(QtCore.QItemSelectionRange(index))
58+
59+
selection_model.select(
60+
item_selection,
61+
(
62+
QtCore.QItemSelectionModel.SelectCurrent |
63+
QtCore.QItemSelectionModel.Rows
64+
)
65+
)
66+
67+
def add_file(self, filename, modified=None):
68+
self.beginResetModel()
69+
70+
if not modified:
71+
modified = "< unknown >"
72+
73+
item = self.ItemClass({
74+
"Filename": filename,
75+
"Modified": modified
76+
})
77+
self.add_child(item)
78+
79+
self.endResetModel()
80+
81+
def data(self, index, role):
82+
if role in [QtCore.Qt.DisplayRole, QtCore.Qt.EditRole]:
83+
if index.column() == 0:
84+
role = self.FilenameRole
85+
elif index.column() == 1:
86+
role = self.ModifiedRole
87+
88+
item = super(WorkFileModel, self).data(index, self.ItemRole)
89+
if role == self.ItemRole:
90+
return item
91+
92+
elif role == self.FilenameRole:
93+
return item["Filename"]
94+
95+
elif role == self.ModifiedRole:
96+
return item["Modified"]
97+
98+
return super(WorkFileModel, self).data(index, role)

0 commit comments

Comments
 (0)