-
Notifications
You must be signed in to change notification settings - Fork 0
/
driveslist.py
230 lines (185 loc) · 9.12 KB
/
driveslist.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
230
import shlex
from PyQt5.QtWidgets import QPushButton, QVBoxLayout, QWidget, QMessageBox, QHBoxLayout, QLabel, QScrollArea, QDialog, QGridLayout, QLineEdit, QCheckBox, QComboBox
import persistence
class DriveWidget(QWidget):
def __init__(self, drive, run_callback, edit_callback, delete_callback):
super().__init__()
layout = QHBoxLayout(self)
label_text = []
label_text.append(
f"Drive: {drive['drive_letter']} {'(Write cache enabled)' if drive['write_cache'] else ''}")
label_text.append(
f" Source: {drive['source_name']}:{drive['source_path']}")
if 'root_folder_id' in drive and drive['root_folder_id']:
label_text.append(f"Root Folder: {drive['root_folder_id']}")
self.drive_label = QLabel(" ".join(label_text))
# Add a stretch factor to the label
layout.addWidget(self.drive_label, 1)
run_button = QPushButton("Run")
run_button.clicked.connect(lambda: run_callback(drive))
layout.addWidget(run_button, 0) # No stretch factor for the button
edit_button = QPushButton("Edit")
edit_button.clicked.connect(lambda: edit_callback(drive))
layout.addWidget(edit_button, 0) # No stretch factor for the button
delete_button = QPushButton("Delete")
delete_button.clicked.connect(lambda: delete_callback(drive))
layout.addWidget(delete_button, 0) # No stretch factor for the button
class DriveListWidget(QWidget):
def __init__(self, parent=None, sources=None):
super().__init__(parent)
self.mainWindow = parent
self.sources = sources or []
self.drives = persistence.load_drives()
self.initUI()
def initUI(self):
layout = QVBoxLayout(self)
# Title and Add button
title_layout = QHBoxLayout()
title_label = QLabel("Mounted Drives")
title_layout.addWidget(title_label, 1)
add_drive_button = QPushButton("Add Drive")
add_drive_button.clicked.connect(self.add_drive)
title_layout.addWidget(add_drive_button, 0)
layout.addLayout(title_layout)
# Scroll area for the drives
self.scroll_area = QScrollArea(self)
self.scroll_area_widget_contents = QWidget()
self.scroll_area_layout = QVBoxLayout(self.scroll_area_widget_contents)
self.scroll_area.setWidgetResizable(True)
self.scroll_area.setWidget(self.scroll_area_widget_contents)
layout.addWidget(self.scroll_area)
self.populate_drives_list()
def populate_drives_list(self):
# Clear existing widgets
for i in reversed(range(self.scroll_area_layout.count())):
widget = self.scroll_area_layout.itemAt(i).widget()
if widget is not None:
widget.deleteLater()
# Add new drive widgets
for drive in self.drives:
drive_widget = DriveWidget(
drive,
self.run_drive,
self.edit_drive, self.delete_drive)
self.scroll_area_layout.addWidget(drive_widget)
# Add a stretch to ensure that drive widgets are aligned to the top
self.scroll_area_layout.addStretch()
def add_drive(self):
dialog = AddEditDriveDialog(self, sources=self.sources)
if dialog.exec_():
new_drive = {
'source_name': dialog.source_name_combobox.currentText(),
'source_path': dialog.source_path_input.text(),
'root_folder_id': dialog.root_folder_id_input.text(),
'write_cache': dialog.write_cache_checkbox.isChecked(),
'drive_letter': dialog.drive_letter_combobox.currentText(),
'custom_args': dialog.custom_args_input.text()
}
self.drives.append(new_drive)
persistence.save_drives(self.drives)
self.populate_drives_list()
def run_drive(self, drive):
if drive:
rclone = self.mainWindow.rclone_config_widget.settings['rclone_path']
args = [
'mount', f"{drive['source_name']}:{drive['source_path']}", drive['drive_letter']]
title = 'drive '+drive['drive_letter']
if drive['root_folder_id']:
args = args+["--drive-root-folder-id", drive['root_folder_id']]
if drive['write_cache']:
# off|minimal|writes|full
args = args + ["--vfs-cache-mode", "full"]
if drive['custom_args']:
args = args + shlex.split(drive['custom_args'], posix=False)
# seems bug python's winpty is skipps the 1st arg
cmd = [rclone, ''] + args
print(cmd)
self.mainWindow.terminal_tabs_widget.addTerminalTab(cmd, title)
def edit_drive(self, drive):
index = self.drives.index(drive)
dialog = AddEditDriveDialog(self, drive=drive, sources=self.sources)
if dialog.exec_():
updated_drive = {
'source_name': dialog.source_name_combobox.currentText(),
'source_path': dialog.source_path_input.text(),
'root_folder_id': dialog.root_folder_id_input.text(),
'write_cache': dialog.write_cache_checkbox.isChecked(),
'drive_letter': dialog.drive_letter_combobox.currentText(),
'custom_args': dialog.custom_args_input.text()
}
self.drives[index] = updated_drive
persistence.save_drives(self.drives)
self.populate_drives_list()
def delete_drive(self, drive):
if QMessageBox.question(self, 'Confirm Delete',
'Are you sure you want to delete this drive?',
QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == QMessageBox.Yes:
self.drives.remove(drive)
persistence.save_drives(self.drives)
self.populate_drives_list()
class AddEditDriveDialog(QDialog):
def __init__(self, parent=None, drive=None, sources=[]):
super().__init__(parent)
self.setGeometry(100, 100, 1400, 1000)
self.drive = drive or {}
self.sources = sources
self.initUI()
def initUI(self):
self.setWindowTitle("Edit Drive")
layout = QGridLayout(self)
row = 0
# Source Name (Editable ComboBox)
layout.addWidget(QLabel("Source Name:"), row, 0)
self.source_name_combobox = QComboBox(self)
self.source_name_combobox.setEditable(True)
self.source_name_combobox.addItems(self.sources)
layout.addWidget(self.source_name_combobox, row, 1)
# Source Path (Text Field)
layout.addWidget(QLabel("Source Path:"), row, 2)
self.source_path_input = QLineEdit(self)
layout.addWidget(self.source_path_input, row, 3)
row += 1
# Root Folder ID (Text Field)
layout.addWidget(QLabel("Root Folder ID:"), row, 0)
self.root_folder_id_input = QLineEdit(self)
layout.addWidget(self.root_folder_id_input, row, 1)
layout.addWidget(QLabel(
"levae empty, (for Computers folder for example) in google drive web, copy folder id from url"), row, 2, 1, 2)
row += 1
# Drive Letter (Editable ComboBox)
layout.addWidget(QLabel("Drive Letter:"), row, 0)
self.drive_letter_combobox = QComboBox(self)
self.drive_letter_combobox.setEditable(True)
self.drive_letter_combobox.addItems(
[chr(i)+":" for i in range(65, 91)]) # A-Z
layout.addWidget(self.drive_letter_combobox, row, 1)
layout.addWidget(QLabel("select not used drive letter"), row, 2, 1, 2)
row += 1
# Write Cache (Checkbox)
layout.addWidget(QLabel("Write Cache:"), row, 0)
self.write_cache_checkbox = QCheckBox(self)
layout.addWidget(self.write_cache_checkbox, row, 1)
row += 1
# Custom Arguments (Text Field)
layout.addWidget(QLabel("Custom Arguments:"), row, 0)
self.custom_args_input = QLineEdit(self)
layout.addWidget(self.custom_args_input, row, 1, 1, 4)
row += 1
# Save Button
save_button = QPushButton("Save", self)
save_button.clicked.connect(self.save)
layout.addWidget(save_button, row, 0, 1, 4) # Span two columns
# Populate fields if editing an existing drive
if self.drive:
self.source_name_combobox.setCurrentText(
self.drive.get('source_name', ''))
self.source_path_input.setText(self.drive.get('source_path', '/'))
self.root_folder_id_input.setText(
self.drive.get('root_folder_id', ''))
self.write_cache_checkbox.setChecked(
self.drive.get('write_cache', False))
self.drive_letter_combobox.setCurrentText(
self.drive.get('drive_letter', ''))
self.custom_args_input.setText(self.drive.get('custom_args', ''))
def save(self):
self.accept()