From: wordring Date: Sat, 15 Aug 2015 22:26:59 +0000 (+0900) Subject: ソケットの終了処理追加。 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=fc5c863e3c8872841801073eb5afe2918ac327e6;p=wordring-tm%2Fwordring-tm.git ソケットの終了処理追加。 --- diff --git a/html/htmlparser.cpp b/html/htmlparser.cpp index 51e14fc..78fb378 100644 --- a/html/htmlparser.cpp +++ b/html/htmlparser.cpp @@ -120,8 +120,7 @@ bool HtmlHandler::comment(QString const &ch) bool HtmlHandler::fatalError(const QXmlParseException & exception) { - //m_document->m_error_message = exception.message(); - qDebug() << exception.message(); + qCritical() << exception.message(); return false; } @@ -135,11 +134,27 @@ bool HtmlHandler::fatalError(const QXmlParseException & exception) // bool HtmlHandler::ignorableWhitespace(QString const &ch) { return true; } // bool HtmlHandler::internalEntityDecl(QString const &name, QString const &value) { return true; } // bool HtmlHandler::processingInstruction(QString const &target, QString const &data) { return true; } -// bool HtmlHandler::resolveEntity(QString const &publicId, QString const &systemId, QXmlInputSource *& ret) { return true; } +/* +bool HtmlHandler::resolveEntity(QString const &publicId, QString const &systemId, QXmlInputSource *& ret) +{ + qDebug() << "HtmlHandler::resolveEntity:" << publicId << ", " << systemId; + ret = 0; + return true; +} +*/ // void HtmlHandler::setDocumentLocator(QXmlLocator * locator) { return true; } -// bool HtmlHandler::skippedEntity(QString const &name) { return true; } +bool HtmlHandler::skippedEntity(QString const &name) +{ + if(name == "nbsp") return characters(" "); + return true; +} // bool HtmlHandler::startCDATA() { return true; } - -// bool HtmlHandler::startEntity(QString const &name) { return true; } +/* +bool HtmlHandler::startEntity(QString const &name) +{ + qDebug() << "HtmlHandler::startEntity: " << name; + return true; +} +*/ // bool HtmlHandler::startPrefixMapping(QString const &prefix, QString const &uri) { return true; } // bool HtmlHandler::warning(const QXmlParseException & exception) { return true; } diff --git a/html/htmlparser.h b/html/htmlparser.h index eb238bf..2e697a4 100644 --- a/html/htmlparser.h +++ b/html/htmlparser.h @@ -46,7 +46,7 @@ public: // virtual bool attributeDecl(QString const &eName, QString const &aName, //QString const &type, QString const &valueDefault, QString const &value); - virtual bool comment(string_type const &ch); + bool comment(string_type const &ch); // virtual bool endCDATA(); // virtual bool endEntity(QString const &name); // virtual bool endPrefixMapping(QString const &prefix); @@ -57,12 +57,12 @@ public: // virtual bool ignorableWhitespace(QString const &ch); // virtual bool internalEntityDecl(QString const &name, QString const &value); // virtual bool processingInstruction(QString const &target, QString const &data); -// virtual bool resolveEntity(QString const &publicId, QString const &systemId, QXmlInputSource *&ret); +// bool resolveEntity(QString const &publicId, QString const &systemId, QXmlInputSource *&ret); // virtual void setDocumentLocator(QXmlLocator * locator); -// virtual bool skippedEntity(QString const &name); + bool skippedEntity(QString const &name); // virtual bool startCDATA(); -// virtual bool startEntity(QString const &name); +// bool startEntity(QString const &name); // virtual bool startPrefixMapping(QString const &prefix, QString const &uri); // virtual bool warning(QXmlParseException const &exception); diff --git a/languages/english/english.cpp b/languages/english/english.cpp index 9836618..6f057ea 100644 --- a/languages/english/english.cpp +++ b/languages/english/english.cpp @@ -50,9 +50,7 @@ Text::pointer EnglishPlugin::divide_into_sentences(QString string_) case 3: if('A' <= c && c <= 'Z') { - Text::pointer s = Text::create(result, cstring); - s->set_data(RangeData::create(begin_, tail_)); - result->append(s); + stuff_sentence(result, cstring, begin_, tail_); cstring.clear(); goto s0; } @@ -62,12 +60,7 @@ Text::pointer EnglishPlugin::divide_into_sentences(QString string_) tail_ = i; cstring.push_back(c); } - if(!cstring.isEmpty()) - { - Text::pointer s = Text::create(result, cstring); - s->set_data(RangeData::create(begin_, tail_)); - result->append(s); - } + if(!cstring.isEmpty()) stuff_sentence(result, cstring, begin_, tail_); return result; } @@ -107,3 +100,30 @@ Text::pointer EnglishPlugin::divide_into_words(Text::pointer sentence) return result; } +QString EnglishPlugin::normalize(QString string) +{ + return string.toLower(); +} + +void EnglishPlugin::stuff_sentence(Text::pointer parent, QString string, + int begin_, int tail_) +{ + // 先頭の空白文字を取り除く。 + while(string.startsWith(' ')) + { + string.remove(0, 1); + ++begin_; + } + // 後方の空白文字を取り除く。 + while(string.endsWith(' ')) + { + string.remove(string.size() - 1, 1); + --tail_; + } + if(string.isEmpty()) return; // 空白文字を取り除いた結果、空になった場合、ここで終わる。 + + // センテンス追加。 + Text::pointer s = Text::create(parent, string); + s->set_data(RangeData::create(begin_, tail_)); + parent->append(s); +} diff --git a/languages/english/english.h b/languages/english/english.h index fa45c05..a636fb7 100644 --- a/languages/english/english.h +++ b/languages/english/english.h @@ -25,6 +25,12 @@ public: Text::pointer divide_into_sentences(QString string); Text::pointer divide_into_words(Text::pointer sentence); + QString normalize(QString string); + +private: + void stuff_sentence(Text::pointer parent, QString string, + int begin_, int tail_); + private: Settings const *m_settings; }; diff --git a/languages/japanese/japanese.cpp b/languages/japanese/japanese.cpp index 296496c..c99745a 100644 --- a/languages/japanese/japanese.cpp +++ b/languages/japanese/japanese.cpp @@ -80,7 +80,10 @@ Text::pointer JapanesePlugin::divide_into_words(Text::pointer sentence) return result; } - +QString JapanesePlugin::normalize(QString string) +{ + return string; +} diff --git a/languages/japanese/japanese.h b/languages/japanese/japanese.h index 1cb0097..18f53db 100644 --- a/languages/japanese/japanese.h +++ b/languages/japanese/japanese.h @@ -28,6 +28,8 @@ public: Text::pointer divide_into_sentences(QString string); Text::pointer divide_into_words(Text::pointer sentence); + QString normalize(QString string); + private: Settings const *m_settings; diff --git a/languages/language/language.h b/languages/language/language.h index a2cff78..43576be 100644 --- a/languages/language/language.h +++ b/languages/language/language.h @@ -65,6 +65,10 @@ public: return result; } + /*! + * \brief 引数として与えられた文字列を正規化して返します。 + */ + virtual QString normalize(QString string) = 0; }; Q_DECLARE_INTERFACE(Language, "net.wordring.tm.language/1.0") diff --git a/proxy/main.cpp b/proxy/main.cpp index 2591b69..f6f09e9 100644 --- a/proxy/main.cpp +++ b/proxy/main.cpp @@ -49,6 +49,9 @@ int main(int argc, char *argv[]) if(!settings.contains("SocketServer/port")) settings.setValue("SocketServer/port", 8081); // ProxyModule if(!settings.contains("ProxyModule/prefix")) settings.setValue("ProxyModule/prefix", "/?"); + // ProxyHandler + if(!settings.contains("ProxyHandler/jscode")) + settings.setValue("ProxyHandler/jscode", "C:/Users/Kouichi/Documents/OSDN/wordring-tm/proxy/tm.js"); // Database if(!settings.contains("Database/root")) @@ -64,11 +67,12 @@ int main(int argc, char *argv[]) service->load_languages(QApplication::applicationDirPath() + "/plugins"); HttpServer *server = new HttpServer(&settings, &w); + w.set_http_port(server->port()); - TM::SocketServer *socket = new TM::SocketServer(&settings, w.editor_widget(), &w); + TM::SocketServer *socket = new TM::SocketServer(&settings, service, w.editor_widget(), &w); server->install(new TM::ProxyModule( - "/tm?", server->port(), socket->port(), server)); + &settings, server->port(), socket->port(), server)); QObject::connect(&w, SIGNAL(closing()), socket, SLOT(abort())); w.show(); diff --git a/proxy/mainwindow.cpp b/proxy/mainwindow.cpp index cf0b6eb..e948868 100644 --- a/proxy/mainwindow.cpp +++ b/proxy/mainwindow.cpp @@ -42,6 +42,11 @@ MainWindow::~MainWindow() TM::EditorWidget* MainWindow::editor_widget() { return m_editor_widget; } +void MainWindow::set_http_port(quint16 http_port) +{ + editor_widget()->set_http_port(http_port); +} + void MainWindow::closeEvent(QCloseEvent *ev) { emit closing(); diff --git a/proxy/mainwindow.h b/proxy/mainwindow.h index 156f6ab..1d1d85b 100644 --- a/proxy/mainwindow.h +++ b/proxy/mainwindow.h @@ -26,6 +26,7 @@ public: ~MainWindow(); TM::EditorWidget* editor_widget(); + void set_http_port(quint16 http_port); signals: void closing(); diff --git a/proxy/tm.js b/proxy/tm.js index 9330053..4869f50 100644 --- a/proxy/tm.js +++ b/proxy/tm.js @@ -63,7 +63,8 @@ window.wordring = { }, onerror: function(ev) { - document.location.href = 'http://www.yahoo.co.jp/'; }, + //document.location.href = 'http://www.yahoo.co.jp/'; + }, onclose: function(ev) { //alert('接続が閉じられました'); diff --git a/proxy/tmdatabase.cpp b/proxy/tmdatabase.cpp index 93a55ea..731c5dd 100644 --- a/proxy/tmdatabase.cpp +++ b/proxy/tmdatabase.cpp @@ -213,8 +213,7 @@ TM::SentenceDatabase::SentenceDatabase(Settings *settings, int site_id, QString "CREATE TABLE IF NOT EXISTS sentences(" "sentence_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," "crc INTEGER," - "source_id INTEGER," - "sentence TEXT," + "UNIQUE(source_id INTEGER, sentence TEXT)," "json TEXT," "user_id INTEGER," "time TIMESTAMP);"); @@ -225,9 +224,11 @@ TM::SentenceDatabase::SentenceDatabase(Settings *settings, int site_id, QString q = m_database.exec("CREATE INDEX IF NOT EXISTS crc_index ON sentences(crc);"); if(q.lastError().isValid()) qFatal("An error occured while create index in SentenceDatabase()."); + q = m_database.exec("CREATE INDEX IF NOT EXISTS source_id_index ON sentences(source_id);"); if(q.lastError().isValid()) qFatal("An error occured while create index in SentenceDatabase()."); + q = m_database.exec("CREATE INDEX IF NOT EXISTS sentence_index ON sentences(sentence);"); if(q.lastError().isValid()) qFatal("An error occured while create index in SentenceDatabase()."); @@ -235,15 +236,21 @@ TM::SentenceDatabase::SentenceDatabase(Settings *settings, int site_id, QString // クエリ作成。 m_find_sentence_id.reset(new QSqlQuery(m_database)); ret = m_find_sentence_id->prepare("SELECT sentence_id FROM sentences WHERE sentence=?;"); - if(!ret) qFatal("An error occured while prepare select statement in SentenceDatabase()."); + if(!ret) qFatal("An error occured while prepare find_sentence_id statement in SentenceDatabase()."); + + m_find_sentence_by_crc.reset(new QSqlQuery(m_database)); + ret = m_find_sentence->prepare("SELECT * FROM sentences WHERE crc=?;"); + if(!ret) qFatal("An error occured while prepare find_sentence_by_crc statement in SentenceDatabase()."); + + m_find_sentence_by_source_id.reset(new QSqlQuery(m_database)); + ret = m_find_sentence->prepare("SELECT * FROM sentences WHERE source_id=?;"); + if(!ret) qFatal("An error occured while prepare select_by_crc statement in SentenceDatabase()."); m_insert_sentence.reset(new QSqlQuery(m_database)); ret = m_insert_sentence->prepare( - "INSERT INTO sentences(crc, source_id, sentence, json, user_id, time) " + "INSERT OR REPLACE INTO sentences(crc, source_id, sentence, json, user_id, time) " "VALUES(?, ?, ?, ?, ?, ?);"); if(!ret) qFatal("An error occured while prepare insert statement in SentenceDatabase()."); - - } TM::SentenceDatabase::~SentenceDatabase() @@ -263,6 +270,12 @@ int TM::SentenceDatabase::sentence_id(QString sentence) return 0; } +/*bool TM::SentenceDatabase::find_sentence(QString sentence, + QString *tsentence, QJsonArray *json) +{ + +} +*/ void TM::SentenceDatabase::insert(int source_id, QString sentence, QString json, int user_id) { QSqlQuery *q = m_insert_sentence.get(); @@ -383,4 +396,19 @@ int TM::Database::find_sentence_id(int site_id, int code, QString sentence) return p->sentence_id(sentence); } +bool TM::Database::find_sentence(int site_id, int scode, QString ssentence, int tcode, + QString *tsentence, QJsonArray *json) +{ + SentenceDatabase::pointer p = find_sentence_database(site_id, scode); + //p->; + + return true; +} + +void TM::Database::insert_sentence(int site_id, int code, int source_id, + QString sentence, QString json, int user_id) +{ + +} + QString TM::Database::root_key() { return "Database/root"; } diff --git a/proxy/tmdatabase.h b/proxy/tmdatabase.h index e1fdc70..b60165c 100644 --- a/proxy/tmdatabase.h +++ b/proxy/tmdatabase.h @@ -96,6 +96,14 @@ public: ~SentenceDatabase(); int sentence_id(QString sentence); + +// bool find_sentence_by_source_sentence( +// QString sentence, QString *tsentence, QJsonArray *json = nullptr); + bool find_sentence_by_crc( + quint32 crc, QString *tsentence, QJsonArray *json = nullptr); + bool find_sentence_by_source_id( + int source_id, QString *tsentence, QJsonArray *json = nullptr); + void insert(int source_id, QString sentence, QString json, int user_id); private: @@ -110,6 +118,9 @@ private: QSqlDatabase m_database; query_pointer m_find_sentence_id; + query_pointer m_find_sentence; + query_pointer m_find_sentence_by_crc; + query_pointer m_find_sentence_by_source_id; query_pointer m_insert_sentence; }; @@ -131,9 +142,14 @@ public: void open_word_database(int code, QString name); int find_word_id(int code, QString word); - +private: SentenceDatabase::pointer find_sentence_database(int site_id, int code); +public: int find_sentence_id(int site_id, int code, QString sentence); + bool find_sentence(int site_id, int scode, QString ssentence, int tcode, + QString *tsentence, QJsonArray *json); + void insert_sentence(int site_id, int code, int source_id, + QString sentence, QString json, int user_id); static QString root_key(); signals: diff --git a/proxy/tmeditorwidget.cpp b/proxy/tmeditorwidget.cpp index b4c5daa..c281604 100644 --- a/proxy/tmeditorwidget.cpp +++ b/proxy/tmeditorwidget.cpp @@ -37,6 +37,7 @@ TM::EditorWidget::EditorWidget(Settings *settings, Service *service, QWidget *pa , m_mutex(QMutex::Recursive) , m_service(service) , m_settings(settings) + , m_http_port(80) , m_socket(nullptr) { QVBoxLayout *vlayout = new QVBoxLayout(this); @@ -111,6 +112,8 @@ void TM::EditorWidget::detach(SocketConnection *) m_socket = nullptr; } +void TM::EditorWidget::set_http_port(quint16 http_port) { m_http_port = http_port; } + /*! * \brief 編集モードを変更します。 */ @@ -123,12 +126,18 @@ void TM::EditorWidget::set_edit_mode(bool mode) m_edit_mode->setChecked(mode); } +/*! + * \brief 編集モードの場合trueを返します。 + */ bool TM::EditorWidget::edit_mode() { QMutexLocker lock(&m_mutex); return m_edit_mode->isChecked(); } +/*! + * \brief リンクモードを設定します。 + */ void TM::EditorWidget::set_link_mode(bool mode) { QMutexLocker lock(&m_mutex); @@ -138,6 +147,9 @@ void TM::EditorWidget::set_link_mode(bool mode) m_link->setChecked(mode); } +/*! + * \brief リンクモードの場合、trueを返します。 + */ bool TM::EditorWidget::link_mode() { QMutexLocker lock(&m_mutex); @@ -155,12 +167,18 @@ void TM::EditorWidget::set_link_mode_disabled(bool disable) m_link->setDisabled(disable); } +/*! + * \brief 原文の言語コードを返します。 + */ int TM::EditorWidget::source_language() { QMutexLocker lock(&m_mutex); return m_slang->data().toInt(); } +/*! + * \brief 訳文の言語コードを返します。 + */ int TM::EditorWidget::target_language() { QMutexLocker lock(&m_mutex); @@ -182,6 +200,12 @@ void TM::EditorWidget::set_string(QString source_, QString target_) m_edit->set_sentences(result); } +/*! + * \brief 言語プラグインが読み込まれるたびに呼び出されます。 + * \param code 言語コード。 + * \param name 言語名。 + * \param icon 言語を表すアイコン。 + */ void TM::EditorWidget::onLanguageLoaded(int code, QString name, QIcon icon) { QString dslanguage = m_settings->value("Widget/defaultSourceLanguage", "English").toString(); @@ -204,6 +228,9 @@ void TM::EditorWidget::onLanguageLoaded(int code, QString name, QIcon icon) connect(taction, SIGNAL(triggered(bool)), this, SLOT(onTargetLanguageTriggered(bool))); } +/*! + * \brief 編集アイコンがクリックされたとき呼び出されます。 + */ void TM::EditorWidget::onEditModeTriggered(bool) { QAction *edit_mode = qobject_cast(sender()); @@ -216,12 +243,18 @@ void TM::EditorWidget::onEditModeTriggered(bool) m_edit->set_edit_mode(checked); } +/*! + * \brief リンクアイコンがクリックされたとき呼び出されます。 + */ void TM::EditorWidget::onLinkModeTriggered(bool checked) { //QAction *link_mode = qobject_cast(sender()); m_edit->set_link_mode(checked); } +/*! + * \brief アクションから原文言語が変更されたとき呼び出されます。 + */ void TM::EditorWidget::onSourceLanguageTriggered(bool) { QAction *saction = qobject_cast(sender()); @@ -230,18 +263,26 @@ void TM::EditorWidget::onSourceLanguageTriggered(bool) m_slang->setData(saction->data()); } +/*! + * \brief アクションから訳文言語が変更されたとき呼び出されます。 + */ void TM::EditorWidget::onTargetLanguageTriggered(bool) { QAction *taction = qobject_cast(sender()); assert(taction); m_tlang->setIcon(taction->icon()); m_tlang->setData(taction->data()); - } +/*! + * \brief ブラウザ・アイコンがクリックされたとき呼び出されます。 + */ void TM::EditorWidget::onBrowserTriggered(bool) { - QDesktopServices::openUrl(QUrl("http://localhost/")); + QString url("http://localhost:"); + url += QString::number(m_http_port) + "/"; + + QDesktopServices::openUrl(QUrl(url)); } // EditorPanel ---------------------------------------------------------------- @@ -252,14 +293,23 @@ TM::EditorPanel::EditorPanel(QWidget *parent) { } +/*! + * \brief 親となるエディタを設定します。 + */ void TM::EditorPanel::set_editor(Editor *editor) { assert(!m_editor); m_editor = editor; } +/*! + * \brief 保持している文を返します。 + */ Text::pointer TM::EditorPanel::sentence() { return m_sentence; } +/*! + * \brief 文を設定します。 + */ void TM::EditorPanel::set_sentence(Text::pointer sentence) { assert(sentence); @@ -275,16 +325,14 @@ void TM::EditorPanel::set_sentence(Text::pointer sentence) } } -bool TM::EditorPanel::is_empty() const -{ - qDebug() << document()->isEmpty(); - return document()->isEmpty(); - if(!m_sentence) return true; - for(Text::const_pointer p = m_sentence->begin(); p; p = p->next()) - if(!p->string().isEmpty()) return true; - return false; -} +/*! + * \brief 内容が空の場合、trueを返します。 + */ +bool TM::EditorPanel::is_empty() const { return document()->isEmpty(); } +/*! + * \brief 引数として与えられた単語に該当する範囲を選択するカーソルを返します。 + */ QTextCursor TM::EditorPanel::select_cursor(Text::pointer word) { RangeData *rd = static_cast(word->data().get()); @@ -297,6 +345,9 @@ QTextCursor TM::EditorPanel::select_cursor(Text::pointer word) return c; } +/*! + * \brief 引数として与えられた位置にある単語を返します。 + */ Text::pointer TM::EditorPanel::select_word(QPoint const &pos) { QTextCursor c = cursorForPosition(pos); @@ -373,6 +424,9 @@ TM::WordLinker* TM::SourcePanel::linker() return &m_linker; } +/*! + * \brief 保持するリンクを色分け表示します。 + */ void TM::SourcePanel::ensure_highlight() { clear_highlight(); @@ -457,6 +511,7 @@ TM::TargetPanel::TargetPanel(QWidget *parent) : EditorPanel(parent) , m_source_panel(nullptr) , m_text_dirty(false) + , m_text_saved(true) { //setContextMenuPolicy(Qt::NoContextMenu); } @@ -472,14 +527,42 @@ void TM::TargetPanel::set_sentence(Text::pointer sentence) { EditorPanel::set_sentence(sentence); set_text_dirty(false); + set_text_saved(false); +} + +/*! + * \brief データベースへの登録が必要な場合、falseを返します。 + * + * パネル内の文字列が編集された場合、trueを返します。 + * 原文パネルがフォーカスを失うと、エディタがこのメンバを呼び出し、 + * データベース登録の必要性を判定します。 + * その後、エディタはデータベース登録を行い、フラグをクリアするので、 + * 次に文字列が編集されるまでtrueを返し続けます。 + */ +bool TM::TargetPanel::is_text_saved() const { return m_text_saved; } + +void TM::TargetPanel::set_text_saved(bool saved) +{ + m_text_saved = saved; } +/*! + * \brief パネル内の文字列が編集された場合、trueを返します。 + * + * エディタがリンクモードに入るとき、このメンバを呼び出し、 + * 単語へ分割する必要があるか判定します。 + * エディタはパネルの文字列を単語に分割した後、set_sentence()によって + * パネルに文を設定するため、次に文字列を編集するまでfalseを返すようになります。 + */ bool TM::TargetPanel::is_text_dirty() const { return m_text_dirty; } +/*! + * \brief パネルの文字列が編集されたかを示すフラグを設定します。 + */ void TM::TargetPanel::set_text_dirty(bool dirty) { m_text_dirty = dirty; - if(dirty) m_editor->parent_widget()->set_link_mode_disabled(false); + if(dirty) m_editor->parent_editor_widget()->set_link_mode_disabled(false); } bool TM::TargetPanel::canInsertFromMimeData(QMimeData const *source) const @@ -492,12 +575,17 @@ void TM::TargetPanel::insertFromMimeData(QMimeData const *source) { TextPanel::insertFromMimeData(source); set_text_dirty(true); + set_text_saved(false); } void TM::TargetPanel::inputMethodEvent(QInputMethodEvent *ev) { if(m_editor->link_mode()) ev->setCommitString(""); - if(!ev->commitString().isEmpty()) set_text_dirty(true); + if(!ev->commitString().isEmpty()) + { + set_text_dirty(true); + set_text_saved(false); + } QPlainTextEdit::inputMethodEvent(ev); } @@ -507,7 +595,11 @@ void TM::TargetPanel::keyPressEvent(QKeyEvent *ev) else { TextPanel::keyPressEvent(ev); - if(!ev->text().isEmpty()) set_text_dirty(true); + if(!ev->text().isEmpty()) + { + set_text_dirty(true); + set_text_saved(false); + } } } @@ -585,7 +677,7 @@ void TM::Editor::clear() ta->clear(); // リンクモードの解除。 set_link_mode(false); - parent_widget()->set_link_mode_disabled(true); + parent_editor_widget()->set_link_mode_disabled(true); } /*! @@ -623,7 +715,7 @@ void TM::Editor::set_link_mode(bool mode_) assert(!mode_ || can_link_mode()); // リンクモードに入るには、条件がある。 m_link_mode = mode_; - parent_widget()->set_link_mode(mode_); + parent_editor_widget()->set_link_mode(mode_); if(mode_) do_link_mode_enter(m_current_source_panel); else if(m_current_source_panel) do_link_mode_leave(m_current_source_panel); @@ -638,7 +730,7 @@ bool TM::Editor::can_link_mode() const return true; } -TM::EditorWidget* TM::Editor::parent_widget() +TM::EditorWidget* TM::Editor::parent_editor_widget() { EditorWidget* result = qobject_cast(parentWidget()); assert(result); @@ -685,7 +777,7 @@ void TM::Editor::do_panel_enter(SourcePanel *panel) TargetPanel *tp = panel->target_panel(); assert(tp); tp->show(); - if(can_link_mode()) parent_widget()->set_link_mode_disabled(false); + if(can_link_mode()) parent_editor_widget()->set_link_mode_disabled(false); } /*! @@ -698,9 +790,13 @@ void TM::Editor::do_panel_leave(SourcePanel *panel) tp->hide(); set_link_mode(false); - parent_widget()->set_link_mode_disabled(true); + parent_editor_widget()->set_link_mode_disabled(true); - qDebug() << "focus out"; + if(!tp->is_text_saved()) + { + //qDebug() << m_service->si + tp->set_text_saved(true); + } } /*! @@ -711,7 +807,7 @@ void TM::Editor::do_link_mode_enter(SourcePanel *panel) assert(panel); TargetPanel *tp = panel->target_panel(); assert(tp); - int tcode = parent_widget()->target_language(); + int tcode = parent_editor_widget()->target_language(); if(tp->is_text_dirty()) { @@ -721,7 +817,7 @@ void TM::Editor::do_link_mode_enter(SourcePanel *panel) if(sentences->size()) { Text::pointer words = m_service->divide_into_words(tcode, sentences->begin()); - tp->set_sentence(words); + tp->set_sentence(words); // ココで、text_dirtyがfalseになる。 } } @@ -736,7 +832,7 @@ void TM::Editor::do_link_mode_leave(SourcePanel *panel) qDebug() << m_current_source_panel->linker()->to_json_array(); assert(panel); panel->commit_link(); - panel->clear_highlight(); + //panel->clear_highlight(); } diff --git a/proxy/tmeditorwidget.h b/proxy/tmeditorwidget.h index 4108335..ab4218b 100644 --- a/proxy/tmeditorwidget.h +++ b/proxy/tmeditorwidget.h @@ -53,6 +53,8 @@ public: void attach(SocketConnection *socket); void detach(SocketConnection *socket); + void set_http_port(quint16 http_port); + void set_edit_mode(bool mode); bool edit_mode(); void set_link_mode(bool mode); @@ -63,11 +65,15 @@ public: int target_language(); void set_string(QString source_, QString target_); + void append_sentence(); + void save_sentence(); signals: void editModeChanged(bool mode_); void linkModeChanged(bool mode_); + void contentsEdited(); + public slots: void onLanguageLoaded(int code, QString name, QIcon icon); void onEditModeTriggered(bool); @@ -80,6 +86,7 @@ private: QMutex m_mutex; Service *m_service; Settings *m_settings; + quint16 m_http_port; SocketConnection *m_socket; QToolBar *m_toolbar; @@ -163,6 +170,9 @@ public: void set_sentence(Text::pointer sentence); + bool is_text_saved() const; + void set_text_saved(bool saved); + bool is_text_dirty() const; void set_text_dirty(bool dirty); @@ -184,22 +194,13 @@ protected: private: SourcePanel *m_source_panel; - bool m_text_dirty; + bool m_text_dirty; /*!< 内容の変更を示すフラグ */ + bool m_text_saved; /*!< データベース登録の必要性を示すフラグ */ }; class Editor : public TextWidget { Q_OBJECT -/* enum : int - { - TextSourceSentence = QTextCharFormat::UserProperty, - TextSourceWord, - TextTargetSentence = QTextCharFormat::UserProperty + 10, - TextTargetWord, - TextCurrentBlock, - TextCurrentEditor, - }; -*/ public: Editor(Settings *settings, Service *service, QWidget *parent); @@ -213,7 +214,7 @@ public: bool can_link_mode() const; - EditorWidget* parent_widget(); + EditorWidget* parent_editor_widget(); TargetPanel* current_target_panel(); TargetPanel const* current_target_panel() const; diff --git a/proxy/tmhttp.cpp b/proxy/tmhttp.cpp index 64ada23..9f61937 100644 --- a/proxy/tmhttp.cpp +++ b/proxy/tmhttp.cpp @@ -2,6 +2,7 @@ #include "html.h" #include "htmlprivate.h" #include "tmservice.h" +#include "settings.h" #include @@ -16,25 +17,41 @@ // ProxyContext --------------------------------------------------------------- -TM::ProxyContext::ProxyContext(QString prefix, quint16 http, quint16 socket) +TM::ProxyContext::ProxyContext(Settings *settings, quint16 http, quint16 socket) : QObject(0) + , m_settings(settings) , m_manager(new QNetworkAccessManager(this)) , m_cookie(new QNetworkCookieJar(this)) - , m_prefix(prefix) - , m_http(http) - , m_socket(socket) + , m_http_port(http) + , m_socket_port(socket) { m_manager->setCookieJar(m_cookie); + assert(settings->contains("ProxyModule/prefix")); + m_prefix = settings->value("ProxyModule/prefix").toString(); + assert(settings->contains("ProxyHandler/jscode")); + m_jscode = settings->value("ProxyHandler/jscode").toString(); } +QNetworkAccessManager* TM::ProxyContext::network_access_manager() +{ + return m_manager; +} + +quint16 TM::ProxyContext::http_port() const { return m_http_port; } + +quint16 TM::ProxyContext::socket_port() const { return m_socket_port; } + +QString TM::ProxyContext::prefix() const { return m_prefix; } + +QString TM::ProxyContext::jscode() const { return m_jscode; } + // ProxyModule ---------------------------------------------------------------- -TM::ProxyModule::ProxyModule(QString prefix, quint16 http, quint16 socket, QObject *parent) +TM::ProxyModule::ProxyModule(Settings *settings, quint16 http, quint16 socket, + QObject *parent) : HttpModule(parent) , m_thread(new QThread(this)) - , m_context(new ProxyContext(prefix, http, socket)) - , m_prefix(prefix) - , m_http(http) + , m_context(new ProxyContext(settings, http, socket)) { m_context->moveToThread(m_thread); connect(m_thread, SIGNAL(finished()), m_context, SLOT(deleteLater())); @@ -51,7 +68,7 @@ TM::ProxyModule::~ProxyModule() HttpHandler* TM::ProxyModule::create_handler(QByteArray method, QByteArray url) { if(method.toLower() != "get") return nullptr; - if(!url.toLower().startsWith(m_prefix.toUtf8())) return nullptr; + if(!url.toLower().startsWith(m_context->prefix().toUtf8())) return nullptr; HttpHandler *handler = new ProxyHandler(m_context); handler->moveToThread(m_thread); @@ -80,9 +97,9 @@ TM::ProxyHandler::~ProxyHandler() int TM::ProxyHandler::run() { m_targetUrl = QUrl::fromUserInput( - m_request->url().remove(0, m_context->m_prefix.toUtf8().length())); + m_request->url().remove(0, m_context->prefix().toUtf8().length())); // HTML取得要求 - m_reply = m_context->m_manager->get(QNetworkRequest(m_targetUrl)); + m_reply = m_context->network_access_manager()->get(QNetworkRequest(m_targetUrl)); connect(m_reply, SIGNAL(finished()), this, SLOT(onNetworkReplyFinished())); return 0; } @@ -159,9 +176,8 @@ int TM::ProxyHandler::response() node = head.insert("style", head.end()); node.insert_text(" .wordring-segment:hover{ color:#ff0000; } ", node.end()); // JS書き込み - //QFile file("C:\\Users\\Kouichi\\Documents\\GitHub\\TM\\Proxy\\tm.js"); - QFile file("tm.js"); + QFile file(m_context->jscode()); file.open(QIODevice::ReadOnly); QByteArray js = file.readAll(); file.close(); @@ -170,7 +186,7 @@ int TM::ProxyHandler::response() // node = head.insert("script", head.end()).set_attribute("type", "text/javascript"); QString str1 = "\nwindow.wordring.port="; - str1 += QString::number(m_context->m_socket) + ";\n"; + str1 += QString::number(m_context->socket_port()) + ";\n"; node.insert_comment(str1, node.end()); // パラグラフ設定 create_paragraph(body.lbegin(), body.ltail()); @@ -308,7 +324,7 @@ void TM::ProxyHandler::create_paragraph(Html::pointer begin_, Html::pointer tail */ QString TM::ProxyHandler::host() const { - return QString("http://localhost:") + QString::number(m_context->m_http); + return QString("http://localhost:") + QString::number(m_context->http_port()); } /*! @@ -317,10 +333,7 @@ QString TM::ProxyHandler::host() const * * 例)/tm? */ -QString TM::ProxyHandler::prefix() const -{ - return m_context->m_prefix; -} +QString TM::ProxyHandler::prefix() const { return m_context->prefix(); } diff --git a/proxy/tmhttp.h b/proxy/tmhttp.h index d90db5c..00a61fe 100644 --- a/proxy/tmhttp.h +++ b/proxy/tmhttp.h @@ -6,6 +6,7 @@ #include #include +#include #include QT_BEGIN_NAMESPACE @@ -26,18 +27,26 @@ class ProxyHandler; class ProxyContext : public QObject { Q_OBJECT - friend class ProxyHandler; public: - ProxyContext(QString prefix, quint16 http, quint16 socket); + ProxyContext(Settings *settings, quint16 http, quint16 socket); + + QNetworkAccessManager* network_access_manager(); + quint16 http_port() const; + quint16 socket_port() const; + QString prefix() const; + QString jscode() const; private: + Settings *m_settings; + QNetworkAccessManager *m_manager; QNetworkCookieJar *m_cookie; + quint16 m_http_port; + quint16 m_socket_port; QString m_prefix; - quint16 m_http; - quint16 m_socket; + QString m_jscode; }; class ProxyModule : public HttpModule @@ -45,7 +54,7 @@ class ProxyModule : public HttpModule Q_OBJECT public: - ProxyModule(QString prefix, quint16 http, quint16 socket, QObject *parent); + ProxyModule(Settings *settings, quint16 http, quint16 socket, QObject *parent); ~ProxyModule(); virtual HttpHandler* create_handler(QByteArray method, QByteArray url); @@ -54,9 +63,6 @@ public: private: QThread *m_thread; ProxyContext *m_context; - - QString m_prefix; - quint16 m_http; }; class ProxyHandler : public HttpHandler diff --git a/proxy/tmservice.cpp b/proxy/tmservice.cpp index a6602f2..80418a1 100644 --- a/proxy/tmservice.cpp +++ b/proxy/tmservice.cpp @@ -5,6 +5,7 @@ #include "tmdatabase.h" #include + #include #include @@ -68,6 +69,46 @@ Text::pointer TM::Service::divide_into_words(int code, Text::pointer sentence) return m_languages[code]->divide_into_words(sentence); } +/*! + * \brief 原文と訳文の対をデータベースへ登録します。 + * \param site_id 翻訳対象サイトを表すID。 + * \param scode 原文の言語コード。 + * \param ssentence 原文の構造化テキスト。 + * \param tcode 訳文の言語コード。 + * \param tsentence 訳文の構造化テキスト。 + * \param json 原文と訳文間の単語リンク。 + */ +void TM::Service::insert_sentence(int site_id, int scode, Text::pointer ssentence, + int tcode, Text::pointer tsentence, QJsonArray json) +{ + QMutexLocker lock(&m_mutex); + + assert(m_languages.contains(scode)); + assert(m_languages.contains(tcode)); + Language *slanguage = m_languages[scode]; + Language *tlanguage = m_languages[tcode]; + + QString sstring = slanguage->normalize(ssentence->to_string()); + QString tstring = tlanguage->normalize(tsentence->to_string()); + + //m_database-> +} + +/*! + * \brief 原文から訳文を検索します。 + * \param site_id 翻訳対象サイトを表すID。 + * \param scode 原文の言語コード。 + * \param ssentence 原文の構造化テキスト。 + * \param tcode 訳文の言語コード。 + * \param tsentence 訳文の構造化テキストを受け取るポインタ。 + * \param json 原文と訳文間の単語リンクを受け取るポインタ。 + * \return 訳文が検索できた場合、trueを返します。 + */ +bool TM::Service::find_sentence(int site_id, int scode, Text::pointer ssentence, int tcode, + Text::pointer *tsentence, QJsonArray *json) +{ + return true; +} diff --git a/proxy/tmservice.h b/proxy/tmservice.h index 07e52b9..32b749c 100644 --- a/proxy/tmservice.h +++ b/proxy/tmservice.h @@ -4,8 +4,9 @@ #include "language.h" #include -#include #include +#include +#include #include #include @@ -34,7 +35,10 @@ public: Text::pointer divide_into_sentences(int code, QString string); Text::pointer divide_into_words(int code, Text::pointer sentence); - //int find_source_id(int code, QString const &source); + void insert_sentence(int site_id, int scode, Text::pointer ssentence, + int tcode, Text::pointer tsentence, QJsonArray json); + bool find_sentence(int site_id, int scode, Text::pointer ssentence, int tcode, + Text::pointer *tsentence, QJsonArray *json); signals: /*! diff --git a/proxy/tmsocket.cpp b/proxy/tmsocket.cpp index 2650e4a..b2850ae 100644 --- a/proxy/tmsocket.cpp +++ b/proxy/tmsocket.cpp @@ -115,8 +115,11 @@ bool TM::TextConverter::is_white_space(QChar const &ch) // SocketConnection ----------------------------------------------------------- -TM::SocketConnection::SocketConnection(EditorWidget *editor_widget, QWebSocket *socket) +TM::SocketConnection::SocketConnection(Settings *settings, Service *service, + EditorWidget *editor_widget, QWebSocket *socket) : QObject(socket) + , m_settings(settings) + , m_service(service) , m_editor_widget(editor_widget) , m_mutex(QMutex::Recursive) , m_edit_mode(false) @@ -237,9 +240,11 @@ void TM::SocketConnection::onBinaryMessageReceived(QByteArray const &message) // SocketServer --------------------------------------------------------------- -TM::SocketServer::SocketServer(Settings *settings, EditorWidget *editor_widget, QObject *parent) +TM::SocketServer::SocketServer(Settings *settings, Service* service, + EditorWidget *editor_widget, QObject *parent) : QObject(parent) , m_settings(settings) + , m_service(service) , m_server(new QWebSocketServer(QStringLiteral("wordring websocket"), QWebSocketServer::NonSecureMode, this)) , m_editor_widget(editor_widget) @@ -275,7 +280,7 @@ void TM::SocketServer::onNewConnection() { QWebSocket *socket = m_server->nextPendingConnection(); connect(socket, SIGNAL(disconnected()), this, SLOT(onDisconnected())); - new SocketConnection(m_editor_widget, socket); + new SocketConnection(m_settings, m_service, m_editor_widget, socket); m_sockets.push_back(socket); } diff --git a/proxy/tmsocket.h b/proxy/tmsocket.h index 912c607..48cdbbc 100644 --- a/proxy/tmsocket.h +++ b/proxy/tmsocket.h @@ -8,7 +8,9 @@ #include #include +#include +#include #include #include @@ -23,6 +25,7 @@ class Settings; namespace TM { +class Service; class EditorWidget; class HtmlData : public RangeData @@ -44,11 +47,12 @@ private: HtmlNode m_node; }; +/*! + * \brief HtmlRangeから構造化テキストに変換するためのクラスです。 + */ class TextConverter { public: - //TextConverter(); - Text::pointer to_text(HtmlRange range); Text::pointer stuff_text(Text::pointer parent, QString const &string); @@ -60,12 +64,27 @@ private: int m_state; }; +class TextSentence +{ + +private: + Text::pointer m_source_sentence; + Text::pointer m_target_sentence; + QJsonArray m_link_data; +}; + +class TextSegment +{ + +}; + class SocketConnection : public QObject { Q_OBJECT public: - SocketConnection(EditorWidget *editor_widget, QWebSocket *socket); + SocketConnection(Settings *settings, Service *service, + EditorWidget *editor_widget, QWebSocket *socket); virtual ~SocketConnection(); //quint16 port() const; @@ -96,6 +115,9 @@ private slots: void onBinaryMessageReceived(QByteArray const &message); private: + Settings *m_settings; + Service *m_service; + QMutex m_mutex; bool m_edit_mode; @@ -113,7 +135,8 @@ class SocketServer : public QObject { Q_OBJECT public: - SocketServer(Settings *settings, EditorWidget *editor_widget, QObject *parent); + SocketServer(Settings *settings, Service* service, + EditorWidget *editor_widget, QObject *parent); ~SocketServer(); quint16 port() const; @@ -132,9 +155,12 @@ signals: private: Settings *m_settings; + Service *m_service; + QWebSocketServer *m_server; - EditorWidget *m_editor_widget; QList m_sockets; + + EditorWidget *m_editor_widget; }; } // namespace TM diff --git a/utility/text.cpp b/utility/text.cpp index 2f1346a..4bbe72c 100644 --- a/utility/text.cpp +++ b/utility/text.cpp @@ -165,7 +165,14 @@ Text::pointer Text::insert_after(pointer position_, QString const &string_) return insert_after(position_, create(self(), string_)); } +Text::pointer Text::remove(pointer position_) +{ + assert(false); // 未実装 + return position_; +} + QString& Text::string() { return m_string; } + QString const& Text::string() const { return m_string; } Text& Text::set_string(QString const &string) diff --git a/utility/text.h b/utility/text.h index 79eb9c6..42cb88d 100644 --- a/utility/text.h +++ b/utility/text.h @@ -45,11 +45,14 @@ public: pointer append(pointer value_); pointer append(QString const &string_); + pointer insert(pointer position_, pointer value_); pointer insert(pointer position_, QString const &string_); pointer insert_after(pointer position, pointer value); pointer insert_after(pointer position_, QString const &string_); + pointer remove(pointer position_); + QString& string(); QString const& string() const; Text& set_string(QString const &string);