Skip to content

Commit 6d5a716

Browse files
committed
App: Activating shortcuts works
[skip ci]
1 parent e4a9255 commit 6d5a716

1 file changed

Lines changed: 66 additions & 21 deletions

File tree

‎scripts/gdrive_app.py‎

Lines changed: 66 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import os
33
import subprocess
44
from typing import List, Dict, Any, Optional
5+
from dataclasses import dataclass
56

67
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
78
QHBoxLayout, QListWidget, QListWidgetItem,
@@ -134,6 +135,10 @@ def get_mime_icon(mime_type: str) -> QIcon:
134135
color = QApplication.palette().windowText().color().name()
135136
if mime_type == 'application/vnd.google-apps.folder':
136137
return get_icon(FilledIcon.FOLDER, is_filled=True, color=color)
138+
elif mime_type == 'application/vnd.google-apps.shortcut+file':
139+
return get_icon(OutlineIcon.FILE_SYMLINK, color="#999999")
140+
elif mime_type == 'application/vnd.google-apps.shortcut+folder':
141+
return get_icon(OutlineIcon.FOLDER_SYMLINK, color="#999999")
137142
elif mime_type == 'application/vnd.google-apps.document':
138143
return get_icon(OutlineIcon.FILE_TEXT, color="#4285F4")
139144
elif mime_type == 'application/vnd.google-apps.spreadsheet':
@@ -155,20 +160,26 @@ def get_mime_icon(mime_type: str) -> QIcon:
155160
else:
156161
return get_icon(OutlineIcon.FILE, color=color)
157162

163+
@dataclass
164+
class HistoryEntry:
165+
id: str
166+
name: str
167+
clicked_item_id: Optional[str] = None
168+
158169
class GDriveApp(QMainWindow):
159170
def __init__(self):
160171
super().__init__()
161172
self.setWindowTitle("Google Drive Explorer")
162173
self.resize(1000, 600)
163174

164-
self.history = []
175+
self.history: List[HistoryEntry] = []
165176
self.history_index = -1
166177
self.current_folder_id = None
167178

168179
self.threadpool = QThreadPool.globalInstance()
169180
self.threadpool.setMaxThreadCount(12)
170181
self.thumbnail_cache = LRUCache(500)
171-
self.item_mapping = {}
182+
self.item_mapping: Dict[QListWidgetItem] = {}
172183

173184
self.init_ui()
174185
self.load_root("my_drive")
@@ -239,7 +250,7 @@ def init_ui(self):
239250
self.update_nav_buttons()
240251
self.file_view.setFocus()
241252

242-
def load_root(self, root_type: str, add_history=True):
253+
def load_root(self, root_type: str, add_history=True, highlight_fileid: str | None = None, clicked_item_id: str | None = None):
243254
if root_type == "my_drive":
244255
items = gcache.get_root_my_drive_children()
245256
self.address_bar.setText("My Drive")
@@ -249,41 +260,56 @@ def load_root(self, root_type: str, add_history=True):
249260

250261
self.current_folder_id = root_type
251262
if add_history:
252-
self.add_to_history(root_type)
263+
self.add_to_history(root_type, clicked_item_id)
253264
self.populate_files(items)
265+
if highlight_fileid and highlight_fileid in self.item_mapping:
266+
item = self.item_mapping[highlight_fileid]
267+
item.setSelected(True)
268+
self.file_view.setCurrentItem(item)
269+
self.file_view.repaint()
254270

255-
def load_folder(self, folder_id: str, folder_name: str, add_history=True):
271+
def load_folder(self, folder_id: str, folder_name: str, add_history=True, highlight_fileid: str | None=None, clicked_item_id: str | None = None):
256272
items = gcache.get_children(folder_id)
257273
self.current_folder_id = folder_id
258274
self.address_bar.setText(folder_name)
259275
if add_history:
260-
self.add_to_history(folder_id)
276+
self.add_to_history(folder_id, clicked_item_id)
261277
self.populate_files(items)
278+
if highlight_fileid and highlight_fileid in self.item_mapping:
279+
item = self.item_mapping[highlight_fileid]
280+
item.setSelected(True)
281+
self.file_view.setCurrentItem(item)
282+
self.file_view.repaint() # Don't let QT wait for the async thumbnails
262283

263-
def add_to_history(self, folder_id: str):
284+
def add_to_history(self, folder_id: str, clicked_item_id: str | None = None):
264285
# Trim future history if we navigated back then clicked a new folder
265286
self.history = self.history[:self.history_index + 1]
266-
self.history.append((folder_id, self.address_bar.text()))
287+
self.history.append(HistoryEntry(
288+
id=folder_id,
289+
name=self.address_bar.text(),
290+
clicked_item_id=clicked_item_id
291+
))
267292
self.history_index += 1
268293
self.update_nav_buttons()
269294

270295
def go_back(self):
271296
if self.history_index > 0:
297+
current_entry = self.history[self.history_index]
272298
self.history_index -= 1
273-
folder_id, name = self.history[self.history_index]
274-
self._load_from_history(folder_id, name)
299+
prev_entry = self.history[self.history_index]
300+
self._load_from_history(prev_entry.id, prev_entry.name, highlight_fileid=current_entry.clicked_item_id)
275301

276302
def go_forward(self):
277303
if self.history_index < len(self.history) - 1:
278304
self.history_index += 1
279-
folder_id, name = self.history[self.history_index]
280-
self._load_from_history(folder_id, name)
305+
entry = self.history[self.history_index]
306+
self._load_from_history(entry.id, entry.name)
281307

282-
def _load_from_history(self, folder_id: str, name: str):
308+
def _load_from_history(self, folder_id: str, name: str, highlight_fileid: str | None = None):
283309
if folder_id in ["my_drive", "shared_with_me"]:
284-
self.load_root(folder_id, add_history=False)
310+
self.load_root(folder_id, add_history=False, highlight_fileid=highlight_fileid)
285311
else:
286-
self.load_folder(folder_id, name, add_history=False)
312+
self.load_folder(folder_id, name, add_history=False, highlight_fileid=highlight_fileid)
287313
self.update_nav_buttons()
288314

289315
def update_nav_buttons(self):
@@ -298,23 +324,33 @@ def populate_files(self, items: List[Dict[str, Any]]):
298324
self.file_view.clear()
299325
self.item_mapping.clear()
300326

301-
# Sort folders first, then files, both alphabetically
327+
# Show folders, then folder shortcuts, then files
302328
folders = []
329+
folder_shortcuts = []
303330
files = []
304331
items_needing_thumbnails = []
305332
for item in items:
306333
mime = item.get('mimeType', '')
307334
if mime == 'application/vnd.google-apps.folder':
308335
folders.append(item)
336+
elif mime == 'application/vnd.google-apps.shortcut' and item['shortcutDetails']['targetMimeType'] == 'application/vnd.google-apps.folder':
337+
folder_shortcuts.append(item)
309338
else:
310339
files.append(item)
311-
312-
folders.sort(key=lambda x: x.get('name', '').lower())
313-
files.sort(key=lambda x: x.get('name', '').lower())
340+
341+
sortkey = lambda x: x.get('name', '').lower()
342+
folders.sort(key=sortkey)
343+
folder_shortcuts.sort(key=sortkey)
344+
files.sort(key=sortkey)
314345

315-
for item in folders + files:
346+
for item in folders + folder_shortcuts + files:
316347
name = item.get('name', 'Unknown')
317348
mime = item.get('mimeType', '')
349+
if item.get('shortcutDetails'):
350+
if item['shortcutDetails']['targetMimeType'] == 'application/vnd.google-apps.folder':
351+
mime += '+folder'
352+
else:
353+
mime += "+file"
318354
file_id = item.get('id', '')
319355

320356
list_item = QListWidgetItem(name)
@@ -348,7 +384,16 @@ def on_item_activated(self, item: QListWidgetItem):
348384
mime = file_data.get('mimeType', '')
349385

350386
if mime == 'application/vnd.google-apps.folder':
351-
self.load_folder(file_data['id'], file_data['name'])
387+
self.load_folder(file_data['id'], file_data['name'], clicked_item_id=file_data['id'])
388+
elif mime == 'application/vnd.google-apps.shortcut':
389+
if file_data['shortcutDetails']['targetMimeType'] == 'application/vnd.google-apps.folder':
390+
target_folder = gcache.get_item(file_data['shortcutDetails']['targetId'])
391+
target_file = None
392+
else:
393+
target_file = gcache.get_item(file_data['shortcutDetails']['targetId'])
394+
target_folder = gcache.get_item(target_file['parent_id'])
395+
target_file = target_file['id']
396+
self.load_folder(target_folder['id'], target_folder['name'], highlight_fileid=target_file, clicked_item_id=file_data['id'])
352397
else:
353398
self.open_file(file_data)
354399

0 commit comments

Comments
 (0)