| // Copyright 2010-2015, Google Inc. |
| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following disclaimer |
| // in the documentation and/or other materials provided with the |
| // distribution. |
| // * Neither the name of Google Inc. nor the names of its |
| // contributors may be used to endorse or promote products derived from |
| // this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| #include "gui/character_pad/hand_writing.h" |
| |
| #ifdef ENABLE_CLOUD_HANDWRITING |
| #include <QtGui/QApplication> |
| #endif // ENABLE_CLOUD_HANDWRITING |
| #include <QtGui/QtGui> |
| #include <QtGui/QMessageBox> |
| |
| #ifdef OS_WIN |
| #include <windows.h> |
| #include <windowsx.h> |
| #endif |
| |
| #ifdef ENABLE_CLOUD_HANDWRITING |
| #include "config/config.pb.h" |
| #include "config/config_handler.h" |
| #include "handwriting/cloud_handwriting.h" |
| #endif // ENABLE_CLOUD_HANDWRITING |
| |
| #include "base/logging.h" |
| #include "client/client.h" |
| #include "config/stats_config_util.h" |
| #include "gui/base/win_util.h" |
| #include "handwriting/handwriting_manager.h" |
| #include "handwriting/zinnia_handwriting.h" |
| #include "session/commands.pb.h" |
| |
| namespace mozc { |
| |
| namespace { |
| enum HandwritingSourceId { |
| kZinniaHandwriting = 0, |
| #ifdef ENABLE_CLOUD_HANDWRITING |
| kCloudHandwriting = 1, |
| #endif // ENABLE_CLOUD_HANDWRITING |
| }; |
| |
| #ifdef ENABLE_CLOUD_HANDWRITING |
| bool SetConfig(client::ClientInterface *client, |
| const config::Config &config) { |
| if (!client->CheckVersionOrRestartServer()) { |
| LOG(ERROR) << "CheckVersionOrRestartServer failed"; |
| return false; |
| } |
| |
| if (!client->SetConfig(config)) { |
| LOG(ERROR) << "SetConfig failed"; |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool GetConfig(client::ClientInterface *client, |
| config::Config *config) { |
| if (!client->CheckVersionOrRestartServer()) { |
| LOG(ERROR) << "CheckVersionOrRestartServer failed"; |
| return false; |
| } |
| |
| if (!client->GetConfig(config)) { |
| LOG(ERROR) << "GetConfig failed"; |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool IsCloudHandwritingAllowed(client::ClientInterface *client) { |
| config::Config config; |
| if (!GetConfig(client, &config)) { |
| return false; |
| } |
| |
| // Note that |allow_cloud_handwriting| has default value 'false'. |
| return config.allow_cloud_handwriting(); |
| } |
| #endif // ENABLE_CLOUD_HANDWRITING |
| |
| } // namespace |
| |
| namespace gui { |
| |
| HandWriting::HandWriting(QWidget *parent) |
| : QMainWindow(parent), |
| usage_stats_enabled_(mozc::config::StatsConfigUtil::IsEnabled()), |
| #ifdef ENABLE_CLOUD_HANDWRITING |
| cloud_handwriting_(new mozc::handwriting::CloudHandwriting), |
| #endif // ENABLE_CLOUD_HANDWRITING |
| zinnia_handwriting_(new mozc::handwriting::ZinniaHandwriting( |
| mozc::handwriting::ZinniaHandwriting::GetModelFileName())) { |
| // To reduce the disk IO of reading the stats config, we load it only when the |
| // class is initialized. There is no problem because the config dialog (on |
| // Mac) and the administrator dialog (on Windows) say that the usage stats |
| // setting changes will take effect after the re-login. |
| |
| #ifdef ENABLE_CLOUD_HANDWRITING |
| client_.reset(client::ClientFactory::NewClient()); |
| #else |
| if (usage_stats_enabled_) { |
| client_.reset(client::ClientFactory::NewClient()); |
| } |
| #endif // ENABLE_CLOUD_HANDWRITING |
| setupUi(this); |
| |
| handWritingCanvas->setListWidget(resultListWidget); |
| |
| fontComboBox->setWritingSystem |
| (static_cast<QFontDatabase::WritingSystem> |
| (QFontDatabase::Any)); |
| fontComboBox->setEditable(false); |
| fontComboBox->setCurrentFont(resultListWidget->font()); |
| |
| QObject::connect(resultListWidget, |
| SIGNAL(itemSelected(const QListWidgetItem*)), |
| this, |
| SLOT(itemSelected(const QListWidgetItem*))); |
| |
| QObject::connect(fontComboBox, |
| SIGNAL(currentFontChanged(const QFont &)), |
| this, SLOT(updateFont(const QFont &))); |
| |
| QObject::connect(sizeComboBox, |
| SIGNAL(currentIndexChanged(int)), |
| this, SLOT(updateFontSize(int))); |
| |
| #ifdef ENABLE_CLOUD_HANDWRITING |
| QObject::connect(handwritingSourceComboBox, |
| SIGNAL(currentIndexChanged(int)), |
| this, SLOT(tryToUpdateHandwritingSource(int))); |
| #else |
| // When cloud handwriting is configured to be disabled, hide the combo box. |
| handwritingSourceComboBox->setVisible(false); |
| #endif // ENABLE_CLOUD_HANDWRITING |
| |
| QObject::connect(clearButton, |
| SIGNAL(clicked()), |
| this, SLOT(clear())); |
| |
| QObject::connect(revertButton, |
| SIGNAL(clicked()), |
| this, SLOT(revert())); |
| |
| QObject::connect(handWritingCanvas, |
| SIGNAL(canvasUpdated()), |
| this, SLOT(updateUIStatus())); |
| |
| // "4" means smallest. |
| sizeComboBox->setCurrentIndex(4); |
| fontComboBox->setCurrentFont(resultListWidget->font()); |
| |
| int default_handwriting_method = kZinniaHandwriting; |
| #ifdef ENABLE_CLOUD_HANDWRITING |
| if (IsCloudHandwritingAllowed(client_.get())) { |
| // If cloud handwriting is enabled, use it by default. |
| // TODO(team): Consider the case where network access is not available. |
| default_handwriting_method = kCloudHandwriting; |
| } |
| #endif // ENABLE_CLOUD_HANDWRITING |
| handwritingSourceComboBox->setCurrentIndex(default_handwriting_method); |
| |
| if (usage_stats_enabled_) { |
| CHECK(client_.get()); |
| // Sends the usage stats event (HANDWRITING_OPEN_EVENT) to mozc converter. |
| commands::SessionCommand command; |
| command.set_type(commands::SessionCommand::USAGE_STATS_EVENT); |
| command.set_usage_stats_event( |
| commands::SessionCommand::HANDWRITING_OPEN_EVENT); |
| commands::Output dummy_output; |
| client_->SendCommand(command, &dummy_output); |
| } |
| |
| updateUIStatus(); |
| repaint(); |
| update(); |
| } |
| |
| HandWriting::~HandWriting() {} |
| |
| void HandWriting::updateFont(const QFont &font) { |
| resultListWidget->updateFont(font); |
| } |
| |
| void HandWriting::updateFontSize(int index) { |
| resultListWidget->updateFontSize(index); |
| } |
| |
| void HandWriting::tryToUpdateHandwritingSource(int index) { |
| switch (index) { |
| case kZinniaHandwriting: |
| updateHandwritingSource(kZinniaHandwriting); |
| break; |
| #ifdef ENABLE_CLOUD_HANDWRITING |
| case kCloudHandwriting: |
| if (TryToEnableCloudHandwriting()) { |
| updateHandwritingSource(kCloudHandwriting); |
| } else { |
| // When user refused to use cloud handwriting, change the |
| // combobox to Zinnia. |
| handwritingSourceComboBox->setCurrentIndex(kZinniaHandwriting); |
| updateHandwritingSource(kZinniaHandwriting); |
| } |
| break; |
| #endif // ENABLE_CLOUD_HANDWRITING |
| default: |
| DLOG(INFO) << "Unknown index = " << index; |
| break; |
| } |
| } |
| |
| void HandWriting::updateHandwritingSource(int index) { |
| switch (index) { |
| case kZinniaHandwriting: |
| mozc::handwriting::HandwritingManager::SetHandwritingModule( |
| zinnia_handwriting_.get()); |
| break; |
| #ifdef ENABLE_CLOUD_HANDWRITING |
| case kCloudHandwriting: |
| mozc::handwriting::HandwritingManager::SetHandwritingModule( |
| cloud_handwriting_.get()); |
| break; |
| #endif // ENABLE_CLOUD_HANDWRITING |
| default: |
| DLOG(INFO) << "Unknown index = " << index; |
| break; |
| } |
| resultListWidget->clear(); |
| handWritingCanvas->restartRecognition(); |
| } |
| |
| void HandWriting::resizeEvent(QResizeEvent *event) { |
| resultListWidget->update(); |
| } |
| |
| void HandWriting::clear() { |
| resultListWidget->clear(); |
| handWritingCanvas->clear(); |
| updateUIStatus(); |
| } |
| |
| void HandWriting::revert() { |
| resultListWidget->clear(); |
| handWritingCanvas->revert(); |
| updateUIStatus(); |
| } |
| |
| void HandWriting::updateUIStatus() { |
| #ifdef OS_MACOSX |
| // Due to a bug of Qt?, the appearance of these buttons |
| // doesn't change on Mac. To fix this issue, always set |
| // true on Mac. |
| clearButton->setEnabled(true); |
| revertButton->setEnabled(true); |
| #else |
| const bool enabled = handWritingCanvas->strokes_size() > 0; |
| clearButton->setEnabled(enabled); |
| revertButton->setEnabled(enabled); |
| #endif |
| } |
| |
| void HandWriting::itemSelected(const QListWidgetItem *item) { |
| if (!usage_stats_enabled_) { |
| return; |
| } |
| CHECK(client_.get()); |
| // Sends the usage stats event (HANDWRITING_COMMIT_EVENT) to mozc converter. |
| commands::SessionCommand command; |
| command.set_type(commands::SessionCommand::USAGE_STATS_EVENT); |
| command.set_usage_stats_event( |
| commands::SessionCommand::HANDWRITING_COMMIT_EVENT); |
| commands::Output dummy_output; |
| client_->SendCommand(command, &dummy_output); |
| } |
| |
| #ifdef OS_WIN |
| bool HandWriting::winEvent(MSG *message, long *result) { |
| if (message != NULL && |
| message->message == WM_LBUTTONDOWN && |
| WinUtil::IsCompositionEnabled()) { |
| const QWidget *widget = qApp->widgetAt( |
| mapToGlobal(QPoint(message->lParam & 0xFFFF, |
| (message->lParam >> 16) & 0xFFFF))); |
| if (widget == centralwidget) { |
| ::PostMessage(message->hwnd, WM_NCLBUTTONDOWN, |
| static_cast<WPARAM>(HTCAPTION), message->lParam); |
| return true; |
| } |
| } |
| |
| return QWidget::winEvent(message, result); |
| } |
| #endif // OS_WIN |
| |
| #ifdef ENABLE_CLOUD_HANDWRITING |
| bool HandWriting::TryToEnableCloudHandwriting() { |
| if (IsCloudHandwritingAllowed(client_.get())) { |
| // Already allowed. Do nothing. |
| return true; |
| } |
| |
| // Currently custom style sheet is used only on Windows. |
| #ifdef OS_WIN |
| // When a custom style sheet is applied, temporarily disable it to |
| // show a message box with default theme. See b/5949615. |
| // Mysteriously, a message box launched from dictionary tool does |
| // not have this issue even when a custom style sheet is applied. |
| // This implies that we might be able to fix this issue in a more |
| // appropriate way. |
| // TODO(yukawa): Investigate why this does not happen on the |
| // dictionary tool and remove this workaround code if possible. |
| // See b/5974593. |
| const QString custom_style_sheet = qApp->styleSheet(); |
| if (!custom_style_sheet.isEmpty()) { |
| qApp->setStyleSheet(""); |
| } |
| #endif // OS_WIN |
| |
| // When cloud handwriting is not allowed, ask the user to enable it. |
| const QMessageBox::StandardButton result = |
| QMessageBox::question( |
| this, |
| tr("Cloud handwriting recognition"), |
| // TODO(yukawa, peria): Update the warning message and have |
| // native check. b/5943541. |
| tr("This feature improve the accuracy of handwriting recognition " |
| "by using a Google web service. To do so, your handwriting " |
| "strokes will be securely sent to Google. Do you want to use " |
| "Cloud handwriting?"), |
| QMessageBox::Yes | QMessageBox::No, QMessageBox::No); |
| |
| // Currently custom style sheet is used only on Windows. |
| #ifdef OS_WIN |
| // Restore the custom style sheet if necessary. |
| if (!custom_style_sheet.isEmpty()) { |
| qApp->setStyleSheet(custom_style_sheet); |
| } |
| #endif // OS_WIN |
| |
| if (result == QMessageBox::No) { |
| // User refused. |
| return false; |
| } |
| |
| // The user allowed to enable the cloud handwriting. Store this info |
| // for later use. |
| config::Config config; |
| if (GetConfig(client_.get(), &config)) { |
| config.set_allow_cloud_handwriting(true); |
| SetConfig(client_.get(), config); |
| } |
| |
| return true; |
| } |
| #endif // ENABLE_CLOUD_HANDWRITING |
| |
| } // namespace gui |
| } // namespace mozc |