From 231cf75bf54e75c6bd4a5bd269b9edac0dcf1f85 Mon Sep 17 00:00:00 2001
From: precondition <57645186+precondition@users.noreply.github.com>
Date: Thu, 23 Jan 2025 13:20:44 +0100
Subject: [PATCH] src/anki/ankiclient: add {pitch-categories} marker
This marker is a comma-separated list of all the distinct pitch accent
categories applicable to the term.
Available pitch accent categories:
1. heiban
2. atamadaka
3. nakadaka
4. kifuku
5. odaka
Partially solves #250.
---
src/anki/ankiclient.cpp | 70 +++++++-
src/anki/ankiclient.h | 29 +++-
src/gui/widgets/settings/ankisettings.cpp | 1 +
src/gui/widgets/settings/ankisettingshelp.ui | 162 +++++++++++--------
4 files changed, 184 insertions(+), 78 deletions(-)
diff --git a/src/anki/ankiclient.cpp b/src/anki/ankiclient.cpp
index 99269b7..c3f8a08 100644
--- a/src/anki/ankiclient.cpp
+++ b/src/anki/ankiclient.cpp
@@ -1124,9 +1124,12 @@ QJsonObject AnkiClient::createAnkiNoteObject(
);
QString pitch;
+ QString pitchCategories;
QString pitchGraph;
QString pitchPosition;
- buildPitchInfo(term.pitches, pitch, pitchGraph, pitchPosition);
+ const bool canBeKifuku{isKifukuApplicable(term.definitions)};
+ buildPitchInfo(term.pitches, canBeKifuku, pitch, pitchCategories,
+ pitchGraph, pitchPosition);
QString tags, tagsBrief;
buildTags(term.tags, tags, tagsBrief);
@@ -1152,6 +1155,7 @@ QJsonObject AnkiClient::createAnkiNoteObject(
value.replace(REPLACE_GLOSSARY_BRIEF, glossaryBrief);
value.replace(REPLACE_GLOSSARY_COMPACT, glossaryCompact);
value.replace(REPLACE_PITCH, pitch);
+ value.replace(REPLACE_PITCH_CATEGORIES, pitchCategories);
value.replace(REPLACE_PITCH_GRAPHS, pitchGraph);
value.replace(REPLACE_PITCH_POSITIONS, pitchPosition);
value.replace(REPLACE_READING, reading);
@@ -1556,7 +1560,9 @@ void AnkiClient::buildCommonNote(
#define PITCH_FORMAT (QString("%2"))
void AnkiClient::buildPitchInfo(const QList &pitches,
+ const bool canBeKifuku,
QString &pitch,
+ QString &pitchCategories,
QString &pitchGraph,
QString &pitchPosition)
{
@@ -1569,6 +1575,8 @@ void AnkiClient::buildPitchInfo(const QList &pitches,
pitchGraph += "";
pitchPosition += "";
+ QSet pitchCategoriesSet{};
+
const bool multipleDicts = pitches.size() > 1;
if (multipleDicts)
@@ -1611,10 +1619,11 @@ void AnkiClient::buildPitchInfo(const QList &pitches,
pitchPosition += "";
}
- /* Build {pitch} marker */
+ /* Build {pitch} and {pitch-categories} markers */
switch (pos)
{
case 0:
+ pitchCategoriesSet << "heiban";
pitch += p.mora.first();
if (p.mora.size() > 1)
{
@@ -1624,6 +1633,7 @@ void AnkiClient::buildPitchInfo(const QList &pitches,
}
break;
case 1:
+ pitchCategoriesSet << (canBeKifuku ? "kifuku" : "atamadaka");
pitch += PITCH_FORMAT.arg(HL_STYLE).arg(p.mora.first());
if (p.mora.size() > 1)
{
@@ -1632,6 +1642,18 @@ void AnkiClient::buildPitchInfo(const QList &pitches,
break;
default:
{
+ if (p.mora.size() == pos)
+ {
+ pitchCategoriesSet << "odaka";
+ }
+ else if (canBeKifuku)
+ {
+ pitchCategoriesSet << "kifuku";
+ }
+ else
+ {
+ pitchCategoriesSet << "nakadaka";
+ }
QString text = p.mora.first();
pitch += text;
@@ -1698,6 +1720,20 @@ void AnkiClient::buildPitchInfo(const QList &pitches,
pitch += "";
pitchGraph += "";
pitchPosition += "";
+
+ bool isFirstPitchCategory{true};
+ for (const QString &pitchCategory : pitchCategoriesSet)
+ {
+ if (isFirstPitchCategory)
+ {
+ pitchCategories += pitchCategory;
+ isFirstPitchCategory = false;
+ }
+ else
+ {
+ pitchCategories += "," + pitchCategory;
+ }
+ }
}
#undef HL_STYLE
@@ -1905,4 +1941,34 @@ QString AnkiClient::fileToBase64(const QString &path)
return file.readAll().toBase64();
}
+bool AnkiClient::isKifukuApplicable(const QList &defs)
+{
+ bool canBeKifuku{false};
+
+ for (const TermDefinition &def : defs)
+ {
+ for (const QString &rule : def.rules)
+ {
+ /* See http://www.edrdg.org/jmwsgi/edhelp.py?svc=jmdict&sid=#kw_pos
+ * for more information on the meaning of JMDict part-of-speech tags
+ * such as "v1", "adj-i", etc.
+ */
+ if (rule == "v1" || // Ichidan verb
+ rule == "v5" || // Godan verb
+ rule == "vk" || // Kuru verb - special class
+ rule == "vz" || // Ichidan verb - zuru verb (alternative form of -jiru verb)
+ rule == "adj-i") // I-adjective (keiyoushi)
+ {
+ canBeKifuku = true;
+ }
+ else if (rule == "vs") // Noun or participle which takes the aux. verb suru
+ {
+ return false;
+ }
+ }
+ }
+
+ return canBeKifuku;
+}
+
/* End Note Helpers */
diff --git a/src/anki/ankiclient.h b/src/anki/ankiclient.h
index c95df5b..11a3993 100644
--- a/src/anki/ankiclient.h
+++ b/src/anki/ankiclient.h
@@ -63,6 +63,7 @@
#define REPLACE_GLOSSARY_BRIEF "{glossary-brief}"
#define REPLACE_GLOSSARY_COMPACT "{glossary-compact}"
#define REPLACE_PITCH "{pitch}"
+#define REPLACE_PITCH_CATEGORIES "{pitch-categories}"
#define REPLACE_PITCH_GRAPHS "{pitch-graph}"
#define REPLACE_PITCH_POSITIONS "{pitch-position}"
#define REPLACE_READING "{reading}"
@@ -477,17 +478,23 @@ private Q_SLOTS:
int getFrequencyAverage(const QList &freq);
/**
- * Creates the HTML representation of the pitch, pitch graph, and pitch
- * position for the given pitches.
- * @param pitches The pitches to turn into HTML.
- * @param[out] pitch The HTML representation of the {pitch} marker.
- * @param[out] pitchGraph The HTML representation of the {pitch-graph}
- * marker.
- * @param[out] pitchPosition The HTML representation of the {pitch-position}
- * marker.
+ * Creates the HTML representation of the pitch, pitch category, pitch graph,
+ * and pitch position for the given pitches.
+ * @param pitches The pitches to turn into HTML.
+ * @param canBeKifuku Is the term an i-adjective or a verb whose
+ * pitch accent is either kifuku or heiban.
+ * @param[out] pitch The HTML representation of the {pitch} marker.
+ * @param[out] pitchCategories The comma-separated representation of the
+ * {pitch-categories} marker.
+ * @param[out] pitchGraph The HTML representation of the {pitch-graph}
+ * marker.
+ * @param[out] pitchPosition The HTML representation of the {pitch-position}
+ * marker.
*/
void buildPitchInfo(const QList &pitches,
+ const bool canBeKifuku,
QString &pitch,
+ QString &pitchCategories,
QString &pitchGraph,
QString &pitchPosition);
@@ -530,6 +537,12 @@ private Q_SLOTS:
*/
static QString fileToBase64(const QString &path);
+ /**
+ * Helper method to determine if the kifuku pitch accent pattern
+ * is potentially applicable to a term, by checking its part-of-speech.
+ */
+ bool isKifukuApplicable(const QList &defs);
+
/* true if a config exists, false otherwise */
bool m_configExists = false;
diff --git a/src/gui/widgets/settings/ankisettings.cpp b/src/gui/widgets/settings/ankisettings.cpp
index a753e02..1c36a30 100644
--- a/src/gui/widgets/settings/ankisettings.cpp
+++ b/src/gui/widgets/settings/ankisettings.cpp
@@ -72,6 +72,7 @@ AnkiSettings::AnkiSettings(QWidget *parent)
REPLACE_GLOSSARY_BRIEF,
REPLACE_GLOSSARY_COMPACT,
REPLACE_PITCH,
+ REPLACE_PITCH_CATEGORIES,
REPLACE_PITCH_GRAPHS,
REPLACE_PITCH_POSITIONS,
REPLACE_READING,
diff --git a/src/gui/widgets/settings/ankisettingshelp.ui b/src/gui/widgets/settings/ankisettingshelp.ui
index 7a57f20..9b5c493 100644
--- a/src/gui/widgets/settings/ankisettingshelp.ui
+++ b/src/gui/widgets/settings/ankisettingshelp.ui
@@ -62,14 +62,14 @@ These will expand to larger expressions in the final card.
- -
+
-
Screenshot of the current frame.
- -
+
-
Title of the video. Filename if no title.
@@ -95,14 +95,7 @@ These will expand to larger expressions in the final card.
- -
-
-
- Pitch graphs for the reading of the term.
-
-
-
- -
+
-
@@ -128,7 +121,7 @@ These will expand to larger expressions in the final card.
- -
+
-
@@ -154,7 +147,7 @@ These will expand to larger expressions in the final card.
- -
+
-
The reading of the word in kana.
@@ -202,7 +195,7 @@ These will expand to larger expressions in the final card.
- -
+
-
Screenshot of the current frame without subtitles if visible.
@@ -228,7 +221,7 @@ These will expand to larger expressions in the final card.
- -
+
-
The current secondary subtitle.
@@ -261,6 +254,63 @@ These will expand to larger expressions in the final card.
+ -
+
+
+
+ 75
+ true
+
+
+
+ {pitch-categories}
+
+
+ Qt::AlignCenter
+
+
+ Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+
+ 75
+ true
+
+
+
+ {pitch-graph}
+
+
+ Qt::AlignCenter
+
+
+ Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+
+ 75
+ true
+
+
+
+ {pitch-position}
+
+
+ Qt::AlignCenter
+
+
+ Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse
+
+
+
-
@@ -322,14 +372,7 @@ These will expand to larger expressions in the final card.
- -
-
-
- Pitch positions for the reading of the term.
-
-
-
- -
+
-
@@ -420,25 +463,6 @@ These will expand to larger expressions in the final card.
- -
-
-
-
- 75
- true
-
-
-
- {pitch-graph}
-
-
- Qt::AlignCenter
-
-
- Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse
-
-
-
-
@@ -458,7 +482,7 @@ These will expand to larger expressions in the final card.
- -
+
-
Bulleted list of the term tags.
@@ -640,26 +664,7 @@ These will expand to larger expressions in the final card.
- -
-
-
-
- 75
- true
-
-
-
- {pitch-position}
-
-
- Qt::AlignCenter
-
-
- Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse
-
-
-
- -
+
-
@@ -698,7 +703,7 @@ These will expand to larger expressions in the final card.
- -
+
-
@@ -724,7 +729,28 @@ These will expand to larger expressions in the final card.
- -
+
-
+
+
+ Comma-separated list of pitch accent categories for the term: heiban, kifuku, atamadaka, nakadaka, odaka
+
+
+
+ -
+
+
+ Pitch graphs for the reading of the term.
+
+
+
+ -
+
+
+ Pitch positions for the reading of the term.
+
+
+
+ -
The current subtitle.
@@ -773,7 +799,7 @@ These will expand to larger expressions in the final card.
- -
+
-
@@ -792,7 +818,7 @@ These will expand to larger expressions in the final card.
- -
+
-
@@ -811,14 +837,14 @@ These will expand to larger expressions in the final card.
- -
+
-
Bulleted list of the term tags without description.
- -
+
-