이글 이어서 올립니다...
def _accept_update(self, detail=None):
"""
Update the progress bar and message.
"""
proc = self._process
proc['progress'].update(
label="finished %d of %d%s\n"
"%d successful, %d failed\n"
"\n"
"%s" % (
proc['counts']['done'],
proc['counts']['elig'],
" (%d skipped)" % proc['counts']['skip']
if proc['counts']['skip']
else "",
proc['counts']['okay'],
proc['counts']['fail'],
"sleeping for %d second%s" % (
proc['throttling']['countdown'],
"s"
if proc['throttling']['countdown'] != 1
else ""
)
if (
proc['throttling'] and
'countdown' in proc['throttling']
)
else " "
),
value=proc['counts']['done'],
detail=detail,
)
def _accept_done(self):
"""
Display statistics and close out the dialog.
"""
self._browser.model.reset()
proc = self._process
proc['progress'].accept()
messages = [
"The %d note%s you selected %s been processed. " % (
proc['counts']['total'],
"s" if proc['counts']['total'] != 1 else "",
"have" if proc['counts']['total'] != 1 else "has",
)
if proc['counts']['done'] == proc['counts']['total']
else "%d of the %d note%s you selected %s processed. " % (
proc['counts']['done'],
proc['counts']['total'],
"s" if proc['counts']['total'] != 1 else "",
"were" if proc['counts']['done'] != 1 else "was",
),
"%d note%s skipped for not having both the source and "
"destination fields. Of those remaining, " % (
proc['counts']['skip'],
"s were" if proc['counts']['skip'] != 1
else " was",
)
if proc['counts']['skip']
else "During processing, "
]
if proc['counts']['fail']:
if proc['counts']['okay']:
messages.append(
"%d note%s successfully updated, but "
"%d note%s failed while processing." % (
proc['counts']['okay'],
"s were" if proc['counts']['okay'] != 1
else " was",
proc['counts']['fail'],
"s" if proc['counts']['fail'] != 1
else "",
)
)
else:
messages.append("no notes were successfully updated.")
messages.append("\n\n")
if len(proc['exceptions']) == 1:
messages.append("The following problem was encountered:")
messages += [
"\n%s (%d time%s)" %
(message, count, "s" if count != 1 else "")
for message, count
in proc['exceptions'].items()
]
else:
messages.append("The following problems were encountered:")
messages += [
"\n- %s (%d time%s)" %
(message, count, "s" if count != 1 else "")
for message, count
in proc['exceptions'].items()
]
messages.append("\n\nThe following note(s) have failed:\n")
messages.append("".join(f"'{note}', " for note in proc['failednotes']))
else:
messages.append("there were no errors.")
if proc['aborted']:
messages.append("\n\n")
messages.append(
"You aborted processing. If you want to rollback the changes "
"to the notes that were already processed, use the Undo "
"AwesomeTTS Batch Update option from the Edit menu."
)
self._addon.config.update(proc['all'])
self._disable_inputs(False)
self._notes = None
self._process = None
super(BrowserGenerator, self).accept()
# this alert is done by way of a singleShot() callback to avoid random
# crashes on Mac OS X, which happen <5% of the time if called directly
aqt.qt.QTimer.singleShot(
0,
lambda: self._alerts("".join(messages), self._browser),
)
def _get_all(self):
"""
Adds support for fields and behavior.
"""
source, dest, append, behavior = self._get_field_values()
# TODO: could be rewritten with {**, **} syntax
return dict(
list(super(BrowserGenerator, self)._get_all().items()) +
[
('last_mass_append', append),
('last_mass_behavior', behavior),
('last_mass_dest', dest),
('last_mass_source', source),
]
)
def _get_field_values(self):
"""
Returns the user's source and destination fields, append state,
and handling mode.
"""
return (
self.findChild(aqt.qt.QComboBox, 'source').currentText(),
self.findChild(aqt.qt.QComboBox, 'dest').currentText(),
self.findChild(aqt.qt.QRadioButton, 'append').isChecked(),
self.findChild(Checkbox, 'behavior').isChecked(),
)
def _on_handling_toggled(self):
"""
Change the text on the behavior checkbox based on the append
or overwrite behavior.
"""
append = self.findChild(aqt.qt.QRadioButton, 'append')
behavior = self.findChild(Checkbox, 'behavior')
behavior.setText(
"Remove Existing [sound:xxx] Tag(s)" if append.isChecked()
else "Wrap the Filename in [sound:xxx] Tag"
)
behavior.setChecked(True)
def _on_behavior_changed(self):
"""
Display a warning about bare filenames if user selects the
override option and disables wrapping the field with a [sound]
tag.
"""
if self.isVisible():
append = self.findChild(aqt.qt.QRadioButton, 'append')
behavior = self.findChild(Checkbox, 'behavior')
if not (append.isChecked() or behavior.isChecked()):
self._alerts(
'Please note that if you use bare filenames, the "Check '
'Media" feature in Anki will not detect those audio '
"files as in-use, even if you insert the field into your "
"templates.",
self,
)
class EditorGenerator(ServiceDialog):
"""
Provides a dialog for adding single media files from the editors.
"""
HELP_USAGE_DESC = "Adding audio to a single note"
HELP_USAGE_SLUG = 'editor'
__slots__ = [
'_editor', # reference to one of the editors in the Anki GUI
]
def __init__(self, editor, *args, **kwargs):
"""
Sets our title.
"""
self._editor = editor
super(EditorGenerator, self).__init__(
title="Add TTS Audio to Note",
*args, **kwargs
)
# UI Construction ########################################################
def _ui_control(self):
"""
Replaces the superclass's version of this with a version that
returns a "Preview and Record" header, larger text input area,
and preview button on its own line.
"""
header = Label("Preview and Record")
header.setFont(self._FONT_HEADER)
text = aqt.qt.QTextEdit()
text.setAcceptRichText(False)
text.setObjectName('text')
text.setTabChangesFocus(True)
text.keyPressEvent = lambda key_event: \
self.accept() if (
key_event.modifiers() & aqt.qt.Qt.KeyboardModifier.ControlModifier and
key_event.key() in [aqt.qt.Qt.Key.Key_Return, aqt.qt.Qt.Key.Key_Enter]
) \
else aqt.qt.QTextEdit.keyPressEvent(text, key_event)
button = aqt.qt.QPushButton("&Preview")
button.setObjectName('preview')
button.clicked.connect(self._on_preview)
layout = aqt.qt.QVBoxLayout()
layout.addWidget(header)
layout.addWidget(Note("This will be inserted as a [sound] tag and "
"synchronized with your collection."))
layout.addWidget(text)
layout.addWidget(button)
layout.addWidget(self._ui_buttons())
return layout
def _ui_buttons(self):
"""
Adjust title of the OK button.
"""
buttons = super(EditorGenerator, self)._ui_buttons()
buttons.findChild(aqt.qt.QAbstractButton, 'okay').setText("&Record")
return buttons
# Events #################################################################
def show(self, *args, **kwargs):
"""
Focus the text area after displaying the dialog.
"""
super(EditorGenerator, self).show(*args, **kwargs)
aqt.qt.QTimer.singleShot(0, self._populate_input_field)
def _populate_input_field(self):
text = self.findChild(aqt.qt.QTextEdit, 'text')
text.setFocus()
editor = self._editor
web = editor.web
from_note = self._addon.strip.from_note
from_unknown = self._addon.strip.from_unknown
app = aqt.qt.QApplication
self.currentlySelectedFieldIndex = editor.currentField
def try_clipboard(subtype):
"""Fetch from given system clipboard."""
return from_unknown(app.clipboard().text(subtype)[0])
def get_current_field_text():
if editor.currentField != None:
# there is currently a selected field
if editor.note != None:
field_value = editor.note.values()[editor.currentField]
return field_value
return False
for origin in [
# first, check if user has selected any text
lambda: from_note(web.selectedText()),
# then, try extracting from the field
lambda: from_note(get_current_field_text()),
# then, try the HTML clipboard
lambda: try_clipboard('html'),
# then, try the text clipboard
lambda: try_clipboard('text'),
]:
try:
prefill = origin()
except BaseException: # e.g. oldaqt.qt.Qt.version, system errors
continue
if prefill:
text.setPlainText(prefill)
text.selectAll()
break
def accept(self):
"""
Given the user's options and text, calls the service to make a
recording. If successful, the options are remembered and the MP3
inserted into the field.
"""
now = self._get_all()
text_input, text_value = self._get_service_text()
def add_audio_tag_to_current_field(path):
self._addon.config.update(now)
super(EditorGenerator, self).accept()
current_field_index = self.currentlySelectedFieldIndex
if current_field_index != None:
# there is currently a selected field
if self._editor.note != None:
# add to end of field
field_value = self._editor.note.fields[current_field_index]
audio_tag = self._editor._addMedia(path)
updated_field_value = f'{field_value} {audio_tag}'
self._editor.note.fields[current_field_index] = updated_field_value
self._editor.set_note(self._editor.note)
return
# if we didn't return at this point, use fallback method
self._editor.addMedia(path)
svc_id = now['last_service']
text_value = self._addon.strip.from_user(text_value)
callbacks = dict(
done=lambda: self._disable_inputs(False),
okay=add_audio_tag_to_current_field,
fail=lambda exception, text_value: (
self._alerts("Cannot record the input phrase with these "
"settings.\n\n%s" % exception, self),
text_input.setFocus(),
),
)
want_human = (self._addon.config['filenames_human'] or '{{text}}' if
self._addon.config['filenames'] == 'human' else False)
self._disable_inputs()
if svc_id.startswith('group:'):
config = self._addon.config
self._addon.router.group(text=text_value,
group=config['groups'][svc_id[6:]],
presets=config['presets'],
callbacks=callbacks,
want_human=want_human,
note=self._editor.note)
else:
options = now['last_options'][now['last_service']]
self._addon.router(svc_id=svc_id,
text=text_value,
options=options,
callbacks=callbacks,
want_human=want_human,
note=self._editor.note)
class _Progress(Dialog):
"""
Provides a dialog that can be displayed while processing.
"""
__slots__ = [
'_maximum' # the value we are counting up to
'_on_cancel' # callable to invoke if the user hits cancel
]
def __init__(self, maximum, on_cancel, *args, **kwargs):
"""
Configures our bar's maximum and r이거 문제있어서 중간에 글추가해요.egisters a cancel callback.
"""
self._maximum = maximum
self._on_cancel = on_cancel
super(_Progress, self).__init__(*args, **kwargs)
# UI Construction ########################################################
def _ui(self):
"""
Builds the interface with a status label and progress bar.
"""
self.setMinimumWidth(500)
status = Note("Please wait...")
status.setAlignment(aqt.qt.Qt.AlignmentFlag.AlignCenter)
status.setObjectName('status')
progress_bar = aqt.qt.QProgressBar()
progress_bar.setMaximum(self._maximum)
progress_bar.setObjectName('bar')
detail = Note("")
detail.setAlignment(aqt.qt.Qt.AlignmentFlag.AlignCenter)
detail.setFixedHeight(100)
detail.setFont(self._FONT_INFO)
detail.setObjectName('detail')
detail.setScaledContents(True)
layout = super(_Progress, self)._ui()
layout.addStretch()
layout.addWidget(status)
layout.addStretch()
layout.addWidget(progress_bar)
layout.addStretch()
layout.addWidget(detail)
layout.addStretch()
layout.addWidget(self._ui_buttons())
return layout
def _ui_buttons(self):
"""
Overrides the default behavior to only have a cancel button.
"""
buttons = aqt.qt.QDialogButtonBox()
buttons.setObjectName('buttons')
buttons.rejected.connect(self.reject)
buttons.setStandardButtons(aqt.qt.QDialogButtonBox.StandardButton.Cancel)
buttons.button(aqt.qt.QDialogButtonBox.StandardButton.Cancel).setAutoDefault(False)
return buttons
# Events #################################################################
def reject(self):
"""
On cancel, disable the button and call our r이거 문제있어서 중간에 글추가해요.egistered callback.
"""
self.findChild(aqt.qt.QDialogButtonBox, 'buttons').setDisabled(True)
self._on_cancel()
def update(self, label, value, detail=None):
"""
Update the status text and bar.
"""
self.findChild(Note, 'status').setText(label)
self.findChild(aqt.qt.QProgressBar, 'bar').setValue(value)
if detail:
self.findChild(Note, 'detail').setText(detail)
유동 말고 고정 남겨봐 이따 시간 나면 한번 봐줌
ㅜㅜ 감사합니다... 감사합니다... 무한 감사합니다... 유동 말고 고정닉?? 디시 가입을 안해서... 잠시만 가입하고 올께
디시 가입하는 방법 이상하네...ㅜㅜ 만약 채팅같이 다른 채널 필요하면 바로 절차밟겠음!! 어차피 계속 여기 갤러리 눈팅하고 내가 쓴글 볼꺼니깐 답변해주면ㄱㅅ!!!
저 문장들이 어디 저장되어있고 어떻게 저 문장들을 읽는데?
어디서 받는진 모르겠는데 뒤져보기 귀찮아서 text 받아서 외부 tts api로 음성 파일 받아오는듯