blob: 4a4e33ed573b8b553c05faa5705aa5750d76b67b [file] [log] [blame]
// 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