#include "settings.h"
#include "html.h"
-#include "htmltag.h"
+#include "tmtext.h"
#include <QMutex>
#include <QMutexLocker>
return pointer(new HtmlData(node_, begin_, tail_));
}
-// TextConverter --------------------------------------------------------------
-
-/*!
- * \brief 引数として与えられたHtmlの範囲から構造化テキストを作成します。
- */
-Text::pointer TM::TextConverter::to_text(HtmlRange range)
-{
- m_state = 0;
- Text::pointer result = Text::create();
- int begin = 0;
-
- for(HtmlNode const &node : range)
- {
- if(node.type() != HtmlNode::Text) continue;
- Text::pointer p = stuff_text(result, node.value());
- if(!p) continue;
- int num = p->string().size();
- HtmlData::pointer hd = HtmlData::create(node, begin, begin + num - 1);
- p->set_data(hd);
- begin += num;
- }
- return result;
-}
-
-/*!
- * \brief 引数として与えられたノードから構造化テキストを作成します。
- *
- * 連続する空白文字を一つにまとめます。
- * 無効なノードが与えられた場合、空の構造化テキストを返します。
- */
-Text::pointer TM::TextConverter::stuff_text(Text::pointer parent, QString const &string)
-{
- QString outstring;
- for(QChar const &ch : string)
- {
- if(is_ignorable_white_space(ch)) continue;
- if(is_white_space(ch)) outstring.append(' ');
- else outstring.append(ch);
- }
- if(outstring.isEmpty()) return Text::pointer();
-
- Text::pointer result = Text::create(parent, outstring);
- parent->append(result);
- return result;
-}
-
-/*!
- * \brief 連続する空白文字を検出します。
- *
- * 最初の空白文字、あるいは空白文字以外は、falseを返します。
- * 連続する空白文字の二番目以降に対してのみtrueを返します。
- */
-bool TM::TextConverter::is_ignorable_white_space(const QChar &ch)
-{
- if(!is_white_space(ch))
- {
- m_state = 0;
- return false;
- }
- if(m_state == 0)
- {
- m_state = 1;
- return false;
- }
- return true;
-}
-
-/*!
- * \brief 引数として与えられたchが空白文字の場合true、それ以外の場合falseを返します。
- */
-bool TM::TextConverter::is_white_space(QChar const &ch)
-{
- switch(ch.unicode())
- {
- case 0x9:
- case 0xA:
- case 0xC:
- case 0xD:
- case 0x20:
- case 0x200B:
- return true;
- }
- return false;
-}
-
-// HtmlConverter --------------------------------------------------------------
-
-
-void TM::HtmlConverter::append(QString string)
-{
- HtmlText::pointer text = HtmlText::create(HtmlText::weak_pointer());
- text->set_value(string);
- m_nodes.append(text);
-}
-
-void TM::HtmlConverter::append(HtmlNode::pointer node, QString string)
-{
- QList<HtmlNode::pointer> left, right;
- for(HtmlNode hn = node->parent(); hn; hn = hn.parent())
- {
- if(hn.tname() == "body") break;
- left.prepend(hn.lself());
- right.append(hn.ltail());
- }
-
- m_nodes.append(left);
- append(string);
- m_nodes.append(right);
-}
-
-QString TM::HtmlConverter::to_string()
-{
- QString result;
-
- adjust();
- for(Html::pointer node : m_nodes) result += node->to_string();
-
- return result;
-}
-
-void TM::HtmlConverter::adjust()
-{
- int adjusted = 0;
- do
- {
- adjusted = 0;
- for(int i = 0; i < m_nodes.size() - 1; i++)
- {
- HtmlNode::pointer p1 = m_nodes.at(i);
- if(p1->type() != Html::Element || p1->place() != Html::Close) continue;
- HtmlNode::pointer p2 = m_nodes.at(i + 1);
- if(p2->type() != Html::Element || p2->place() != Html::Open) continue;
-
- if(p1->lbegin() == p2->lbegin())
- {
- m_nodes.removeAt(i);
- m_nodes.removeAt(i);
- ++adjusted;
- }
- }
- }
- while(adjusted);
-}
-
-// TextSegment ----------------------------------------------------------------
-
-TM::TextSegment::TextSegment(
- Service *service, int scode, int segment_id, QString source)
- : m_segment_id(segment_id)
- , m_document(source.toUtf8())
-{
- HtmlNode body = m_document.first("html").first("body");
- TextConverter tc;
- m_text = tc.to_text(HtmlRange(body, body));
-
- Text::pointer sentences = service->divide_into_sentences(scode, m_text->to_string());
- int i = 0;
- int previous_crc = 0;
- for(Text::pointer s = sentences->begin(); s; s = s->next()) // s: sentence
- {
- Text::pointer words = service->divide_into_words(scode, s);
- int crc = service->crc32(scode, words->to_string());
- TextSentence::pointer sentence =
- TextSentence::create(segment_id, i++, crc, words);
- sentence->set_previous_crc(previous_crc);
- m_sentences.append(sentence);
- previous_crc = crc;
- }
-
- int next_crc = 0;
- for(int i = m_sentences.size() - 1; 0 <= i; i--)
- {
- TextSentence::pointer sentence = m_sentences.at(i);
- sentence->set_next_crc(next_crc);
- next_crc = sentence->crc();
- }
-}
-
-int TM::TextSegment::segment_id() const { return m_segment_id; }
-
-int TM::TextSegment::size() const { return m_sentences.size(); }
-
-TM::TextSentence::pointer TM::TextSegment::at(int index)
-{
- assert(0 <= index && index < m_sentences.size());
- return m_sentences.at(index);
-}
-
-TM::TextSegment::iterator TM::TextSegment::begin() { return m_sentences.begin(); }
-
-TM::TextSegment::iterator TM::TextSegment::end() { return m_sentences.end(); }
-
-HtmlNode::pointer TM::TextSegment::find_html_node_by_offset(int offset)
-{
- HtmlNode::pointer result;
-
- for(Text::pointer p = m_text->begin(); p; p = p->next())
- {
- UserData::pointer ud = p->data();
- assert(ud->type() == HtmlData::Type);
- HtmlData *hd = static_cast<HtmlData*>(ud.get());
- if(hd->begin() <= offset && offset <= hd->tail())
- {
- result = hd->node().lself();
- break;
- }
- }
- return result;
-}
-
-/*!
- * \brief セグメント全体をHTML文字列に変換します。
- */
-QString TM::TextSegment::to_html()
-{
- QString result;
- for(TextSentence::pointer sentence : m_sentences)
- {
- if(!sentence->target_sentence())
- result += to_html_from_source(sentence);
- else result += to_html_from_target(sentence);
- result += "\r\n";
- }
- return result;
-}
-
-/*!
- * \brief 原文をHTMLに変換します。
- *
- * 訳文のついていない文のために在ります。
- */
-QString TM::TextSegment::to_html_from_source(TextSentence::pointer sentence)
-{
- HtmlConverter hc;
-
- UserData *ud = sentence->source_sentence()->data().get();
- assert(ud->type() == RangeData::Type);
- RangeData *rd = static_cast<RangeData*>(ud);
- int sentence_offset = rd->begin();
-
- Text::pointer source_sentence = sentence->source_sentence();
- if(!source_sentence) return "";
-
- for(Text::pointer word = source_sentence->begin(); word; word = word->next())
- {
- QString string = word->to_string();
- UserData *ud = word->data().get();
- assert(ud->type() == RangeData::Type);
- RangeData *rd = static_cast<RangeData*>(ud);
- int word_offset = sentence_offset + rd->begin();
- HtmlNode::pointer node = find_html_node_by_offset(word_offset);
- if(node) hc.append(node, string);
- else hc.append(string);
- }
- return hc.to_string();
-}
-
-/*!
- * \brief 訳文をHTMLに変換します。
- */
-QString TM::TextSegment::to_html_from_target(TextSentence::pointer sentence)
-{
- HtmlConverter hc;
-
- WordLinker* linker = sentence->linker();
- UserData *ud = sentence->source_sentence()->data().get();
- assert(ud->type() == RangeData::Type);
- RangeData *rd = static_cast<RangeData*>(ud);
- int sentence_offset = rd->begin();
-
- Text::pointer target_sentence = sentence->target_sentence();
- if(!target_sentence) return "";
-
- for(Text::pointer word = target_sentence->begin(); word; word = word->next())
- {
- QString string = word->to_string();
- WordLink::pointer link = linker->find(WordLink::Target, word);
- if(!link) hc.append(string);
- else
- {
- UserData::pointer ud = link->sources()->at(0)->data();
- assert(ud->type() == RangeData::Type);
- RangeData *rd = static_cast<RangeData*>(ud.get());
- int word_offset = sentence_offset + rd->begin();
- HtmlNode::pointer node = find_html_node_by_offset(word_offset);
- if(node) hc.append(node, string);
- else hc.append(string);
- }
- }
- return hc.to_string();
-}
-
-TM::TextSegment::pointer TM::TextSegment::create(
- Service *service, int scode, int segment_id, QString source)
-{
- return pointer(new TextSegment(service, scode, segment_id, source));
-}
-
// SocketConnection -----------------------------------------------------------
TM::SocketConnection::SocketConnection(Settings *settings, Service *service,
, m_editor_widget(editor_widget)
, m_site_id(0)
, m_edit_mode(false)
- , m_source_language_code(0)
+ , m_scode(0)
, m_target_language_code(0)
{
qRegisterMetaType<pointer>();
* \brief データベースへセンテンスの登録とブラウザへの反映を行います。
* \param segment_id セグメントのID。
* \param index センテンスのインデックス。
+ *
+ * エディタから呼び出されます。
*/
void TM::SocketConnection::save_sentence(int segment_id, int index)
{
set_edit_mode(edit_mode);
}
+void TM::SocketConnection::changeLanguage()
+{
+ QJsonObject json;
+ json["cmd"] = "reload";
+ send_message(json);
+}
+
/*!
* \brief ブラウザに編集モードを反映します。
*
void TM::SocketConnection::do_edit_segment(QJsonObject const &json)
{
assert(json.contains("segment_id"));
+ if(!json.contains("segment_id")) return;
int segment_id = json["segment_id"].toString().toInt();
segment_map_iterator it = m_segments.find(segment_id);
set_edit_mode(m_editor_widget->edit_mode());
- m_source_language_code = m_editor_widget->source_language();
+ m_scode = m_editor_widget->source_language();
m_target_language_code = m_editor_widget->target_language();
m_url = QUrl(json["url"].toString());
m_site_id = m_service->find_site_id(m_url.host());
// セグメントの挿入。
TextSegment::pointer segment = TextSegment::create(
- m_service, m_source_language_code, segment_id, html);
+ m_service, m_scode, segment_id, html);
m_segments.insert(segment_id, segment);
// センテンス完全一致訳文の検索。
{
m_service->find_sentence(
segment_id, sentence->index(),
- m_url.host(), m_source_language_code, m_target_language_code,
+ m_url.host(), m_scode, m_target_language_code,
sentence, pointer(this));
}
}