diff --git a/YACReader/YACReader.pro b/YACReader/YACReader.pro index 1227a908..3ff5f1a8 100644 --- a/YACReader/YACReader.pro +++ b/YACReader/YACReader.pro @@ -29,7 +29,7 @@ INCLUDEPATH += /usr/local/include/poppler/qt4 LIBS += -L/usr/local/lib -lpoppler-qt4 } -QT += network webkit phonon opengl +QT += network phonon opengl CONFIG += release CONFIG -= flat diff --git a/YACReader/files.qrc b/YACReader/files.qrc index 6bce09ab..453372fa 100644 --- a/YACReader/files.qrc +++ b/YACReader/files.qrc @@ -3,7 +3,6 @@ ../files/about.html ../files/helpYACReader.html ../files/shortcuts.html - ../files/translator.html diff --git a/YACReader/images.qrc b/YACReader/images.qrc index 535f84f2..c0c13672 100644 --- a/YACReader/images.qrc +++ b/YACReader/images.qrc @@ -69,5 +69,9 @@ ../images/useNewFlowButton.png ../images/useOldFlowButton.png ../images/notificationsLabel.png + ../images/fromTo.png + ../images/dropDownArrow.png + ../images/translatorSearch.png + ../images/speaker.png diff --git a/YACReader/translator.cpp b/YACReader/translator.cpp index ced688a2..85029c67 100644 --- a/YACReader/translator.cpp +++ b/YACReader/translator.cpp @@ -6,63 +6,285 @@ #include #include #include +#include "translator.h" + +#include "yacreader_busy_widget.h" + #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include -#include "translator.h" +#include + +#define APPID "417CEAD93449502CC3C9B69FED26C54118E62BCC" YACReaderTranslator::YACReaderTranslator(QWidget * parent) -:QWidget(parent) +:QWidget(parent),drag(false) { + QString scrollBarStyle = "QScrollBar:vertical { border: none; background: #404040; width: 7px; margin: 0 3px 0 0; }" + "QScrollBar::handle:vertical { background: #DDDDDD; width: 7px; min-height: 20px; }" + "QScrollBar::add-line:vertical { border: none; background: #404040; height: 10px; subcontrol-position: bottom; subcontrol-origin: margin; margin: 0 3px 0 0;}" + + "QScrollBar::sub-line:vertical { border: none; background: #404040; height: 10px; subcontrol-position: top; subcontrol-origin: margin; margin: 0 3px 0 0;}" + "QScrollBar::up-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-up.png') center top no-repeat;}" + "QScrollBar::down-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-down.png') center top no-repeat;}" + + "QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {background: none; }"; + this->setCursor(QCursor(Qt::ArrowCursor)); this->setAutoFillBackground(true); this->setBackgroundRole(QPalette::Window); QPalette p(this->palette()); - p.setColor(QPalette::Window, QColor(96,96,96)); + p.setColor(QPalette::Window, QColor("#404040")); this->setPalette(p); QVBoxLayout *layout = new QVBoxLayout(this); - QWebView * view = new QWebView(); - QFile f(":/files/translator.html"); - f.open(QIODevice::ReadOnly); - QTextStream txtS(&f); - txtS.setCodec(QTextCodec::codecForName("UTF-8")); - QString contentHTML = txtS.readAll(); - view->setHtml(contentHTML); - view->page()->setLinkDelegationPolicy(QWebPage::DelegateExternalLinks); - connect(view->page(),SIGNAL(linkClicked(QUrl)),this,SLOT(play(QUrl))); - QHBoxLayout * buttonBar = new QHBoxLayout(); + //TITLE BAR + QHBoxLayout * titleBar = new QHBoxLayout(); QPushButton * close = new QPushButton(QIcon(QPixmap(":/images/close.png")),""); close->setFlat(true); - buttonBar->addStretch(); - close->resize(18,18); - buttonBar->addWidget(close); - buttonBar->setMargin(0); + QLabel * title = new QLabel(tr("YACReader translator")); + title->setStyleSheet("QLabel {font-size:18px; font-family:Arial; color:white;}"); + titleBar->addWidget(title); + titleBar->addStretch(); + close->resize(14,14); + close->setStyleSheet("QPushButton {margin:0;padding:0;border:none;}"); + titleBar->addWidget(close); + titleBar->setContentsMargins(0,0,0,0); + titleBar->setSpacing(0); connect(close,SIGNAL(clicked()),this->parent(),SLOT(animateHideTranslator())); - layout->setMargin(0); - layout->setSpacing(0); + layout->addLayout(titleBar); - layout->addLayout(buttonBar); - layout->addWidget(view); + //INPUT TEXT + text = new QTextEdit(this); + text->setMinimumHeight(110); + text->setMaximumHeight(110); + layout->addSpacing(12); + layout->addWidget(text); + text->setStyleSheet("QTextEdit{border:none;background:#2a2a2a;color:white; font-size:12px; padding:6px;}"+scrollBarStyle); - resize(view->size().width()/1.60,view->size().height()); + //COMBOBOXES + QHBoxLayout * combos = new QHBoxLayout(); + from = new QComboBox(this); + to = new QComboBox(this); + QString comboBoxStyle = "QComboBox {border:none;background:#2a2a2a;color:white;font-size:12px;font-family:Arial;padding-left:8px;}" + "QComboBox::down-arrow {image: url(:/images/dropDownArrow.png);}" + "QComboBox::drop-down {border:none; padding-right:10px;}" + "QComboBox QAbstractItemView {border: none; background:#272727; color:white; selection-background-color: #202020; outline:none;}" + "QComboBox QAbstractItemView::item {padding-left:8px;}" + scrollBarStyle + ; + from->setStyleSheet(comboBoxStyle); + to->setStyleSheet(comboBoxStyle); + from->setFixedHeight(22); + to->setFixedHeight(22); + QLabel * arrow = new QLabel(this); + QPixmap arrowPixmap(":/images/fromTo.png"); + arrow->setPixmap(arrowPixmap); + QPushButton * searchButton = new QPushButton(this); + searchButton->setIcon(QIcon(":/images/translatorSearch.png")); + searchButton->setStyleSheet("QPushButton {border:none; background:#2a2a2a;}"); + searchButton->setFixedSize(22,22); + combos->addWidget(from,1); + combos->addSpacing(9); + combos->addWidget(arrow,0); + combos->addSpacing(9); + combos->addWidget(to,1); + combos->addSpacing(9); + combos->addWidget(searchButton,0); + layout->addSpacing(12); + layout->addLayout(combos); + + + //RESULTS + QHBoxLayout * resultsTitleLayout = new QHBoxLayout(); + resultsTitle = new QLabel(tr("Translation")); + resultsTitle->setStyleSheet("QLabel {font-family:Arial;font-size:14px;color:#e3e3e3;}"); + speakButton = new QPushButton(this); + speakButton->setStyleSheet("QPushButton {border:none;}"); + speakButton->setIcon(QIcon(":/images/speaker.png")); + resultsTitleLayout->addWidget(resultsTitle,0,Qt::AlignVCenter); + resultsTitleLayout->addSpacing(10); + resultsTitleLayout->addWidget(speakButton,0,Qt::AlignVCenter); + resultsTitleLayout->addStretch(); + + layout->addSpacing(15); + layout->addLayout(resultsTitleLayout); + layout->addSpacing(12); + + resultText = new QLabel(); + resultText->setWordWrap(true); + resultText->setStyleSheet("QLabel {color:white;font-size:12px;}"); + resultText->setText("ñlkas lakj dflkaj lasd jflie lkajd fie kljads ijef lasei afsliej ljse f"); + layout->addWidget(resultText); + + layout->addStretch(); + + //CLEAR BUTTON + clearButton = new QPushButton(tr("clear")); + layout->addWidget(clearButton,0,Qt::AlignRight); + clearButton->setMinimumWidth(95); + clearButton->setStyleSheet("QPushButton {border:1px solid #212121; background:#2a2a2a; color:white; font-family:Arial; font-size:12px; padding-top:5px; padding-bottom:5px;}"); + + resize(400,479); music = createPlayer(MusicCategory); + layout->setMargin(0); + layout->setContentsMargins(18,12,18,12); + setContentsMargins(0,0,0,0); + layout->setSpacing(0); + + hideResults(); + populateCombos(); + + busyIndicator = new YACReaderBusyWidget(this); + busyIndicator->move((this->width()-busyIndicator->width())/2,(this->height()-busyIndicator->height())*2/3); + busyIndicator->hide(); + show(); + + connect(searchButton,SIGNAL(pressed()),this,SLOT(translate())); + connect(speakButton,SIGNAL(pressed()),this,SLOT(play())); + connect(clearButton,SIGNAL(pressed()),this,SLOT(clear())); } -void YACReaderTranslator::play(const QUrl & url) +void YACReaderTranslator::hideResults() { - MediaSource src(url); + resultsTitle->setHidden(true); + speakButton->setHidden(true); + resultText->setHidden(true); +} + +void YACReaderTranslator::clear() +{ + hideResults(); + text->clear(); +} + +void YACReaderTranslator::translate() +{ + QString text = this->text->toPlainText(); + if(text.isEmpty()) + return; + QString from = this->from->itemData(this->from->currentIndex()).toString(); + QString to = this->to->itemData(this->to->currentIndex()).toString(); + + TranslationLoader * translationLoader = new TranslationLoader(text,from,to); + connect(translationLoader,SIGNAL(requestFinished(QString)),this,SLOT(setTranslation(QString))); + connect(translationLoader,SIGNAL(error()),this,SLOT(error())); + connect(translationLoader,SIGNAL(timeOut()),this,SLOT(error())); + connect(translationLoader,SIGNAL(finished()),translationLoader,SLOT(deleteLater())); + + TextToSpeachLoader * tts = new TextToSpeachLoader(text,from); + connect(tts,SIGNAL(requestFinished(QUrl)),this,SLOT(setSpeak(QUrl))); + connect(tts,SIGNAL(error()),this,SLOT(error())); + connect(tts,SIGNAL(timeOut()),this,SLOT(error())); + connect(tts,SIGNAL(finished()),tts,SLOT(deleteLater())); + + translationLoader->start(); + tts->start(); + + resultsTitle->setText(tr("Translation")); + + hideResults(); + + busyIndicator->show(); +} + +void YACReaderTranslator::error() +{ + resultsTitle->setText(tr("Service not available")); + resultsTitle->setHidden(false); + busyIndicator->hide(); +} + +void YACReaderTranslator::setSpeak(const QUrl & url) +{ + resultsTitle->setHidden(false); + speakButton->setHidden(false); + + ttsSource = url; +} + +void YACReaderTranslator::setTranslation(const QString & string) +{ + resultText->setText(string); + + resultsTitle->setHidden(false); + resultText->setHidden(false); + busyIndicator->hide(); +} + +void YACReaderTranslator::populateCombos() +{ + QList combos; + combos.append(from); + combos.append(to); + + for(int i=0;iaddItem("Arabic","ar"); + combo->addItem("Bulgarian","bg"); + combo->addItem("Catalan","ca"); + combo->addItem("Chinese Simplified","zh-CHS"); + combo->addItem("Chinese Traditional","zh-CHT"); + combo->addItem("Czech","cs"); + combo->addItem("Danish","da"); + combo->addItem("Dutch","nl"); + combo->addItem("English","en"); + combo->addItem("Estonian","et"); + combo->addItem("Finnish","fi"); + combo->addItem("French","fr"); + combo->addItem("German","de"); + combo->addItem("Greek","el"); + combo->addItem("Haitian Creole","ht"); + combo->addItem("Hebrew","he"); + combo->addItem("Hindi","hi"); + combo->addItem("Hungarian","hu"); + combo->addItem("Indonesian","id"); + combo->addItem("Italian","it"); + combo->addItem("Japanese","ja"); + combo->addItem("Korean","ko"); + combo->addItem("Latvian","lv"); + combo->addItem("Lithuanian","lt"); + combo->addItem("Norwegian","no"); + combo->addItem("Polish","pl"); + combo->addItem("Portuguese","pt"); + combo->addItem("Romanian","ro"); + combo->addItem("Russian","ru"); + combo->addItem("Slovak","sk"); + combo->addItem("Slovenian","sl"); + combo->addItem("Spanish","es"); + combo->addItem("Swedish","sv"); + combo->addItem("Thai","th"); + combo->addItem("Turkish","tr"); + combo->addItem("Ukrainian","uk"); + combo->addItem("Vietnamese","vi"); + } + from->setCurrentIndex(from->findText("English")); + to->setCurrentIndex(from->findText("Spanish")); +} + +void YACReaderTranslator::play() +{ + //QMessageBox::question(this,"xxx",ttsSource.toString()); + MediaSource src(ttsSource); src.setAutoDelete(true); - music->setCurrentSource(src); - music->play(); + music->setCurrentSource(src); + music->play(); } YACReaderTranslator::~YACReaderTranslator() @@ -72,8 +294,12 @@ YACReaderTranslator::~YACReaderTranslator() void YACReaderTranslator::mousePressEvent(QMouseEvent *event) { - drag = true; - click = event->pos(); + QPoint p = mapTo(this,event->pos()); + if(p.y() < 40) + { + drag = true; + click = event->pos(); + } } void YACReaderTranslator::mouseReleaseEvent(QMouseEvent *event) @@ -88,3 +314,94 @@ void YACReaderTranslator::mouseMoveEvent(QMouseEvent * event) } +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + +TranslationLoader::TranslationLoader(QString text, QString from, QString to) + :QThread(),text(text),from(from),to(to) +{ +} + +void TranslationLoader::run() +{ + QNetworkAccessManager manager; + QEventLoop q; + QTimer tT; + + tT.setSingleShot(true); + connect(&tT, SIGNAL(timeout()), &q, SLOT(quit())); + connect(&manager, SIGNAL(finished(QNetworkReply*)),&q, SLOT(quit())); + + QString url = "http://api.microsofttranslator.com/V2/Ajax.svc/Translate?appid=%1&from=%2&to=%3&text=%4&contentType=text/plain"; + url = url.arg(APPID).arg(from).arg(to).arg(text); + + QNetworkReply *reply = manager.get(QNetworkRequest(QUrl(url))); + + tT.start(5000); // 5s timeout + q.exec(); + + if(tT.isActive()){ + // download complete + if(reply->error() == QNetworkReply::NoError) + { + QString utf8 = QString::fromUtf8(reply->readAll()); + utf8 = utf8.remove(0,1); + utf8 = utf8.remove(utf8.count()-1,1); + + QString translated(utf8); + emit(requestFinished(translated)); + } + else + emit(error()); + } else { + emit(timeOut()); + } +} + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + + +TextToSpeachLoader::TextToSpeachLoader(QString text, QString language) + :QThread(),text(text),language(language) +{ +} + + +void TextToSpeachLoader::run() +{ + QNetworkAccessManager manager; + QEventLoop q; + QTimer tT; + + tT.setSingleShot(true); + connect(&tT, SIGNAL(timeout()), &q, SLOT(quit())); + connect(&manager, SIGNAL(finished(QNetworkReply*)),&q, SLOT(quit())); + + QString url = "http://api.microsofttranslator.com/V2/Ajax.svc/Speak?appid=%1&language=%2&text=%3&contentType=text/plain"; + url = url.arg(APPID).arg(language).arg(text); + + QNetworkReply *reply = manager.get(QNetworkRequest(QUrl(url))); + + tT.start(5000); // 5s timeout + q.exec(); + + if(tT.isActive()){ + // download complete + if(reply->error() == QNetworkReply::NoError) + { + QString utf8 = QString::fromUtf8(reply->readAll()); + utf8 = utf8.remove(0,1); + utf8 = utf8.remove(utf8.count()-1,1); + utf8 = utf8.replace("\\",""); + + emit(requestFinished(QUrl(utf8))); + } + else + emit(error()); + } else { + emit(timeOut()); + } +} diff --git a/YACReader/translator.h b/YACReader/translator.h index 759ce22c..71fb49e9 100644 --- a/YACReader/translator.h +++ b/YACReader/translator.h @@ -4,7 +4,16 @@ class QUrl; class QMouseEvent; class QPoint; -#include +class QTextEdit; +class QComboBox; +class QLabel; +class QPushButton; +class YACReaderBusyWidget; + +#include +#include +#include + #include using namespace Phonon; @@ -17,16 +26,66 @@ class YACReaderTranslator : public QWidget ~YACReaderTranslator(); public slots: - void play(const QUrl & url); + void play(); + + protected slots: + void translate(); + void setSpeak(const QUrl & url); + void setTranslation(const QString & string); + void error(); + void clear(); protected: void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent ( QMouseEvent * event ); + void hideResults(); + + void populateCombos(); bool drag; QPoint click; private: MediaObject * music; + QTextEdit * text; + QComboBox * from; + QComboBox * to; + QLabel * resultsTitle; + QPushButton * speakButton; + QLabel * resultText; + YACReaderBusyWidget * busyIndicator; + QUrl ttsSource; + QPushButton * clearButton; + }; +class TranslationLoader : public QThread +{ + Q_OBJECT +public: + TranslationLoader(QString text, QString from, QString to); +signals: + void requestFinished(QString); + void timeOut(); + void error(); +private: + QString text; + QString from; + QString to; + void run(); +}; + +class TextToSpeachLoader : public QThread +{ + Q_OBJECT +public: + TextToSpeachLoader(QString text, QString language); +signals: + void requestFinished(QUrl); + void timeOut(); + void error(); +private: + QString text; + QString language; + void run(); +}; #endif \ No newline at end of file diff --git a/YACReader/viewer.cpp b/YACReader/viewer.cpp index 58305bd3..81ed5730 100644 --- a/YACReader/viewer.cpp +++ b/YACReader/viewer.cpp @@ -12,7 +12,6 @@ #include "page_label_widget.h" #include "notifications_label_widget.h" -#include #include #define STEPS 22 diff --git a/images/close.png b/images/close.png index 964f2065..54d51b35 100644 Binary files a/images/close.png and b/images/close.png differ diff --git a/images/dropDownArrow.png b/images/dropDownArrow.png new file mode 100644 index 00000000..db5ea8d8 Binary files /dev/null and b/images/dropDownArrow.png differ diff --git a/images/fromTo.png b/images/fromTo.png new file mode 100644 index 00000000..87ec680d Binary files /dev/null and b/images/fromTo.png differ diff --git a/images/speaker.png b/images/speaker.png new file mode 100644 index 00000000..e75be689 Binary files /dev/null and b/images/speaker.png differ diff --git a/images/translatorSearch.png b/images/translatorSearch.png new file mode 100644 index 00000000..066f21e9 Binary files /dev/null and b/images/translatorSearch.png differ