파이썬 관련해서 질문좀 하겠습니다...tts 프로그램을 쓰다보면,?-1f1f7; 이렇게 생긴 이모지가 포함된 문장이 있다고 가정한다면,예를들자면,gall.dcinside.com


아래 글쓴 사람인데, generator.py 파일 입니다 [1/2]https://gall.dcinside.com/board/view/?id=programming&no=2612215&page=1 파이썬 관련해서 질문좀 하겠습니다... - 프로그래밍 갤러gall.dcinside.com



이글 이어서 올립니다...



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)