Anchor-annotator 0.3.3__py3-none-any.whl → 0.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {Anchor_annotator-0.3.3.dist-info → Anchor_annotator-0.5.0.dist-info}/METADATA +1 -1
- Anchor_annotator-0.5.0.dist-info/RECORD +22 -0
- anchor/_version.py +2 -2
- anchor/main.py +178 -62
- anchor/models.py +88 -54
- anchor/plot.py +316 -115
- anchor/resources_rc.py +6475 -4801
- anchor/settings.py +195 -95
- anchor/ui_error_dialog.py +15 -16
- anchor/ui_main_window.py +40 -612
- anchor/ui_preferences.py +75 -44
- anchor/undo.py +15 -5
- anchor/widgets.py +98 -132
- anchor/workers.py +29 -1
- Anchor_annotator-0.3.3.dist-info/RECORD +0 -22
- {Anchor_annotator-0.3.3.dist-info → Anchor_annotator-0.5.0.dist-info}/LICENSE +0 -0
- {Anchor_annotator-0.3.3.dist-info → Anchor_annotator-0.5.0.dist-info}/WHEEL +0 -0
- {Anchor_annotator-0.3.3.dist-info → Anchor_annotator-0.5.0.dist-info}/top_level.txt +0 -0
anchor/widgets.py
CHANGED
@@ -57,7 +57,7 @@ class ErrorButtonBox(QtWidgets.QDialogButtonBox):
|
|
57
57
|
super().__init__(*args, **kwargs)
|
58
58
|
self.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Close)
|
59
59
|
self.report_bug_button = QtWidgets.QPushButton("Report bug")
|
60
|
-
self.report_bug_button.setIcon(QtGui.QIcon("
|
60
|
+
self.report_bug_button.setIcon(QtGui.QIcon.fromTheme("folder-open"))
|
61
61
|
self.addButton(self.report_bug_button, QtWidgets.QDialogButtonBox.ButtonRole.ActionRole)
|
62
62
|
|
63
63
|
|
@@ -74,10 +74,7 @@ class MediaPlayer(QtMultimedia.QMediaPlayer): # pragma: no cover
|
|
74
74
|
self.start_load_time = None
|
75
75
|
self.min_time = None
|
76
76
|
self.selection_model = None
|
77
|
-
self.
|
78
|
-
self.timer.setInterval(1)
|
79
|
-
self.timer.timeout.connect(self.checkStop)
|
80
|
-
# self.positionChanged.connect(self.checkStop)
|
77
|
+
self.positionChanged.connect(self.checkStop)
|
81
78
|
# self.positionChanged.connect(self.positionDebug)
|
82
79
|
self.errorOccurred.connect(self.handle_error)
|
83
80
|
o = None
|
@@ -89,7 +86,6 @@ class MediaPlayer(QtMultimedia.QMediaPlayer): # pragma: no cover
|
|
89
86
|
self._audio_output.setDevice(self.devices.defaultAudioOutput())
|
90
87
|
self.setAudioOutput(self._audio_output)
|
91
88
|
self.playbackStateChanged.connect(self.reset_position)
|
92
|
-
self.set_volume(self.settings.value(self.settings.VOLUME))
|
93
89
|
self.fade_in_anim = QtCore.QPropertyAnimation(self._audio_output, b"volume")
|
94
90
|
self.fade_in_anim.setDuration(10)
|
95
91
|
self.fade_in_anim.setStartValue(0.1)
|
@@ -105,6 +101,7 @@ class MediaPlayer(QtMultimedia.QMediaPlayer): # pragma: no cover
|
|
105
101
|
self.fade_out_anim.setKeyValueAt(0.1, self._audio_output.volume())
|
106
102
|
self.fade_out_anim.finished.connect(super().pause)
|
107
103
|
self.file_path = None
|
104
|
+
self.set_volume(self.settings.value(self.settings.VOLUME))
|
108
105
|
|
109
106
|
def setMuted(self, muted: bool):
|
110
107
|
self.audioOutput().setMuted(muted)
|
@@ -125,7 +122,6 @@ class MediaPlayer(QtMultimedia.QMediaPlayer): # pragma: no cover
|
|
125
122
|
or self.currentTime() >= self.maxTime()
|
126
123
|
):
|
127
124
|
self.setCurrentTime(self.startTime())
|
128
|
-
self.timer.start()
|
129
125
|
super(MediaPlayer, self).play()
|
130
126
|
if fade_in:
|
131
127
|
self.fade_in_anim.start()
|
@@ -153,14 +149,11 @@ class MediaPlayer(QtMultimedia.QMediaPlayer): # pragma: no cover
|
|
153
149
|
def reset_position(self):
|
154
150
|
state = self.playbackState()
|
155
151
|
if state == QtMultimedia.QMediaPlayer.PlaybackState.StoppedState:
|
156
|
-
self.timer.stop()
|
157
152
|
self.setCurrentTime(self.startTime())
|
158
|
-
self.timeChanged.emit(self.currentTime())
|
159
|
-
elif state == QtMultimedia.QMediaPlayer.PlaybackState.PausedState:
|
160
|
-
self.timer.stop()
|
161
153
|
|
162
154
|
def update_audio_device(self):
|
163
155
|
self._audio_output.setDevice(self.devices.defaultAudioOutput())
|
156
|
+
self.setAudioOutput(self._audio_output)
|
164
157
|
|
165
158
|
def refresh_settings(self):
|
166
159
|
self.settings.sync()
|
@@ -177,9 +170,9 @@ class MediaPlayer(QtMultimedia.QMediaPlayer): # pragma: no cover
|
|
177
170
|
self.selection_model.fileChanged.connect(self.loadNewFile)
|
178
171
|
self.selection_model.viewChanged.connect(self.update_times)
|
179
172
|
self.selection_model.selectionAudioChanged.connect(self.update_selection_times)
|
180
|
-
self.selection_model.currentTimeChanged.connect(self.update_selection_times)
|
181
173
|
|
182
174
|
def set_volume(self, volume: int):
|
175
|
+
self.settings.setValue(self.settings.VOLUME, volume)
|
183
176
|
if self.audioOutput() is None:
|
184
177
|
return
|
185
178
|
linearVolume = QtMultimedia.QtAudio.convertVolume(
|
@@ -188,6 +181,8 @@ class MediaPlayer(QtMultimedia.QMediaPlayer): # pragma: no cover
|
|
188
181
|
QtMultimedia.QtAudio.VolumeScale.LinearVolumeScale,
|
189
182
|
)
|
190
183
|
self.audioOutput().setVolume(linearVolume)
|
184
|
+
self.fade_in_anim.setEndValue(linearVolume)
|
185
|
+
self.fade_out_anim.setStartValue(linearVolume)
|
191
186
|
|
192
187
|
def volume(self) -> int:
|
193
188
|
if self.audioOutput() is None:
|
@@ -203,13 +198,17 @@ class MediaPlayer(QtMultimedia.QMediaPlayer): # pragma: no cover
|
|
203
198
|
)
|
204
199
|
return volume
|
205
200
|
|
206
|
-
def update_selection_times(self):
|
207
|
-
self.
|
201
|
+
def update_selection_times(self, update=False):
|
202
|
+
if update or self.playbackState() != QtMultimedia.QMediaPlayer.PlaybackState.PlayingState:
|
203
|
+
self.setCurrentTime(self.startTime())
|
208
204
|
|
209
205
|
def update_times(self):
|
206
|
+
if self.playbackState() == QtMultimedia.QMediaPlayer.PlaybackState.PlayingState:
|
207
|
+
return
|
210
208
|
if self.currentTime() < self.startTime() or self.currentTime() > self.maxTime():
|
211
209
|
self.stop()
|
212
210
|
if self.playbackState() != QtMultimedia.QMediaPlayer.PlaybackState.PlayingState:
|
211
|
+
self.stop()
|
213
212
|
self.setCurrentTime(self.startTime())
|
214
213
|
|
215
214
|
def loadNewFile(self, *args):
|
@@ -238,27 +237,14 @@ class MediaPlayer(QtMultimedia.QMediaPlayer): # pragma: no cover
|
|
238
237
|
def setCurrentTime(self, time):
|
239
238
|
if time is None:
|
240
239
|
time = 0
|
241
|
-
if self.playbackState() == QtMultimedia.QMediaPlayer.PlaybackState.PlayingState:
|
242
|
-
return
|
243
240
|
pos = int(time * 1000)
|
244
241
|
self.setPosition(pos)
|
245
|
-
self.timeChanged.emit(self.currentTime())
|
246
242
|
|
247
243
|
def checkStop(self):
|
248
|
-
|
249
|
-
self.stop()
|
250
|
-
self.setSource(
|
251
|
-
QtCore.QUrl.fromLocalFile(
|
252
|
-
self.selection_model.model().file.sound_file.sound_file_path
|
253
|
-
)
|
254
|
-
)
|
255
|
-
self.play()
|
256
|
-
return
|
244
|
+
self.timeChanged.emit(self.currentTime())
|
257
245
|
if self.playbackState() == QtMultimedia.QMediaPlayer.PlaybackState.PlayingState:
|
258
246
|
if self.maxTime() is None or self.currentTime() > self.maxTime():
|
259
247
|
self.stop()
|
260
|
-
self.reset_position()
|
261
|
-
self.timeChanged.emit(self.currentTime())
|
262
248
|
|
263
249
|
|
264
250
|
class NewSpeakerField(QtWidgets.QLineEdit):
|
@@ -286,9 +272,7 @@ class NewSpeakerField(QtWidgets.QLineEdit):
|
|
286
272
|
self.setSizePolicy(
|
287
273
|
QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Preferred
|
288
274
|
)
|
289
|
-
clear_icon = QtGui.QIcon()
|
290
|
-
clear_icon.addFile(":clear.svg", mode=QtGui.QIcon.Mode.Normal, state=QtGui.QIcon.State.Off)
|
291
|
-
clear_icon.addFile(":disabled/clear.svg", mode=QtGui.QIcon.Mode.Active)
|
275
|
+
clear_icon = QtGui.QIcon.fromTheme("edit-clear")
|
292
276
|
|
293
277
|
self.clear_action = QtGui.QAction(icon=clear_icon, parent=self)
|
294
278
|
self.clear_action.triggered.connect(self.clear)
|
@@ -469,9 +453,7 @@ class CompleterLineEdit(QtWidgets.QWidget):
|
|
469
453
|
# self.model = QtCore.QStringListModel(self)
|
470
454
|
# self.completer.setModel(self.model)
|
471
455
|
layout.addWidget(self.line_edit)
|
472
|
-
clear_icon = QtGui.QIcon()
|
473
|
-
clear_icon.addFile(":clear.svg", mode=QtGui.QIcon.Mode.Normal, state=QtGui.QIcon.State.Off)
|
474
|
-
clear_icon.addFile(":disabled/clear.svg", mode=QtGui.QIcon.Mode.Active)
|
456
|
+
clear_icon = QtGui.QIcon.fromTheme("edit-clear")
|
475
457
|
self.button = QtWidgets.QToolButton(self)
|
476
458
|
self.button.clicked.connect(self.clear_text)
|
477
459
|
self.line_edit.textChanged.connect(self.check_actions)
|
@@ -530,9 +512,7 @@ class ClearableDropDown(QtWidgets.QWidget):
|
|
530
512
|
self.combo_box = QtWidgets.QComboBox(self)
|
531
513
|
layout = QtWidgets.QHBoxLayout()
|
532
514
|
layout.addWidget(self.combo_box)
|
533
|
-
clear_icon = QtGui.QIcon()
|
534
|
-
clear_icon.addFile(":clear.svg", mode=QtGui.QIcon.Mode.Normal, state=QtGui.QIcon.State.Off)
|
535
|
-
clear_icon.addFile(":disabled/clear.svg", mode=QtGui.QIcon.Mode.Active)
|
515
|
+
clear_icon = QtGui.QIcon.fromTheme("edit-clear")
|
536
516
|
self.combo_box.currentIndexChanged.connect(self.check_actions)
|
537
517
|
self.button = QtWidgets.QToolButton(self)
|
538
518
|
self.button.clicked.connect(self.clear_index)
|
@@ -583,10 +563,10 @@ class PaginationWidget(QtWidgets.QToolBar):
|
|
583
563
|
self.num_pages = 1
|
584
564
|
self.result_count = 0
|
585
565
|
self.next_page_action = QtGui.QAction(
|
586
|
-
icon=QtGui.QIcon("
|
566
|
+
icon=QtGui.QIcon.fromTheme("media-seek-forward"), text="Next page"
|
587
567
|
)
|
588
568
|
self.previous_page_action = QtGui.QAction(
|
589
|
-
icon=QtGui.QIcon("
|
569
|
+
icon=QtGui.QIcon.fromTheme("media-seek-backward"), text="Previous page"
|
590
570
|
)
|
591
571
|
self.addWidget(w)
|
592
572
|
self.page_label = QtWidgets.QLabel("Page 1 of 1")
|
@@ -1034,9 +1014,7 @@ class ClearableField(InternalToolButtonEdit):
|
|
1034
1014
|
def __init__(self, *args):
|
1035
1015
|
super().__init__(*args)
|
1036
1016
|
|
1037
|
-
clear_icon = QtGui.QIcon()
|
1038
|
-
clear_icon.addFile(":clear.svg", mode=QtGui.QIcon.Mode.Normal, state=QtGui.QIcon.State.Off)
|
1039
|
-
clear_icon.addFile(":disabled/clear.svg", mode=QtGui.QIcon.Mode.Active)
|
1017
|
+
clear_icon = QtGui.QIcon.fromTheme("edit-clear")
|
1040
1018
|
self.clear_action = QtGui.QAction(icon=clear_icon, parent=self)
|
1041
1019
|
self.clear_action.triggered.connect(self.clear)
|
1042
1020
|
self.clear_action.setVisible(False)
|
@@ -1090,28 +1068,16 @@ class SearchBox(ClearableField):
|
|
1090
1068
|
|
1091
1069
|
self.clear_action.triggered.connect(self.returnPressed.emit)
|
1092
1070
|
|
1093
|
-
regex_icon = QtGui.QIcon()
|
1094
|
-
regex_icon.addFile(":regex.svg", mode=QtGui.QIcon.Mode.Normal, state=QtGui.QIcon.State.Off)
|
1095
|
-
regex_icon.addFile(
|
1096
|
-
":highlighted/regex.svg", mode=QtGui.QIcon.Mode.Normal, state=QtGui.QIcon.State.On
|
1097
|
-
)
|
1071
|
+
regex_icon = QtGui.QIcon.fromTheme("edit-regex")
|
1098
1072
|
|
1099
1073
|
self.regex_action = QtGui.QAction(icon=regex_icon, parent=self)
|
1100
1074
|
self.regex_action.setCheckable(True)
|
1101
1075
|
|
1102
|
-
word_icon = QtGui.QIcon()
|
1103
|
-
word_icon.addFile(":word.svg", mode=QtGui.QIcon.Mode.Normal, state=QtGui.QIcon.State.Off)
|
1104
|
-
word_icon.addFile(
|
1105
|
-
":highlighted/word.svg", mode=QtGui.QIcon.Mode.Normal, state=QtGui.QIcon.State.On
|
1106
|
-
)
|
1076
|
+
word_icon = QtGui.QIcon.fromTheme("edit-word")
|
1107
1077
|
self.word_action = QtGui.QAction(icon=word_icon, parent=self)
|
1108
1078
|
self.word_action.setCheckable(True)
|
1109
1079
|
|
1110
|
-
case_icon = QtGui.QIcon()
|
1111
|
-
case_icon.addFile(":case.svg", mode=QtGui.QIcon.Mode.Normal, state=QtGui.QIcon.State.Off)
|
1112
|
-
case_icon.addFile(
|
1113
|
-
":highlighted/case.svg", mode=QtGui.QIcon.Mode.Normal, state=QtGui.QIcon.State.On
|
1114
|
-
)
|
1080
|
+
case_icon = QtGui.QIcon.fromTheme("edit-case")
|
1115
1081
|
self.case_action = QtGui.QAction(icon=case_icon, parent=self)
|
1116
1082
|
self.case_action.setCheckable(True)
|
1117
1083
|
|
@@ -1415,7 +1381,7 @@ class IconDelegate(QtWidgets.QStyledItemDelegate):
|
|
1415
1381
|
options = QtWidgets.QStyleOptionViewItem(option)
|
1416
1382
|
self.initStyleOption(options, index)
|
1417
1383
|
if options.checkState == QtCore.Qt.CheckState.Checked:
|
1418
|
-
icon = QtGui.QIcon(":
|
1384
|
+
icon = QtGui.QIcon(":oov-check.svg")
|
1419
1385
|
icon.paint(painter, options.rect, QtCore.Qt.AlignmentFlag.AlignCenter)
|
1420
1386
|
|
1421
1387
|
painter.restore()
|
@@ -1428,10 +1394,10 @@ class ModelIconDelegate(QtWidgets.QStyledItemDelegate):
|
|
1428
1394
|
|
1429
1395
|
self.settings = AnchorSettings()
|
1430
1396
|
self.icon_mapping = {
|
1431
|
-
"available": QtGui.QIcon("
|
1432
|
-
"unavailable": QtGui.QIcon("
|
1433
|
-
"remote": QtGui.QIcon("
|
1434
|
-
"unknown": QtGui.QIcon("
|
1397
|
+
"available": QtGui.QIcon.fromTheme("emblem-default"),
|
1398
|
+
"unavailable": QtGui.QIcon.fromTheme("emblem-important"),
|
1399
|
+
"remote": QtGui.QIcon.fromTheme("sync-synchronizing"),
|
1400
|
+
"unknown": QtGui.QIcon.fromTheme("emblem-unknown"),
|
1435
1401
|
}
|
1436
1402
|
|
1437
1403
|
def refresh_settings(self):
|
@@ -1452,7 +1418,16 @@ class ModelIconDelegate(QtWidgets.QStyledItemDelegate):
|
|
1452
1418
|
options = QtWidgets.QStyleOptionViewItem(option)
|
1453
1419
|
self.initStyleOption(options, index)
|
1454
1420
|
icon = self.icon_mapping[options.text]
|
1455
|
-
|
1421
|
+
r = option.rect
|
1422
|
+
half_size = int(self.settings.icon_size / 2)
|
1423
|
+
x = r.left() + (r.width() / 2) - half_size
|
1424
|
+
y = r.top() + (r.height() / 2) - half_size
|
1425
|
+
options.rect = QtCore.QRect(x, y, self.settings.icon_size, self.settings.icon_size)
|
1426
|
+
icon.paint(
|
1427
|
+
painter,
|
1428
|
+
options.rect,
|
1429
|
+
QtCore.Qt.AlignmentFlag.AlignCenter | QtCore.Qt.AlignmentFlag.AlignVCenter,
|
1430
|
+
)
|
1456
1431
|
|
1457
1432
|
painter.restore()
|
1458
1433
|
|
@@ -1474,7 +1449,7 @@ class StoppableProgressBar(QtWidgets.QWidget):
|
|
1474
1449
|
layout.addWidget(self.progress_bar)
|
1475
1450
|
self.cancel_button = QtWidgets.QToolButton()
|
1476
1451
|
self.cancel_action = QtGui.QAction("select", self)
|
1477
|
-
self.cancel_action.setIcon(QtGui.QIcon("
|
1452
|
+
self.cancel_action.setIcon(QtGui.QIcon.fromTheme("edit-clear"))
|
1478
1453
|
self.cancel_action.triggered.connect(worker.cancel)
|
1479
1454
|
self.cancel_button.setDefaultAction(self.cancel_action)
|
1480
1455
|
layout.addWidget(self.cancel_button)
|
@@ -1542,7 +1517,7 @@ class ProgressMenu(QtWidgets.QMenu):
|
|
1542
1517
|
class ProgressWidget(QtWidgets.QPushButton):
|
1543
1518
|
def __init__(self, *args):
|
1544
1519
|
super().__init__(*args)
|
1545
|
-
self.done_icon = QtGui.QIcon("
|
1520
|
+
self.done_icon = QtGui.QIcon.fromTheme("emblem-default")
|
1546
1521
|
self.animated = QtGui.QMovie(":spinning_blue.svg")
|
1547
1522
|
self.animated.frameChanged.connect(self.update_animation)
|
1548
1523
|
self.setIcon(self.done_icon)
|
@@ -1781,34 +1756,16 @@ class PronunciationInput(QtWidgets.QToolBar):
|
|
1781
1756
|
self.setContentsMargins(0, 0, 0, 0)
|
1782
1757
|
self.setFocusProxy(self.input)
|
1783
1758
|
|
1784
|
-
accept_icon = QtGui.QIcon()
|
1785
|
-
accept_icon.addFile(
|
1786
|
-
":check-circle.svg", mode=QtGui.QIcon.Mode.Normal, state=QtGui.QIcon.State.Off
|
1787
|
-
)
|
1788
|
-
accept_icon.addFile(
|
1789
|
-
":highlighted/check-circle.svg",
|
1790
|
-
mode=QtGui.QIcon.Mode.Normal,
|
1791
|
-
state=QtGui.QIcon.State.On,
|
1792
|
-
)
|
1759
|
+
accept_icon = QtGui.QIcon.fromTheme("emblem-default")
|
1793
1760
|
|
1794
1761
|
self.accept_action = QtGui.QAction(icon=accept_icon, parent=self)
|
1795
1762
|
self.accept_action.triggered.connect(self.returnPressed.emit)
|
1796
1763
|
|
1797
|
-
cancel_icon = QtGui.QIcon()
|
1798
|
-
cancel_icon.addFile(":undo.svg", mode=QtGui.QIcon.Mode.Normal, state=QtGui.QIcon.State.Off)
|
1799
|
-
cancel_icon.addFile(
|
1800
|
-
":highlighted/undo.svg", mode=QtGui.QIcon.Mode.Normal, state=QtGui.QIcon.State.On
|
1801
|
-
)
|
1764
|
+
cancel_icon = QtGui.QIcon.fromTheme("edit-undo")
|
1802
1765
|
|
1803
1766
|
self.cancel_action = QtGui.QAction(icon=cancel_icon, parent=self)
|
1804
1767
|
self.cancel_action.triggered.connect(self.cancel)
|
1805
|
-
keyboard_icon = QtGui.QIcon()
|
1806
|
-
keyboard_icon.addFile(
|
1807
|
-
":keyboard.svg", mode=QtGui.QIcon.Mode.Normal, state=QtGui.QIcon.State.Off
|
1808
|
-
)
|
1809
|
-
keyboard_icon.addFile(
|
1810
|
-
":highlighted/keyboard.svg", mode=QtGui.QIcon.Mode.Normal, state=QtGui.QIcon.State.On
|
1811
|
-
)
|
1768
|
+
keyboard_icon = QtGui.QIcon.fromTheme("input-keyboard")
|
1812
1769
|
|
1813
1770
|
self.keyboard_widget = QtWidgets.QPushButton(self)
|
1814
1771
|
self.keyboard_widget.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus)
|
@@ -1834,7 +1791,7 @@ class PronunciationInput(QtWidgets.QToolBar):
|
|
1834
1791
|
self.returnPressed.emit()
|
1835
1792
|
return True
|
1836
1793
|
elif (
|
1837
|
-
isinstance(watched,
|
1794
|
+
isinstance(watched, IpaKeyboard)
|
1838
1795
|
and event.type() == QtCore.QEvent.Type.KeyPress
|
1839
1796
|
and event.key() not in {QtGui.Qt.Key.Key_Escape}
|
1840
1797
|
):
|
@@ -1925,14 +1882,18 @@ class CountDelegate(QtWidgets.QStyledItemDelegate):
|
|
1925
1882
|
super().paint(painter, option, index)
|
1926
1883
|
painter.save()
|
1927
1884
|
r = option.rect
|
1928
|
-
|
1885
|
+
half_size = int(self.settings.icon_size / 2)
|
1929
1886
|
x = r.left() + r.width() - self.settings.icon_size
|
1930
|
-
y = r.top()
|
1887
|
+
y = r.top() + (r.height() / 2) - half_size
|
1931
1888
|
options = QtWidgets.QStyleOptionViewItem(option)
|
1932
|
-
options.rect = QtCore.QRect(x, y,
|
1889
|
+
options.rect = QtCore.QRect(x, y, self.settings.icon_size, self.settings.icon_size)
|
1933
1890
|
self.initStyleOption(options, index)
|
1934
|
-
icon = QtGui.QIcon("
|
1935
|
-
icon.paint(
|
1891
|
+
icon = QtGui.QIcon.fromTheme("folder-open")
|
1892
|
+
icon.paint(
|
1893
|
+
painter,
|
1894
|
+
options.rect,
|
1895
|
+
QtCore.Qt.AlignmentFlag.AlignCenter | QtCore.Qt.AlignmentFlag.AlignVCenter,
|
1896
|
+
)
|
1936
1897
|
|
1937
1898
|
painter.restore()
|
1938
1899
|
|
@@ -1956,14 +1917,18 @@ class WordTypeDelegate(QtWidgets.QStyledItemDelegate):
|
|
1956
1917
|
super().paint(painter, option, index)
|
1957
1918
|
painter.save()
|
1958
1919
|
r = option.rect
|
1959
|
-
|
1920
|
+
half_size = int(self.settings.icon_size / 2)
|
1960
1921
|
x = r.left() + r.width() - self.settings.icon_size
|
1961
|
-
y = r.top()
|
1922
|
+
y = r.top() + (r.height() / 2) - half_size
|
1962
1923
|
options = QtWidgets.QStyleOptionViewItem(option)
|
1963
|
-
options.rect = QtCore.QRect(x, y,
|
1924
|
+
options.rect = QtCore.QRect(x, y, self.settings.icon_size, self.settings.icon_size)
|
1964
1925
|
self.initStyleOption(options, index)
|
1965
|
-
icon = QtGui.QIcon("
|
1966
|
-
icon.paint(
|
1926
|
+
icon = QtGui.QIcon.fromTheme("sync-synchronizing")
|
1927
|
+
icon.paint(
|
1928
|
+
painter,
|
1929
|
+
options.rect,
|
1930
|
+
QtCore.Qt.AlignmentFlag.AlignCenter | QtCore.Qt.AlignmentFlag.AlignVCenter,
|
1931
|
+
)
|
1967
1932
|
|
1968
1933
|
painter.restore()
|
1969
1934
|
|
@@ -2498,13 +2463,13 @@ class SpeakerViewDelegate(QtWidgets.QStyledItemDelegate):
|
|
2498
2463
|
painter.save()
|
2499
2464
|
|
2500
2465
|
r = option.rect
|
2501
|
-
|
2466
|
+
half_size = int(self.settings.icon_size / 2)
|
2502
2467
|
x = r.left() + r.width() - self.settings.icon_size
|
2503
|
-
y = r.top()
|
2468
|
+
y = r.top() + (r.height() / 2) - half_size
|
2504
2469
|
options = QtWidgets.QStyleOptionViewItem(option)
|
2505
|
-
options.rect = QtCore.QRect(x, y,
|
2470
|
+
options.rect = QtCore.QRect(x, y, self.settings.icon_size, self.settings.icon_size)
|
2506
2471
|
self.initStyleOption(options, index)
|
2507
|
-
icon = QtGui.QIcon("
|
2472
|
+
icon = QtGui.QIcon.fromTheme("folder-open")
|
2508
2473
|
icon.paint(painter, options.rect, QtCore.Qt.AlignmentFlag.AlignCenter)
|
2509
2474
|
|
2510
2475
|
painter.restore()
|
@@ -2529,11 +2494,11 @@ class ButtonDelegate(QtWidgets.QStyledItemDelegate):
|
|
2529
2494
|
) -> None:
|
2530
2495
|
painter.save()
|
2531
2496
|
r = option.rect
|
2532
|
-
|
2497
|
+
half_size = int(self.settings.icon_size / 2)
|
2533
2498
|
x = r.left() + r.width() - self.settings.icon_size
|
2534
|
-
y = r.top()
|
2499
|
+
y = r.top() + (r.height() / 2) - half_size
|
2535
2500
|
options = QtWidgets.QStyleOptionViewItem(option)
|
2536
|
-
options.rect = QtCore.QRect(x, y,
|
2501
|
+
options.rect = QtCore.QRect(x, y, self.settings.icon_size, self.settings.icon_size)
|
2537
2502
|
self.initStyleOption(options, index)
|
2538
2503
|
icon = QtGui.QIcon(self.icon_path)
|
2539
2504
|
icon.paint(painter, options.rect, QtCore.Qt.AlignmentFlag.AlignCenter)
|
@@ -2546,6 +2511,7 @@ class SpeakerClustersWidget(QtWidgets.QWidget):
|
|
2546
2511
|
|
2547
2512
|
def __init__(self, *args, **kwargs):
|
2548
2513
|
super().__init__(*args, **kwargs)
|
2514
|
+
self.speaker_model = None
|
2549
2515
|
self.settings = AnchorSettings()
|
2550
2516
|
self.settings.sync()
|
2551
2517
|
form_layout = QtWidgets.QHBoxLayout()
|
@@ -2640,7 +2606,7 @@ class DiarizationTable(AnchorTableView):
|
|
2640
2606
|
self.doubleClicked.connect(self.search_utterance)
|
2641
2607
|
self.clicked.connect(self.reassign_utterance)
|
2642
2608
|
self.diarization_model: Optional[DiarizationModel] = None
|
2643
|
-
self.selection_model: Optional[
|
2609
|
+
self.selection_model: Optional[FileSelectionModel] = None
|
2644
2610
|
self.set_reference_utterance_action = QtGui.QAction("Use utterance as reference", self)
|
2645
2611
|
self.set_reference_utterance_action.triggered.connect(self.set_reference_utterance)
|
2646
2612
|
self.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu)
|
@@ -2648,7 +2614,7 @@ class DiarizationTable(AnchorTableView):
|
|
2648
2614
|
|
2649
2615
|
def generate_context_menu(self, location):
|
2650
2616
|
menu = QtWidgets.QMenu()
|
2651
|
-
|
2617
|
+
menu.setStyleSheet(self.settings.menu_style_sheet)
|
2652
2618
|
menu.addAction(self.set_reference_utterance_action)
|
2653
2619
|
menu.exec_(self.mapToGlobal(location))
|
2654
2620
|
|
@@ -2656,7 +2622,7 @@ class DiarizationTable(AnchorTableView):
|
|
2656
2622
|
rows = self.selectionModel().selectedRows()
|
2657
2623
|
if not rows:
|
2658
2624
|
return
|
2659
|
-
utterance_id = self.diarization_model.
|
2625
|
+
utterance_id = self.diarization_model.utterance_ids[rows[0].row()]
|
2660
2626
|
self.diarization_model.set_utterance_filter(utterance_id)
|
2661
2627
|
self.referenceUtteranceSelected.emit(
|
2662
2628
|
self.diarization_model.data(
|
@@ -2665,7 +2631,7 @@ class DiarizationTable(AnchorTableView):
|
|
2665
2631
|
)
|
2666
2632
|
)
|
2667
2633
|
|
2668
|
-
def set_models(self, model: DiarizationModel, selection_model:
|
2634
|
+
def set_models(self, model: DiarizationModel, selection_model: FileSelectionModel):
|
2669
2635
|
self.diarization_model = model
|
2670
2636
|
self.selection_model = selection_model
|
2671
2637
|
self.setModel(model)
|
@@ -2684,14 +2650,14 @@ class DiarizationTable(AnchorTableView):
|
|
2684
2650
|
return
|
2685
2651
|
if index.column() == 0:
|
2686
2652
|
row = index.row()
|
2687
|
-
utterance_id = self.diarization_model.
|
2653
|
+
utterance_id = self.diarization_model.utterance_ids[row]
|
2688
2654
|
if utterance_id is None:
|
2689
2655
|
return
|
2690
2656
|
with self.diarization_model.corpus_model.corpus.session() as session:
|
2691
2657
|
try:
|
2692
|
-
file_id, begin, end,
|
2658
|
+
file_id, begin, end, speaker_id = (
|
2693
2659
|
session.query(
|
2694
|
-
Utterance.file_id, Utterance.begin, Utterance.end, Utterance.
|
2660
|
+
Utterance.file_id, Utterance.begin, Utterance.end, Utterance.speaker_id
|
2695
2661
|
)
|
2696
2662
|
.filter(Utterance.id == utterance_id)
|
2697
2663
|
.first()
|
@@ -2701,19 +2667,18 @@ class DiarizationTable(AnchorTableView):
|
|
2701
2667
|
return
|
2702
2668
|
else:
|
2703
2669
|
if index.column() == 1:
|
2704
|
-
speaker_id = self.diarization_model.
|
2670
|
+
speaker_id = self.diarization_model.suggested_indices[index.row()]
|
2705
2671
|
else:
|
2706
|
-
speaker_id = self.diarization_model.
|
2672
|
+
speaker_id = self.diarization_model.speaker_indices[index.row()]
|
2707
2673
|
with self.diarization_model.corpus_model.corpus.session() as session:
|
2708
2674
|
c = session.query(Corpus).first()
|
2709
2675
|
try:
|
2710
|
-
utterance_id, file_id, begin, end
|
2676
|
+
utterance_id, file_id, begin, end = (
|
2711
2677
|
session.query(
|
2712
2678
|
Utterance.id,
|
2713
2679
|
Utterance.file_id,
|
2714
2680
|
Utterance.begin,
|
2715
2681
|
Utterance.end,
|
2716
|
-
Utterance.channel,
|
2717
2682
|
)
|
2718
2683
|
.join(Utterance.speaker)
|
2719
2684
|
.filter(Utterance.speaker_id == speaker_id)
|
@@ -2725,12 +2690,12 @@ class DiarizationTable(AnchorTableView):
|
|
2725
2690
|
except TypeError:
|
2726
2691
|
self.selection_model.clearSelection()
|
2727
2692
|
return
|
2728
|
-
self.selection_model.set_current_utterance(utterance_id)
|
2729
2693
|
self.selection_model.set_current_file(
|
2730
2694
|
file_id,
|
2731
2695
|
begin,
|
2732
2696
|
end,
|
2733
|
-
|
2697
|
+
utterance_id,
|
2698
|
+
speaker_id,
|
2734
2699
|
force_update=True,
|
2735
2700
|
)
|
2736
2701
|
|
@@ -3069,11 +3034,11 @@ class DictionaryWidget(QtWidgets.QWidget):
|
|
3069
3034
|
self.current_search_query = None
|
3070
3035
|
self.current_search_text = ""
|
3071
3036
|
self.refresh_word_counts_action = QtGui.QAction(self)
|
3072
|
-
self.refresh_word_counts_action.setIcon(QtGui.QIcon("
|
3037
|
+
self.refresh_word_counts_action.setIcon(QtGui.QIcon.fromTheme("tools-check-spelling"))
|
3073
3038
|
self.refresh_word_counts_action.setEnabled(True)
|
3074
3039
|
self.toolbar.addAction(self.refresh_word_counts_action)
|
3075
3040
|
self.rebuild_lexicon_action = QtGui.QAction(self)
|
3076
|
-
self.rebuild_lexicon_action.setIcon(QtGui.QIcon("
|
3041
|
+
self.rebuild_lexicon_action.setIcon(QtGui.QIcon.fromTheme("sync-synchronizing"))
|
3077
3042
|
self.rebuild_lexicon_action.setEnabled(True)
|
3078
3043
|
self.toolbar.addAction(self.rebuild_lexicon_action)
|
3079
3044
|
dict_layout.addWidget(self.toolbar)
|
@@ -3280,7 +3245,7 @@ class SpeakerWidget(QtWidgets.QWidget):
|
|
3280
3245
|
def set_models(
|
3281
3246
|
self,
|
3282
3247
|
corpus_model: CorpusModel,
|
3283
|
-
selection_model:
|
3248
|
+
selection_model: FileSelectionModel,
|
3284
3249
|
speaker_model: SpeakerModel,
|
3285
3250
|
):
|
3286
3251
|
self.speaker_model = speaker_model
|
@@ -3312,31 +3277,33 @@ class SpeakerWidget(QtWidgets.QWidget):
|
|
3312
3277
|
|
3313
3278
|
|
3314
3279
|
class ColorEdit(QtWidgets.QPushButton): # pragma: no cover
|
3280
|
+
colorChanged = QtCore.Signal()
|
3281
|
+
|
3315
3282
|
def __init__(self, parent=None):
|
3316
3283
|
super(ColorEdit, self).__init__(parent=parent)
|
3317
3284
|
self.setText("")
|
3318
3285
|
self.clicked.connect(self.open_dialog)
|
3286
|
+
self.color = None
|
3319
3287
|
|
3320
|
-
def set_color(self, color: QtGui.QColor):
|
3321
|
-
|
3288
|
+
def set_color(self, color: typing.Union[str, QtGui.QColor]):
|
3289
|
+
if isinstance(color, str):
|
3290
|
+
color = QtGui.QColor(color)
|
3291
|
+
self.color = color
|
3322
3292
|
self.update_icon()
|
3323
3293
|
|
3324
3294
|
def update_icon(self):
|
3325
3295
|
pixmap = QtGui.QPixmap(100, 100)
|
3326
|
-
pixmap.fill(self.
|
3296
|
+
pixmap.fill(self.color)
|
3327
3297
|
icon = QtGui.QIcon(pixmap)
|
3328
3298
|
icon.addPixmap(pixmap, QtGui.QIcon.Mode.Disabled)
|
3329
3299
|
self.setIcon(icon)
|
3330
3300
|
|
3331
|
-
@property
|
3332
|
-
def color(self) -> str:
|
3333
|
-
return self._color.name()
|
3334
|
-
|
3335
3301
|
def open_dialog(self):
|
3336
3302
|
color = QtWidgets.QColorDialog.getColor()
|
3337
|
-
if color.isValid():
|
3338
|
-
self.
|
3303
|
+
if color.isValid() and self.color != color.name():
|
3304
|
+
self.color = color.name()
|
3339
3305
|
self.update_icon()
|
3306
|
+
self.colorChanged.emit()
|
3340
3307
|
|
3341
3308
|
|
3342
3309
|
class FontDialog(QtWidgets.QFontDialog):
|
@@ -3488,8 +3455,8 @@ class PathSelectWidget(QtWidgets.QWidget):
|
|
3488
3455
|
self.setLayout(layout)
|
3489
3456
|
|
3490
3457
|
self.select_button.clicked.connect(self.select_path)
|
3491
|
-
self.exists_icon = QtGui.QIcon("
|
3492
|
-
self.not_exists_icon = QtGui.QIcon("
|
3458
|
+
self.exists_icon = QtGui.QIcon.fromTheme("emblem-default")
|
3459
|
+
self.not_exists_icon = QtGui.QIcon.fromTheme("emblem-important")
|
3493
3460
|
|
3494
3461
|
def value(self):
|
3495
3462
|
if not self.path_edit.text():
|
@@ -3576,7 +3543,6 @@ class ModelSelectWidget(QtWidgets.QWidget):
|
|
3576
3543
|
for i, m in enumerate(self.model.models):
|
3577
3544
|
if not m.available_locally or not os.path.exists(m.path):
|
3578
3545
|
continue
|
3579
|
-
print(m.name, m.path, os.path.exists(m.path))
|
3580
3546
|
self.model_select.addItem(m.name, userData=m.id)
|
3581
3547
|
if m.id == current_model:
|
3582
3548
|
index = i
|
anchor/workers.py
CHANGED
@@ -3071,7 +3071,11 @@ class WaveformWorker(FunctionWorker): # pragma: no cover
|
|
3071
3071
|
def run(self):
|
3072
3072
|
self.stopped.clear()
|
3073
3073
|
with self.lock:
|
3074
|
-
|
3074
|
+
try:
|
3075
|
+
y, _ = soundfile.read(self.file_path)
|
3076
|
+
except soundfile.LibsndfileError:
|
3077
|
+
logger.warning(f"Could not read {self.file_path}")
|
3078
|
+
y = None
|
3075
3079
|
if self.stopped.is_set():
|
3076
3080
|
return
|
3077
3081
|
self.signals.result.emit((y, self.file_path))
|
@@ -3351,6 +3355,9 @@ class DownloadWorker(FunctionWorker): # pragma: no cover
|
|
3351
3355
|
class ImportCorpusWorker(FunctionWorker): # pragma: no cover
|
3352
3356
|
def __init__(self, *args):
|
3353
3357
|
super().__init__("Importing corpus", *args)
|
3358
|
+
self.corpus_path = None
|
3359
|
+
self.dictionary_path = None
|
3360
|
+
self.reset = None
|
3354
3361
|
|
3355
3362
|
def stop(self):
|
3356
3363
|
if hasattr(self, "corpus") and self.corpus is not None:
|
@@ -3365,6 +3372,25 @@ class ImportCorpusWorker(FunctionWorker): # pragma: no cover
|
|
3365
3372
|
config.CLEAN = self.reset
|
3366
3373
|
corpus_name = os.path.basename(self.corpus_path)
|
3367
3374
|
dataset_type = inspect_database(corpus_name)
|
3375
|
+
if (
|
3376
|
+
dataset_type is DatasetType.ACOUSTIC_CORPUS_WITH_DICTIONARY
|
3377
|
+
and self.dictionary_path is None
|
3378
|
+
):
|
3379
|
+
string = f"postgresql+psycopg2://@/{corpus_name}?host={config.database_socket()}"
|
3380
|
+
try:
|
3381
|
+
engine = sqlalchemy.create_engine(
|
3382
|
+
string,
|
3383
|
+
poolclass=sqlalchemy.NullPool,
|
3384
|
+
pool_reset_on_return=None,
|
3385
|
+
isolation_level="AUTOCOMMIT",
|
3386
|
+
logging_name="inspect_dataset_engine",
|
3387
|
+
).execution_options(logging_token="inspect_dataset_engine")
|
3388
|
+
with sqlalchemy.orm.Session(engine) as session:
|
3389
|
+
dictionary = session.query(Dictionary.path).first()
|
3390
|
+
if dictionary is not None:
|
3391
|
+
self.dictionary_path = dictionary[0]
|
3392
|
+
except (sqlalchemy.exc.OperationalError, sqlalchemy.exc.ProgrammingError):
|
3393
|
+
pass
|
3368
3394
|
try:
|
3369
3395
|
if dataset_type is DatasetType.NONE:
|
3370
3396
|
if self.dictionary_path and os.path.exists(self.dictionary_path):
|
@@ -3650,6 +3676,8 @@ class ImportG2PModelWorker(FunctionWorker): # pragma: no cover
|
|
3650
3676
|
try:
|
3651
3677
|
generator = Generator(g2p_model_path=self.model_path, num_pronunciations=5)
|
3652
3678
|
generator.setup()
|
3679
|
+
except shutil.ReadError:
|
3680
|
+
self.signals.result.emit(None)
|
3653
3681
|
except Exception:
|
3654
3682
|
exctype, value = sys.exc_info()[:2]
|
3655
3683
|
self.signals.error.emit((exctype, value, traceback.format_exc()))
|
@@ -1,22 +0,0 @@
|
|
1
|
-
anchor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
anchor/__main__.py,sha256=5ufG8lcx2x1am-04xI991AG7saJd24dxPw5JzjmB878,45
|
3
|
-
anchor/_version.py,sha256=FKnJIExgNrZG2xJ0y_dGNBpxGbGBYylvfat-jHhLUuM,411
|
4
|
-
anchor/command_line.py,sha256=EucG805HyWk_zkMO9RXv9Yj0I0JVdDLZb1_DX2_ISjM,503
|
5
|
-
anchor/db.py,sha256=ef4lO6HtCKoxC9CorIc0ZbPxKpjHa576a0ZIBOWNU9E,4956
|
6
|
-
anchor/main.py,sha256=wX6LLudTX5-HOxqBB-BGLXTdYJuDGQbV11gA2XBvQ8w,120605
|
7
|
-
anchor/models.py,sha256=sCZf5wF6g1KorMgb0AifmqhaxZp5fiYmlmaJoow-tFI,95230
|
8
|
-
anchor/plot.py,sha256=eNVG9sDdRA9_KKrHKSb2TF66bIluJsJzVnTGN3q-Brk,104878
|
9
|
-
anchor/resources_rc.py,sha256=94wgxDTpP4Oy55Br7CZ_YnmvaqzHr4n-AydBPhZc-es,8427242
|
10
|
-
anchor/settings.py,sha256=QdfBtJowHpkBLzJ_3bZRKxF1rJDBW9Z5kp83sJVz0pA,46965
|
11
|
-
anchor/ui_corpus_manager.py,sha256=e3ybOd4UdYarrLBATxI8vIFnioa4R_BHrbsEz5mJ5eA,8564
|
12
|
-
anchor/ui_error_dialog.py,sha256=c_QS0s1VaJEV9AhcrQZQyWHHpUPudWjJY1NI7Ytipio,3832
|
13
|
-
anchor/ui_main_window.py,sha256=MYb4PtV1sHYgnc3QwPphKjU3LepzBJpxllhN4nyDook,63525
|
14
|
-
anchor/ui_preferences.py,sha256=MOC2dY4qkViW9cUbC0DVSO7FLg-dGSbmR630WFQ6V9c,41843
|
15
|
-
anchor/undo.py,sha256=HXhrzV-T2JKwPd28KCaR9S6GWmi2Wr2Xk7IBEonRRCs,32564
|
16
|
-
anchor/widgets.py,sha256=arL006v_cOGWudEF4Adbh_wRjiyFRGHP9BXOtfCr0h0,158301
|
17
|
-
anchor/workers.py,sha256=iWLBGCg6jJr_OmVFJCRGMgF5Rw5G9IhpdNiqDv8ZBxU,171083
|
18
|
-
Anchor_annotator-0.3.3.dist-info/LICENSE,sha256=C0oIsblENEgWQ7XMNdYoXyXsIA5wa3YF0I9lK3H7A1s,1076
|
19
|
-
Anchor_annotator-0.3.3.dist-info/METADATA,sha256=KPemKhTKt7Rh3N4-k-f8V4tHoAkvoUKrhUlonplJrLo,1500
|
20
|
-
Anchor_annotator-0.3.3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
21
|
-
Anchor_annotator-0.3.3.dist-info/top_level.txt,sha256=wX6ZKxImGRZKFQjs3f6XYw_TfbAp6Xs3SmbLfLbFAJ0,7
|
22
|
-
Anchor_annotator-0.3.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|