-
Notifications
You must be signed in to change notification settings - Fork 0
/
QueueDialog.py
222 lines (172 loc) · 8.87 KB
/
QueueDialog.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
#Import basic modules
import os
#Import basic modules
import os
import re
#Import the main window object (mw) from aqt
from aqt import mw
#Import the "show info" tool from utils.py
from aqt.utils import showInfo
#Import all of the Qt GUI library
from aqt.qt import *
#Import local .py modules
from . import Utils
echo = Utils.echo
from . import CustomQt
#Class to instantiate a QueueDialog object
class QueueDialog(QDialog):
def __init__(self, Comparer, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
self.Comparer = Comparer
self.queue = Comparer.queue
self.triggers = False
self.maxRows = 1000
#Create a layout
self.setWindowTitle("Action Queue")
self.layout = QVBoxLayout(self)
self.setLayout(self.layout)
#Add the intro explanation
self.intro = QLabel('''Below are all of the duplicates found in the groups. You can select an action to perform on each note from the dropdown menu.
If you want to change the action for all duplicates in a group at once, close this window, select the appropiate action from the dropdown menu
and reopen this window by pressing 'show duplicates'. If you hover over a duplicate note you will be able to see all of its fields.
Some notes are marked as duplicates multiple times and all of the set actions will therefore be performed upon it.''', self)
self.intro.setAlignment(Qt.AlignCenter)
self.layout.addWidget(self.intro)
#Add a table widget to display the queue
#and determine the available actions per group
self.queueTable = QTableWidget(self)
self.queueTable.setColumnCount(self.Comparer.groupNum * 3)
actions = []
headers = []
for i in range(self.Comparer.groupNum):
headers.extend([f'Group {i+1}: Note fields', 'Action', 'Tag/Replacement'])
actions.append(self.Comparer.groups[i].actions)
self.queueTable.setHorizontalHeaderLabels(headers)
self.layout.addWidget(self.queueTable)
#Add all of the duplicates found as rows
for rowIndex in range(len(self.queue)):
#Increase the number of rows in the table by 1
self.queueTable.setRowCount(rowIndex+1)
#Add the appropiate widgets for ever group to the row
for groupIndex in range(self.Comparer.groupNum):
self.addRow(rowIndex, groupIndex, actions)
#When the rowIndex exceeds the maximum number of rows,
#stop adding new rows and attach a message to the explanation
if rowIndex + 1 >= self.maxRows:
self.intro.setText(self.intro.text() +
f'\n\nSince there are more than {self.maxRows} duplicates, the queue has been broken up.\
\nAfter processing the current items the other items can be processed.')
break
#Add a button to start the actions
self.startButton = QPushButton('Perform actions', self)
self.layout.addWidget(self.startButton)
self.startButton.clicked.connect(self.askConfirmation)
#Resize the columns
for groupIndex in range(self.Comparer.groupNum):
self.queueTable.horizontalHeader().setSectionResizeMode(0 + groupIndex*3, QHeaderView.Stretch)
self.queueTable.horizontalHeader().setSectionResizeMode(1 + groupIndex*3, QHeaderView.Fixed)
self.queueTable.horizontalHeader().setSectionResizeMode(2 + groupIndex*3, QHeaderView.Fixed)
self.queueTable.horizontalHeader().resizeSection(1 + groupIndex*3, 105)
self.queueTable.horizontalHeader().resizeSection(2 + groupIndex*3, 105)
#Resize the rows
self.queueTable.resizeRowsToContents()
self.triggers = True
#Method to add an widget to an table cell
def addTableWidget(self, rowIndex, columnIndex, widget):
item = QTableWidgetItem()
item.widget = widget
self.queueTable.setItem(rowIndex, columnIndex, item)
self.queueTable.setCellWidget(rowIndex, columnIndex, widget)
#Method to add an row:
def addRow(self, rowIndex, groupIndex, actions):
#Retrieve the duplicate notes for the row to be added
note = self.queue[rowIndex][groupIndex]
#Add a description of the fields and their values to the first column per group
fields = QLabel('<br>'.join([f"<b>{f['name']}:</b> {f['value']}" for f in note['compareFields']]))
#fields = QPushButton('<br>'.join([f"<b>{f['name']}:</b> {f['value']}" for f in note['compareFields']]))
fields.setToolTip('<br>'.join([f"<b>{fName}:</b> {fValue}" for fName, fValue in note['fields'].items()]))
self.addTableWidget(rowIndex, groupIndex*3, fields)
#fields.clicked.connect(lambda: self.editNote(note['id']))
#Create a combobox for the action to be added to the table, add the row index to it,
#disable the wheel event
actionBox = QComboBox(self)
actionBox.rowIndex = rowIndex
actionBox.groupIndex = groupIndex
actionBox.addItems(actions[groupIndex])
actionBox.wheelEvent = lambda event: None
self.addTableWidget(rowIndex, 1 + groupIndex*3, actionBox)
#Create a textbox for the replace / tag action and add it to the table
textBox = QLineEdit(self)
textBox.rowIndex = rowIndex
textBox.groupIndex = groupIndex
self.addTableWidget(rowIndex, 2 + groupIndex*3, textBox)
#Link the correct lambda functions to the widgets
actionBox.currentIndexChanged.connect(lambda: self.selectAction(actionBox, textBox))
textBox.textChanged.connect(lambda: self.enterText(textBox, actionBox))
#Also select the correct action, which is either a set one or the default one
action = self.queue[rowIndex][groupIndex].get('action', self.Comparer.groups[groupIndex].duplicateAction)
actionBox.setCurrentText(action)
#Update the text box based on the selected action
self.updateTextBox(rowIndex, groupIndex, textBox, action)
#Method trigger when an action is selected and it should be updated in it
def selectAction(self, actionBox, textBox):
if self.triggers == False:
return
self.triggers = False
#Retrieve the row index, group index and selected action
rowIndex = actionBox.rowIndex
groupIndex = actionBox.groupIndex
action = actionBox.currentText()
#Update the action in the queue
self.newAction(rowIndex, groupIndex, action)
#Update the text field
self.updateTextBox(rowIndex, groupIndex, textBox, action)
self.triggers = True
#Method to update the action in the queue
def newAction(self, rowIndex, groupIndex, action, overWrite = True):
note = self.queue[rowIndex][groupIndex]
if overWrite or 'action' not in note:
note['action'] = action
return note['action']
#Method trigger when text is entered
def enterText(self, textBox, actionBox):
if self.triggers == False:
return
self.triggers = False
#Retrieve the row index, group index and selected action
rowIndex = actionBox.rowIndex
groupIndex = actionBox.groupIndex
action = actionBox.currentText()
#Update the text in the queue
if action == 'Tag with...':
self.updateText(rowIndex, groupIndex, textBox.text(), 'tag')
elif action.startswith('Replace'):
self.updateText(rowIndex, groupIndex, textBox.text(), 'replacement')
self.triggers = True
#Method to update the entered text
def updateText(self, rowIndex, groupIndex, text, textType):
note = self.queue[rowIndex][groupIndex]
note[textType] = text
#Method to update the text field based on the selected action
def updateTextBox(self, rowIndex, groupIndex, textBox, action):
note = self.queue[rowIndex][groupIndex]
text = ''
if action == 'Tag with...':
text = note['tag']
elif action.startswith('Replace'):
text = note['replacement']
textBox.setText(text)
#Method to ask for conformation for performing the actions by creating a message box
def askConfirmation(self):
msg = QMessageBox()
msg.setIcon(QMessageBox.Question)
msg.setText("All actions have been set and are ready to be performed.")
msg.setInformativeText("Are you sure you want to perform the set actions on the notes?")
msg.setWindowTitle("Confirmation")
msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
res = msg.exec()
#When the user agrees, close the current window
#and perform the actions
if res == QMessageBox.Ok:
self.accept()
self.Comparer.performActions(self.maxRows)