Finish 2.0.0
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						@ -5,4 +5,6 @@
 | 
			
		||||
*.user
 | 
			
		||||
 | 
			
		||||
*.exe
 | 
			
		||||
distr/content/
 | 
			
		||||
distr/content/
 | 
			
		||||
 | 
			
		||||
*.tar.gz
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										19
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,19 @@
 | 
			
		||||
language: cpp
 | 
			
		||||
compiler:
 | 
			
		||||
  - gcc
 | 
			
		||||
  - clang
 | 
			
		||||
sudo: required
 | 
			
		||||
dist: trusty
 | 
			
		||||
install: ./scripts/install_deps.sh
 | 
			
		||||
script: cd scripts && ./make_all.sh
 | 
			
		||||
branches:
 | 
			
		||||
  only:
 | 
			
		||||
    - master
 | 
			
		||||
    - develop
 | 
			
		||||
    - /release.*/
 | 
			
		||||
    - /.*travis/
 | 
			
		||||
os:
 | 
			
		||||
  - linux
 | 
			
		||||
email:
 | 
			
		||||
  on_success: change
 | 
			
		||||
  on_failure: change
 | 
			
		||||
							
								
								
									
										204
									
								
								3rd-party/qtsingleapplication/qtlocalpeer.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,204 @@
 | 
			
		||||
/****************************************************************************
 | 
			
		||||
**
 | 
			
		||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 | 
			
		||||
** Contact: http://www.qt-project.org/legal
 | 
			
		||||
**
 | 
			
		||||
** This file is part of the Qt Solutions component.
 | 
			
		||||
**
 | 
			
		||||
** $QT_BEGIN_LICENSE:BSD$
 | 
			
		||||
** You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
**
 | 
			
		||||
** "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 Digia Plc and its Subsidiary(-ies) 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."
 | 
			
		||||
**
 | 
			
		||||
** $QT_END_LICENSE$
 | 
			
		||||
**
 | 
			
		||||
****************************************************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "qtlocalpeer.h"
 | 
			
		||||
#include <QCoreApplication>
 | 
			
		||||
#include <QDataStream>
 | 
			
		||||
#include <QTime>
 | 
			
		||||
 | 
			
		||||
#if defined(Q_OS_WIN)
 | 
			
		||||
#include <QLibrary>
 | 
			
		||||
#include <qt_windows.h>
 | 
			
		||||
typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*);
 | 
			
		||||
static PProcessIdToSessionId pProcessIdToSessionId = 0;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(Q_OS_UNIX)
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace QtLP_Private {
 | 
			
		||||
#include "qtlockedfile.cpp"
 | 
			
		||||
#if defined(Q_OS_WIN)
 | 
			
		||||
#include "qtlockedfile_win.cpp"
 | 
			
		||||
#else
 | 
			
		||||
#include "qtlockedfile_unix.cpp"
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char* QtLocalPeer::ack = "ack";
 | 
			
		||||
 | 
			
		||||
QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId)
 | 
			
		||||
    : QObject(parent), id(appId)
 | 
			
		||||
{
 | 
			
		||||
    QString prefix = id;
 | 
			
		||||
    if (id.isEmpty()) {
 | 
			
		||||
        id = QCoreApplication::applicationFilePath();
 | 
			
		||||
#if defined(Q_OS_WIN)
 | 
			
		||||
        id = id.toLower();
 | 
			
		||||
#endif
 | 
			
		||||
        prefix = id.section(QLatin1Char('/'), -1);
 | 
			
		||||
    }
 | 
			
		||||
    prefix.remove(QRegExp("[^a-zA-Z]"));
 | 
			
		||||
    prefix.truncate(6);
 | 
			
		||||
 | 
			
		||||
    QByteArray idc = id.toUtf8();
 | 
			
		||||
    quint16 idNum = qChecksum(idc.constData(), idc.size());
 | 
			
		||||
    socketName = QLatin1String("qtsingleapp-") + prefix
 | 
			
		||||
                 + QLatin1Char('-') + QString::number(idNum, 16);
 | 
			
		||||
 | 
			
		||||
#if defined(Q_OS_WIN)
 | 
			
		||||
    if (!pProcessIdToSessionId) {
 | 
			
		||||
        QLibrary lib("kernel32");
 | 
			
		||||
        pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId");
 | 
			
		||||
    }
 | 
			
		||||
    if (pProcessIdToSessionId) {
 | 
			
		||||
        DWORD sessionId = 0;
 | 
			
		||||
        pProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
 | 
			
		||||
        socketName += QLatin1Char('-') + QString::number(sessionId, 16);
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
    socketName += QLatin1Char('-') + QString::number(::getuid(), 16);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    server = new QLocalServer(this);
 | 
			
		||||
    QString lockName = QDir(QDir::tempPath()).absolutePath()
 | 
			
		||||
                       + QLatin1Char('/') + socketName
 | 
			
		||||
                       + QLatin1String("-lockfile");
 | 
			
		||||
    lockFile.setFileName(lockName);
 | 
			
		||||
    lockFile.open(QIODevice::ReadWrite);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool QtLocalPeer::isClient()
 | 
			
		||||
{
 | 
			
		||||
    if (lockFile.isLocked())
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false))
 | 
			
		||||
        return true;
 | 
			
		||||
 | 
			
		||||
    bool res = server->listen(socketName);
 | 
			
		||||
#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0))
 | 
			
		||||
    // ### Workaround
 | 
			
		||||
    if (!res && server->serverError() == QAbstractSocket::AddressInUseError) {
 | 
			
		||||
        QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName);
 | 
			
		||||
        res = server->listen(socketName);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    if (!res)
 | 
			
		||||
        qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString()));
 | 
			
		||||
    QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection()));
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool QtLocalPeer::sendMessage(const QString &message, int timeout)
 | 
			
		||||
{
 | 
			
		||||
    if (!isClient())
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    QLocalSocket socket;
 | 
			
		||||
    bool connOk = false;
 | 
			
		||||
    for(int i = 0; i < 2; i++) {
 | 
			
		||||
        // Try twice, in case the other instance is just starting up
 | 
			
		||||
        socket.connectToServer(socketName);
 | 
			
		||||
        connOk = socket.waitForConnected(timeout/2);
 | 
			
		||||
        if (connOk || i)
 | 
			
		||||
            break;
 | 
			
		||||
        int ms = 250;
 | 
			
		||||
#if defined(Q_OS_WIN)
 | 
			
		||||
        Sleep(DWORD(ms));
 | 
			
		||||
#else
 | 
			
		||||
        struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
 | 
			
		||||
        nanosleep(&ts, NULL);
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
    if (!connOk)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    QByteArray uMsg(message.toUtf8());
 | 
			
		||||
    QDataStream ds(&socket);
 | 
			
		||||
    ds.writeBytes(uMsg.constData(), uMsg.size());
 | 
			
		||||
    bool res = socket.waitForBytesWritten(timeout);
 | 
			
		||||
    if (res) {
 | 
			
		||||
        res &= socket.waitForReadyRead(timeout);   // wait for ack
 | 
			
		||||
        if (res)
 | 
			
		||||
            res &= (socket.read(qstrlen(ack)) == ack);
 | 
			
		||||
    }
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void QtLocalPeer::receiveConnection()
 | 
			
		||||
{
 | 
			
		||||
    QLocalSocket* socket = server->nextPendingConnection();
 | 
			
		||||
    if (!socket)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    while (socket->bytesAvailable() < (int)sizeof(quint32))
 | 
			
		||||
        socket->waitForReadyRead();
 | 
			
		||||
    QDataStream ds(socket);
 | 
			
		||||
    QByteArray uMsg;
 | 
			
		||||
    quint32 remaining;
 | 
			
		||||
    ds >> remaining;
 | 
			
		||||
    uMsg.resize(remaining);
 | 
			
		||||
    int got = 0;
 | 
			
		||||
    char* uMsgBuf = uMsg.data();
 | 
			
		||||
    do {
 | 
			
		||||
        got = ds.readRawData(uMsgBuf, remaining);
 | 
			
		||||
        remaining -= got;
 | 
			
		||||
        uMsgBuf += got;
 | 
			
		||||
    } while (remaining && got >= 0 && socket->waitForReadyRead(2000));
 | 
			
		||||
    if (got < 0) {
 | 
			
		||||
        qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData());
 | 
			
		||||
        delete socket;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    QString message(QString::fromUtf8(uMsg));
 | 
			
		||||
    socket->write(ack, qstrlen(ack));
 | 
			
		||||
    socket->waitForBytesWritten(1000);
 | 
			
		||||
    socket->waitForDisconnected(1000); // make sure client reads ack
 | 
			
		||||
    delete socket;
 | 
			
		||||
    emit messageReceived(message); //### (might take a long time to return)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										77
									
								
								3rd-party/qtsingleapplication/qtlocalpeer.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,77 @@
 | 
			
		||||
/****************************************************************************
 | 
			
		||||
**
 | 
			
		||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 | 
			
		||||
** Contact: http://www.qt-project.org/legal
 | 
			
		||||
**
 | 
			
		||||
** This file is part of the Qt Solutions component.
 | 
			
		||||
**
 | 
			
		||||
** $QT_BEGIN_LICENSE:BSD$
 | 
			
		||||
** You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
**
 | 
			
		||||
** "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 Digia Plc and its Subsidiary(-ies) 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."
 | 
			
		||||
**
 | 
			
		||||
** $QT_END_LICENSE$
 | 
			
		||||
**
 | 
			
		||||
****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef QTLOCALPEER_H
 | 
			
		||||
#define QTLOCALPEER_H
 | 
			
		||||
 | 
			
		||||
#include <QLocalServer>
 | 
			
		||||
#include <QLocalSocket>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
 | 
			
		||||
#include "qtlockedfile.h"
 | 
			
		||||
 | 
			
		||||
class QtLocalPeer : public QObject
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    QtLocalPeer(QObject *parent = 0, const QString &appId = QString());
 | 
			
		||||
    bool isClient();
 | 
			
		||||
    bool sendMessage(const QString &message, int timeout);
 | 
			
		||||
    QString applicationId() const
 | 
			
		||||
        { return id; }
 | 
			
		||||
 | 
			
		||||
Q_SIGNALS:
 | 
			
		||||
    void messageReceived(const QString &message);
 | 
			
		||||
 | 
			
		||||
protected Q_SLOTS:
 | 
			
		||||
    void receiveConnection();
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    QString id;
 | 
			
		||||
    QString socketName;
 | 
			
		||||
    QLocalServer* server;
 | 
			
		||||
    QtLP_Private::QtLockedFile lockFile;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    static const char* ack;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // QTLOCALPEER_H
 | 
			
		||||
							
								
								
									
										193
									
								
								3rd-party/qtsingleapplication/qtlockedfile.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,193 @@
 | 
			
		||||
/****************************************************************************
 | 
			
		||||
**
 | 
			
		||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 | 
			
		||||
** Contact: http://www.qt-project.org/legal
 | 
			
		||||
**
 | 
			
		||||
** This file is part of the Qt Solutions component.
 | 
			
		||||
**
 | 
			
		||||
** $QT_BEGIN_LICENSE:BSD$
 | 
			
		||||
** You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
**
 | 
			
		||||
** "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 Digia Plc and its Subsidiary(-ies) 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."
 | 
			
		||||
**
 | 
			
		||||
** $QT_END_LICENSE$
 | 
			
		||||
**
 | 
			
		||||
****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "qtlockedfile.h"
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    \class QtLockedFile
 | 
			
		||||
 | 
			
		||||
    \brief The QtLockedFile class extends QFile with advisory locking
 | 
			
		||||
    functions.
 | 
			
		||||
 | 
			
		||||
    A file may be locked in read or write mode. Multiple instances of
 | 
			
		||||
    \e QtLockedFile, created in multiple processes running on the same
 | 
			
		||||
    machine, may have a file locked in read mode. Exactly one instance
 | 
			
		||||
    may have it locked in write mode. A read and a write lock cannot
 | 
			
		||||
    exist simultaneously on the same file.
 | 
			
		||||
 | 
			
		||||
    The file locks are advisory. This means that nothing prevents
 | 
			
		||||
    another process from manipulating a locked file using QFile or
 | 
			
		||||
    file system functions offered by the OS. Serialization is only
 | 
			
		||||
    guaranteed if all processes that access the file use
 | 
			
		||||
    QLockedFile. Also, while holding a lock on a file, a process
 | 
			
		||||
    must not open the same file again (through any API), or locks
 | 
			
		||||
    can be unexpectedly lost.
 | 
			
		||||
 | 
			
		||||
    The lock provided by an instance of \e QtLockedFile is released
 | 
			
		||||
    whenever the program terminates. This is true even when the
 | 
			
		||||
    program crashes and no destructors are called.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*! \enum QtLockedFile::LockMode
 | 
			
		||||
 | 
			
		||||
    This enum describes the available lock modes.
 | 
			
		||||
 | 
			
		||||
    \value ReadLock A read lock.
 | 
			
		||||
    \value WriteLock A write lock.
 | 
			
		||||
    \value NoLock Neither a read lock nor a write lock.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    Constructs an unlocked \e QtLockedFile object. This constructor
 | 
			
		||||
    behaves in the same way as \e QFile::QFile().
 | 
			
		||||
 | 
			
		||||
    \sa QFile::QFile()
 | 
			
		||||
*/
 | 
			
		||||
QtLockedFile::QtLockedFile()
 | 
			
		||||
    : QFile()
 | 
			
		||||
{
 | 
			
		||||
#ifdef Q_OS_WIN
 | 
			
		||||
    wmutex = 0;
 | 
			
		||||
    rmutex = 0;
 | 
			
		||||
#endif
 | 
			
		||||
    m_lock_mode = NoLock;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    Constructs an unlocked QtLockedFile object with file \a name. This
 | 
			
		||||
    constructor behaves in the same way as \e QFile::QFile(const
 | 
			
		||||
    QString&).
 | 
			
		||||
 | 
			
		||||
    \sa QFile::QFile()
 | 
			
		||||
*/
 | 
			
		||||
QtLockedFile::QtLockedFile(const QString &name)
 | 
			
		||||
    : QFile(name)
 | 
			
		||||
{
 | 
			
		||||
#ifdef Q_OS_WIN
 | 
			
		||||
    wmutex = 0;
 | 
			
		||||
    rmutex = 0;
 | 
			
		||||
#endif
 | 
			
		||||
    m_lock_mode = NoLock;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
  Opens the file in OpenMode \a mode.
 | 
			
		||||
 | 
			
		||||
  This is identical to QFile::open(), with the one exception that the
 | 
			
		||||
  Truncate mode flag is disallowed. Truncation would conflict with the
 | 
			
		||||
  advisory file locking, since the file would be modified before the
 | 
			
		||||
  write lock is obtained. If truncation is required, use resize(0)
 | 
			
		||||
  after obtaining the write lock.
 | 
			
		||||
 | 
			
		||||
  Returns true if successful; otherwise false.
 | 
			
		||||
 | 
			
		||||
  \sa QFile::open(), QFile::resize()
 | 
			
		||||
*/
 | 
			
		||||
bool QtLockedFile::open(OpenMode mode)
 | 
			
		||||
{
 | 
			
		||||
    if (mode & QIODevice::Truncate) {
 | 
			
		||||
        qWarning("QtLockedFile::open(): Truncate mode not allowed.");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    return QFile::open(mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    Returns \e true if this object has a in read or write lock;
 | 
			
		||||
    otherwise returns \e false.
 | 
			
		||||
 | 
			
		||||
    \sa lockMode()
 | 
			
		||||
*/
 | 
			
		||||
bool QtLockedFile::isLocked() const
 | 
			
		||||
{
 | 
			
		||||
    return m_lock_mode != NoLock;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    Returns the type of lock currently held by this object, or \e
 | 
			
		||||
    QtLockedFile::NoLock.
 | 
			
		||||
 | 
			
		||||
    \sa isLocked()
 | 
			
		||||
*/
 | 
			
		||||
QtLockedFile::LockMode QtLockedFile::lockMode() const
 | 
			
		||||
{
 | 
			
		||||
    return m_lock_mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    \fn bool QtLockedFile::lock(LockMode mode, bool block = true)
 | 
			
		||||
 | 
			
		||||
    Obtains a lock of type \a mode. The file must be opened before it
 | 
			
		||||
    can be locked.
 | 
			
		||||
 | 
			
		||||
    If \a block is true, this function will block until the lock is
 | 
			
		||||
    aquired. If \a block is false, this function returns \e false
 | 
			
		||||
    immediately if the lock cannot be aquired.
 | 
			
		||||
 | 
			
		||||
    If this object already has a lock of type \a mode, this function
 | 
			
		||||
    returns \e true immediately. If this object has a lock of a
 | 
			
		||||
    different type than \a mode, the lock is first released and then a
 | 
			
		||||
    new lock is obtained.
 | 
			
		||||
 | 
			
		||||
    This function returns \e true if, after it executes, the file is
 | 
			
		||||
    locked by this object, and \e false otherwise.
 | 
			
		||||
 | 
			
		||||
    \sa unlock(), isLocked(), lockMode()
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    \fn bool QtLockedFile::unlock()
 | 
			
		||||
 | 
			
		||||
    Releases a lock.
 | 
			
		||||
 | 
			
		||||
    If the object has no lock, this function returns immediately.
 | 
			
		||||
 | 
			
		||||
    This function returns \e true if, after it executes, the file is
 | 
			
		||||
    not locked by this object, and \e false otherwise.
 | 
			
		||||
 | 
			
		||||
    \sa lock(), isLocked(), lockMode()
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    \fn QtLockedFile::~QtLockedFile()
 | 
			
		||||
 | 
			
		||||
    Destroys the \e QtLockedFile object. If any locks were held, they
 | 
			
		||||
    are released.
 | 
			
		||||
*/
 | 
			
		||||
							
								
								
									
										97
									
								
								3rd-party/qtsingleapplication/qtlockedfile.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,97 @@
 | 
			
		||||
/****************************************************************************
 | 
			
		||||
**
 | 
			
		||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 | 
			
		||||
** Contact: http://www.qt-project.org/legal
 | 
			
		||||
**
 | 
			
		||||
** This file is part of the Qt Solutions component.
 | 
			
		||||
**
 | 
			
		||||
** $QT_BEGIN_LICENSE:BSD$
 | 
			
		||||
** You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
**
 | 
			
		||||
** "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 Digia Plc and its Subsidiary(-ies) 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."
 | 
			
		||||
**
 | 
			
		||||
** $QT_END_LICENSE$
 | 
			
		||||
**
 | 
			
		||||
****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef QTLOCKEDFILE_H
 | 
			
		||||
#define QTLOCKEDFILE_H
 | 
			
		||||
 | 
			
		||||
#include <QFile>
 | 
			
		||||
#ifdef Q_OS_WIN
 | 
			
		||||
#include <QVector>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(Q_OS_WIN)
 | 
			
		||||
#  if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT)
 | 
			
		||||
#    define QT_QTLOCKEDFILE_EXPORT
 | 
			
		||||
#  elif defined(QT_QTLOCKEDFILE_IMPORT)
 | 
			
		||||
#    if defined(QT_QTLOCKEDFILE_EXPORT)
 | 
			
		||||
#      undef QT_QTLOCKEDFILE_EXPORT
 | 
			
		||||
#    endif
 | 
			
		||||
#    define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport)
 | 
			
		||||
#  elif defined(QT_QTLOCKEDFILE_EXPORT)
 | 
			
		||||
#    undef QT_QTLOCKEDFILE_EXPORT
 | 
			
		||||
#    define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport)
 | 
			
		||||
#  endif
 | 
			
		||||
#else
 | 
			
		||||
#  define QT_QTLOCKEDFILE_EXPORT
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace QtLP_Private {
 | 
			
		||||
 | 
			
		||||
class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    enum LockMode { NoLock = 0, ReadLock, WriteLock };
 | 
			
		||||
 | 
			
		||||
    QtLockedFile();
 | 
			
		||||
    QtLockedFile(const QString &name);
 | 
			
		||||
    ~QtLockedFile();
 | 
			
		||||
 | 
			
		||||
    bool open(OpenMode mode);
 | 
			
		||||
 | 
			
		||||
    bool lock(LockMode mode, bool block = true);
 | 
			
		||||
    bool unlock();
 | 
			
		||||
    bool isLocked() const;
 | 
			
		||||
    LockMode lockMode() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
#ifdef Q_OS_WIN
 | 
			
		||||
    Qt::HANDLE wmutex;
 | 
			
		||||
    Qt::HANDLE rmutex;
 | 
			
		||||
    QVector<Qt::HANDLE> rmutexes;
 | 
			
		||||
    QString mutexname;
 | 
			
		||||
 | 
			
		||||
    Qt::HANDLE getMutexHandle(int idx, bool doCreate);
 | 
			
		||||
    bool waitMutex(Qt::HANDLE mutex, bool doBlock);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
    LockMode m_lock_mode;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										115
									
								
								3rd-party/qtsingleapplication/qtlockedfile_unix.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,115 @@
 | 
			
		||||
/****************************************************************************
 | 
			
		||||
**
 | 
			
		||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 | 
			
		||||
** Contact: http://www.qt-project.org/legal
 | 
			
		||||
**
 | 
			
		||||
** This file is part of the Qt Solutions component.
 | 
			
		||||
**
 | 
			
		||||
** $QT_BEGIN_LICENSE:BSD$
 | 
			
		||||
** You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
**
 | 
			
		||||
** "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 Digia Plc and its Subsidiary(-ies) 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."
 | 
			
		||||
**
 | 
			
		||||
** $QT_END_LICENSE$
 | 
			
		||||
**
 | 
			
		||||
****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
 | 
			
		||||
#include "qtlockedfile.h"
 | 
			
		||||
 | 
			
		||||
bool QtLockedFile::lock(LockMode mode, bool block)
 | 
			
		||||
{
 | 
			
		||||
    if (!isOpen()) {
 | 
			
		||||
        qWarning("QtLockedFile::lock(): file is not opened");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
    if (mode == NoLock)
 | 
			
		||||
        return unlock();
 | 
			
		||||
           
 | 
			
		||||
    if (mode == m_lock_mode)
 | 
			
		||||
        return true;
 | 
			
		||||
 | 
			
		||||
    if (m_lock_mode != NoLock)
 | 
			
		||||
        unlock();
 | 
			
		||||
 | 
			
		||||
    struct flock fl;
 | 
			
		||||
    fl.l_whence = SEEK_SET;
 | 
			
		||||
    fl.l_start = 0;
 | 
			
		||||
    fl.l_len = 0;
 | 
			
		||||
    fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK;
 | 
			
		||||
    int cmd = block ? F_SETLKW : F_SETLK;
 | 
			
		||||
    int ret = fcntl(handle(), cmd, &fl);
 | 
			
		||||
    
 | 
			
		||||
    if (ret == -1) {
 | 
			
		||||
        if (errno != EINTR && errno != EAGAIN)
 | 
			
		||||
            qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    m_lock_mode = mode;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool QtLockedFile::unlock()
 | 
			
		||||
{
 | 
			
		||||
    if (!isOpen()) {
 | 
			
		||||
        qWarning("QtLockedFile::unlock(): file is not opened");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!isLocked())
 | 
			
		||||
        return true;
 | 
			
		||||
 | 
			
		||||
    struct flock fl;
 | 
			
		||||
    fl.l_whence = SEEK_SET;
 | 
			
		||||
    fl.l_start = 0;
 | 
			
		||||
    fl.l_len = 0;
 | 
			
		||||
    fl.l_type = F_UNLCK;
 | 
			
		||||
    int ret = fcntl(handle(), F_SETLKW, &fl);
 | 
			
		||||
    
 | 
			
		||||
    if (ret == -1) {
 | 
			
		||||
        qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    m_lock_mode = NoLock;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QtLockedFile::~QtLockedFile()
 | 
			
		||||
{
 | 
			
		||||
    if (isOpen())
 | 
			
		||||
        unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										211
									
								
								3rd-party/qtsingleapplication/qtlockedfile_win.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,211 @@
 | 
			
		||||
/****************************************************************************
 | 
			
		||||
**
 | 
			
		||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 | 
			
		||||
** Contact: http://www.qt-project.org/legal
 | 
			
		||||
**
 | 
			
		||||
** This file is part of the Qt Solutions component.
 | 
			
		||||
**
 | 
			
		||||
** $QT_BEGIN_LICENSE:BSD$
 | 
			
		||||
** You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
**
 | 
			
		||||
** "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 Digia Plc and its Subsidiary(-ies) 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."
 | 
			
		||||
**
 | 
			
		||||
** $QT_END_LICENSE$
 | 
			
		||||
**
 | 
			
		||||
****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "qtlockedfile.h"
 | 
			
		||||
#include <qt_windows.h>
 | 
			
		||||
#include <QFileInfo>
 | 
			
		||||
 | 
			
		||||
#define MUTEX_PREFIX "QtLockedFile mutex "
 | 
			
		||||
// Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS
 | 
			
		||||
#define MAX_READERS MAXIMUM_WAIT_OBJECTS
 | 
			
		||||
 | 
			
		||||
#if QT_VERSION >= 0x050000
 | 
			
		||||
#define QT_WA(unicode, ansi) unicode
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate)
 | 
			
		||||
{
 | 
			
		||||
    if (mutexname.isEmpty()) {
 | 
			
		||||
        QFileInfo fi(*this);
 | 
			
		||||
        mutexname = QString::fromLatin1(MUTEX_PREFIX)
 | 
			
		||||
                    + fi.absoluteFilePath().toLower();
 | 
			
		||||
    }
 | 
			
		||||
    QString mname(mutexname);
 | 
			
		||||
    if (idx >= 0)
 | 
			
		||||
        mname += QString::number(idx);
 | 
			
		||||
 | 
			
		||||
    Qt::HANDLE mutex;
 | 
			
		||||
    if (doCreate) {
 | 
			
		||||
        QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); },
 | 
			
		||||
               { mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } );
 | 
			
		||||
        if (!mutex) {
 | 
			
		||||
            qErrnoWarning("QtLockedFile::lock(): CreateMutex failed");
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); },
 | 
			
		||||
               { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } );
 | 
			
		||||
        if (!mutex) {
 | 
			
		||||
            if (GetLastError() != ERROR_FILE_NOT_FOUND)
 | 
			
		||||
                qErrnoWarning("QtLockedFile::lock(): OpenMutex failed");
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return mutex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock)
 | 
			
		||||
{
 | 
			
		||||
    Q_ASSERT(mutex);
 | 
			
		||||
    DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0);
 | 
			
		||||
    switch (res) {
 | 
			
		||||
    case WAIT_OBJECT_0:
 | 
			
		||||
    case WAIT_ABANDONED:
 | 
			
		||||
        return true;
 | 
			
		||||
        break;
 | 
			
		||||
    case WAIT_TIMEOUT:
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed");
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool QtLockedFile::lock(LockMode mode, bool block)
 | 
			
		||||
{
 | 
			
		||||
    if (!isOpen()) {
 | 
			
		||||
        qWarning("QtLockedFile::lock(): file is not opened");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (mode == NoLock)
 | 
			
		||||
        return unlock();
 | 
			
		||||
 | 
			
		||||
    if (mode == m_lock_mode)
 | 
			
		||||
        return true;
 | 
			
		||||
 | 
			
		||||
    if (m_lock_mode != NoLock)
 | 
			
		||||
        unlock();
 | 
			
		||||
 | 
			
		||||
    if (!wmutex && !(wmutex = getMutexHandle(-1, true)))
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    if (!waitMutex(wmutex, block))
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    if (mode == ReadLock) {
 | 
			
		||||
        int idx = 0;
 | 
			
		||||
        for (; idx < MAX_READERS; idx++) {
 | 
			
		||||
            rmutex = getMutexHandle(idx, false);
 | 
			
		||||
            if (!rmutex || waitMutex(rmutex, false))
 | 
			
		||||
                break;
 | 
			
		||||
            CloseHandle(rmutex);
 | 
			
		||||
        }
 | 
			
		||||
        bool ok = true;
 | 
			
		||||
        if (idx >= MAX_READERS) {
 | 
			
		||||
            qWarning("QtLockedFile::lock(): too many readers");
 | 
			
		||||
            rmutex = 0;
 | 
			
		||||
            ok = false;
 | 
			
		||||
        }
 | 
			
		||||
        else if (!rmutex) {
 | 
			
		||||
            rmutex = getMutexHandle(idx, true);
 | 
			
		||||
            if (!rmutex || !waitMutex(rmutex, false))
 | 
			
		||||
                ok = false;
 | 
			
		||||
        }
 | 
			
		||||
        if (!ok && rmutex) {
 | 
			
		||||
            CloseHandle(rmutex);
 | 
			
		||||
            rmutex = 0;
 | 
			
		||||
        }
 | 
			
		||||
        ReleaseMutex(wmutex);
 | 
			
		||||
        if (!ok)
 | 
			
		||||
            return false;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        Q_ASSERT(rmutexes.isEmpty());
 | 
			
		||||
        for (int i = 0; i < MAX_READERS; i++) {
 | 
			
		||||
            Qt::HANDLE mutex = getMutexHandle(i, false);
 | 
			
		||||
            if (mutex)
 | 
			
		||||
                rmutexes.append(mutex);
 | 
			
		||||
        }
 | 
			
		||||
        if (rmutexes.size()) {
 | 
			
		||||
            DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(),
 | 
			
		||||
                                               TRUE, block ? INFINITE : 0);
 | 
			
		||||
            if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) {
 | 
			
		||||
                if (res != WAIT_TIMEOUT)
 | 
			
		||||
                    qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed");
 | 
			
		||||
                m_lock_mode = WriteLock;  // trick unlock() to clean up - semiyucky
 | 
			
		||||
                unlock();
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    m_lock_mode = mode;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QtLockedFile::unlock()
 | 
			
		||||
{
 | 
			
		||||
    if (!isOpen()) {
 | 
			
		||||
        qWarning("QtLockedFile::unlock(): file is not opened");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!isLocked())
 | 
			
		||||
        return true;
 | 
			
		||||
 | 
			
		||||
    if (m_lock_mode == ReadLock) {
 | 
			
		||||
        ReleaseMutex(rmutex);
 | 
			
		||||
        CloseHandle(rmutex);
 | 
			
		||||
        rmutex = 0;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        foreach(Qt::HANDLE mutex, rmutexes) {
 | 
			
		||||
            ReleaseMutex(mutex);
 | 
			
		||||
            CloseHandle(mutex);
 | 
			
		||||
        }
 | 
			
		||||
        rmutexes.clear();
 | 
			
		||||
        ReleaseMutex(wmutex);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    m_lock_mode = QtLockedFile::NoLock;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QtLockedFile::~QtLockedFile()
 | 
			
		||||
{
 | 
			
		||||
    if (isOpen())
 | 
			
		||||
        unlock();
 | 
			
		||||
    if (wmutex)
 | 
			
		||||
        CloseHandle(wmutex);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										347
									
								
								3rd-party/qtsingleapplication/qtsingleapplication.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,347 @@
 | 
			
		||||
/****************************************************************************
 | 
			
		||||
**
 | 
			
		||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 | 
			
		||||
** Contact: http://www.qt-project.org/legal
 | 
			
		||||
**
 | 
			
		||||
** This file is part of the Qt Solutions component.
 | 
			
		||||
**
 | 
			
		||||
** $QT_BEGIN_LICENSE:BSD$
 | 
			
		||||
** You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
**
 | 
			
		||||
** "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 Digia Plc and its Subsidiary(-ies) 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."
 | 
			
		||||
**
 | 
			
		||||
** $QT_END_LICENSE$
 | 
			
		||||
**
 | 
			
		||||
****************************************************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "qtsingleapplication.h"
 | 
			
		||||
#include "qtlocalpeer.h"
 | 
			
		||||
#include <QWidget>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    \class QtSingleApplication qtsingleapplication.h
 | 
			
		||||
    \brief The QtSingleApplication class provides an API to detect and
 | 
			
		||||
    communicate with running instances of an application.
 | 
			
		||||
 | 
			
		||||
    This class allows you to create applications where only one
 | 
			
		||||
    instance should be running at a time. I.e., if the user tries to
 | 
			
		||||
    launch another instance, the already running instance will be
 | 
			
		||||
    activated instead. Another usecase is a client-server system,
 | 
			
		||||
    where the first started instance will assume the role of server,
 | 
			
		||||
    and the later instances will act as clients of that server.
 | 
			
		||||
 | 
			
		||||
    By default, the full path of the executable file is used to
 | 
			
		||||
    determine whether two processes are instances of the same
 | 
			
		||||
    application. You can also provide an explicit identifier string
 | 
			
		||||
    that will be compared instead.
 | 
			
		||||
 | 
			
		||||
    The application should create the QtSingleApplication object early
 | 
			
		||||
    in the startup phase, and call isRunning() to find out if another
 | 
			
		||||
    instance of this application is already running. If isRunning()
 | 
			
		||||
    returns false, it means that no other instance is running, and
 | 
			
		||||
    this instance has assumed the role as the running instance. In
 | 
			
		||||
    this case, the application should continue with the initialization
 | 
			
		||||
    of the application user interface before entering the event loop
 | 
			
		||||
    with exec(), as normal.
 | 
			
		||||
 | 
			
		||||
    The messageReceived() signal will be emitted when the running
 | 
			
		||||
    application receives messages from another instance of the same
 | 
			
		||||
    application. When a message is received it might be helpful to the
 | 
			
		||||
    user to raise the application so that it becomes visible. To
 | 
			
		||||
    facilitate this, QtSingleApplication provides the
 | 
			
		||||
    setActivationWindow() function and the activateWindow() slot.
 | 
			
		||||
 | 
			
		||||
    If isRunning() returns true, another instance is already
 | 
			
		||||
    running. It may be alerted to the fact that another instance has
 | 
			
		||||
    started by using the sendMessage() function. Also data such as
 | 
			
		||||
    startup parameters (e.g. the name of the file the user wanted this
 | 
			
		||||
    new instance to open) can be passed to the running instance with
 | 
			
		||||
    this function. Then, the application should terminate (or enter
 | 
			
		||||
    client mode).
 | 
			
		||||
 | 
			
		||||
    If isRunning() returns true, but sendMessage() fails, that is an
 | 
			
		||||
    indication that the running instance is frozen.
 | 
			
		||||
 | 
			
		||||
    Here's an example that shows how to convert an existing
 | 
			
		||||
    application to use QtSingleApplication. It is very simple and does
 | 
			
		||||
    not make use of all QtSingleApplication's functionality (see the
 | 
			
		||||
    examples for that).
 | 
			
		||||
 | 
			
		||||
    \code
 | 
			
		||||
    // Original
 | 
			
		||||
    int main(int argc, char **argv)
 | 
			
		||||
    {
 | 
			
		||||
        QApplication app(argc, argv);
 | 
			
		||||
 | 
			
		||||
        MyMainWidget mmw;
 | 
			
		||||
        mmw.show();
 | 
			
		||||
        return app.exec();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Single instance
 | 
			
		||||
    int main(int argc, char **argv)
 | 
			
		||||
    {
 | 
			
		||||
        QtSingleApplication app(argc, argv);
 | 
			
		||||
 | 
			
		||||
        if (app.isRunning())
 | 
			
		||||
            return !app.sendMessage(someDataString);
 | 
			
		||||
 | 
			
		||||
        MyMainWidget mmw;
 | 
			
		||||
        app.setActivationWindow(&mmw);
 | 
			
		||||
        mmw.show();
 | 
			
		||||
        return app.exec();
 | 
			
		||||
    }
 | 
			
		||||
    \endcode
 | 
			
		||||
 | 
			
		||||
    Once this QtSingleApplication instance is destroyed (normally when
 | 
			
		||||
    the process exits or crashes), when the user next attempts to run the
 | 
			
		||||
    application this instance will not, of course, be encountered. The
 | 
			
		||||
    next instance to call isRunning() or sendMessage() will assume the
 | 
			
		||||
    role as the new running instance.
 | 
			
		||||
 | 
			
		||||
    For console (non-GUI) applications, QtSingleCoreApplication may be
 | 
			
		||||
    used instead of this class, to avoid the dependency on the QtGui
 | 
			
		||||
    library.
 | 
			
		||||
 | 
			
		||||
    \sa QtSingleCoreApplication
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void QtSingleApplication::sysInit(const QString &appId)
 | 
			
		||||
{
 | 
			
		||||
    actWin = 0;
 | 
			
		||||
    peer = new QtLocalPeer(this, appId);
 | 
			
		||||
    connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    Creates a QtSingleApplication object. The application identifier
 | 
			
		||||
    will be QCoreApplication::applicationFilePath(). \a argc, \a
 | 
			
		||||
    argv, and \a GUIenabled are passed on to the QAppliation constructor.
 | 
			
		||||
 | 
			
		||||
    If you are creating a console application (i.e. setting \a
 | 
			
		||||
    GUIenabled to false), you may consider using
 | 
			
		||||
    QtSingleCoreApplication instead.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled)
 | 
			
		||||
    : QApplication(argc, argv, GUIenabled)
 | 
			
		||||
{
 | 
			
		||||
    sysInit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    Creates a QtSingleApplication object with the application
 | 
			
		||||
    identifier \a appId. \a argc and \a argv are passed on to the
 | 
			
		||||
    QAppliation constructor.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv)
 | 
			
		||||
    : QApplication(argc, argv)
 | 
			
		||||
{
 | 
			
		||||
    sysInit(appId);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if QT_VERSION < 0x050000
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    Creates a QtSingleApplication object. The application identifier
 | 
			
		||||
    will be QCoreApplication::applicationFilePath(). \a argc, \a
 | 
			
		||||
    argv, and \a type are passed on to the QAppliation constructor.
 | 
			
		||||
*/
 | 
			
		||||
QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type)
 | 
			
		||||
    : QApplication(argc, argv, type)
 | 
			
		||||
{
 | 
			
		||||
    sysInit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#  if defined(Q_WS_X11)
 | 
			
		||||
/*!
 | 
			
		||||
  Special constructor for X11, ref. the documentation of
 | 
			
		||||
  QApplication's corresponding constructor. The application identifier
 | 
			
		||||
  will be QCoreApplication::applicationFilePath(). \a dpy, \a visual,
 | 
			
		||||
  and \a cmap are passed on to the QApplication constructor.
 | 
			
		||||
*/
 | 
			
		||||
QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap)
 | 
			
		||||
    : QApplication(dpy, visual, cmap)
 | 
			
		||||
{
 | 
			
		||||
    sysInit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
  Special constructor for X11, ref. the documentation of
 | 
			
		||||
  QApplication's corresponding constructor. The application identifier
 | 
			
		||||
  will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a
 | 
			
		||||
  argv, \a visual, and \a cmap are passed on to the QApplication
 | 
			
		||||
  constructor.
 | 
			
		||||
*/
 | 
			
		||||
QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap)
 | 
			
		||||
    : QApplication(dpy, argc, argv, visual, cmap)
 | 
			
		||||
{
 | 
			
		||||
    sysInit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
  Special constructor for X11, ref. the documentation of
 | 
			
		||||
  QApplication's corresponding constructor. The application identifier
 | 
			
		||||
  will be \a appId. \a dpy, \a argc, \a
 | 
			
		||||
  argv, \a visual, and \a cmap are passed on to the QApplication
 | 
			
		||||
  constructor.
 | 
			
		||||
*/
 | 
			
		||||
QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap)
 | 
			
		||||
    : QApplication(dpy, argc, argv, visual, cmap)
 | 
			
		||||
{
 | 
			
		||||
    sysInit(appId);
 | 
			
		||||
}
 | 
			
		||||
#  endif // Q_WS_X11
 | 
			
		||||
#endif // QT_VERSION < 0x050000
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    Returns true if another instance of this application is running;
 | 
			
		||||
    otherwise false.
 | 
			
		||||
 | 
			
		||||
    This function does not find instances of this application that are
 | 
			
		||||
    being run by a different user (on Windows: that are running in
 | 
			
		||||
    another session).
 | 
			
		||||
 | 
			
		||||
    \sa sendMessage()
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
bool QtSingleApplication::isRunning()
 | 
			
		||||
{
 | 
			
		||||
    return peer->isClient();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    Tries to send the text \a message to the currently running
 | 
			
		||||
    instance. The QtSingleApplication object in the running instance
 | 
			
		||||
    will emit the messageReceived() signal when it receives the
 | 
			
		||||
    message.
 | 
			
		||||
 | 
			
		||||
    This function returns true if the message has been sent to, and
 | 
			
		||||
    processed by, the current instance. If there is no instance
 | 
			
		||||
    currently running, or if the running instance fails to process the
 | 
			
		||||
    message within \a timeout milliseconds, this function return false.
 | 
			
		||||
 | 
			
		||||
    \sa isRunning(), messageReceived()
 | 
			
		||||
*/
 | 
			
		||||
bool QtSingleApplication::sendMessage(const QString &message, int timeout)
 | 
			
		||||
{
 | 
			
		||||
    return peer->sendMessage(message, timeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    Returns the application identifier. Two processes with the same
 | 
			
		||||
    identifier will be regarded as instances of the same application.
 | 
			
		||||
*/
 | 
			
		||||
QString QtSingleApplication::id() const
 | 
			
		||||
{
 | 
			
		||||
    return peer->applicationId();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
  Sets the activation window of this application to \a aw. The
 | 
			
		||||
  activation window is the widget that will be activated by
 | 
			
		||||
  activateWindow(). This is typically the application's main window.
 | 
			
		||||
 | 
			
		||||
  If \a activateOnMessage is true (the default), the window will be
 | 
			
		||||
  activated automatically every time a message is received, just prior
 | 
			
		||||
  to the messageReceived() signal being emitted.
 | 
			
		||||
 | 
			
		||||
  \sa activateWindow(), messageReceived()
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage)
 | 
			
		||||
{
 | 
			
		||||
    actWin = aw;
 | 
			
		||||
    if (activateOnMessage)
 | 
			
		||||
        connect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow()));
 | 
			
		||||
    else
 | 
			
		||||
        disconnect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    Returns the applications activation window if one has been set by
 | 
			
		||||
    calling setActivationWindow(), otherwise returns 0.
 | 
			
		||||
 | 
			
		||||
    \sa setActivationWindow()
 | 
			
		||||
*/
 | 
			
		||||
QWidget* QtSingleApplication::activationWindow() const
 | 
			
		||||
{
 | 
			
		||||
    return actWin;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
  De-minimizes, raises, and activates this application's activation window.
 | 
			
		||||
  This function does nothing if no activation window has been set.
 | 
			
		||||
 | 
			
		||||
  This is a convenience function to show the user that this
 | 
			
		||||
  application instance has been activated when he has tried to start
 | 
			
		||||
  another instance.
 | 
			
		||||
 | 
			
		||||
  This function should typically be called in response to the
 | 
			
		||||
  messageReceived() signal. By default, that will happen
 | 
			
		||||
  automatically, if an activation window has been set.
 | 
			
		||||
 | 
			
		||||
  \sa setActivationWindow(), messageReceived(), initialize()
 | 
			
		||||
*/
 | 
			
		||||
void QtSingleApplication::activateWindow()
 | 
			
		||||
{
 | 
			
		||||
    if (actWin) {
 | 
			
		||||
        actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized);
 | 
			
		||||
        actWin->raise();
 | 
			
		||||
        actWin->activateWindow();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    \fn void QtSingleApplication::messageReceived(const QString& message)
 | 
			
		||||
 | 
			
		||||
    This signal is emitted when the current instance receives a \a
 | 
			
		||||
    message from another instance of this application.
 | 
			
		||||
 | 
			
		||||
    \sa sendMessage(), setActivationWindow(), activateWindow()
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    \fn void QtSingleApplication::initialize(bool dummy = true)
 | 
			
		||||
 | 
			
		||||
    \obsolete
 | 
			
		||||
*/
 | 
			
		||||
							
								
								
									
										105
									
								
								3rd-party/qtsingleapplication/qtsingleapplication.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,105 @@
 | 
			
		||||
/****************************************************************************
 | 
			
		||||
**
 | 
			
		||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 | 
			
		||||
** Contact: http://www.qt-project.org/legal
 | 
			
		||||
**
 | 
			
		||||
** This file is part of the Qt Solutions component.
 | 
			
		||||
**
 | 
			
		||||
** $QT_BEGIN_LICENSE:BSD$
 | 
			
		||||
** You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
**
 | 
			
		||||
** "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 Digia Plc and its Subsidiary(-ies) 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."
 | 
			
		||||
**
 | 
			
		||||
** $QT_END_LICENSE$
 | 
			
		||||
**
 | 
			
		||||
****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef QTSINGLEAPPLICATION_H
 | 
			
		||||
#define QTSINGLEAPPLICATION_H
 | 
			
		||||
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
 | 
			
		||||
class QtLocalPeer;
 | 
			
		||||
 | 
			
		||||
#if defined(Q_OS_WIN)
 | 
			
		||||
#  if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT)
 | 
			
		||||
#    define QT_QTSINGLEAPPLICATION_EXPORT
 | 
			
		||||
#  elif defined(QT_QTSINGLEAPPLICATION_IMPORT)
 | 
			
		||||
#    if defined(QT_QTSINGLEAPPLICATION_EXPORT)
 | 
			
		||||
#      undef QT_QTSINGLEAPPLICATION_EXPORT
 | 
			
		||||
#    endif
 | 
			
		||||
#    define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport)
 | 
			
		||||
#  elif defined(QT_QTSINGLEAPPLICATION_EXPORT)
 | 
			
		||||
#    undef QT_QTSINGLEAPPLICATION_EXPORT
 | 
			
		||||
#    define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport)
 | 
			
		||||
#  endif
 | 
			
		||||
#else
 | 
			
		||||
#  define QT_QTSINGLEAPPLICATION_EXPORT
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    QtSingleApplication(int &argc, char **argv, bool GUIenabled = true);
 | 
			
		||||
    QtSingleApplication(const QString &id, int &argc, char **argv);
 | 
			
		||||
#if QT_VERSION < 0x050000
 | 
			
		||||
    QtSingleApplication(int &argc, char **argv, Type type);
 | 
			
		||||
#  if defined(Q_WS_X11)
 | 
			
		||||
    QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0);
 | 
			
		||||
    QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0);
 | 
			
		||||
    QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0);
 | 
			
		||||
#  endif // Q_WS_X11
 | 
			
		||||
#endif // QT_VERSION < 0x050000
 | 
			
		||||
 | 
			
		||||
    bool isRunning();
 | 
			
		||||
    QString id() const;
 | 
			
		||||
 | 
			
		||||
    void setActivationWindow(QWidget* aw, bool activateOnMessage = true);
 | 
			
		||||
    QWidget* activationWindow() const;
 | 
			
		||||
 | 
			
		||||
    // Obsolete:
 | 
			
		||||
    void initialize(bool dummy = true)
 | 
			
		||||
        { isRunning(); Q_UNUSED(dummy) }
 | 
			
		||||
 | 
			
		||||
public Q_SLOTS:
 | 
			
		||||
    bool sendMessage(const QString &message, int timeout = 5000);
 | 
			
		||||
    void activateWindow();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Q_SIGNALS:
 | 
			
		||||
    void messageReceived(const QString &message);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void sysInit(const QString &appId = QString());
 | 
			
		||||
    QtLocalPeer *peer;
 | 
			
		||||
    QWidget *actWin;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // QTSINGLEAPPLICATION_H
 | 
			
		||||
							
								
								
									
										17
									
								
								3rd-party/qtsingleapplication/qtsingleapplication.pri
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,17 @@
 | 
			
		||||
#include(../common.pri)
 | 
			
		||||
INCLUDEPATH += $$PWD
 | 
			
		||||
DEPENDPATH += $$PWD
 | 
			
		||||
QT *= network
 | 
			
		||||
greaterThan(QT_MAJOR_VERSION, 4): QT *= widgets
 | 
			
		||||
 | 
			
		||||
qtsingleapplication-uselib:!qtsingleapplication-buildlib {
 | 
			
		||||
    LIBS += -L$$QTSINGLEAPPLICATION_LIBDIR -l$$QTSINGLEAPPLICATION_LIBNAME
 | 
			
		||||
} else {
 | 
			
		||||
    SOURCES += $$PWD/qtsingleapplication.cpp $$PWD/qtlocalpeer.cpp
 | 
			
		||||
    HEADERS += $$PWD/qtsingleapplication.h $$PWD/qtlocalpeer.h
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
win32 {
 | 
			
		||||
    contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTSINGLEAPPLICATION_EXPORT
 | 
			
		||||
    else:qtsingleapplication-uselib:DEFINES += QT_QTSINGLEAPPLICATION_IMPORT
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										149
									
								
								3rd-party/qtsingleapplication/qtsinglecoreapplication.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,149 @@
 | 
			
		||||
/****************************************************************************
 | 
			
		||||
**
 | 
			
		||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 | 
			
		||||
** Contact: http://www.qt-project.org/legal
 | 
			
		||||
**
 | 
			
		||||
** This file is part of the Qt Solutions component.
 | 
			
		||||
**
 | 
			
		||||
** $QT_BEGIN_LICENSE:BSD$
 | 
			
		||||
** You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
**
 | 
			
		||||
** "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 Digia Plc and its Subsidiary(-ies) 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."
 | 
			
		||||
**
 | 
			
		||||
** $QT_END_LICENSE$
 | 
			
		||||
**
 | 
			
		||||
****************************************************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "qtsinglecoreapplication.h"
 | 
			
		||||
#include "qtlocalpeer.h"
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    \class QtSingleCoreApplication qtsinglecoreapplication.h
 | 
			
		||||
    \brief A variant of the QtSingleApplication class for non-GUI applications.
 | 
			
		||||
 | 
			
		||||
    This class is a variant of QtSingleApplication suited for use in
 | 
			
		||||
    console (non-GUI) applications. It is an extension of
 | 
			
		||||
    QCoreApplication (instead of QApplication). It does not require
 | 
			
		||||
    the QtGui library.
 | 
			
		||||
 | 
			
		||||
    The API and usage is identical to QtSingleApplication, except that
 | 
			
		||||
    functions relating to the "activation window" are not present, for
 | 
			
		||||
    obvious reasons. Please refer to the QtSingleApplication
 | 
			
		||||
    documentation for explanation of the usage.
 | 
			
		||||
 | 
			
		||||
    A QtSingleCoreApplication instance can communicate to a
 | 
			
		||||
    QtSingleApplication instance if they share the same application
 | 
			
		||||
    id. Hence, this class can be used to create a light-weight
 | 
			
		||||
    command-line tool that sends commands to a GUI application.
 | 
			
		||||
 | 
			
		||||
    \sa QtSingleApplication
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    Creates a QtSingleCoreApplication object. The application identifier
 | 
			
		||||
    will be QCoreApplication::applicationFilePath(). \a argc and \a
 | 
			
		||||
    argv are passed on to the QCoreAppliation constructor.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv)
 | 
			
		||||
    : QCoreApplication(argc, argv)
 | 
			
		||||
{
 | 
			
		||||
    peer = new QtLocalPeer(this);
 | 
			
		||||
    connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    Creates a QtSingleCoreApplication object with the application
 | 
			
		||||
    identifier \a appId. \a argc and \a argv are passed on to the
 | 
			
		||||
    QCoreAppliation constructor.
 | 
			
		||||
*/
 | 
			
		||||
QtSingleCoreApplication::QtSingleCoreApplication(const QString &appId, int &argc, char **argv)
 | 
			
		||||
    : QCoreApplication(argc, argv)
 | 
			
		||||
{
 | 
			
		||||
    peer = new QtLocalPeer(this, appId);
 | 
			
		||||
    connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    Returns true if another instance of this application is running;
 | 
			
		||||
    otherwise false.
 | 
			
		||||
 | 
			
		||||
    This function does not find instances of this application that are
 | 
			
		||||
    being run by a different user (on Windows: that are running in
 | 
			
		||||
    another session).
 | 
			
		||||
 | 
			
		||||
    \sa sendMessage()
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
bool QtSingleCoreApplication::isRunning()
 | 
			
		||||
{
 | 
			
		||||
    return peer->isClient();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    Tries to send the text \a message to the currently running
 | 
			
		||||
    instance. The QtSingleCoreApplication object in the running instance
 | 
			
		||||
    will emit the messageReceived() signal when it receives the
 | 
			
		||||
    message.
 | 
			
		||||
 | 
			
		||||
    This function returns true if the message has been sent to, and
 | 
			
		||||
    processed by, the current instance. If there is no instance
 | 
			
		||||
    currently running, or if the running instance fails to process the
 | 
			
		||||
    message within \a timeout milliseconds, this function return false.
 | 
			
		||||
 | 
			
		||||
    \sa isRunning(), messageReceived()
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
bool QtSingleCoreApplication::sendMessage(const QString &message, int timeout)
 | 
			
		||||
{
 | 
			
		||||
    return peer->sendMessage(message, timeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    Returns the application identifier. Two processes with the same
 | 
			
		||||
    identifier will be regarded as instances of the same application.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
QString QtSingleCoreApplication::id() const
 | 
			
		||||
{
 | 
			
		||||
    return peer->applicationId();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
    \fn void QtSingleCoreApplication::messageReceived(const QString& message)
 | 
			
		||||
 | 
			
		||||
    This signal is emitted when the current instance receives a \a
 | 
			
		||||
    message from another instance of this application.
 | 
			
		||||
 | 
			
		||||
    \sa sendMessage()
 | 
			
		||||
*/
 | 
			
		||||
							
								
								
									
										71
									
								
								3rd-party/qtsingleapplication/qtsinglecoreapplication.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,71 @@
 | 
			
		||||
/****************************************************************************
 | 
			
		||||
**
 | 
			
		||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 | 
			
		||||
** Contact: http://www.qt-project.org/legal
 | 
			
		||||
**
 | 
			
		||||
** This file is part of the Qt Solutions component.
 | 
			
		||||
**
 | 
			
		||||
** $QT_BEGIN_LICENSE:BSD$
 | 
			
		||||
** You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
**
 | 
			
		||||
** "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 Digia Plc and its Subsidiary(-ies) 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."
 | 
			
		||||
**
 | 
			
		||||
** $QT_END_LICENSE$
 | 
			
		||||
**
 | 
			
		||||
****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef QTSINGLECOREAPPLICATION_H
 | 
			
		||||
#define QTSINGLECOREAPPLICATION_H
 | 
			
		||||
 | 
			
		||||
#include <QCoreApplication>
 | 
			
		||||
 | 
			
		||||
class QtLocalPeer;
 | 
			
		||||
 | 
			
		||||
class QtSingleCoreApplication : public QCoreApplication
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    QtSingleCoreApplication(int &argc, char **argv);
 | 
			
		||||
    QtSingleCoreApplication(const QString &id, int &argc, char **argv);
 | 
			
		||||
 | 
			
		||||
    bool isRunning();
 | 
			
		||||
    QString id() const;
 | 
			
		||||
 | 
			
		||||
public Q_SLOTS:
 | 
			
		||||
    bool sendMessage(const QString &message, int timeout = 5000);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Q_SIGNALS:
 | 
			
		||||
    void messageReceived(const QString &message);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    QtLocalPeer* peer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // QTSINGLECOREAPPLICATION_H
 | 
			
		||||
							
								
								
									
										10
									
								
								3rd-party/qtsingleapplication/qtsinglecoreapplication.pri
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,10 @@
 | 
			
		||||
INCLUDEPATH	+= $$PWD
 | 
			
		||||
DEPENDPATH      += $$PWD
 | 
			
		||||
HEADERS		+= $$PWD/qtsinglecoreapplication.h $$PWD/qtlocalpeer.h
 | 
			
		||||
SOURCES		+= $$PWD/qtsinglecoreapplication.cpp $$PWD/qtlocalpeer.cpp
 | 
			
		||||
 | 
			
		||||
QT *= network
 | 
			
		||||
 | 
			
		||||
win32:contains(TEMPLATE, lib):contains(CONFIG, shared) {
 | 
			
		||||
    DEFINES += QT_QTSINGLECOREAPPLICATION_EXPORT=__declspec(dllexport)
 | 
			
		||||
}
 | 
			
		||||
@ -1,92 +1,192 @@
 | 
			
		||||
#include "GlobalActionHelper.h"
 | 
			
		||||
 | 
			
		||||
#include <qt_windows.h>
 | 
			
		||||
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
 | 
			
		||||
QHash<QPair<quint32, quint32>, QAction*> GlobalActionHelper::actions_;
 | 
			
		||||
QHash<QPair<quint32, quint32>, QAction *> GlobalActionHelper::actions_;
 | 
			
		||||
 | 
			
		||||
bool GlobalActionHelper::nativeEventFilter(const QByteArray& eventType,
 | 
			
		||||
                                           void* message, long* result)
 | 
			
		||||
{
 | 
			
		||||
void GlobalActionHelper::init () {
 | 
			
		||||
  qApp->installNativeEventFilter (new GlobalActionHelper);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GlobalActionHelper::makeGlobal (QAction *action) {
 | 
			
		||||
  QKeySequence hotKey = action->shortcut ();
 | 
			
		||||
  if (hotKey.isEmpty ()) {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier |
 | 
			
		||||
                                  Qt::AltModifier | Qt::MetaModifier;
 | 
			
		||||
  Qt::Key key = hotKey.isEmpty () ?
 | 
			
		||||
                Qt::Key (0) :
 | 
			
		||||
                Qt::Key ((hotKey[0] ^ allMods) & hotKey[0]);
 | 
			
		||||
  Qt::KeyboardModifiers mods = hotKey.isEmpty () ?
 | 
			
		||||
                               Qt::KeyboardModifiers (0) :
 | 
			
		||||
                               Qt::KeyboardModifiers (hotKey[0] & allMods);
 | 
			
		||||
  const quint32 nativeKey = nativeKeycode (key);
 | 
			
		||||
  const quint32 nativeMods = nativeModifiers (mods);
 | 
			
		||||
  const bool res = registerHotKey (nativeKey, nativeMods);
 | 
			
		||||
  if (res) {
 | 
			
		||||
    actions_.insert (qMakePair (nativeKey, nativeMods), action);
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    qWarning () << "Failed to register global hotkey:" << hotKey.toString ();
 | 
			
		||||
  }
 | 
			
		||||
  return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GlobalActionHelper::removeGlobal (QAction *action) {
 | 
			
		||||
  QKeySequence hotKey = action->shortcut ();
 | 
			
		||||
  if (hotKey.isEmpty ()) {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier |
 | 
			
		||||
                                  Qt::AltModifier | Qt::MetaModifier;
 | 
			
		||||
  Qt::Key key = hotKey.isEmpty () ?
 | 
			
		||||
                Qt::Key (0) :
 | 
			
		||||
                Qt::Key ((hotKey[0] ^ allMods) & hotKey[0]);
 | 
			
		||||
  Qt::KeyboardModifiers mods = hotKey.isEmpty () ?
 | 
			
		||||
                               Qt::KeyboardModifiers (0) :
 | 
			
		||||
                               Qt::KeyboardModifiers (hotKey[0] & allMods);
 | 
			
		||||
  const quint32 nativeKey = nativeKeycode (key);
 | 
			
		||||
  const quint32 nativeMods = nativeModifiers (mods);
 | 
			
		||||
  if (!actions_.contains (qMakePair (nativeKey, nativeMods))) {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  const bool res = unregisterHotKey (nativeKey, nativeMods);
 | 
			
		||||
  if (res) {
 | 
			
		||||
    actions_.remove (qMakePair (nativeKey, nativeMods));
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    qWarning () << "Failed to unregister global hotkey:" << hotKey.toString ();
 | 
			
		||||
  }
 | 
			
		||||
  return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GlobalActionHelper::triggerHotKey (quint32 nativeKey, quint32 nativeMods) {
 | 
			
		||||
  QAction *action = actions_.value (qMakePair (nativeKey, nativeMods));
 | 
			
		||||
  if (action && action->isEnabled ()) {
 | 
			
		||||
    action->activate (QAction::Trigger);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(Q_OS_LINUX)
 | 
			
		||||
#  include <QX11Info>
 | 
			
		||||
#  include <X11/Xlib.h>
 | 
			
		||||
#  include <xcb/xcb_event.h>
 | 
			
		||||
 | 
			
		||||
static bool error = false;
 | 
			
		||||
 | 
			
		||||
static int customHandler (Display *display, XErrorEvent *event) {
 | 
			
		||||
  Q_UNUSED (display);
 | 
			
		||||
  switch (event->error_code) {
 | 
			
		||||
    case BadAccess:
 | 
			
		||||
    case BadValue:
 | 
			
		||||
    case BadWindow:
 | 
			
		||||
      if (event->request_code == 33 /* X_GrabKey */ ||
 | 
			
		||||
          event->request_code == 34 /* X_UngrabKey */) {
 | 
			
		||||
        error = true;
 | 
			
		||||
      }
 | 
			
		||||
    default:
 | 
			
		||||
      return 0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GlobalActionHelper::registerHotKey (quint32 nativeKey, quint32 nativeMods) {
 | 
			
		||||
  Display *display = QX11Info::display ();
 | 
			
		||||
  Window window = QX11Info::appRootWindow ();
 | 
			
		||||
  Bool owner = True;
 | 
			
		||||
  int pointer = GrabModeAsync;
 | 
			
		||||
  int keyboard = GrabModeAsync;
 | 
			
		||||
  error = false;
 | 
			
		||||
  int (*handler)(Display *display, XErrorEvent *event) = XSetErrorHandler (customHandler);
 | 
			
		||||
  XGrabKey (display, nativeKey, nativeMods, window, owner, pointer, keyboard);
 | 
			
		||||
  // allow numlock
 | 
			
		||||
  XGrabKey (display, nativeKey, nativeMods | Mod2Mask, window, owner, pointer, keyboard);
 | 
			
		||||
  XSync (display, False);
 | 
			
		||||
  XSetErrorHandler (handler);
 | 
			
		||||
  return !error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GlobalActionHelper::unregisterHotKey (quint32 nativeKey, quint32 nativeMods) {
 | 
			
		||||
  Display *display = QX11Info::display ();
 | 
			
		||||
  Window window = QX11Info::appRootWindow ();
 | 
			
		||||
  error = false;
 | 
			
		||||
  int (*handler)(Display *display, XErrorEvent *event) = XSetErrorHandler (customHandler);
 | 
			
		||||
  XUngrabKey (display, nativeKey, nativeMods, window);
 | 
			
		||||
  // allow numlock
 | 
			
		||||
  XUngrabKey (display, nativeKey, nativeMods | Mod2Mask, window);
 | 
			
		||||
  XSync (display, False);
 | 
			
		||||
  XSetErrorHandler (handler);
 | 
			
		||||
  return !error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GlobalActionHelper::nativeEventFilter (const QByteArray &eventType,
 | 
			
		||||
                                            void *message, long *result) {
 | 
			
		||||
  Q_UNUSED (eventType);
 | 
			
		||||
  Q_UNUSED (result);
 | 
			
		||||
  MSG* msg = static_cast<MSG*>(message);
 | 
			
		||||
  if (msg->message == WM_HOTKEY)
 | 
			
		||||
  {
 | 
			
		||||
    const quint32 keycode = HIWORD(msg->lParam);
 | 
			
		||||
    const quint32 modifiers = LOWORD(msg->lParam);
 | 
			
		||||
    QAction* action = actions_.value (qMakePair (keycode, modifiers));
 | 
			
		||||
    Q_CHECK_PTR (action);
 | 
			
		||||
    action->activate (QAction::Trigger);
 | 
			
		||||
  xcb_generic_event_t *event = static_cast<xcb_generic_event_t *>(message);
 | 
			
		||||
  if (event->response_type == XCB_KEY_PRESS) {
 | 
			
		||||
    xcb_key_press_event_t *keyEvent = static_cast<xcb_key_press_event_t *>(message);
 | 
			
		||||
    const quint32 keycode = keyEvent->detail;
 | 
			
		||||
    const quint32 modifiers = keyEvent->state & ~XCB_MOD_MASK_2;
 | 
			
		||||
    triggerHotKey (keycode, modifiers);
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GlobalActionHelper::init()
 | 
			
		||||
{
 | 
			
		||||
  qApp->installNativeEventFilter (new GlobalActionHelper);
 | 
			
		||||
quint32 GlobalActionHelper::nativeKeycode (Qt::Key key) {
 | 
			
		||||
  Display *display = QX11Info::display ();
 | 
			
		||||
  KeySym keySym =  XStringToKeysym (qPrintable (QKeySequence (key).toString ()));
 | 
			
		||||
  return XKeysymToKeycode (display, keySym);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GlobalActionHelper::makeGlobal(QAction* action)
 | 
			
		||||
{
 | 
			
		||||
  QKeySequence hotKey = action->shortcut ();
 | 
			
		||||
  if (hotKey.isEmpty ())
 | 
			
		||||
  {
 | 
			
		||||
    return true;
 | 
			
		||||
quint32 GlobalActionHelper::nativeModifiers (Qt::KeyboardModifiers modifiers) {
 | 
			
		||||
  quint32 native = 0;
 | 
			
		||||
  if (modifiers & Qt::ShiftModifier) {
 | 
			
		||||
    native |= ShiftMask;
 | 
			
		||||
  }
 | 
			
		||||
  Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier |
 | 
			
		||||
                                  Qt::AltModifier | Qt::MetaModifier;
 | 
			
		||||
  Qt::Key key = hotKey.isEmpty() ?
 | 
			
		||||
                  Qt::Key(0) :
 | 
			
		||||
                  Qt::Key((hotKey[0] ^ allMods) & hotKey[0]);
 | 
			
		||||
  Qt::KeyboardModifiers mods = hotKey.isEmpty() ?
 | 
			
		||||
                                 Qt::KeyboardModifiers(0) :
 | 
			
		||||
                                 Qt::KeyboardModifiers(hotKey[0] & allMods);
 | 
			
		||||
  const quint32 nativeKey = nativeKeycode(key);
 | 
			
		||||
  const quint32 nativeMods = nativeModifiers(mods);
 | 
			
		||||
  const bool res = registerHotKey(nativeKey, nativeMods);
 | 
			
		||||
  if (res)
 | 
			
		||||
    actions_.insert (qMakePair(nativeKey, nativeMods), action);
 | 
			
		||||
  else
 | 
			
		||||
    qWarning() << "Failed to register global hotkey:" << hotKey.toString();
 | 
			
		||||
  return res;
 | 
			
		||||
  if (modifiers & Qt::ControlModifier) {
 | 
			
		||||
    native |= ControlMask;
 | 
			
		||||
  }
 | 
			
		||||
  if (modifiers & Qt::AltModifier) {
 | 
			
		||||
    native |= Mod1Mask;
 | 
			
		||||
  }
 | 
			
		||||
  if (modifiers & Qt::MetaModifier) {
 | 
			
		||||
    native |= Mod4Mask;
 | 
			
		||||
  }
 | 
			
		||||
  return native;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GlobalActionHelper::removeGlobal(QAction *action)
 | 
			
		||||
{
 | 
			
		||||
  QKeySequence hotKey = action->shortcut ();
 | 
			
		||||
  if (hotKey.isEmpty ())
 | 
			
		||||
  {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier |
 | 
			
		||||
                                  Qt::AltModifier | Qt::MetaModifier;
 | 
			
		||||
  Qt::Key key = hotKey.isEmpty() ?
 | 
			
		||||
                  Qt::Key(0) :
 | 
			
		||||
                  Qt::Key((hotKey[0] ^ allMods) & hotKey[0]);
 | 
			
		||||
  Qt::KeyboardModifiers mods = hotKey.isEmpty() ?
 | 
			
		||||
                                 Qt::KeyboardModifiers(0) :
 | 
			
		||||
                                 Qt::KeyboardModifiers(hotKey[0] & allMods);
 | 
			
		||||
  const quint32 nativeKey = nativeKeycode(key);
 | 
			
		||||
  const quint32 nativeMods = nativeModifiers(mods);
 | 
			
		||||
  if (!actions_.contains (qMakePair(nativeKey, nativeMods)))
 | 
			
		||||
  {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  const bool res = unregisterHotKey(nativeKey, nativeMods);
 | 
			
		||||
  if (res)
 | 
			
		||||
    actions_.remove (qMakePair(nativeKey, nativeMods));
 | 
			
		||||
  else
 | 
			
		||||
    qWarning() << "Failed to unregister global hotkey:" << hotKey.toString();
 | 
			
		||||
  return res;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#elif defined(Q_OS_WIN)
 | 
			
		||||
#  include <qt_windows.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool GlobalActionHelper::registerHotKey (quint32 nativeKey, quint32 nativeMods) {
 | 
			
		||||
  return RegisterHotKey (0, nativeMods ^ nativeKey, nativeMods, nativeKey);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
quint32 GlobalActionHelper::nativeKeycode(Qt::Key key)
 | 
			
		||||
{
 | 
			
		||||
  switch (key)
 | 
			
		||||
  {
 | 
			
		||||
bool GlobalActionHelper::unregisterHotKey (quint32 nativeKey, quint32 nativeMods) {
 | 
			
		||||
  return UnregisterHotKey (0, nativeMods ^ nativeKey);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GlobalActionHelper::nativeEventFilter (const QByteArray &eventType,
 | 
			
		||||
                                            void *message, long *result) {
 | 
			
		||||
  Q_UNUSED (eventType);
 | 
			
		||||
  Q_UNUSED (result);
 | 
			
		||||
  MSG *msg = static_cast<MSG *>(message);
 | 
			
		||||
  if (msg->message == WM_HOTKEY) {
 | 
			
		||||
    const quint32 keycode = HIWORD (msg->lParam);
 | 
			
		||||
    const quint32 modifiers = LOWORD (msg->lParam);
 | 
			
		||||
    triggerHotKey (keycode, modifiers);
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
quint32 GlobalActionHelper::nativeKeycode (Qt::Key key) {
 | 
			
		||||
  switch (key) {
 | 
			
		||||
    case Qt::Key_Escape:
 | 
			
		||||
      return VK_ESCAPE;
 | 
			
		||||
    case Qt::Key_Tab:
 | 
			
		||||
@ -191,9 +291,6 @@ quint32 GlobalActionHelper::nativeKeycode(Qt::Key key)
 | 
			
		||||
      return VK_MEDIA_PLAY_PAUSE;
 | 
			
		||||
    case Qt::Key_MediaStop:
 | 
			
		||||
      return VK_MEDIA_STOP;
 | 
			
		||||
      // couldn't find those in VK_*
 | 
			
		||||
      //case Qt::Key_MediaLast:
 | 
			
		||||
      //case Qt::Key_MediaRecord:
 | 
			
		||||
    case Qt::Key_VolumeDown:
 | 
			
		||||
      return VK_VOLUME_DOWN;
 | 
			
		||||
    case Qt::Key_VolumeUp:
 | 
			
		||||
@ -201,7 +298,7 @@ quint32 GlobalActionHelper::nativeKeycode(Qt::Key key)
 | 
			
		||||
    case Qt::Key_VolumeMute:
 | 
			
		||||
      return VK_VOLUME_MUTE;
 | 
			
		||||
 | 
			
		||||
      // numbers
 | 
			
		||||
    // numbers
 | 
			
		||||
    case Qt::Key_0:
 | 
			
		||||
    case Qt::Key_1:
 | 
			
		||||
    case Qt::Key_2:
 | 
			
		||||
@ -214,7 +311,7 @@ quint32 GlobalActionHelper::nativeKeycode(Qt::Key key)
 | 
			
		||||
    case Qt::Key_9:
 | 
			
		||||
      return key;
 | 
			
		||||
 | 
			
		||||
      // letters
 | 
			
		||||
    // letters
 | 
			
		||||
    case Qt::Key_A:
 | 
			
		||||
    case Qt::Key_B:
 | 
			
		||||
    case Qt::Key_C:
 | 
			
		||||
@ -248,29 +345,23 @@ quint32 GlobalActionHelper::nativeKeycode(Qt::Key key)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
quint32 GlobalActionHelper::nativeModifiers(Qt::KeyboardModifiers modifiers)
 | 
			
		||||
{
 | 
			
		||||
quint32 GlobalActionHelper::nativeModifiers (Qt::KeyboardModifiers modifiers) {
 | 
			
		||||
  // MOD_ALT, MOD_CONTROL, (MOD_KEYUP), MOD_SHIFT, MOD_WIN
 | 
			
		||||
  quint32 native = 0;
 | 
			
		||||
  if (modifiers & Qt::ShiftModifier)
 | 
			
		||||
  if (modifiers & Qt::ShiftModifier) {
 | 
			
		||||
    native |= MOD_SHIFT;
 | 
			
		||||
  if (modifiers & Qt::ControlModifier)
 | 
			
		||||
  }
 | 
			
		||||
  if (modifiers & Qt::ControlModifier) {
 | 
			
		||||
    native |= MOD_CONTROL;
 | 
			
		||||
  if (modifiers & Qt::AltModifier)
 | 
			
		||||
  }
 | 
			
		||||
  if (modifiers & Qt::AltModifier) {
 | 
			
		||||
    native |= MOD_ALT;
 | 
			
		||||
  if (modifiers & Qt::MetaModifier)
 | 
			
		||||
  }
 | 
			
		||||
  if (modifiers & Qt::MetaModifier) {
 | 
			
		||||
    native |= MOD_WIN;
 | 
			
		||||
  }
 | 
			
		||||
  //if (modifiers & Qt::KeypadModifier)
 | 
			
		||||
  //if (modifiers & Qt::GroupSwitchModifier)
 | 
			
		||||
  return native;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GlobalActionHelper::registerHotKey(quint32 nativeKey, quint32 nativeMods)
 | 
			
		||||
{
 | 
			
		||||
  return RegisterHotKey(0, nativeMods ^ nativeKey, nativeMods, nativeKey);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GlobalActionHelper::unregisterHotKey(quint32 nativeKey, quint32 nativeMods)
 | 
			
		||||
{
 | 
			
		||||
  return UnregisterHotKey(0, nativeMods ^ nativeKey);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -6,23 +6,23 @@
 | 
			
		||||
#include <QAbstractNativeEventFilter>
 | 
			
		||||
#include <QAction>
 | 
			
		||||
 | 
			
		||||
class GlobalActionHelper : public QAbstractNativeEventFilter
 | 
			
		||||
{
 | 
			
		||||
class GlobalActionHelper : public QAbstractNativeEventFilter {
 | 
			
		||||
  public:
 | 
			
		||||
    bool nativeEventFilter (const QByteArray &eventType, void *message,
 | 
			
		||||
                            long *result);
 | 
			
		||||
 | 
			
		||||
    static void init ();
 | 
			
		||||
    static bool makeGlobal (QAction* action);
 | 
			
		||||
    static bool removeGlobal (QAction* action);
 | 
			
		||||
    static bool makeGlobal (QAction *action);
 | 
			
		||||
    static bool removeGlobal (QAction *action);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    static QHash<QPair<quint32, quint32>, QAction*> actions_;
 | 
			
		||||
    static QHash<QPair<quint32, quint32>, QAction *> actions_;
 | 
			
		||||
 | 
			
		||||
    static quint32 nativeKeycode (Qt::Key key);
 | 
			
		||||
    static quint32 nativeModifiers (Qt::KeyboardModifiers modifiers);
 | 
			
		||||
    static bool registerHotKey (quint32 nativeKey, quint32 nativeMods);
 | 
			
		||||
    static bool unregisterHotKey (quint32 nativeKey, quint32 nativeMods);
 | 
			
		||||
    static void triggerHotKey (quint32 nativeKey, quint32 nativeMods);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,93 +0,0 @@
 | 
			
		||||
#include <QWebView>
 | 
			
		||||
#include <QWebFrame>
 | 
			
		||||
#include <QWebElement>
 | 
			
		||||
#include <QSettings>
 | 
			
		||||
#include <QNetworkReply>
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
 | 
			
		||||
#include "GoogleWebTranslator.h"
 | 
			
		||||
#include "Settings.h"
 | 
			
		||||
#include "StAssert.h"
 | 
			
		||||
 | 
			
		||||
GoogleWebTranslator::GoogleWebTranslator()
 | 
			
		||||
  : QObject (), view_ (new QWebView),
 | 
			
		||||
    isLoadFinished_ (true), isTranslationFinished_ (false) {
 | 
			
		||||
 | 
			
		||||
  view_->settings()->setAttribute(QWebSettings::AutoLoadImages, false);
 | 
			
		||||
  connect (view_, SIGNAL (loadStarted()), this, SLOT (loadStarted()));
 | 
			
		||||
  connect (view_, SIGNAL (loadFinished(bool)), this, SLOT (loadFinished(bool)));
 | 
			
		||||
 | 
			
		||||
  connect (view_->page()->networkAccessManager(), SIGNAL (finished(QNetworkReply*)),
 | 
			
		||||
           this, SLOT(replyFinished(QNetworkReply*)));
 | 
			
		||||
  applySettings ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GoogleWebTranslator::~GoogleWebTranslator() {
 | 
			
		||||
  delete view_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GoogleWebTranslator::translate(ProcessingItem item) {
 | 
			
		||||
  queue_.push_back (item);
 | 
			
		||||
  if (isLoadFinished_) {
 | 
			
		||||
    load (item);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GoogleWebTranslator::applySettings(){
 | 
			
		||||
  QSettings settings;
 | 
			
		||||
  settings.beginGroup (settings_names::translationGroup);
 | 
			
		||||
  translationLanguage_ = settings.value (settings_names::translationLanguage,
 | 
			
		||||
                                         settings_values::translationLanguage).toString ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GoogleWebTranslator::loadStarted() {
 | 
			
		||||
  isLoadFinished_ = false;
 | 
			
		||||
  isTranslationFinished_ = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GoogleWebTranslator::loadFinished(bool ok) {
 | 
			
		||||
  isLoadFinished_ = true;
 | 
			
		||||
  if (ok && !isTranslationFinished_) {
 | 
			
		||||
      return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!queue_.isEmpty()) {
 | 
			
		||||
    ProcessingItem item = queue_.front();
 | 
			
		||||
    queue_.pop_front();
 | 
			
		||||
    if (ok) {
 | 
			
		||||
      QWebElementCollection result = view_->page()->mainFrame()->findAllElements("#result_box > span");
 | 
			
		||||
      item.translated = "";
 | 
			
		||||
      foreach (const QWebElement& element, result) {
 | 
			
		||||
        item.translated += element.toInnerXml() + " ";
 | 
			
		||||
      }
 | 
			
		||||
      emit translated(item, !item.translated.isEmpty());
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      emit translated (item, false);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!queue_.isEmpty()) {
 | 
			
		||||
    load (queue_.front());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GoogleWebTranslator::replyFinished(QNetworkReply *reply)
 | 
			
		||||
{
 | 
			
		||||
  if (reply->url().toString().contains ("/translate_a/single")) {
 | 
			
		||||
    isTranslationFinished_ = true;
 | 
			
		||||
    if (isLoadFinished_) {
 | 
			
		||||
      QTimer::singleShot(2000, this, SLOT(loadFinished()));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GoogleWebTranslator::load(const ProcessingItem &item) {
 | 
			
		||||
  ST_ASSERT (!item.recognized.isEmpty ());
 | 
			
		||||
  if (translationLanguage_.isEmpty ()) {
 | 
			
		||||
    emit error (tr ("Неверные парметры для перевода."));
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  QUrl url (QString ("https://translate.google.com/#auto/%1/%2").arg(translationLanguage_, item.recognized));
 | 
			
		||||
  view_->setUrl(url);
 | 
			
		||||
}
 | 
			
		||||
@ -1,43 +0,0 @@
 | 
			
		||||
#ifndef GOOGLEWEBTRANSLATOR_H
 | 
			
		||||
#define GOOGLEWEBTRANSLATOR_H
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
 | 
			
		||||
#include "ProcessingItem.h"
 | 
			
		||||
 | 
			
		||||
class QWebView;
 | 
			
		||||
class QUrl;
 | 
			
		||||
class QNetworkReply;
 | 
			
		||||
 | 
			
		||||
class GoogleWebTranslator : public QObject
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
  public:
 | 
			
		||||
    GoogleWebTranslator();
 | 
			
		||||
    ~GoogleWebTranslator();
 | 
			
		||||
 | 
			
		||||
  signals:
 | 
			
		||||
    void translated (ProcessingItem item, bool success);
 | 
			
		||||
    void error (QString text);
 | 
			
		||||
 | 
			
		||||
  public slots:
 | 
			
		||||
    void translate (ProcessingItem item);
 | 
			
		||||
    void applySettings ();
 | 
			
		||||
 | 
			
		||||
  private slots:
 | 
			
		||||
    void loadStarted ();
 | 
			
		||||
    void loadFinished(bool ok=true);
 | 
			
		||||
    void replyFinished(QNetworkReply * reply);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    void load (const ProcessingItem& item);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    QVector<ProcessingItem> queue_;
 | 
			
		||||
    QString translationLanguage_;
 | 
			
		||||
    QWebView *view_;
 | 
			
		||||
    bool isLoadFinished_;
 | 
			
		||||
    bool isTranslationFinished_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // GOOGLEWEBTRANSLATOR_H
 | 
			
		||||
@ -7,146 +7,150 @@
 | 
			
		||||
#include "ImageProcessing.h"
 | 
			
		||||
#include "StAssert.h"
 | 
			
		||||
 | 
			
		||||
#ifdef WIN32
 | 
			
		||||
#include <windows.h>
 | 
			
		||||
qint64 getFreeMemory ()
 | 
			
		||||
{
 | 
			
		||||
#if defined(Q_OS_LINUX)
 | 
			
		||||
#  include <fstream>
 | 
			
		||||
#  include <limits>
 | 
			
		||||
qint64 getFreeMemory () {
 | 
			
		||||
  std::string token;
 | 
			
		||||
  std::ifstream file ("/proc/meminfo");
 | 
			
		||||
  qint64 freeMem = 0;
 | 
			
		||||
  while (file >> token) {
 | 
			
		||||
    if (token == "MemFree:" || token == "Buffers:" || token == "Cached:") {
 | 
			
		||||
      unsigned long mem = 0;
 | 
			
		||||
      freeMem += (file >> mem) ? mem : 0;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return freeMem * 1024;
 | 
			
		||||
}
 | 
			
		||||
#elif defined(Q_OS_WIN)
 | 
			
		||||
#  include <windows.h>
 | 
			
		||||
qint64 getFreeMemory () {
 | 
			
		||||
  MEMORYSTATUSEX statex;
 | 
			
		||||
  statex.dwLength = sizeof (statex);
 | 
			
		||||
  if (GlobalMemoryStatusEx (&statex))
 | 
			
		||||
  {
 | 
			
		||||
  if (GlobalMemoryStatusEx (&statex)) {
 | 
			
		||||
    return statex.ullAvailPhys;
 | 
			
		||||
  }
 | 
			
		||||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
Pix *convertImage(const QImage& image)
 | 
			
		||||
{
 | 
			
		||||
Pix * convertImage (const QImage &image) {
 | 
			
		||||
  PIX *pix;
 | 
			
		||||
 | 
			
		||||
  QImage swapped = image.rgbSwapped();
 | 
			
		||||
  int width = swapped.width();
 | 
			
		||||
  int height = swapped.height();
 | 
			
		||||
  int depth = swapped.depth();
 | 
			
		||||
  int wpl = swapped.bytesPerLine() / 4;
 | 
			
		||||
  int width = image.width ();
 | 
			
		||||
  int height = image.height ();
 | 
			
		||||
  int depth = image.depth ();
 | 
			
		||||
  int bytesPerLine = image.bytesPerLine ();
 | 
			
		||||
  int wpl = bytesPerLine / 4;
 | 
			
		||||
 | 
			
		||||
  pix = pixCreate(width, height, depth);
 | 
			
		||||
  pixSetWpl(pix, wpl);
 | 
			
		||||
  pixSetColormap(pix, NULL);
 | 
			
		||||
  l_uint32 *outData = pix->data;
 | 
			
		||||
 | 
			
		||||
  for (int y = 0; y < height; y++)
 | 
			
		||||
  {
 | 
			
		||||
    l_uint32 *lines = outData + y * wpl;
 | 
			
		||||
    QByteArray a((const char*)swapped.scanLine(y), swapped.bytesPerLine());
 | 
			
		||||
    for (int j = 0; j < a.size(); j++)
 | 
			
		||||
    {
 | 
			
		||||
      *((l_uint8 *)lines + j) = a[j];
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  pix = pixCreate (width, height, depth);
 | 
			
		||||
  pixSetWpl (pix, wpl);
 | 
			
		||||
  pixSetColormap (pix, NULL);
 | 
			
		||||
  memmove (pix->data, image.bits (), bytesPerLine * height);
 | 
			
		||||
 | 
			
		||||
  const qreal toDPM = 1.0 / 0.0254;
 | 
			
		||||
  int resolutionX = swapped.dotsPerMeterX() / toDPM;
 | 
			
		||||
  int resolutionY = swapped.dotsPerMeterY() / toDPM;
 | 
			
		||||
  int resolutionX = image.dotsPerMeterX () / toDPM;
 | 
			
		||||
  int resolutionY = image.dotsPerMeterY () / toDPM;
 | 
			
		||||
 | 
			
		||||
  if (resolutionX < 300) resolutionX = 300;
 | 
			
		||||
  if (resolutionY < 300) resolutionY = 300;
 | 
			
		||||
  pixSetResolution(pix, resolutionX, resolutionY);
 | 
			
		||||
 | 
			
		||||
  return pixEndianByteSwapNew(pix);
 | 
			
		||||
  if (resolutionX < 300) {
 | 
			
		||||
    resolutionX = 300;
 | 
			
		||||
  }
 | 
			
		||||
  if (resolutionY < 300) {
 | 
			
		||||
    resolutionY = 300;
 | 
			
		||||
  }
 | 
			
		||||
  pixSetResolution (pix, resolutionX, resolutionY);
 | 
			
		||||
  return pix;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QImage convertImage(Pix &image)
 | 
			
		||||
{
 | 
			
		||||
  int width = pixGetWidth(&image);
 | 
			
		||||
  int height = pixGetHeight(&image);
 | 
			
		||||
  int depth = pixGetDepth(&image);
 | 
			
		||||
  int bytesPerLine = pixGetWpl(&image) * 4;
 | 
			
		||||
  l_uint32 * datas = pixGetData(pixEndianByteSwapNew(&image));
 | 
			
		||||
QImage convertImage (Pix &image) {
 | 
			
		||||
  int width = pixGetWidth (&image);
 | 
			
		||||
  int height = pixGetHeight (&image);
 | 
			
		||||
  int depth = pixGetDepth (&image);
 | 
			
		||||
  int bytesPerLine = pixGetWpl (&image) * 4;
 | 
			
		||||
  l_uint32 *datas = pixGetData (&image);
 | 
			
		||||
 | 
			
		||||
  QImage::Format format;
 | 
			
		||||
  if (depth == 1)
 | 
			
		||||
  if (depth == 1) {
 | 
			
		||||
    format = QImage::Format_Mono;
 | 
			
		||||
  else if (depth == 8)
 | 
			
		||||
  }
 | 
			
		||||
  else if (depth == 8) {
 | 
			
		||||
    format = QImage::Format_Indexed8;
 | 
			
		||||
  else
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    format = QImage::Format_RGB32;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  QImage result((uchar*)datas, width, height, bytesPerLine, format);
 | 
			
		||||
  QImage result ((uchar *)datas, width, height, bytesPerLine, format);
 | 
			
		||||
 | 
			
		||||
  // Set resolution
 | 
			
		||||
  l_int32 	xres, yres;
 | 
			
		||||
  pixGetResolution(&image, &xres, &yres);
 | 
			
		||||
  l_int32 xres, yres;
 | 
			
		||||
  pixGetResolution (&image, &xres, &yres);
 | 
			
		||||
  const qreal toDPM = 1.0 / 0.0254;
 | 
			
		||||
  result.setDotsPerMeterX(xres * toDPM);
 | 
			
		||||
  result.setDotsPerMeterY(yres * toDPM);
 | 
			
		||||
  result.setDotsPerMeterX (xres * toDPM);
 | 
			
		||||
  result.setDotsPerMeterY (yres * toDPM);
 | 
			
		||||
 | 
			
		||||
  // Handle pallete
 | 
			
		||||
  QVector<QRgb> _bwCT;
 | 
			
		||||
  _bwCT.append(qRgb(255,255,255));
 | 
			
		||||
  _bwCT.append(qRgb(0,0,0));
 | 
			
		||||
  _bwCT.append (qRgb (255,255,255));
 | 
			
		||||
  _bwCT.append (qRgb (0,0,0));
 | 
			
		||||
 | 
			
		||||
  QVector<QRgb> _grayscaleCT(256);
 | 
			
		||||
  for (int i = 0; i < 256; i++)  {
 | 
			
		||||
    _grayscaleCT.append(qRgb(i, i, i));
 | 
			
		||||
  QVector<QRgb> _grayscaleCT (256);
 | 
			
		||||
  for (int i = 0; i < 256; i++) {
 | 
			
		||||
    _grayscaleCT.append (qRgb (i, i, i));
 | 
			
		||||
  }
 | 
			
		||||
  switch (depth) {
 | 
			
		||||
    case 1:
 | 
			
		||||
      result.setColorTable(_bwCT);
 | 
			
		||||
      result.setColorTable (_bwCT);
 | 
			
		||||
      break;
 | 
			
		||||
    case 8:
 | 
			
		||||
      result.setColorTable(_grayscaleCT);
 | 
			
		||||
      result.setColorTable (_grayscaleCT);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      result.setColorTable(_grayscaleCT);
 | 
			
		||||
      result.setColorTable (_grayscaleCT);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (result.isNull()) {
 | 
			
		||||
    static QImage none(0,0,QImage::Format_Invalid);
 | 
			
		||||
    qDebug("Invalid format!!!\n");
 | 
			
		||||
  if (result.isNull ()) {
 | 
			
		||||
    static QImage none (0,0,QImage::Format_Invalid);
 | 
			
		||||
    qDebug ("Invalid format!!!\n");
 | 
			
		||||
    return none;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return result.rgbSwapped();
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Pix *prepareImage(const QImage &image, int preferredScale)
 | 
			
		||||
{
 | 
			
		||||
  Pix* pix = convertImage (image);
 | 
			
		||||
Pix * prepareImage (const QImage &image, int preferredScale) {
 | 
			
		||||
  Pix *pix = convertImage (image);
 | 
			
		||||
  ST_ASSERT (pix != NULL);
 | 
			
		||||
 | 
			
		||||
  Pix* gray = pixConvertRGBToGray (pix, 0.0, 0.0, 0.0);
 | 
			
		||||
  Pix *gray = pixConvertRGBToGray (pix, 0.0, 0.0, 0.0);
 | 
			
		||||
  ST_ASSERT (gray != NULL);
 | 
			
		||||
  pixDestroy (&pix);
 | 
			
		||||
 | 
			
		||||
  Pix* scaled = gray;
 | 
			
		||||
  if (preferredScale > 0)
 | 
			
		||||
  {
 | 
			
		||||
  Pix *scaled = gray;
 | 
			
		||||
  if (preferredScale > 0) {
 | 
			
		||||
    float maxScaleX = MAX_INT16 / double (gray->w);
 | 
			
		||||
    float scaleX = std::min (float (preferredScale), maxScaleX);
 | 
			
		||||
    float maxScaleY = MAX_INT16 / double (gray->h);
 | 
			
		||||
    float scaleY = std::min (float (preferredScale), maxScaleY);
 | 
			
		||||
    float scale = std::min (scaleX, scaleY);
 | 
			
		||||
 | 
			
		||||
#ifdef WIN32
 | 
			
		||||
    qint64 availableMemory = getFreeMemory () * 0.95;
 | 
			
		||||
    qint32 actualSize = gray->w * gray->h * gray->d / 8;
 | 
			
		||||
    float maxScaleMemory = float (availableMemory) / actualSize;
 | 
			
		||||
    scale = std::min (scale, maxScaleMemory);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    if (availableMemory > 0) {
 | 
			
		||||
      qint32 actualSize = gray->w * gray->h * gray->d / 8;
 | 
			
		||||
      float maxScaleMemory = float (availableMemory) / actualSize;
 | 
			
		||||
      scale = std::min (scale, maxScaleMemory);
 | 
			
		||||
    }
 | 
			
		||||
    scaled = pixScale (gray, scale, scale);
 | 
			
		||||
    if (scaled == NULL) {
 | 
			
		||||
      scaled = gray;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  ST_ASSERT (scaled != NULL);
 | 
			
		||||
  if (scaled != gray)
 | 
			
		||||
  {
 | 
			
		||||
  if (scaled != gray) {
 | 
			
		||||
    pixDestroy (&gray);
 | 
			
		||||
  }
 | 
			
		||||
  return scaled;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cleanupImage(Pix **image)
 | 
			
		||||
{
 | 
			
		||||
void cleanupImage (Pix **image) {
 | 
			
		||||
  pixDestroy (image);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -6,13 +6,13 @@
 | 
			
		||||
class Pix;
 | 
			
		||||
 | 
			
		||||
//! Convert QImage to Leptonica's PIX.
 | 
			
		||||
Pix* convertImage(const QImage& image);
 | 
			
		||||
Pix * convertImage (const QImage &image);
 | 
			
		||||
//! Convert Leptonica's PIX to QImage.
 | 
			
		||||
QImage convertImage(Pix &image);
 | 
			
		||||
QImage convertImage (Pix &image);
 | 
			
		||||
 | 
			
		||||
//! Propare image for OCR.
 | 
			
		||||
Pix* prepareImage (const QImage& image, int preferredScale);
 | 
			
		||||
Pix * prepareImage (const QImage &image, int preferredScale);
 | 
			
		||||
//! Free allocated resources for image.
 | 
			
		||||
void cleanupImage (Pix** image);
 | 
			
		||||
void cleanupImage (Pix **image);
 | 
			
		||||
 | 
			
		||||
#endif // IMAGEPROCESSING_H
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
The MIT License (MIT)
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2014 Gres (gres@gres.biz)
 | 
			
		||||
Copyright (c) 2015 Gres (gres@gres.biz)
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 | 
			
		||||
@ -3,109 +3,100 @@
 | 
			
		||||
 | 
			
		||||
#include "LanguageHelper.h"
 | 
			
		||||
#include "Settings.h"
 | 
			
		||||
#include "StAssert.h"
 | 
			
		||||
 | 
			
		||||
LanguageHelper::LanguageHelper()
 | 
			
		||||
{
 | 
			
		||||
LanguageHelper::LanguageHelper () {
 | 
			
		||||
  init ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList LanguageHelper::availableOcrLanguagesUi() const
 | 
			
		||||
{
 | 
			
		||||
QStringList LanguageHelper::availableOcrLanguagesUi () const {
 | 
			
		||||
  QStringList uiItems;
 | 
			
		||||
  foreach (const QString& item, availableOcrLanguages_)
 | 
			
		||||
  {
 | 
			
		||||
  foreach (const QString &item, availableOcrLanguages_) {
 | 
			
		||||
    uiItems << ocrCodeToUi (item);
 | 
			
		||||
  }
 | 
			
		||||
  uiItems.sort ();
 | 
			
		||||
  return uiItems;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const QStringList &LanguageHelper::availableOcrLanguages() const
 | 
			
		||||
{
 | 
			
		||||
const QStringList &LanguageHelper::availableOcrLanguages () const {
 | 
			
		||||
  return availableOcrLanguages_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList LanguageHelper::availableOcrLanguages(const QString &path) const
 | 
			
		||||
{
 | 
			
		||||
QStringList LanguageHelper::availableOcrLanguages (const QString &path) const {
 | 
			
		||||
  QDir dir (path + "/tessdata/");
 | 
			
		||||
  if (!dir.exists ())
 | 
			
		||||
  {
 | 
			
		||||
  if (!dir.exists ()) {
 | 
			
		||||
    return QStringList ();
 | 
			
		||||
  }
 | 
			
		||||
  QStringList items;
 | 
			
		||||
  QStringList files = dir.entryList (QStringList () << "*.traineddata", QDir::Files);
 | 
			
		||||
  foreach (const QString& file, files)
 | 
			
		||||
  {
 | 
			
		||||
  foreach (const QString &file, files) {
 | 
			
		||||
    QString lang = file.left (file.indexOf ("."));
 | 
			
		||||
    items << lang;
 | 
			
		||||
  }
 | 
			
		||||
  return items;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList LanguageHelper::availableOcrLanguagesUi(const QString &path) const
 | 
			
		||||
{
 | 
			
		||||
QStringList LanguageHelper::availableOcrLanguagesUi (const QString &path) const {
 | 
			
		||||
  QStringList uiItems, items;
 | 
			
		||||
  items = availableOcrLanguages (path);
 | 
			
		||||
  foreach (const QString& item, items)
 | 
			
		||||
  {
 | 
			
		||||
  foreach (const QString &item, items) {
 | 
			
		||||
    uiItems << ocrCodeToUi (item);
 | 
			
		||||
  }
 | 
			
		||||
  uiItems.sort ();
 | 
			
		||||
  return uiItems;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList LanguageHelper::translateLanguagesUi() const
 | 
			
		||||
{
 | 
			
		||||
QStringList LanguageHelper::translateLanguagesUi () const {
 | 
			
		||||
  QStringList uiItems = translateLanguages_.keys ();
 | 
			
		||||
  uiItems.sort ();
 | 
			
		||||
  return uiItems;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList LanguageHelper::translateLanguages() const
 | 
			
		||||
{
 | 
			
		||||
QStringList LanguageHelper::translateLanguages () const {
 | 
			
		||||
  return translateLanguages_.values ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString LanguageHelper::translateCodeToUi(const QString &text) const
 | 
			
		||||
{
 | 
			
		||||
QString LanguageHelper::translateCodeToUi (const QString &text) const {
 | 
			
		||||
  return translateLanguages_.key (text, text);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString LanguageHelper::translateUiToCode(const QString &text) const
 | 
			
		||||
{
 | 
			
		||||
QString LanguageHelper::translateUiToCode (const QString &text) const {
 | 
			
		||||
  return translateLanguages_.value (text, text);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString LanguageHelper::ocrCodeToUi(const QString &text) const
 | 
			
		||||
{
 | 
			
		||||
QString LanguageHelper::ocrCodeToUi (const QString &text) const {
 | 
			
		||||
  return ocrLanguages_.key (text, text);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString LanguageHelper::ocrUiToCode(const QString &text) const
 | 
			
		||||
{
 | 
			
		||||
QString LanguageHelper::ocrUiToCode (const QString &text) const {
 | 
			
		||||
  return ocrLanguages_.value (text, text);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString LanguageHelper::translateForOcrCode(const QString &text) const
 | 
			
		||||
{
 | 
			
		||||
  QString ocrUi = ocrUiToCode (text);
 | 
			
		||||
  QString translate = translateCodeToUi (ocrUi);
 | 
			
		||||
  if (translate == ocrUi)
 | 
			
		||||
  {
 | 
			
		||||
    translate = "auto";
 | 
			
		||||
QString LanguageHelper::ocrToTranslateCodes (const QString &text) const {
 | 
			
		||||
  QString ocrUi = ocrCodeToUi (text);
 | 
			
		||||
  QString translateCode = translateUiToCode (ocrUi);
 | 
			
		||||
  if (translateCode == ocrUi) {
 | 
			
		||||
    translateCode = "auto";
 | 
			
		||||
  }
 | 
			
		||||
  return translate;
 | 
			
		||||
  return translateCode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LanguageHelper::init()
 | 
			
		||||
{
 | 
			
		||||
QString LanguageHelper::translateToOcrCodes (const QString &text) const {
 | 
			
		||||
  QString translateUi = translateCodeToUi (text);
 | 
			
		||||
  QString ocrCode = ocrUiToCode (translateUi);
 | 
			
		||||
  if (translateUi == ocrCode) {
 | 
			
		||||
    return QString ();
 | 
			
		||||
  }
 | 
			
		||||
  return ocrCode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LanguageHelper::init () {
 | 
			
		||||
  initOcrLanguages ();
 | 
			
		||||
  initTranslateLanguages ();
 | 
			
		||||
  updateAvailableOcrLanguages ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LanguageHelper::updateAvailableOcrLanguages()
 | 
			
		||||
{
 | 
			
		||||
void LanguageHelper::updateAvailableOcrLanguages () {
 | 
			
		||||
  availableOcrLanguages_.clear ();
 | 
			
		||||
  QSettings settings;
 | 
			
		||||
  settings.beginGroup (settings_names::recogntionGroup);
 | 
			
		||||
@ -114,131 +105,197 @@ void LanguageHelper::updateAvailableOcrLanguages()
 | 
			
		||||
  availableOcrLanguages_ = availableOcrLanguages (tessDataPlace);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LanguageHelper::initTranslateLanguages()
 | 
			
		||||
{
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Afrikaans"),"af");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Albanian"),"sq");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Arabic"),"ar");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Armenian"),"hy");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Azerbaijani"),"az");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Basque"),"eu");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Belarusian"),"be");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Bulgarian"),"bg");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Catalan"),"ca");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Chinese (Simplified)"),"zh-CN");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Chinese (Traditional)"),"zh-TW");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Croatian"),"hr");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Czech"),"cs");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Danish"),"da");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Dutch"),"nl");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("English"),"en");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Estonian"),"et");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Filipino"),"tl");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Finnish"),"fi");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("French"),"fr");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Galician"),"gl");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Georgian"),"ka");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("German"),"de");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Greek"),"el");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Haitian Creole"),"ht");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Hebrew"),"iw");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Hindi"),"hi");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Hungarian"),"hu");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Icelandic"),"is");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Indonesian"),"id");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Irish"),"ga");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Italian"),"it");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Japanese"),"ja");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Korean"),"ko");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Latvian"),"lv");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Lithuanian"),"lt");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Macedonian"),"mk");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Malay"),"ms");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Maltese"),"mt");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Norwegian"),"no");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Persian"),"fa");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Polish"),"pl");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Portuguese"),"pt");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Romanian"),"ro");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Russian"),"ru");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Serbian"),"sr");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Slovak"),"sk");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Slovenian"),"sl");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Spanish"),"es");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Swahili"),"sw");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Swedish"),"sv");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Thai"),"th");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Turkish"),"tr");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Ukrainian"),"uk");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Urdu"),"ur");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Vietnamese"),"vi");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Welsh"),"cy");
 | 
			
		||||
  translateLanguages_.insert(QObject::tr("Yiddish"),"yi");
 | 
			
		||||
void LanguageHelper::updateMenu (QMenu *menu, const QStringList &languages, int groupSize) const {
 | 
			
		||||
  ST_ASSERT (menu != NULL);
 | 
			
		||||
  menu->clear ();
 | 
			
		||||
  if (languages.isEmpty ()) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (languages.size () <= groupSize) {
 | 
			
		||||
    foreach (const QString &language, languages) {
 | 
			
		||||
      menu->addAction (language);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    int subIndex = groupSize;
 | 
			
		||||
    QMenu *subMenu = NULL;
 | 
			
		||||
    QString prevLetter;
 | 
			
		||||
    foreach (const QString &language, languages) {
 | 
			
		||||
      QString curLetter = language.left (1);
 | 
			
		||||
      if (++subIndex >= groupSize && prevLetter != curLetter) {
 | 
			
		||||
        if (subMenu != NULL) {
 | 
			
		||||
          subMenu->setTitle (subMenu->title () + " - " + prevLetter);
 | 
			
		||||
        }
 | 
			
		||||
        subMenu = menu->addMenu (curLetter);
 | 
			
		||||
        subIndex = 0;
 | 
			
		||||
      }
 | 
			
		||||
      prevLetter = curLetter;
 | 
			
		||||
      subMenu->addAction (language);
 | 
			
		||||
    }
 | 
			
		||||
    subMenu->setTitle (subMenu->title () + " - " + prevLetter);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LanguageHelper::initOcrLanguages()
 | 
			
		||||
{
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Ancient Greek"),"grc");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Esperanto alternative"),"epo_alt");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("English"),"eng");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Ukrainian"),"ukr");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Turkish"),"tur");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Thai"),"tha");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Tagalog"),"tgl");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Telugu"),"tel");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Tamil"),"tam");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Swedish"),"swe");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Swahili"),"swa");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Serbian"),"srp");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Albanian"),"sqi");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Spanish"),"spa");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Slovenian"),"slv");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Slovakian"),"slk");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Romanian"),"ron");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Portuguese"),"por");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Polish"),"pol");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Norwegian"),"nor");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Dutch"),"nld");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Malay"),"msa");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Maltese"),"mlt");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Macedonian"),"mkd");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Malayalam"),"mal");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Lithuanian"),"lit");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Latvian"),"lav");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Korean"),"kor");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Kannada"),"kan");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Italian"),"ita");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Icelandic"),"isl");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Indonesian"),"ind");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Cherokee"),"chr");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Hungarian"),"hun");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Croatian"),"hrv");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Hindi"),"hin");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Hebrew"),"heb");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Galician"),"glg");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Middle French (ca. 1400-1600)"),"frm");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Frankish"),"frk");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("French"),"fra");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Finnish"),"fin");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Basque"),"eus");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Estonian"),"est");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Math / equation"),"equ");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Esperanto"),"epo");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Middle English (1100-1500)"),"enm");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Greek"),"ell");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("German"),"deu");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Danish"),"dan");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Czech"),"ces");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Catalan"),"cat");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Bulgarian"),"bul");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Bengali"),"ben");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Belarusian"),"bel");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Azerbaijani"),"aze");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Arabic"),"ara");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Afrikaans"),"afr");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Japanese"),"jpn");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Chinese (Simplified)"),"chi_sim");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Chinese (Traditional)"),"chi_tra");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Russian"),"rus");
 | 
			
		||||
  ocrLanguages_.insert(QObject::tr("Vietnamese"),"vie");
 | 
			
		||||
void LanguageHelper::initTranslateLanguages () {
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Afrikaans"),"af");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Albanian"),"sq");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Arabic"),"ar");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Armenian"),"hy");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Azerbaijani"),"az");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Basque"),"eu");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Belarusian"),"be");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Bulgarian"),"bg");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Catalan"),"ca");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Chinese (Simplified)"),"zh-CN");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Chinese (Traditional)"),"zh-TW");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Croatian"),"hr");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Czech"),"cs");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Danish"),"da");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Dutch"),"nl");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("English"),"en");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Estonian"),"et");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Filipino"),"tl");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Finnish"),"fi");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("French"),"fr");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Galician"),"gl");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Georgian"),"ka");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("German"),"de");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Greek"),"el");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Haitian Creole"),"ht");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Hebrew"),"iw");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Hindi"),"hi");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Hungarian"),"hu");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Icelandic"),"is");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Indonesian"),"id");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Irish"),"ga");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Italian"),"it");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Japanese"),"ja");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Korean"),"ko");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Latvian"),"lv");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Lithuanian"),"lt");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Macedonian"),"mk");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Malay"),"ms");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Maltese"),"mt");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Norwegian"),"no");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Persian"),"fa");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Polish"),"pl");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Portuguese"),"pt");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Romanian"),"ro");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Russian"),"ru");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Serbian"),"sr");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Slovak"),"sk");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Slovenian"),"sl");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Spanish"),"es");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Swahili"),"sw");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Swedish"),"sv");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Thai"),"th");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Turkish"),"tr");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Ukrainian"),"uk");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Urdu"),"ur");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Vietnamese"),"vi");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Welsh"),"cy");
 | 
			
		||||
  translateLanguages_.insert (QObject::tr ("Yiddish"),"yi");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LanguageHelper::initOcrLanguages () {
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Ancient Greek"),"grc");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Esperanto alternative"),"epo_alt");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("English"),"eng");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Ukrainian"),"ukr");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Turkish"),"tur");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Thai"),"tha");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Tagalog"),"tgl");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Telugu"),"tel");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Tamil"),"tam");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Swedish"),"swe");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Swahili"),"swa");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Serbian"),"srp");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Albanian"),"sqi");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Spanish"),"spa");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Slovenian"),"slv");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Slovakian"),"slk");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Romanian"),"ron");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Portuguese"),"por");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Polish"),"pol");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Norwegian"),"nor");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Dutch"),"nld");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Malay"),"msa");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Maltese"),"mlt");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Macedonian"),"mkd");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Malayalam"),"mal");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Lithuanian"),"lit");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Latvian"),"lav");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Korean"),"kor");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Kannada"),"kan");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Italian"),"ita");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Icelandic"),"isl");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Indonesian"),"ind");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Cherokee"),"chr");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Hungarian"),"hun");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Croatian"),"hrv");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Hindi"),"hin");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Hebrew"),"heb");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Galician"),"glg");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Middle French (ca. 1400-1600)"),"frm");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Frankish"),"frk");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("French"),"fra");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Finnish"),"fin");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Basque"),"eus");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Estonian"),"est");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Math / equation"),"equ");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Esperanto"),"epo");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Middle English (1100-1500)"),"enm");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Greek"),"ell");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("German"),"deu");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Danish"),"dan");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Czech"),"ces");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Catalan"),"cat");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Bulgarian"),"bul");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Bengali"),"ben");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Belarusian"),"bel");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Azerbaijani"),"aze");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Arabic"),"ara");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Afrikaans"),"afr");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Japanese"),"jpn");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Chinese (Simplified)"),"chi_sim");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Chinese (Traditional)"),"chi_tra");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Russian"),"rus");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Vietnamese"),"vie");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Amharic"),"amh");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Assamese"),"asm");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Tibetan"),"bod");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Bosnian"),"bos");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Cebuano"),"ceb");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Welsh"),"cym");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Dzongkha"),"dzo");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Persian"),"fas");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Irish"),"gle");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Gujarati"),"guj");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Haitian"),"hat");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Inuktitut"),"iku");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Javanese"),"jav");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Georgian"),"kat");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Kazakh"),"kaz");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Khmer"),"khm");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Kirghiz"),"kir");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Kurdish"),"kur");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Lao"),"lao");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Latin"),"lat");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Marathi"),"mar");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Burmese"),"mya");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Nepali"),"nep");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Oriya"),"ori");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Panjabi"),"pan");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Pushto"),"pus");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Sanskrit"),"san");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Sinhala"),"sin");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Syriac"),"syr");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Tajik"),"tgk");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Tigrinya"),"tir");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Uighur"),"uig");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Urdu"),"urd");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Uzbek"),"uzb");
 | 
			
		||||
  ocrLanguages_.insert (QObject::tr ("Yiddish"),"yid");
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -3,28 +3,32 @@
 | 
			
		||||
 | 
			
		||||
#include <QMap>
 | 
			
		||||
#include <QStringList>
 | 
			
		||||
#include <QMenu>
 | 
			
		||||
 | 
			
		||||
class LanguageHelper
 | 
			
		||||
{
 | 
			
		||||
class LanguageHelper {
 | 
			
		||||
  public:
 | 
			
		||||
    LanguageHelper ();
 | 
			
		||||
 | 
			
		||||
    QStringList availableOcrLanguagesUi () const;
 | 
			
		||||
    const QStringList& availableOcrLanguages () const;
 | 
			
		||||
    QStringList availableOcrLanguagesUi (const QString& path) const;
 | 
			
		||||
    const QStringList &availableOcrLanguages () const;
 | 
			
		||||
    QStringList availableOcrLanguagesUi (const QString &path) const;
 | 
			
		||||
    QStringList translateLanguagesUi () const;
 | 
			
		||||
    QStringList translateLanguages () const;
 | 
			
		||||
 | 
			
		||||
    QString translateCodeToUi (const QString& text) const;
 | 
			
		||||
    QString translateUiToCode (const QString& text) const;
 | 
			
		||||
    QString ocrCodeToUi (const QString& text) const;
 | 
			
		||||
    QString ocrUiToCode (const QString& text) const;
 | 
			
		||||
    QString translateForOcrCode (const QString& text) const;
 | 
			
		||||
    QString translateCodeToUi (const QString &text) const;
 | 
			
		||||
    QString translateUiToCode (const QString &text) const;
 | 
			
		||||
    QString ocrCodeToUi (const QString &text) const;
 | 
			
		||||
    QString ocrUiToCode (const QString &text) const;
 | 
			
		||||
    QString ocrToTranslateCodes (const QString &text) const;
 | 
			
		||||
    QString translateToOcrCodes (const QString &text) const;
 | 
			
		||||
 | 
			
		||||
    void updateAvailableOcrLanguages ();
 | 
			
		||||
 | 
			
		||||
    //! Update languages menu. Group items into submenus if needed.
 | 
			
		||||
    void updateMenu (QMenu *menu, const QStringList &languages, int groupSize = 10) const;
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    QStringList availableOcrLanguages (const QString& path) const;
 | 
			
		||||
    QStringList availableOcrLanguages (const QString &path) const;
 | 
			
		||||
    void init ();
 | 
			
		||||
    void initTranslateLanguages ();
 | 
			
		||||
    void initOcrLanguages ();
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										452
									
								
								Manager.cpp
									
									
									
									
									
								
							
							
						
						@ -5,89 +5,105 @@
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QDesktopWidget>
 | 
			
		||||
#include <QScreen>
 | 
			
		||||
#include <QDesktopWidget>
 | 
			
		||||
#include <QThread>
 | 
			
		||||
#include <QSettings>
 | 
			
		||||
#include <QClipboard>
 | 
			
		||||
#include <QMessageBox>
 | 
			
		||||
#include <QInputDialog>
 | 
			
		||||
#include <QNetworkProxy>
 | 
			
		||||
 | 
			
		||||
#include "Settings.h"
 | 
			
		||||
#include "SettingsEditor.h"
 | 
			
		||||
#include "SelectionDialog.h"
 | 
			
		||||
#include "GlobalActionHelper.h"
 | 
			
		||||
#include "Recognizer.h"
 | 
			
		||||
#include "Translator.h"
 | 
			
		||||
#include "WebTranslator.h"
 | 
			
		||||
#include "ResultDialog.h"
 | 
			
		||||
#include "LanguageHelper.h"
 | 
			
		||||
#include "StAssert.h"
 | 
			
		||||
#include "Utils.h"
 | 
			
		||||
#include "Updater.h"
 | 
			
		||||
 | 
			
		||||
Manager::Manager(QObject *parent) :
 | 
			
		||||
  QObject(parent),
 | 
			
		||||
  trayIcon_ (new QSystemTrayIcon (QIcon (":/images/icon.png"), this)),
 | 
			
		||||
Manager::Manager (QObject *parent) :
 | 
			
		||||
  QObject (parent),
 | 
			
		||||
  trayIcon_ (new QSystemTrayIcon (this)),
 | 
			
		||||
  dictionary_ (new LanguageHelper),
 | 
			
		||||
  selection_ (new SelectionDialog (*dictionary_)),
 | 
			
		||||
  resultDialog_ (new ResultDialog),
 | 
			
		||||
  captureAction_ (NULL), repeatAction_ (NULL), clipboardAction_ (NULL),
 | 
			
		||||
  useResultDialog_ (true)
 | 
			
		||||
{
 | 
			
		||||
  resultDialog_ (new ResultDialog (*dictionary_)),
 | 
			
		||||
  updater_ (new Updater (this)), updateTimer_ (new QTimer (this)),
 | 
			
		||||
  captureAction_ (NULL), repeatCaptureAction_ (NULL),
 | 
			
		||||
  repeatAction_ (NULL), clipboardAction_ (NULL),
 | 
			
		||||
  useResultDialog_ (true), doTranslation_ (true), itemProcessingCount_ (0) {
 | 
			
		||||
  updateNormalIcon ();
 | 
			
		||||
  GlobalActionHelper::init ();
 | 
			
		||||
  qRegisterMetaType<ProcessingItem>();
 | 
			
		||||
 | 
			
		||||
  // Recognizer
 | 
			
		||||
  Recognizer* recognizer = new Recognizer;
 | 
			
		||||
  connect (selection_, SIGNAL (selected (ProcessingItem)),
 | 
			
		||||
  Recognizer *recognizer = new Recognizer;
 | 
			
		||||
  connect (this, SIGNAL (requestRecognize (ProcessingItem)),
 | 
			
		||||
           recognizer, SLOT (recognize (ProcessingItem)));
 | 
			
		||||
  connect (recognizer, SIGNAL (recognized (ProcessingItem)),
 | 
			
		||||
           this, SIGNAL (requestTranslate (ProcessingItem)));
 | 
			
		||||
  connect (recognizer, SIGNAL (error (QString)),
 | 
			
		||||
           SLOT (showError (QString)));
 | 
			
		||||
  connect (this, SIGNAL (settingsEdited ()),
 | 
			
		||||
           recognizer, SLOT (applySettings ()));
 | 
			
		||||
  QThread* recognizerThread = new QThread (this);
 | 
			
		||||
  QThread *recognizerThread = new QThread (this);
 | 
			
		||||
  threads_ << recognizerThread;
 | 
			
		||||
  recognizer->moveToThread (recognizerThread);
 | 
			
		||||
  recognizerThread->start ();
 | 
			
		||||
  connect (qApp, SIGNAL (aboutToQuit ()), recognizerThread, SLOT (quit ()));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // Translator
 | 
			
		||||
  Translator* translator = new Translator;
 | 
			
		||||
  connect (recognizer, SIGNAL (recognized (ProcessingItem)),
 | 
			
		||||
  WebTranslator *translator = new WebTranslator;
 | 
			
		||||
  connect (this, SIGNAL (requestTranslate (ProcessingItem)),
 | 
			
		||||
           translator, SLOT (translate (ProcessingItem)));
 | 
			
		||||
  connect (translator, SIGNAL (translated (ProcessingItem)),
 | 
			
		||||
           SLOT (showResult (ProcessingItem)));
 | 
			
		||||
  connect (translator, SIGNAL (error (QString)),
 | 
			
		||||
           SLOT (showError (QString)));
 | 
			
		||||
  connect (this, SIGNAL (settingsEdited ()),
 | 
			
		||||
           translator, SLOT (applySettings ()));
 | 
			
		||||
  QThread* translatorThread = new QThread (this);
 | 
			
		||||
  translator->moveToThread (translatorThread);
 | 
			
		||||
  translatorThread->start ();
 | 
			
		||||
  connect (qApp, SIGNAL (aboutToQuit ()), translatorThread, SLOT (quit ()));
 | 
			
		||||
 | 
			
		||||
  connect (translator, SIGNAL (translated (ProcessingItem)),
 | 
			
		||||
           SLOT (showResult (ProcessingItem)));
 | 
			
		||||
 | 
			
		||||
  connect (this, SIGNAL (showPixmap (QPixmap)),
 | 
			
		||||
           selection_, SLOT (setPixmap (QPixmap)));
 | 
			
		||||
 | 
			
		||||
  connect (this, SIGNAL (settingsEdited ()), selection_, SLOT (updateMenu ()));
 | 
			
		||||
  connect (this, SIGNAL (settingsEdited ()), this, SLOT (applySettings ()));
 | 
			
		||||
  selection_->setWindowIcon (trayIcon_->icon ());
 | 
			
		||||
  resultDialog_->setWindowIcon (trayIcon_->icon ());
 | 
			
		||||
 | 
			
		||||
  connect (updater_, SIGNAL (updated ()), SIGNAL (settingsEdited ()));
 | 
			
		||||
  connect (updater_, SIGNAL (error (QString)), SLOT (showError (QString)));
 | 
			
		||||
  updateTimer_->setSingleShot (true);
 | 
			
		||||
  connect (updateTimer_, SIGNAL (timeout ()), SLOT (checkForUpdates ()));
 | 
			
		||||
 | 
			
		||||
  resultDialog_->setWindowIcon (trayIcon_->icon ());
 | 
			
		||||
  connect (this, SIGNAL (settingsEdited ()), resultDialog_, SLOT (applySettings ()));
 | 
			
		||||
  connect (resultDialog_, SIGNAL (requestRecognize (ProcessingItem)),
 | 
			
		||||
           this, SIGNAL (requestRecognize (ProcessingItem)));
 | 
			
		||||
  connect (resultDialog_, SIGNAL (requestTranslate (ProcessingItem)),
 | 
			
		||||
           this, SIGNAL (requestTranslate (ProcessingItem)));
 | 
			
		||||
  connect (resultDialog_, SIGNAL (requestClipboard ()), SLOT (copyLastToClipboard ()));
 | 
			
		||||
  connect (resultDialog_, SIGNAL (requestImageClipboard ()),
 | 
			
		||||
           SLOT (copyLastImageToClipboard ()));
 | 
			
		||||
  connect (resultDialog_, SIGNAL (requestEdition (ProcessingItem)),
 | 
			
		||||
           this, SLOT (editRecognized (ProcessingItem)));
 | 
			
		||||
 | 
			
		||||
  connect (trayIcon_, SIGNAL (activated (QSystemTrayIcon::ActivationReason)),
 | 
			
		||||
           SLOT (processTrayAction (QSystemTrayIcon::ActivationReason)));
 | 
			
		||||
 | 
			
		||||
  trayIcon_->setContextMenu (trayContextMenu ());
 | 
			
		||||
  updateActionsState ();
 | 
			
		||||
  trayIcon_->show ();
 | 
			
		||||
 | 
			
		||||
  applySettings ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QMenu*Manager::trayContextMenu()
 | 
			
		||||
{
 | 
			
		||||
  QMenu* menu = new QMenu ();
 | 
			
		||||
QMenu * Manager::trayContextMenu () {
 | 
			
		||||
  QMenu *menu = new QMenu ();
 | 
			
		||||
  captureAction_ = menu->addAction (tr ("Захват"), this, SLOT (capture ()));
 | 
			
		||||
  QMenu* translateMenu = menu->addMenu (tr ("Перевод"));
 | 
			
		||||
  repeatAction_ = translateMenu->addAction (tr ("Повторить"), this,
 | 
			
		||||
  repeatCaptureAction_ = menu->addAction (tr ("Повторить захват"),
 | 
			
		||||
                                          this, SLOT (repeatCapture ()));
 | 
			
		||||
  QMenu *translateMenu = menu->addMenu (tr ("Результат"));
 | 
			
		||||
  repeatAction_ = translateMenu->addAction (tr ("Показать"), this,
 | 
			
		||||
                                            SLOT (showLast ()));
 | 
			
		||||
  clipboardAction_ = translateMenu->addAction (tr ("Скопировать"), this,
 | 
			
		||||
  clipboardAction_ = translateMenu->addAction (tr ("В буфер"), this,
 | 
			
		||||
                                               SLOT (copyLastToClipboard ()));
 | 
			
		||||
  menu->addAction (tr ("Настройки"), this, SLOT (settings ()));
 | 
			
		||||
  menu->addAction (tr ("О программе"), this, SLOT (about ()));
 | 
			
		||||
@ -95,133 +111,347 @@ QMenu*Manager::trayContextMenu()
 | 
			
		||||
  return menu;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::applySettings()
 | 
			
		||||
{
 | 
			
		||||
void Manager::updateActionsState (bool isEnabled) {
 | 
			
		||||
#ifdef Q_OS_LINUX
 | 
			
		||||
  // Avoid unneeded tray blinking (required to update context menu).
 | 
			
		||||
  QList<QAction *> actions;
 | 
			
		||||
  actions << captureAction_ << repeatCaptureAction_ << repeatAction_ << clipboardAction_;
 | 
			
		||||
  QList<bool> states;
 | 
			
		||||
  foreach (const QAction * action, actions) {
 | 
			
		||||
    states << action->isEnabled ();
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  captureAction_->setEnabled (isEnabled);
 | 
			
		||||
  repeatCaptureAction_->setEnabled (isEnabled && !selections_.isEmpty ());
 | 
			
		||||
  const ProcessingItem &lastItem = resultDialog_->item ();
 | 
			
		||||
  repeatAction_->setEnabled (isEnabled && lastItem.isValid ());
 | 
			
		||||
  clipboardAction_->setEnabled (isEnabled && lastItem.isValid ());
 | 
			
		||||
#ifdef Q_OS_LINUX
 | 
			
		||||
  for (int i = 0, end = actions.size (); i < end; ++i) {
 | 
			
		||||
    if (states.at (i) != actions.at (i)->isEnabled ()) {
 | 
			
		||||
      trayIcon_->hide ();
 | 
			
		||||
      trayIcon_->show ();
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::applySettings () {
 | 
			
		||||
#define GET(NAME) settings.value (settings_names::NAME, settings_values::NAME)
 | 
			
		||||
  QSettings settings;
 | 
			
		||||
  settings.beginGroup (settings_names::guiGroup);
 | 
			
		||||
  QString captureHotkey = settings.value (settings_names::captureHotkey,
 | 
			
		||||
                                          settings_values::captureHotkey).toString ();
 | 
			
		||||
 | 
			
		||||
  QStringList globalActionsFailed;
 | 
			
		||||
  Q_CHECK_PTR (captureAction_);
 | 
			
		||||
  GlobalActionHelper::removeGlobal (captureAction_);
 | 
			
		||||
  captureAction_->setShortcut (captureHotkey);
 | 
			
		||||
  GlobalActionHelper::makeGlobal (captureAction_);
 | 
			
		||||
  captureAction_->setShortcut (GET (captureHotkey).toString ());
 | 
			
		||||
  if (!GlobalActionHelper::makeGlobal (captureAction_)) {
 | 
			
		||||
    globalActionsFailed << captureAction_->shortcut ().toString ();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Q_CHECK_PTR (repeatCaptureAction_);
 | 
			
		||||
  GlobalActionHelper::removeGlobal (repeatCaptureAction_);
 | 
			
		||||
  repeatCaptureAction_->setShortcut (GET (repeatCaptureHotkey).toString ());
 | 
			
		||||
  if (!GlobalActionHelper::makeGlobal (repeatCaptureAction_)) {
 | 
			
		||||
    globalActionsFailed << repeatCaptureAction_->shortcut ().toString ();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  QString repeatHotkey = settings.value (settings_names::repeatHotkey,
 | 
			
		||||
                                         settings_values::repeatHotkey).toString ();
 | 
			
		||||
  Q_CHECK_PTR (repeatAction_);
 | 
			
		||||
  GlobalActionHelper::removeGlobal (repeatAction_);
 | 
			
		||||
  repeatAction_->setShortcut (repeatHotkey);
 | 
			
		||||
  GlobalActionHelper::makeGlobal (repeatAction_);
 | 
			
		||||
  repeatAction_->setShortcut (GET (repeatHotkey).toString ());
 | 
			
		||||
  if (!GlobalActionHelper::makeGlobal (repeatAction_)) {
 | 
			
		||||
    globalActionsFailed << repeatAction_->shortcut ().toString ();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  QString clipboardHotkey = settings.value (settings_names::clipboardHotkey,
 | 
			
		||||
                                            settings_values::clipboardHotkey).toString ();
 | 
			
		||||
  Q_CHECK_PTR (clipboardAction_);
 | 
			
		||||
  GlobalActionHelper::removeGlobal (clipboardAction_);
 | 
			
		||||
  clipboardAction_->setShortcut (clipboardHotkey);
 | 
			
		||||
  GlobalActionHelper::makeGlobal (clipboardAction_);
 | 
			
		||||
  clipboardAction_->setShortcut (GET (clipboardHotkey).toString ());
 | 
			
		||||
  if (!GlobalActionHelper::makeGlobal (clipboardAction_)) {
 | 
			
		||||
    globalActionsFailed << clipboardAction_->shortcut ().toString ();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!globalActionsFailed.isEmpty ()) {
 | 
			
		||||
    showError (tr ("Failed to register global shortcuts:\n%1")
 | 
			
		||||
               .arg (globalActionsFailed.join ("\n")));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Depends on SettingsEditor button indexes. 1==dialog
 | 
			
		||||
  useResultDialog_ = settings.value (settings_names::resultShowType,
 | 
			
		||||
                                     settings_values::resultShowType).toBool ();
 | 
			
		||||
  useResultDialog_ = GET (resultShowType).toBool ();
 | 
			
		||||
 | 
			
		||||
  QNetworkProxy proxy = QNetworkProxy::applicationProxy ();
 | 
			
		||||
  QList<int> proxyTypes = proxyTypeOrder ();
 | 
			
		||||
  int proxyTypeIndex = std::min (GET (proxyType).toInt (), proxyTypes.size ());
 | 
			
		||||
  proxy.setType (QNetworkProxy::ProxyType (proxyTypes.at (std::max (proxyTypeIndex, 0))));
 | 
			
		||||
  proxy.setHostName (GET (proxyHostName).toString ());
 | 
			
		||||
  proxy.setPort (GET (proxyPort).toInt ());
 | 
			
		||||
  proxy.setUser (GET (proxyUser).toString ());
 | 
			
		||||
  if (GET (proxySavePassword).toBool ()) {
 | 
			
		||||
    proxy.setPassword (encode (GET (proxyPassword).toString ()));
 | 
			
		||||
  }
 | 
			
		||||
  QNetworkProxy::setApplicationProxy (proxy);
 | 
			
		||||
 | 
			
		||||
  scheduleUpdate ();
 | 
			
		||||
  settings.endGroup ();
 | 
			
		||||
 | 
			
		||||
  settings.beginGroup (settings_names::recogntionGroup);
 | 
			
		||||
  defaultOrcLanguage_ = GET (ocrLanguage).toString ();
 | 
			
		||||
  settings.endGroup ();
 | 
			
		||||
 | 
			
		||||
  settings.beginGroup (settings_names::translationGroup);
 | 
			
		||||
  defaultTranslationLanguage_ = GET (translationLanguage).toString ();
 | 
			
		||||
  doTranslation_ = GET (doTranslation).toBool ();
 | 
			
		||||
  settings.endGroup ();
 | 
			
		||||
 | 
			
		||||
  Q_CHECK_PTR (dictionary_);
 | 
			
		||||
  dictionary_->updateAvailableOcrLanguages ();
 | 
			
		||||
#undef GET
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Manager::~Manager()
 | 
			
		||||
{
 | 
			
		||||
void Manager::scheduleUpdate (bool justChecked) {
 | 
			
		||||
#define GET(NAME) settings.value (settings_names::NAME, settings_values::NAME)
 | 
			
		||||
  QSettings settings;
 | 
			
		||||
  settings.beginGroup (settings_names::guiGroup);
 | 
			
		||||
  updateTimer_->stop ();
 | 
			
		||||
  if (justChecked) {
 | 
			
		||||
    settings.setValue (settings_names::lastUpdateCheck, QDateTime::currentDateTime ());
 | 
			
		||||
  }
 | 
			
		||||
  QDateTime nextUpdateCheck = updater_->nextCheckTime (GET (lastUpdateCheck).toDateTime (),
 | 
			
		||||
                                                       GET (autoUpdateType).toInt ());
 | 
			
		||||
  if (nextUpdateCheck.isValid ()) {
 | 
			
		||||
    updateTimer_->start (QDateTime::currentDateTime ().msecsTo (nextUpdateCheck));
 | 
			
		||||
  }
 | 
			
		||||
#undef GET
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::capture()
 | 
			
		||||
{
 | 
			
		||||
  QList<QScreen*> screens = QApplication::screens ();
 | 
			
		||||
  ST_ASSERT (!screens.isEmpty ());
 | 
			
		||||
  QScreen* screen = screens.first ();
 | 
			
		||||
  Q_CHECK_PTR (screen);
 | 
			
		||||
  WId desktopId = QApplication::desktop ()->winId ();
 | 
			
		||||
  QPixmap pixmap = screen->grabWindow (desktopId);
 | 
			
		||||
  ST_ASSERT (!pixmap.isNull ());
 | 
			
		||||
  emit showPixmap (pixmap);
 | 
			
		||||
void Manager::checkForUpdates () {
 | 
			
		||||
  updater_->checkForUpdates ();
 | 
			
		||||
  scheduleUpdate (true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::settings()
 | 
			
		||||
{
 | 
			
		||||
Manager::~Manager () {
 | 
			
		||||
  foreach (SelectionDialog * selection, selections_.values ()) {
 | 
			
		||||
    selection->hide ();
 | 
			
		||||
    delete selection;
 | 
			
		||||
  }
 | 
			
		||||
  trayIcon_->hide ();
 | 
			
		||||
  delete trayIcon_->contextMenu ();
 | 
			
		||||
  foreach (QThread * thread, threads_) {
 | 
			
		||||
    thread->quit ();
 | 
			
		||||
    thread->wait (1000000);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::capture () {
 | 
			
		||||
  QList<QScreen *> screens = QApplication::screens ();
 | 
			
		||||
  foreach (QScreen * screen, screens) {
 | 
			
		||||
    QRect geometry = screen->availableGeometry ();
 | 
			
		||||
    QPixmap pixmap = screen->grabWindow (0, geometry.x (), geometry.y (),
 | 
			
		||||
                                         geometry.width (), geometry.height ());
 | 
			
		||||
    QString name = screen->name ();
 | 
			
		||||
    if (!selections_.contains (name)) {
 | 
			
		||||
      SelectionDialog *selection = new SelectionDialog (*dictionary_);
 | 
			
		||||
      selection->setWindowIcon (trayIcon_->icon ());
 | 
			
		||||
      connect (this, SIGNAL (closeSelections ()), selection, SLOT (close ()));
 | 
			
		||||
      connect (this, SIGNAL (settingsEdited ()), selection, SLOT (applySettings ()));
 | 
			
		||||
      connect (selection, SIGNAL (selected (ProcessingItem)),
 | 
			
		||||
               SLOT (handleSelection (ProcessingItem)));
 | 
			
		||||
      connect (selection, SIGNAL (rejected ()), SIGNAL (closeSelections ()));
 | 
			
		||||
      selections_[name] = selection;
 | 
			
		||||
    }
 | 
			
		||||
    SelectionDialog *selection = selections_[name];
 | 
			
		||||
    selection->setPixmap (pixmap, geometry);
 | 
			
		||||
  }
 | 
			
		||||
  updateActionsState ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::handleSelection (ProcessingItem item) {
 | 
			
		||||
  bool altMod = item.modifiers & Qt::AltModifier;
 | 
			
		||||
  bool doTranslation = (doTranslation_ && !altMod) || (!doTranslation_ && altMod);
 | 
			
		||||
  if (doTranslation) {
 | 
			
		||||
    item.translateLanguage = defaultTranslationLanguage_;
 | 
			
		||||
  }
 | 
			
		||||
  if (item.ocrLanguage.isEmpty ()) {
 | 
			
		||||
    item.ocrLanguage = defaultOrcLanguage_;
 | 
			
		||||
  }
 | 
			
		||||
  if (item.swapLanguages_) {
 | 
			
		||||
    QString translate = (item.translateLanguage.isEmpty ())
 | 
			
		||||
                        ? defaultTranslationLanguage_ : item.translateLanguage;
 | 
			
		||||
    if (doTranslation) {
 | 
			
		||||
      item.translateLanguage = dictionary_->ocrToTranslateCodes (item.ocrLanguage);
 | 
			
		||||
    }
 | 
			
		||||
    item.sourceLanguage.clear ();
 | 
			
		||||
    item.ocrLanguage = dictionary_->translateToOcrCodes (translate);
 | 
			
		||||
    if (item.ocrLanguage.isEmpty ()) {
 | 
			
		||||
      showError (tr ("Не найден подходящий язык распознавания."));
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (item.sourceLanguage.isEmpty ()) {
 | 
			
		||||
    item.sourceLanguage = dictionary_->ocrToTranslateCodes (item.ocrLanguage);
 | 
			
		||||
  }
 | 
			
		||||
  emit requestRecognize (item);
 | 
			
		||||
  ++itemProcessingCount_;
 | 
			
		||||
  updateNormalIcon ();
 | 
			
		||||
  if (!(item.modifiers & Qt::ControlModifier)) {
 | 
			
		||||
    emit closeSelections ();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::repeatCapture () {
 | 
			
		||||
  if (selections_.isEmpty ()) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  QList<QScreen *> screens = QApplication::screens ();
 | 
			
		||||
  foreach (QScreen * screen, screens) {
 | 
			
		||||
    QString name = screen->name ();
 | 
			
		||||
    if (!selections_.contains (name)) {
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    SelectionDialog *selection = selections_[name];
 | 
			
		||||
    selection->show ();
 | 
			
		||||
    selection->activateWindow ();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::settings () {
 | 
			
		||||
  SettingsEditor editor (*dictionary_);
 | 
			
		||||
  editor.setWindowIcon (trayIcon_->icon ());
 | 
			
		||||
  connect (&editor, SIGNAL (settingsEdited ()), SIGNAL (settingsEdited ()));
 | 
			
		||||
  connect (&editor, SIGNAL (updateCheckRequested ()), SLOT (checkForUpdates ()));
 | 
			
		||||
  updateActionsState (false);
 | 
			
		||||
  editor.exec ();
 | 
			
		||||
  updateActionsState (true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::close()
 | 
			
		||||
{
 | 
			
		||||
void Manager::close () {
 | 
			
		||||
  QApplication::quit ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::about()
 | 
			
		||||
{
 | 
			
		||||
  QString version = "1.2.3";
 | 
			
		||||
  QString text = tr ("Программа для распознавания текста на экране.\n"\
 | 
			
		||||
void Manager::about () {
 | 
			
		||||
  QString text = tr ("Программа для распознавания текста на экране.\n" \
 | 
			
		||||
                     "Создана с использованием Qt, tesseract-ocr, Google Translate.\n"
 | 
			
		||||
                     "Автор: Gres (translator@gres.biz)\n"
 | 
			
		||||
                     "Версия: %1 от %2 %3").arg (version)
 | 
			
		||||
      .arg (__DATE__).arg (__TIME__);
 | 
			
		||||
                     "Версия: %1 от %2 %3").arg (updater_->currentAppVersion ())
 | 
			
		||||
                 .arg (__DATE__).arg (__TIME__);
 | 
			
		||||
  QString tips = tr ("\n\nПодсказки.\n"
 | 
			
		||||
                     "Клик по иконке в трее:\n"
 | 
			
		||||
                     "* левой кнопкой - отобразить последний результат\n"
 | 
			
		||||
                     "* средней кнопкой - скопировать последний результат в буфер обмена\n"
 | 
			
		||||
#ifdef Q_OS_WIN
 | 
			
		||||
                     "* двойной клик - повторный захват последнего экрана\n"
 | 
			
		||||
#endif
 | 
			
		||||
                     "\n"
 | 
			
		||||
                     "Захвата изображения при зажатых кнопках:\n"
 | 
			
		||||
                     "* Ctrl - не выходить из режима захвата\n"
 | 
			
		||||
                     "* Alt - выполнить перевод, если в настройках он выключен "
 | 
			
		||||
                     "(и наоборот, не выполнять, если включен)\n"
 | 
			
		||||
                     "");
 | 
			
		||||
 | 
			
		||||
  QMessageBox message (QMessageBox::Information, tr ("О программе"), text,
 | 
			
		||||
  QMessageBox message (QMessageBox::Information, tr ("О программе"), text + tips,
 | 
			
		||||
                       QMessageBox::Ok);
 | 
			
		||||
  message.setIconPixmap (trayIcon_->icon ().pixmap (QSize (64, 64)));
 | 
			
		||||
  message.exec ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::processTrayAction(QSystemTrayIcon::ActivationReason reason)
 | 
			
		||||
{
 | 
			
		||||
  if (reason == QSystemTrayIcon::Trigger)
 | 
			
		||||
  {
 | 
			
		||||
void Manager::processTrayAction (QSystemTrayIcon::ActivationReason reason) {
 | 
			
		||||
  if (reason == QSystemTrayIcon::Trigger && repeatAction_->isEnabled ()) {
 | 
			
		||||
    showLast ();
 | 
			
		||||
  }
 | 
			
		||||
  else if (reason == QSystemTrayIcon::MiddleClick)
 | 
			
		||||
  {
 | 
			
		||||
  else if (reason == QSystemTrayIcon::MiddleClick && clipboardAction_->isEnabled ()) {
 | 
			
		||||
    copyLastToClipboard  ();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::showLast()
 | 
			
		||||
{
 | 
			
		||||
  if (lastItem_.isValid ())
 | 
			
		||||
  {
 | 
			
		||||
    showResult (lastItem_);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::copyLastToClipboard()
 | 
			
		||||
{
 | 
			
		||||
  if (lastItem_.isValid ())
 | 
			
		||||
  {
 | 
			
		||||
    QClipboard* clipboard = QApplication::clipboard ();
 | 
			
		||||
    QString message = lastItem_.recognized + " - " + lastItem_.translated;
 | 
			
		||||
    clipboard->setText (message);
 | 
			
		||||
    trayIcon_->showMessage (tr ("Перевод"),
 | 
			
		||||
                            tr ("Последний перевод был скопирован в буфер обмена."),
 | 
			
		||||
    trayIcon_->showMessage (tr ("Результат"),
 | 
			
		||||
                            tr ("Последний результат был скопирован в буфер обмена."),
 | 
			
		||||
                            QSystemTrayIcon::Information);
 | 
			
		||||
  }
 | 
			
		||||
  else if (reason == QSystemTrayIcon::DoubleClick && repeatCaptureAction_->isEnabled ()) {
 | 
			
		||||
    repeatCapture ();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::showResult(ProcessingItem item)
 | 
			
		||||
{
 | 
			
		||||
  ST_ASSERT (item.isValid ());
 | 
			
		||||
  lastItem_ = item;
 | 
			
		||||
  if (useResultDialog_)
 | 
			
		||||
  {
 | 
			
		||||
void Manager::editRecognized (ProcessingItem item) {
 | 
			
		||||
  QString fixed = QInputDialog::getMultiLineText (
 | 
			
		||||
    NULL, tr ("Правка"), tr ("Исправьте распознанный текст"), item.recognized);
 | 
			
		||||
  if (!fixed.isEmpty ()) {
 | 
			
		||||
    item.recognized = fixed;
 | 
			
		||||
    ++itemProcessingCount_;
 | 
			
		||||
    updateNormalIcon ();
 | 
			
		||||
    emit requestTranslate (item);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::showLast () {
 | 
			
		||||
  const ProcessingItem &item = resultDialog_->item ();
 | 
			
		||||
  if (item.isValid ()) {
 | 
			
		||||
    ++itemProcessingCount_;
 | 
			
		||||
    showResult (item);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::copyLastToClipboard () {
 | 
			
		||||
  const ProcessingItem &item = resultDialog_->item ();
 | 
			
		||||
  if (item.isValid ()) {
 | 
			
		||||
    QClipboard *clipboard = QApplication::clipboard ();
 | 
			
		||||
    QString message = item.recognized;
 | 
			
		||||
    if (!item.translated.isEmpty ()) {
 | 
			
		||||
      message += " - " + item.translated;
 | 
			
		||||
    }
 | 
			
		||||
    clipboard->setText (message);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::copyLastImageToClipboard () {
 | 
			
		||||
  const ProcessingItem &item = resultDialog_->item ();
 | 
			
		||||
  if (item.isValid ()) {
 | 
			
		||||
    QClipboard *clipboard = QApplication::clipboard ();
 | 
			
		||||
    clipboard->setPixmap (item.source);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::showResult (ProcessingItem item) {
 | 
			
		||||
  --itemProcessingCount_;
 | 
			
		||||
  if (!item.isValid ()) {
 | 
			
		||||
    // delay because it can show error
 | 
			
		||||
    QTimer::singleShot (3000, this, SLOT (updateNormalIcon ()));
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  changeIcon (IconTypeSuccess);
 | 
			
		||||
  if (useResultDialog_) {
 | 
			
		||||
    resultDialog_->showResult (item);
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
  else {
 | 
			
		||||
    QString message = item.recognized + " - " + item.translated;
 | 
			
		||||
    trayIcon_->showMessage (tr ("Перевод"), message, QSystemTrayIcon::Information);
 | 
			
		||||
    trayIcon_->showMessage (tr ("Результат"), message, QSystemTrayIcon::Information);
 | 
			
		||||
  }
 | 
			
		||||
  updateActionsState ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::showError (QString text) {
 | 
			
		||||
  qCritical () << text;
 | 
			
		||||
  changeIcon (IconTypeError);
 | 
			
		||||
  trayIcon_->showMessage (tr ("Ошибка"), text, QSystemTrayIcon::Critical);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::changeIcon (int iconType, int timeoutMsec) {
 | 
			
		||||
  QString fileName;
 | 
			
		||||
  switch (iconType) {
 | 
			
		||||
    case IconTypeSuccess:
 | 
			
		||||
      fileName = ":/images/STIconGreen.png";
 | 
			
		||||
      break;
 | 
			
		||||
    case IconTypeError:
 | 
			
		||||
      fileName = ":/images/STIconRed.png";
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      return;
 | 
			
		||||
  }
 | 
			
		||||
  trayIcon_->setIcon (QIcon (fileName));
 | 
			
		||||
  if (timeoutMsec > 0) {
 | 
			
		||||
    QTimer::singleShot (timeoutMsec, this, SLOT (updateNormalIcon ()));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Manager::showError(QString text)
 | 
			
		||||
{
 | 
			
		||||
  qCritical () << text;
 | 
			
		||||
  trayIcon_->showMessage (tr ("Ошибка"), text, QSystemTrayIcon::Critical);
 | 
			
		||||
void Manager::updateNormalIcon () {
 | 
			
		||||
  QString fileName = itemProcessingCount_ > 0
 | 
			
		||||
                     ? ":/images/STIconOrange.png" : ":/images/STIconBlue.png";
 | 
			
		||||
  trayIcon_->setIcon (QIcon (fileName));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										57
									
								
								Manager.h
									
									
									
									
									
								
							
							
						
						@ -3,6 +3,7 @@
 | 
			
		||||
 | 
			
		||||
#include <QPixmap>
 | 
			
		||||
#include <QSystemTrayIcon>
 | 
			
		||||
#include <QMap>
 | 
			
		||||
 | 
			
		||||
#include "ProcessingItem.h"
 | 
			
		||||
 | 
			
		||||
@ -12,46 +13,72 @@ class QMenu;
 | 
			
		||||
class SelectionDialog;
 | 
			
		||||
class ResultDialog;
 | 
			
		||||
class LanguageHelper;
 | 
			
		||||
class Updater;
 | 
			
		||||
 | 
			
		||||
class Manager : public QObject {
 | 
			
		||||
  Q_OBJECT
 | 
			
		||||
 | 
			
		||||
  enum IconType {
 | 
			
		||||
    IconTypeNormal, IconTypeWorking, IconTypeError, IconTypeSuccess
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class Manager : public QObject
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
  public:
 | 
			
		||||
    explicit Manager(QObject *parent = 0);
 | 
			
		||||
    explicit Manager (QObject *parent = 0);
 | 
			
		||||
    ~Manager ();
 | 
			
		||||
 | 
			
		||||
  signals:
 | 
			
		||||
    void showPixmap (QPixmap pixmap);
 | 
			
		||||
    void requestRecognize (ProcessingItem item);
 | 
			
		||||
    void requestTranslate (ProcessingItem item);
 | 
			
		||||
    void closeSelections ();
 | 
			
		||||
    void settingsEdited ();
 | 
			
		||||
 | 
			
		||||
  private slots:
 | 
			
		||||
    void capture ();
 | 
			
		||||
    void repeatCapture ();
 | 
			
		||||
    void settings ();
 | 
			
		||||
    void close ();
 | 
			
		||||
    void about ();
 | 
			
		||||
    void showLast ();
 | 
			
		||||
    void copyLastToClipboard ();
 | 
			
		||||
    void copyLastImageToClipboard ();
 | 
			
		||||
 | 
			
		||||
    void applySettings ();
 | 
			
		||||
    void checkForUpdates ();
 | 
			
		||||
 | 
			
		||||
    void processTrayAction (QSystemTrayIcon::ActivationReason reason);
 | 
			
		||||
 | 
			
		||||
    void editRecognized (ProcessingItem item);
 | 
			
		||||
    void handleSelection (ProcessingItem item);
 | 
			
		||||
    void showResult (ProcessingItem item);
 | 
			
		||||
    void showError (QString text);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    QMenu* trayContextMenu ();
 | 
			
		||||
    void updateNormalIcon ();
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    QSystemTrayIcon* trayIcon_;
 | 
			
		||||
    LanguageHelper* dictionary_;
 | 
			
		||||
    SelectionDialog* selection_;
 | 
			
		||||
    ResultDialog* resultDialog_;
 | 
			
		||||
    QAction* captureAction_;
 | 
			
		||||
    QAction* repeatAction_;
 | 
			
		||||
    QAction* clipboardAction_;
 | 
			
		||||
    ProcessingItem lastItem_;
 | 
			
		||||
    QMenu * trayContextMenu ();
 | 
			
		||||
    void updateActionsState (bool isEnabled = true);
 | 
			
		||||
    void changeIcon (int iconType, int timeoutMsec = 3000);
 | 
			
		||||
    void scheduleUpdate (bool justChecked = false);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    QSystemTrayIcon *trayIcon_;
 | 
			
		||||
    LanguageHelper *dictionary_;
 | 
			
		||||
    //! Selection dialogs for each screen. Key - screen name.
 | 
			
		||||
    QMap<QString, SelectionDialog *> selections_;
 | 
			
		||||
    ResultDialog *resultDialog_;
 | 
			
		||||
    Updater *updater_;
 | 
			
		||||
    QTimer *updateTimer_;
 | 
			
		||||
    QAction *captureAction_;
 | 
			
		||||
    QAction *repeatCaptureAction_;
 | 
			
		||||
    QAction *repeatAction_;
 | 
			
		||||
    QAction *clipboardAction_;
 | 
			
		||||
    bool useResultDialog_;
 | 
			
		||||
    //! Used threads. For proper termination.
 | 
			
		||||
    QList<QThread *> threads_;
 | 
			
		||||
    QString defaultTranslationLanguage_;
 | 
			
		||||
    QString defaultOrcLanguage_;
 | 
			
		||||
    bool doTranslation_;
 | 
			
		||||
    int itemProcessingCount_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // MANAGER_H
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,17 @@
 | 
			
		||||
#include "ProcessingItem.h"
 | 
			
		||||
 | 
			
		||||
bool ProcessingItem::isValid() const
 | 
			
		||||
{
 | 
			
		||||
ProcessingItem::ProcessingItem ()
 | 
			
		||||
  : swapLanguages_ (false) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ProcessingItem::isValid (bool checkOnlyInput) const {
 | 
			
		||||
  bool valid = true;
 | 
			
		||||
  valid &= (!screenPos.isNull ());
 | 
			
		||||
  valid &= (!source.isNull ());
 | 
			
		||||
  valid &= (!recognized.isEmpty ());
 | 
			
		||||
  valid &= (!translated.isEmpty ());
 | 
			
		||||
  valid &= (!ocrLanguage.isEmpty ());
 | 
			
		||||
  if (!checkOnlyInput) {
 | 
			
		||||
    valid &= (!recognized.isEmpty ());
 | 
			
		||||
  }
 | 
			
		||||
  return valid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -3,18 +3,22 @@
 | 
			
		||||
 | 
			
		||||
#include <QPixmap>
 | 
			
		||||
 | 
			
		||||
struct ProcessingItem
 | 
			
		||||
{
 | 
			
		||||
    QPoint screenPos;
 | 
			
		||||
    QPixmap source;
 | 
			
		||||
    QString recognized;
 | 
			
		||||
    QString translated;
 | 
			
		||||
struct ProcessingItem {
 | 
			
		||||
  ProcessingItem ();
 | 
			
		||||
  QPoint screenPos;
 | 
			
		||||
  QPixmap source;
 | 
			
		||||
  QString recognized;
 | 
			
		||||
  QString translated;
 | 
			
		||||
 | 
			
		||||
    QString ocrLanguage;
 | 
			
		||||
    QString sourceLanguage;
 | 
			
		||||
  QString ocrLanguage;
 | 
			
		||||
  QString sourceLanguage;
 | 
			
		||||
  QString translateLanguage;
 | 
			
		||||
 | 
			
		||||
    bool isValid () const;
 | 
			
		||||
  Qt::KeyboardModifiers modifiers;
 | 
			
		||||
  bool swapLanguages_;
 | 
			
		||||
 | 
			
		||||
  bool isValid (bool checkOnlyInput = false) const;
 | 
			
		||||
};
 | 
			
		||||
Q_DECLARE_METATYPE(ProcessingItem)
 | 
			
		||||
Q_DECLARE_METATYPE (ProcessingItem)
 | 
			
		||||
 | 
			
		||||
#endif // PROCESSINGITEM_H
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,5 @@
 | 
			
		||||
[](https://travis-ci.org/OneMoreGres/ScreenTranslator.svg)
 | 
			
		||||
 | 
			
		||||
Screen Translator
 | 
			
		||||
=================
 | 
			
		||||
 | 
			
		||||
@ -14,7 +16,7 @@ Usage
 | 
			
		||||
 | 
			
		||||
Features
 | 
			
		||||
--------
 | 
			
		||||
* Many OCR languages (can be modified dynamicly)
 | 
			
		||||
* Many OCR languages (can be modified dynamically)
 | 
			
		||||
* Global hotkeys for main actions
 | 
			
		||||
* Copy last translation to clipboard
 | 
			
		||||
* Repeat last translation
 | 
			
		||||
@ -27,12 +29,13 @@ Limitations
 | 
			
		||||
-----------
 | 
			
		||||
* Works only on primary screen
 | 
			
		||||
* Can not capture some dynamic web-pages
 | 
			
		||||
* Not very precise OCR (need better preprocessing steps)
 | 
			
		||||
* Not very precise OCR
 | 
			
		||||
* Not all functions are cross-platform (may be bugged on some systems)
 | 
			
		||||
 | 
			
		||||
Used software
 | 
			
		||||
-------------
 | 
			
		||||
* see [Qt 5](http://qt-project.org/)
 | 
			
		||||
* see [Tesseract](https://code.google.com/p/tesseract-ocr/)
 | 
			
		||||
* see [Leptonica](http://leptonica.com/) (Tesseract dependency)
 | 
			
		||||
* Google Translate
 | 
			
		||||
* several online translation services
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -8,23 +8,23 @@
 | 
			
		||||
#include "Settings.h"
 | 
			
		||||
#include "ImageProcessing.h"
 | 
			
		||||
#include "StAssert.h"
 | 
			
		||||
#include "RecognizerHelper.h"
 | 
			
		||||
 | 
			
		||||
Recognizer::Recognizer(QObject *parent) :
 | 
			
		||||
  QObject(parent),
 | 
			
		||||
  engine_ (NULL), imageScale_ (0)
 | 
			
		||||
{
 | 
			
		||||
Recognizer::Recognizer (QObject *parent) :
 | 
			
		||||
  QObject (parent),
 | 
			
		||||
  engine_ (NULL), recognizerHelper_ (new RecognizerHelper), imageScale_ (0) {
 | 
			
		||||
  applySettings ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Recognizer::applySettings()
 | 
			
		||||
{
 | 
			
		||||
void Recognizer::applySettings () {
 | 
			
		||||
  QSettings settings;
 | 
			
		||||
  settings.beginGroup (settings_names::recogntionGroup);
 | 
			
		||||
 | 
			
		||||
  recognizerHelper_->load ();
 | 
			
		||||
 | 
			
		||||
  tessDataDir_ = settings.value (settings_names::tessDataPlace,
 | 
			
		||||
                                 settings_values::tessDataPlace).toString ();
 | 
			
		||||
  if (tessDataDir_.right (1) != "/")
 | 
			
		||||
  {
 | 
			
		||||
  if (tessDataDir_.right (1) != "/") {
 | 
			
		||||
    tessDataDir_ += "/";
 | 
			
		||||
  }
 | 
			
		||||
  ocrLanguage_ = settings.value (settings_names::ocrLanguage,
 | 
			
		||||
@ -35,22 +35,18 @@ void Recognizer::applySettings()
 | 
			
		||||
  initEngine (engine_, ocrLanguage_);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Recognizer::initEngine(tesseract::TessBaseAPI *&engine, const QString& language)
 | 
			
		||||
{
 | 
			
		||||
  if (tessDataDir_.isEmpty () || language.isEmpty ())
 | 
			
		||||
  {
 | 
			
		||||
bool Recognizer::initEngine (tesseract::TessBaseAPI * &engine, const QString &language) {
 | 
			
		||||
  if (tessDataDir_.isEmpty () || language.isEmpty ()) {
 | 
			
		||||
    emit error (tr ("Неверные параметры для OCR"));
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  if (engine != NULL)
 | 
			
		||||
  {
 | 
			
		||||
  if (engine != NULL) {
 | 
			
		||||
    delete engine;
 | 
			
		||||
  }
 | 
			
		||||
  engine = new tesseract::TessBaseAPI();
 | 
			
		||||
  int result = engine->Init(qPrintable (tessDataDir_), qPrintable (language),
 | 
			
		||||
  engine = new tesseract::TessBaseAPI ();
 | 
			
		||||
  int result = engine->Init (qPrintable (tessDataDir_), qPrintable (language),
 | 
			
		||||
                             tesseract::OEM_DEFAULT);
 | 
			
		||||
  if (result != 0)
 | 
			
		||||
  {
 | 
			
		||||
  if (result != 0) {
 | 
			
		||||
    emit error (tr ("Ошибка инициализации OCR: %1").arg (result));
 | 
			
		||||
    delete engine;
 | 
			
		||||
    engine = NULL;
 | 
			
		||||
@ -59,42 +55,39 @@ bool Recognizer::initEngine(tesseract::TessBaseAPI *&engine, const QString& lang
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Recognizer::recognize(ProcessingItem item)
 | 
			
		||||
{
 | 
			
		||||
  ST_ASSERT (!item.source.isNull ());
 | 
			
		||||
  bool isCustomLanguage = (!item.ocrLanguage.isEmpty () &&
 | 
			
		||||
                           item.ocrLanguage != ocrLanguage_);
 | 
			
		||||
  tesseract::TessBaseAPI* engine = (isCustomLanguage) ? NULL : engine_;
 | 
			
		||||
  if (engine == NULL)
 | 
			
		||||
  {
 | 
			
		||||
    QString language = (isCustomLanguage) ? item.ocrLanguage : ocrLanguage_;
 | 
			
		||||
    if (!initEngine (engine, language))
 | 
			
		||||
    {
 | 
			
		||||
void Recognizer::recognize (ProcessingItem item) {
 | 
			
		||||
  if (!item.isValid (true)) {
 | 
			
		||||
    emit recognized (item);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  bool isCustomLanguage = (item.ocrLanguage != ocrLanguage_);
 | 
			
		||||
  tesseract::TessBaseAPI *engine = (isCustomLanguage) ? NULL : engine_;
 | 
			
		||||
  QString language = (isCustomLanguage) ? item.ocrLanguage : ocrLanguage_;
 | 
			
		||||
  if (engine == NULL) {
 | 
			
		||||
    if (!initEngine (engine, language)) {
 | 
			
		||||
      emit recognized (item);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Pix* image = prepareImage (item.source.toImage (), imageScale_);
 | 
			
		||||
  Pix *image = prepareImage (item.source.toImage (), imageScale_);
 | 
			
		||||
  ST_ASSERT (image != NULL);
 | 
			
		||||
  engine->SetImage (image);
 | 
			
		||||
  char* outText = engine->GetUTF8Text();
 | 
			
		||||
  engine->Clear();
 | 
			
		||||
  char *outText = engine->GetUTF8Text ();
 | 
			
		||||
  engine->Clear ();
 | 
			
		||||
  cleanupImage (&image);
 | 
			
		||||
 | 
			
		||||
  QString result = QString (outText).trimmed ();
 | 
			
		||||
  delete [] outText;
 | 
			
		||||
  if (isCustomLanguage)
 | 
			
		||||
  {
 | 
			
		||||
  if (isCustomLanguage) {
 | 
			
		||||
    delete engine;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!result.isEmpty ())
 | 
			
		||||
  {
 | 
			
		||||
    item.recognized = result;
 | 
			
		||||
    emit recognized (item);
 | 
			
		||||
  if (!result.isEmpty ()) {
 | 
			
		||||
    item.recognized = recognizerHelper_->substitute (result, language);
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
  else {
 | 
			
		||||
    emit error (tr ("Текст не распознан."));
 | 
			
		||||
  }
 | 
			
		||||
  emit recognized (item);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										17
									
								
								Recognizer.h
									
									
									
									
									
								
							
							
						
						@ -6,16 +6,16 @@
 | 
			
		||||
 | 
			
		||||
#include "ProcessingItem.h"
 | 
			
		||||
 | 
			
		||||
namespace tesseract
 | 
			
		||||
{
 | 
			
		||||
namespace tesseract {
 | 
			
		||||
  class TessBaseAPI;
 | 
			
		||||
}
 | 
			
		||||
class RecognizerHelper;
 | 
			
		||||
 | 
			
		||||
class Recognizer : public QObject {
 | 
			
		||||
  Q_OBJECT
 | 
			
		||||
 | 
			
		||||
class Recognizer : public QObject
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
  public:
 | 
			
		||||
    explicit Recognizer(QObject *parent = 0);
 | 
			
		||||
    explicit Recognizer (QObject *parent = 0);
 | 
			
		||||
 | 
			
		||||
  signals:
 | 
			
		||||
    void recognized (ProcessingItem item);
 | 
			
		||||
@ -26,10 +26,11 @@ class Recognizer : public QObject
 | 
			
		||||
    void applySettings ();
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    bool initEngine (tesseract::TessBaseAPI*&engine, const QString &language);
 | 
			
		||||
    bool initEngine (tesseract::TessBaseAPI * &engine, const QString &language);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    tesseract::TessBaseAPI* engine_;
 | 
			
		||||
    tesseract::TessBaseAPI *engine_;
 | 
			
		||||
    RecognizerHelper *recognizerHelper_;
 | 
			
		||||
 | 
			
		||||
    QString tessDataDir_;
 | 
			
		||||
    QString ocrLanguage_;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										88
									
								
								RecognizerHelper.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,88 @@
 | 
			
		||||
#include <QDir>
 | 
			
		||||
#include <QFile>
 | 
			
		||||
#include <QFileInfo>
 | 
			
		||||
#include <QSettings>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
 | 
			
		||||
#include "RecognizerHelper.h"
 | 
			
		||||
 | 
			
		||||
RecognizerHelper::RecognizerHelper ()
 | 
			
		||||
  : fileName_ ("st_subs.csv") {
 | 
			
		||||
#ifdef Q_OS_LINUX
 | 
			
		||||
  QDir settingDir = QFileInfo (QSettings ().fileName ()).dir ();
 | 
			
		||||
  fileName_ = settingDir.absoluteFilePath (fileName_);
 | 
			
		||||
#else
 | 
			
		||||
  fileName_ = QApplication::applicationDirPath () + QDir::separator () + fileName_;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RecognizerHelper::load () {
 | 
			
		||||
  subs_.clear ();
 | 
			
		||||
  QFile f (fileName_);
 | 
			
		||||
  if (!f.open (QFile::ReadOnly)) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  QByteArray data = f.readAll ();
 | 
			
		||||
  f.close ();
 | 
			
		||||
  QStringList lines = QString::fromUtf8 (data).split ('\n', QString::SkipEmptyParts);
 | 
			
		||||
  foreach (const QString &line, lines) {
 | 
			
		||||
    QStringList parts = line.mid (1, line.size () - 2).split ("\",\""); // remove "
 | 
			
		||||
    if (parts.size () < 3) {
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    subs_.append (Sub (parts[0], parts[1], parts[2]));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RecognizerHelper::save () {
 | 
			
		||||
  QFile f (fileName_);
 | 
			
		||||
  if (!f.open (QFile::WriteOnly)) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  foreach (const Sub &sub, subs_) {
 | 
			
		||||
    QStringList parts = QStringList () << sub.language << sub.source << sub.target;
 | 
			
		||||
    QString line = "\"" + parts.join ("\",\"") + "\"\n";
 | 
			
		||||
    f.write (line.toUtf8 ());
 | 
			
		||||
  }
 | 
			
		||||
  f.close ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString RecognizerHelper::substitute (const QString &source, const QString &language) const {
 | 
			
		||||
  QString result = source;
 | 
			
		||||
  while (true) {
 | 
			
		||||
    int bestMatchIndex = -1;
 | 
			
		||||
    int bestMatchLen = 0;
 | 
			
		||||
    int index = -1;
 | 
			
		||||
    foreach (const Sub &sub, subs_) {
 | 
			
		||||
      ++index;
 | 
			
		||||
      if (sub.language != language || !result.contains (sub.source)) {
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
      int len = sub.source.length ();
 | 
			
		||||
      if (len > bestMatchLen) {
 | 
			
		||||
        bestMatchLen = len;
 | 
			
		||||
        bestMatchIndex = index;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (bestMatchIndex > -1) {
 | 
			
		||||
      const Sub &sub = subs_.at (bestMatchIndex);
 | 
			
		||||
      result.replace (sub.source, sub.target);
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const RecognizerHelper::Subs &RecognizerHelper::subs () const {
 | 
			
		||||
  return subs_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RecognizerHelper::setSubs (const Subs &subs) {
 | 
			
		||||
  subs_ = subs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RecognizerHelper::Sub::Sub (const QString &language, const QString &source, const QString &target)
 | 
			
		||||
  : language (language), source (source), target (target) {
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								RecognizerHelper.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,33 @@
 | 
			
		||||
#ifndef RECOGNIZERHELPER_H
 | 
			
		||||
#define RECOGNIZERHELPER_H
 | 
			
		||||
 | 
			
		||||
#include <QString>
 | 
			
		||||
 | 
			
		||||
class RecognizerHelper {
 | 
			
		||||
  public:
 | 
			
		||||
    struct Sub {
 | 
			
		||||
      Sub (const QString &language = QString (), const QString &source = QString (),
 | 
			
		||||
           const QString &target = QString ());
 | 
			
		||||
      QString language;
 | 
			
		||||
      QString source;
 | 
			
		||||
      QString target;
 | 
			
		||||
    };
 | 
			
		||||
    typedef QList<Sub> Subs;
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    RecognizerHelper ();
 | 
			
		||||
 | 
			
		||||
    void load ();
 | 
			
		||||
    void save ();
 | 
			
		||||
 | 
			
		||||
    QString substitute (const QString &source, const QString& language) const;
 | 
			
		||||
 | 
			
		||||
    const Subs &subs () const;
 | 
			
		||||
    void setSubs (const Subs &subs);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    QString fileName_;
 | 
			
		||||
    Subs subs_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // RECOGNIZERHELPER_H
 | 
			
		||||
@ -2,6 +2,10 @@
 | 
			
		||||
    <qresource prefix="/">
 | 
			
		||||
        <file>translations/translation_en.qm</file>
 | 
			
		||||
        <file>translations/translation_ru.qm</file>
 | 
			
		||||
        <file>images/icon.png</file>
 | 
			
		||||
        <file>images/STIconBlue.png</file>
 | 
			
		||||
        <file>images/STIconGreen.png</file>
 | 
			
		||||
        <file>images/STIconOrange.png</file>
 | 
			
		||||
        <file>images/STIconRed.png</file>
 | 
			
		||||
        <file>version.json</file>
 | 
			
		||||
    </qresource>
 | 
			
		||||
</RCC>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										130
									
								
								ResultDialog.cpp
									
									
									
									
									
								
							
							
						
						@ -1,69 +1,121 @@
 | 
			
		||||
#include "ResultDialog.h"
 | 
			
		||||
#include "ui_ResultDialog.h"
 | 
			
		||||
#include "StAssert.h"
 | 
			
		||||
#include "LanguageHelper.h"
 | 
			
		||||
 | 
			
		||||
#include <QDesktopWidget>
 | 
			
		||||
#include <QMouseEvent>
 | 
			
		||||
#include <QMenu>
 | 
			
		||||
 | 
			
		||||
ResultDialog::ResultDialog(QWidget *parent) :
 | 
			
		||||
  QDialog(parent),
 | 
			
		||||
  ui(new Ui::ResultDialog),
 | 
			
		||||
  isShowAtCapturePos_ (true)
 | 
			
		||||
{
 | 
			
		||||
  ui->setupUi(this);
 | 
			
		||||
ResultDialog::ResultDialog (const LanguageHelper &dictionary, QWidget *parent) :
 | 
			
		||||
  QDialog (parent),
 | 
			
		||||
  ui (new Ui::ResultDialog),
 | 
			
		||||
  dictionary_ (dictionary),
 | 
			
		||||
  contextMenu_ (NULL), recognizeSubMenu_ (NULL),  translateSubMenu_ (NULL),
 | 
			
		||||
  clipboardAction_ (NULL), imageClipboardAction_ (NULL), correctAction_ (NULL) {
 | 
			
		||||
  ui->setupUi (this);
 | 
			
		||||
  setWindowFlags (Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint |
 | 
			
		||||
                  Qt::WindowStaysOnTopHint);
 | 
			
		||||
                  Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
 | 
			
		||||
 | 
			
		||||
  QString styleSheet =
 | 
			
		||||
    "#recognizeLabel, #translateLabel {"
 | 
			
		||||
    "color: black;"
 | 
			
		||||
    "background: qlineargradient(x1:0, y1:0, x2:1, y2:1,"
 | 
			
		||||
    "stop:0 darkGray, stop: 0.5 lightGray, stop:1 darkGray);"
 | 
			
		||||
    "}";
 | 
			
		||||
  setStyleSheet (styleSheet);
 | 
			
		||||
 | 
			
		||||
  installEventFilter (this);
 | 
			
		||||
  createContextMenu ();
 | 
			
		||||
  applySettings ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultDialog::~ResultDialog()
 | 
			
		||||
{
 | 
			
		||||
ResultDialog::~ResultDialog () {
 | 
			
		||||
  delete contextMenu_;
 | 
			
		||||
  delete ui;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ResultDialog::eventFilter(QObject* object, QEvent* event)
 | 
			
		||||
{
 | 
			
		||||
const ProcessingItem &ResultDialog::item () const {
 | 
			
		||||
  return item_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ResultDialog::applySettings () {
 | 
			
		||||
  dictionary_.updateMenu (recognizeSubMenu_, dictionary_.availableOcrLanguagesUi ());
 | 
			
		||||
  dictionary_.updateMenu (translateSubMenu_, dictionary_.translateLanguagesUi ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ResultDialog::createContextMenu () {
 | 
			
		||||
  contextMenu_ = new QMenu ();
 | 
			
		||||
  recognizeSubMenu_ = contextMenu_->addMenu (tr ("Распознать другой язык"));
 | 
			
		||||
  translateSubMenu_ = contextMenu_->addMenu (tr ("Перевести на другой язык"));
 | 
			
		||||
  clipboardAction_ = contextMenu_->addAction (tr ("Скопировать в буфер"));
 | 
			
		||||
  imageClipboardAction_ = contextMenu_->addAction (tr ("Скопировать рисунок в буфер"));
 | 
			
		||||
  correctAction_ = contextMenu_->addAction (tr ("Исправить распознанный текст"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ResultDialog::eventFilter (QObject *object, QEvent *event) {
 | 
			
		||||
  Q_UNUSED (object);
 | 
			
		||||
  if (event->type () == QEvent::MouseButtonRelease)
 | 
			
		||||
  {
 | 
			
		||||
  if (event->type () == QEvent::MouseButtonPress) {
 | 
			
		||||
    Qt::MouseButton button = static_cast<QMouseEvent *>(event)->button ();
 | 
			
		||||
    if (button == Qt::RightButton) {
 | 
			
		||||
      QAction *action = contextMenu_->exec (QCursor::pos ());
 | 
			
		||||
      if (recognizeSubMenu_->findChildren<QAction *> ().contains (action)) {
 | 
			
		||||
        ProcessingItem item = item_;
 | 
			
		||||
        item.translated = item.recognized = QString ();
 | 
			
		||||
        item.ocrLanguage = dictionary_.ocrUiToCode (action->text ());
 | 
			
		||||
        emit requestRecognize (item);
 | 
			
		||||
      }
 | 
			
		||||
      else if (translateSubMenu_->findChildren<QAction *> ().contains (action)) {
 | 
			
		||||
        ProcessingItem item = item_;
 | 
			
		||||
        item.translated.clear ();
 | 
			
		||||
        item.translateLanguage = dictionary_.translateUiToCode (action->text ());
 | 
			
		||||
        emit requestTranslate (item);
 | 
			
		||||
      }
 | 
			
		||||
      else if (action == clipboardAction_) {
 | 
			
		||||
        emit requestClipboard ();
 | 
			
		||||
      }
 | 
			
		||||
      else if (action == imageClipboardAction_) {
 | 
			
		||||
        emit requestImageClipboard ();
 | 
			
		||||
      }
 | 
			
		||||
      else if (action == correctAction_) {
 | 
			
		||||
        emit requestEdition (item_);
 | 
			
		||||
        // Return because Manager calls showResult() before hide() otherwise.
 | 
			
		||||
        return QDialog::eventFilter (object, event);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    hide ();
 | 
			
		||||
  }
 | 
			
		||||
  else if (event->type () == QEvent::WindowDeactivate) {
 | 
			
		||||
    hide ();
 | 
			
		||||
  }
 | 
			
		||||
  return QDialog::eventFilter (object, event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ResultDialog::showResult(ProcessingItem item)
 | 
			
		||||
{
 | 
			
		||||
  ST_ASSERT (!item.source.isNull ());
 | 
			
		||||
  ST_ASSERT (!item.recognized.isEmpty ());
 | 
			
		||||
  ST_ASSERT (!item.translated.isEmpty ());
 | 
			
		||||
  ST_ASSERT (!item.screenPos.isNull ());
 | 
			
		||||
 | 
			
		||||
void ResultDialog::showResult (ProcessingItem item) {
 | 
			
		||||
  ST_ASSERT (item.isValid ());
 | 
			
		||||
  item_ = item;
 | 
			
		||||
  ui->sourceLabel->setPixmap (item.source);
 | 
			
		||||
  ui->recognizeLabel->setText (item.recognized);
 | 
			
		||||
  ui->translateLabel->setText (item.translated);
 | 
			
		||||
  bool gotTranslation = !item.translated.isEmpty ();
 | 
			
		||||
  ui->translateLabel->setVisible (gotTranslation);
 | 
			
		||||
  ui->translateLine->setVisible (gotTranslation);
 | 
			
		||||
 | 
			
		||||
  show ();
 | 
			
		||||
  adjustSize ();
 | 
			
		||||
#ifdef Q_OS_LINUX
 | 
			
		||||
  hide (); // buggy otherwise (on some systems)
 | 
			
		||||
  show ();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  QDesktopWidget* desktop = QApplication::desktop ();
 | 
			
		||||
  QDesktopWidget *desktop = QApplication::desktop ();
 | 
			
		||||
  Q_CHECK_PTR (desktop);
 | 
			
		||||
  if (isShowAtCapturePos_)
 | 
			
		||||
  {
 | 
			
		||||
    QPoint correction = QPoint (ui->frame->lineWidth (), ui->frame->lineWidth ());
 | 
			
		||||
    move (item.screenPos - correction);
 | 
			
		||||
    QRect screenRect = desktop->screenGeometry (this);
 | 
			
		||||
    int minY = screenRect.bottom () - height ();
 | 
			
		||||
    if (y () > minY)
 | 
			
		||||
    {
 | 
			
		||||
      move (x (), minY);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
 | 
			
		||||
    QRect screenRect = desktop->availableGeometry (this);
 | 
			
		||||
    ST_ASSERT (screenRect.isValid ());
 | 
			
		||||
    QPoint newPos (screenRect.width () - width (), screenRect.height () - height ());
 | 
			
		||||
    move (newPos);
 | 
			
		||||
  QPoint correction = QPoint ((width () - item.source.width ()) / 2, ui->frame->lineWidth ());
 | 
			
		||||
  move (item.screenPos - correction);
 | 
			
		||||
  QRect screenRect = desktop->screenGeometry (this);
 | 
			
		||||
  int minY = screenRect.bottom () - height ();
 | 
			
		||||
  if (y () > minY) {
 | 
			
		||||
    move (x (), minY);
 | 
			
		||||
  }
 | 
			
		||||
  activateWindow ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -2,30 +2,50 @@
 | 
			
		||||
#define RESULTDIALOG_H
 | 
			
		||||
 | 
			
		||||
#include <QDialog>
 | 
			
		||||
#include <QMenu>
 | 
			
		||||
 | 
			
		||||
#include "ProcessingItem.h"
 | 
			
		||||
 | 
			
		||||
namespace Ui {
 | 
			
		||||
  class ResultDialog;
 | 
			
		||||
}
 | 
			
		||||
class LanguageHelper;
 | 
			
		||||
 | 
			
		||||
class ResultDialog : public QDialog
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
class ResultDialog : public QDialog {
 | 
			
		||||
  Q_OBJECT
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    explicit ResultDialog(QWidget *parent = 0);
 | 
			
		||||
    ~ResultDialog();
 | 
			
		||||
    explicit ResultDialog (const LanguageHelper &dictionary, QWidget *parent = 0);
 | 
			
		||||
    ~ResultDialog ();
 | 
			
		||||
 | 
			
		||||
  signals:
 | 
			
		||||
    void requestRecognize (ProcessingItem item);
 | 
			
		||||
    void requestTranslate (ProcessingItem item);
 | 
			
		||||
    void requestClipboard (); // Assume that slot will be called immediately.
 | 
			
		||||
    void requestImageClipboard (); // Assume that slot will be called immediately.
 | 
			
		||||
    void requestEdition (ProcessingItem item);
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    const ProcessingItem &item () const;
 | 
			
		||||
    bool eventFilter (QObject *object, QEvent *event);
 | 
			
		||||
 | 
			
		||||
  public slots:
 | 
			
		||||
    void showResult (ProcessingItem item);
 | 
			
		||||
    void applySettings ();
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    void createContextMenu ();
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    Ui::ResultDialog *ui;
 | 
			
		||||
    bool isShowAtCapturePos_;
 | 
			
		||||
    const LanguageHelper &dictionary_;
 | 
			
		||||
    QMenu *contextMenu_;
 | 
			
		||||
    QMenu *recognizeSubMenu_;
 | 
			
		||||
    QMenu *translateSubMenu_;
 | 
			
		||||
    QAction *clipboardAction_;
 | 
			
		||||
    QAction *imageClipboardAction_;
 | 
			
		||||
    QAction *correctAction_;
 | 
			
		||||
    ProcessingItem item_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // RESULTDIALOG_H
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,16 @@
 | 
			
		||||
   <string>Результат</string>
 | 
			
		||||
  </property>
 | 
			
		||||
  <layout class="QGridLayout" name="gridLayout">
 | 
			
		||||
   <property name="margin">
 | 
			
		||||
   <property name="leftMargin">
 | 
			
		||||
    <number>0</number>
 | 
			
		||||
   </property>
 | 
			
		||||
   <property name="topMargin">
 | 
			
		||||
    <number>0</number>
 | 
			
		||||
   </property>
 | 
			
		||||
   <property name="rightMargin">
 | 
			
		||||
    <number>0</number>
 | 
			
		||||
   </property>
 | 
			
		||||
   <property name="bottomMargin">
 | 
			
		||||
    <number>0</number>
 | 
			
		||||
   </property>
 | 
			
		||||
   <property name="spacing">
 | 
			
		||||
@ -29,7 +38,16 @@
 | 
			
		||||
      <enum>QFrame::Plain</enum>
 | 
			
		||||
     </property>
 | 
			
		||||
     <layout class="QGridLayout" name="gridLayout_2">
 | 
			
		||||
      <property name="margin">
 | 
			
		||||
      <property name="leftMargin">
 | 
			
		||||
       <number>0</number>
 | 
			
		||||
      </property>
 | 
			
		||||
      <property name="topMargin">
 | 
			
		||||
       <number>0</number>
 | 
			
		||||
      </property>
 | 
			
		||||
      <property name="rightMargin">
 | 
			
		||||
       <number>0</number>
 | 
			
		||||
      </property>
 | 
			
		||||
      <property name="bottomMargin">
 | 
			
		||||
       <number>0</number>
 | 
			
		||||
      </property>
 | 
			
		||||
      <property name="spacing">
 | 
			
		||||
@ -49,7 +67,7 @@
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="1" column="0">
 | 
			
		||||
       <widget class="Line" name="line_2">
 | 
			
		||||
       <widget class="Line" name="recognizeLine">
 | 
			
		||||
        <property name="orientation">
 | 
			
		||||
         <enum>Qt::Horizontal</enum>
 | 
			
		||||
        </property>
 | 
			
		||||
@ -69,7 +87,7 @@
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="3" column="0">
 | 
			
		||||
       <widget class="Line" name="line">
 | 
			
		||||
       <widget class="Line" name="translateLine">
 | 
			
		||||
        <property name="orientation">
 | 
			
		||||
         <enum>Qt::Horizontal</enum>
 | 
			
		||||
        </property>
 | 
			
		||||
 | 
			
		||||
@ -10,11 +10,21 @@ greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 | 
			
		||||
 | 
			
		||||
TARGET = ScreenTranslator
 | 
			
		||||
TEMPLATE = app
 | 
			
		||||
CONFIG += c++11
 | 
			
		||||
 | 
			
		||||
INCLUDEPATH += ../include
 | 
			
		||||
win32{
 | 
			
		||||
    INCLUDEPATH += $$PWD/../build/mingw/deps/include
 | 
			
		||||
    LIBS += -L$$PWD/../build/mingw/deps/lib -lws2_32
 | 
			
		||||
}
 | 
			
		||||
linux{
 | 
			
		||||
    QT += x11extras
 | 
			
		||||
    INCLUDEPATH += $$PWD/../build/linux/deps/include
 | 
			
		||||
    LIBS += -L$$PWD/../build/linux/deps/lib -lX11 -Wl,-rpath,.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LIBS += -L../bin -ltesseract -llept -ltiff -lgif -ljpeg -lz
 | 
			
		||||
LIBS += -lWs2_32
 | 
			
		||||
LIBS += -ltesseract -llept
 | 
			
		||||
 | 
			
		||||
include(3rd-party/qtsingleapplication/qtsingleapplication.pri)
 | 
			
		||||
 | 
			
		||||
SOURCES += main.cpp\
 | 
			
		||||
    Manager.cpp \
 | 
			
		||||
@ -22,12 +32,16 @@ SOURCES += main.cpp\
 | 
			
		||||
    SelectionDialog.cpp \
 | 
			
		||||
    GlobalActionHelper.cpp \
 | 
			
		||||
    Recognizer.cpp \
 | 
			
		||||
    Translator.cpp \
 | 
			
		||||
    ResultDialog.cpp \
 | 
			
		||||
    ProcessingItem.cpp \
 | 
			
		||||
    ImageProcessing.cpp \
 | 
			
		||||
    LanguageHelper.cpp \
 | 
			
		||||
    GoogleWebTranslator.cpp
 | 
			
		||||
    WebTranslator.cpp \
 | 
			
		||||
    WebTranslatorProxy.cpp \
 | 
			
		||||
    TranslatorHelper.cpp \
 | 
			
		||||
    RecognizerHelper.cpp \
 | 
			
		||||
    Utils.cpp \
 | 
			
		||||
    Updater.cpp
 | 
			
		||||
 | 
			
		||||
HEADERS  += \
 | 
			
		||||
    Manager.h \
 | 
			
		||||
@ -35,14 +49,18 @@ HEADERS  += \
 | 
			
		||||
    SelectionDialog.h \
 | 
			
		||||
    GlobalActionHelper.h \
 | 
			
		||||
    Recognizer.h \
 | 
			
		||||
    Translator.h \
 | 
			
		||||
    Settings.h \
 | 
			
		||||
    ProcessingItem.h \
 | 
			
		||||
    ResultDialog.h \
 | 
			
		||||
    ImageProcessing.h \
 | 
			
		||||
    LanguageHelper.h \
 | 
			
		||||
    GoogleWebTranslator.h \
 | 
			
		||||
    StAssert.h
 | 
			
		||||
    WebTranslator.h \
 | 
			
		||||
    WebTranslatorProxy.h \
 | 
			
		||||
    StAssert.h \
 | 
			
		||||
    TranslatorHelper.h \
 | 
			
		||||
    RecognizerHelper.h \
 | 
			
		||||
    Utils.h \
 | 
			
		||||
    Updater.h
 | 
			
		||||
 | 
			
		||||
FORMS    += \
 | 
			
		||||
    SettingsEditor.ui \
 | 
			
		||||
@ -56,11 +74,19 @@ TRANSLATIONS += \
 | 
			
		||||
    translations/translation_en.ts \
 | 
			
		||||
    translations/translation_ru.ts
 | 
			
		||||
 | 
			
		||||
win32{
 | 
			
		||||
RC_FILE = app.rc
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OTHER_FILES += \
 | 
			
		||||
    app.rc \
 | 
			
		||||
    images/icon.ico \
 | 
			
		||||
    README.md
 | 
			
		||||
    images/* \
 | 
			
		||||
    translators/* \
 | 
			
		||||
    scripts/* \
 | 
			
		||||
    distr/* \
 | 
			
		||||
    version.json \
 | 
			
		||||
    README.md \
 | 
			
		||||
    uncrustify.cfg\
 | 
			
		||||
    .travis.yml \
 | 
			
		||||
    TODO.md
 | 
			
		||||
 | 
			
		||||
QMAKE_TARGET_COMPANY = Gres
 | 
			
		||||
QMAKE_TARGET_PRODUCT = Screen Translator
 | 
			
		||||
QMAKE_TARGET_COPYRIGHT = Copyright (c) Gres
 | 
			
		||||
VERSION = 2.0.0.0
 | 
			
		||||
RC_ICONS = images/icon.ico
 | 
			
		||||
 | 
			
		||||
@ -8,159 +8,115 @@
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QMenu>
 | 
			
		||||
 | 
			
		||||
SelectionDialog::SelectionDialog(const LanguageHelper &dictionary, QWidget *parent) :
 | 
			
		||||
  QDialog(parent),
 | 
			
		||||
  ui(new Ui::SelectionDialog), dictionary_ (dictionary),
 | 
			
		||||
  languageMenu_ (new QMenu)
 | 
			
		||||
{
 | 
			
		||||
  ui->setupUi(this);
 | 
			
		||||
SelectionDialog::SelectionDialog (const LanguageHelper &dictionary, QWidget *parent) :
 | 
			
		||||
  QDialog (parent),
 | 
			
		||||
  ui (new Ui::SelectionDialog), dictionary_ (dictionary),
 | 
			
		||||
  languageMenu_ (new QMenu), swapLanguagesAction_ (NULL) {
 | 
			
		||||
  ui->setupUi (this);
 | 
			
		||||
  setWindowFlags (Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint |
 | 
			
		||||
                  Qt::WindowStaysOnTopHint);
 | 
			
		||||
                  Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
 | 
			
		||||
 | 
			
		||||
  ui->label->setAutoFillBackground(false);
 | 
			
		||||
  ui->label->setAutoFillBackground (false);
 | 
			
		||||
  ui->label->installEventFilter (this);
 | 
			
		||||
 | 
			
		||||
  updateMenu ();
 | 
			
		||||
  applySettings ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SelectionDialog::~SelectionDialog()
 | 
			
		||||
{
 | 
			
		||||
SelectionDialog::~SelectionDialog () {
 | 
			
		||||
  delete languageMenu_;
 | 
			
		||||
  delete ui;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SelectionDialog::updateMenu()
 | 
			
		||||
{
 | 
			
		||||
  Q_CHECK_PTR (languageMenu_);
 | 
			
		||||
  languageMenu_->clear ();
 | 
			
		||||
  QStringList languages = dictionary_.availableOcrLanguagesUi ();
 | 
			
		||||
  if (languages.isEmpty ())
 | 
			
		||||
  {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const int max = 10;
 | 
			
		||||
 | 
			
		||||
  if (languages.size () <= max)
 | 
			
		||||
  {
 | 
			
		||||
    foreach (const QString& language, languages)
 | 
			
		||||
    {
 | 
			
		||||
      languageMenu_->addAction (language);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    int subIndex = max;
 | 
			
		||||
    QMenu* subMenu = NULL;
 | 
			
		||||
    QString prevLetter;
 | 
			
		||||
    foreach (const QString& language, languages)
 | 
			
		||||
    {
 | 
			
		||||
      QString curLetter = language.left (1);
 | 
			
		||||
      if (++subIndex >= max && prevLetter != curLetter)
 | 
			
		||||
      {
 | 
			
		||||
        if (subMenu != NULL)
 | 
			
		||||
        {
 | 
			
		||||
          subMenu->setTitle (subMenu->title () + " - " + prevLetter);
 | 
			
		||||
        }
 | 
			
		||||
        subMenu = languageMenu_->addMenu (curLetter);
 | 
			
		||||
        subIndex = 0;
 | 
			
		||||
      }
 | 
			
		||||
      prevLetter = curLetter;
 | 
			
		||||
      subMenu->addAction (language);
 | 
			
		||||
    }
 | 
			
		||||
    subMenu->setTitle (subMenu->title () + " - " + prevLetter);
 | 
			
		||||
void SelectionDialog::applySettings () {
 | 
			
		||||
  dictionary_.updateMenu (languageMenu_, dictionary_.availableOcrLanguagesUi ());
 | 
			
		||||
  if (!languageMenu_->isEmpty ()) {
 | 
			
		||||
    swapLanguagesAction_ = languageMenu_->addAction (tr ("Поменять язык текста и перевода"));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SelectionDialog::eventFilter(QObject* object, QEvent* event)
 | 
			
		||||
{
 | 
			
		||||
  if (object != ui->label)
 | 
			
		||||
  {
 | 
			
		||||
bool SelectionDialog::eventFilter (QObject *object, QEvent *event) {
 | 
			
		||||
  if (object != ui->label) {
 | 
			
		||||
    return QDialog::eventFilter (object, event);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (event->type () == QEvent::Show)
 | 
			
		||||
  {
 | 
			
		||||
  if (event->type () == QEvent::Show) {
 | 
			
		||||
    startSelectPos_ = currentSelectPos_ = QPoint ();
 | 
			
		||||
  }
 | 
			
		||||
  else if (event->type () == QEvent::MouseButtonPress)
 | 
			
		||||
  {
 | 
			
		||||
    QMouseEvent* mouseEvent = static_cast <QMouseEvent*> (event);
 | 
			
		||||
  else if (event->type () == QEvent::MouseButtonPress) {
 | 
			
		||||
    QMouseEvent *mouseEvent = static_cast <QMouseEvent *> (event);
 | 
			
		||||
    if ((mouseEvent->button () == Qt::LeftButton ||
 | 
			
		||||
         mouseEvent->button () == Qt::RightButton) && startSelectPos_.isNull ())
 | 
			
		||||
    {
 | 
			
		||||
         mouseEvent->button () == Qt::RightButton) && startSelectPos_.isNull ()) {
 | 
			
		||||
      startSelectPos_ = mouseEvent->pos ();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else if (event->type () == QEvent::MouseMove)
 | 
			
		||||
  {
 | 
			
		||||
    QMouseEvent* mouseEvent = static_cast <QMouseEvent*> (event);
 | 
			
		||||
  else if (event->type () == QEvent::MouseMove) {
 | 
			
		||||
    QMouseEvent *mouseEvent = static_cast <QMouseEvent *> (event);
 | 
			
		||||
    if ((mouseEvent->buttons () & Qt::LeftButton ||
 | 
			
		||||
        mouseEvent->buttons () & Qt::RightButton) && !startSelectPos_.isNull ())
 | 
			
		||||
    {
 | 
			
		||||
         mouseEvent->buttons () & Qt::RightButton) && !startSelectPos_.isNull ()) {
 | 
			
		||||
      currentSelectPos_ = mouseEvent->pos ();
 | 
			
		||||
      ui->label->repaint ();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else if (event->type () == QEvent::Paint)
 | 
			
		||||
  {
 | 
			
		||||
  else if (event->type () == QEvent::Paint) {
 | 
			
		||||
    QRect selection = QRect (startSelectPos_, currentSelectPos_).normalized ();
 | 
			
		||||
    if (selection.isValid ())
 | 
			
		||||
    {
 | 
			
		||||
    if (selection.isValid ()) {
 | 
			
		||||
      QPainter painter (ui->label);
 | 
			
		||||
      painter.setPen (Qt::red);
 | 
			
		||||
      painter.drawRect (selection);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else if (event->type () == QEvent::MouseButtonRelease)
 | 
			
		||||
  {
 | 
			
		||||
    QMouseEvent* mouseEvent = static_cast <QMouseEvent*> (event);
 | 
			
		||||
  else if (event->type () == QEvent::MouseButtonRelease) {
 | 
			
		||||
    QMouseEvent *mouseEvent = static_cast <QMouseEvent *> (event);
 | 
			
		||||
    if (mouseEvent->button () == Qt::LeftButton ||
 | 
			
		||||
        mouseEvent->button () == Qt::RightButton)
 | 
			
		||||
    {
 | 
			
		||||
      if (startSelectPos_.isNull () || currentPixmap_.isNull ())
 | 
			
		||||
      {
 | 
			
		||||
        mouseEvent->button () == Qt::RightButton) {
 | 
			
		||||
      if (startSelectPos_.isNull () || currentPixmap_.isNull ()) {
 | 
			
		||||
        return QDialog::eventFilter (object, event);
 | 
			
		||||
      }
 | 
			
		||||
      QPoint endPos = mouseEvent->pos ();
 | 
			
		||||
      QRect selection = QRect (startSelectPos_, endPos).normalized ();
 | 
			
		||||
      startSelectPos_ = currentSelectPos_ = QPoint ();
 | 
			
		||||
      QPixmap selectedPixmap = currentPixmap_.copy (selection);
 | 
			
		||||
      if (!selectedPixmap.isNull ())
 | 
			
		||||
      {
 | 
			
		||||
        ProcessingItem item;
 | 
			
		||||
        item.source = selectedPixmap;
 | 
			
		||||
        item.screenPos = selection.topLeft ();
 | 
			
		||||
      if (selectedPixmap.width () < 3 || selectedPixmap.height () < 3) {
 | 
			
		||||
        reject ();
 | 
			
		||||
        return QDialog::eventFilter (object, event);
 | 
			
		||||
      }
 | 
			
		||||
      ProcessingItem item;
 | 
			
		||||
      item.source = selectedPixmap;
 | 
			
		||||
      item.screenPos = pos () + selection.topLeft ();
 | 
			
		||||
      item.modifiers = mouseEvent->modifiers ();
 | 
			
		||||
 | 
			
		||||
        if (mouseEvent->button () == Qt::RightButton &&
 | 
			
		||||
            !languageMenu_->children ().isEmpty ())
 | 
			
		||||
        {
 | 
			
		||||
          QAction* action = languageMenu_->exec (QCursor::pos ());
 | 
			
		||||
          if (action == NULL)
 | 
			
		||||
          {
 | 
			
		||||
            reject ();
 | 
			
		||||
            return QDialog::eventFilter (object, event);
 | 
			
		||||
          }
 | 
			
		||||
      if (mouseEvent->button () == Qt::RightButton &&
 | 
			
		||||
          !languageMenu_->children ().isEmpty ()) {
 | 
			
		||||
        QAction *action = languageMenu_->exec (QCursor::pos ());
 | 
			
		||||
        if (action == NULL) {
 | 
			
		||||
          reject ();
 | 
			
		||||
          return QDialog::eventFilter (object, event);
 | 
			
		||||
        }
 | 
			
		||||
        if (action == swapLanguagesAction_) {
 | 
			
		||||
          item.swapLanguages_ = true;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
          item.ocrLanguage = dictionary_.ocrUiToCode (action->text ());
 | 
			
		||||
          ST_ASSERT (!item.ocrLanguage.isEmpty ());
 | 
			
		||||
          item.sourceLanguage = dictionary_.translateForOcrCode (item.ocrLanguage);
 | 
			
		||||
          item.sourceLanguage = dictionary_.ocrToTranslateCodes (item.ocrLanguage);
 | 
			
		||||
          ST_ASSERT (!item.sourceLanguage.isEmpty ());
 | 
			
		||||
        }
 | 
			
		||||
        emit selected (item);
 | 
			
		||||
        accept ();
 | 
			
		||||
      }
 | 
			
		||||
      emit selected (item);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return QDialog::eventFilter (object, event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SelectionDialog::setPixmap(QPixmap pixmap)
 | 
			
		||||
{
 | 
			
		||||
void SelectionDialog::setPixmap (QPixmap pixmap, const QRect &showGeometry) {
 | 
			
		||||
  ST_ASSERT (!pixmap.isNull ());
 | 
			
		||||
  ST_ASSERT (!showGeometry.isEmpty ());
 | 
			
		||||
  currentPixmap_ = pixmap;
 | 
			
		||||
  QPalette palette = this->palette ();
 | 
			
		||||
  palette.setBrush (this->backgroundRole (), pixmap);
 | 
			
		||||
  this->setPalette (palette);
 | 
			
		||||
  this->resize (pixmap.size ());
 | 
			
		||||
  this->setGeometry (showGeometry);
 | 
			
		||||
 | 
			
		||||
  show ();
 | 
			
		||||
  setFocus ();
 | 
			
		||||
  activateWindow ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -12,30 +12,32 @@ namespace Ui {
 | 
			
		||||
}
 | 
			
		||||
class LanguageHelper;
 | 
			
		||||
 | 
			
		||||
class SelectionDialog : public QDialog
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
class SelectionDialog : public QDialog {
 | 
			
		||||
  Q_OBJECT
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    explicit SelectionDialog(const LanguageHelper& dictionary, QWidget *parent = 0);
 | 
			
		||||
    ~SelectionDialog();
 | 
			
		||||
    explicit SelectionDialog (const LanguageHelper &dictionary, QWidget *parent = 0);
 | 
			
		||||
    ~SelectionDialog ();
 | 
			
		||||
 | 
			
		||||
    bool eventFilter (QObject *object, QEvent *event);
 | 
			
		||||
 | 
			
		||||
  signals:
 | 
			
		||||
    void selected (ProcessingItem pixmap);
 | 
			
		||||
    void nothingSelected ();
 | 
			
		||||
 | 
			
		||||
  public slots:
 | 
			
		||||
    void setPixmap (QPixmap pixmap);
 | 
			
		||||
    void updateMenu ();
 | 
			
		||||
    //! Show pixmap with given geometry.
 | 
			
		||||
    void setPixmap (QPixmap pixmap, const QRect &showGeometry);
 | 
			
		||||
    void applySettings ();
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    Ui::SelectionDialog *ui;
 | 
			
		||||
    const LanguageHelper& dictionary_;
 | 
			
		||||
    const LanguageHelper &dictionary_;
 | 
			
		||||
    QPoint startSelectPos_;
 | 
			
		||||
    QPoint currentSelectPos_;
 | 
			
		||||
    QPixmap currentPixmap_;
 | 
			
		||||
    QMenu* languageMenu_;
 | 
			
		||||
    QMenu *languageMenu_;
 | 
			
		||||
    QAction *swapLanguagesAction_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // SELECTIONDIALOG_H
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										37
									
								
								Settings.h
									
									
									
									
									
								
							
							
						
						@ -3,15 +3,23 @@
 | 
			
		||||
 | 
			
		||||
#include <QString>
 | 
			
		||||
 | 
			
		||||
namespace settings_names
 | 
			
		||||
{
 | 
			
		||||
namespace settings_names {
 | 
			
		||||
  //! UI
 | 
			
		||||
  const QString guiGroup = "GUI";
 | 
			
		||||
  const QString geometry = "geometry";
 | 
			
		||||
  const QString captureHotkey = "captureHotkey";
 | 
			
		||||
  const QString repeatCaptureHotkey = "repeatCaptureHotkey";
 | 
			
		||||
  const QString repeatHotkey = "repeatHotkey";
 | 
			
		||||
  const QString clipboardHotkey = "clipboardHotkey";
 | 
			
		||||
  const QString resultShowType = "resultShowType";
 | 
			
		||||
  const QString proxyType = "proxyType";
 | 
			
		||||
  const QString proxyHostName = "proxyHostName";
 | 
			
		||||
  const QString proxyPort = "proxyPort";
 | 
			
		||||
  const QString proxyUser = "proxyUser";
 | 
			
		||||
  const QString proxyPassword = "proxyPassword";
 | 
			
		||||
  const QString proxySavePassword = "proxySavePassword";
 | 
			
		||||
  const QString autoUpdateType = "autoUpdateType";
 | 
			
		||||
  const QString lastUpdateCheck = "lastUpdateCheck";
 | 
			
		||||
 | 
			
		||||
  //! Recognition
 | 
			
		||||
  const QString recogntionGroup = "Recognition";
 | 
			
		||||
@ -21,30 +29,49 @@ namespace settings_names
 | 
			
		||||
 | 
			
		||||
  //! Translation
 | 
			
		||||
  const QString translationGroup = "Translation";
 | 
			
		||||
  const QString doTranslation = "doTranslation";
 | 
			
		||||
  const QString sourceLanguage = "source_language";
 | 
			
		||||
  const QString translationLanguage = "translation_language";
 | 
			
		||||
 | 
			
		||||
  const QString translationTimeout = "translation_timeout";
 | 
			
		||||
  const QString translationDebugMode = "translation_debug";
 | 
			
		||||
  const QString translators = "translators";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace settings_values
 | 
			
		||||
{
 | 
			
		||||
namespace settings_values {
 | 
			
		||||
  const QString appName = "ScreenTranslator";
 | 
			
		||||
  const QString companyName = "Gres";
 | 
			
		||||
 | 
			
		||||
  //! UI
 | 
			
		||||
  const QString captureHotkey = "Ctrl+Alt+Z";
 | 
			
		||||
  const QString repeatCaptureHotkey = "Ctrl+Alt+S";
 | 
			
		||||
  const QString repeatHotkey = "Ctrl+Alt+X";
 | 
			
		||||
  const QString clipboardHotkey = "Ctrl+Alt+C";
 | 
			
		||||
  const QString resultShowType = "1";//dialog
 | 
			
		||||
  const int proxyType = 0;
 | 
			
		||||
  const QString proxyHostName = "";
 | 
			
		||||
  const int proxyPort = 8080;
 | 
			
		||||
  const QString proxyUser = "";
 | 
			
		||||
  const QString proxyPassword = "";
 | 
			
		||||
  const bool proxySavePassword = false;
 | 
			
		||||
  const int autoUpdateType = 0; //Never
 | 
			
		||||
  const QString lastUpdateCheck = "";
 | 
			
		||||
 | 
			
		||||
  //! Recognition
 | 
			
		||||
#if defined(Q_OS_LINUX)
 | 
			
		||||
  const QString tessDataPlace = "/usr/share/tesseract-ocr/";
 | 
			
		||||
#else
 | 
			
		||||
  const QString tessDataPlace = "./";
 | 
			
		||||
#endif
 | 
			
		||||
  const QString ocrLanguage = "eng";
 | 
			
		||||
  const int imageScale = 5;
 | 
			
		||||
 | 
			
		||||
  //! Translation
 | 
			
		||||
  const bool doTranslation = true;
 | 
			
		||||
  const QString sourceLanguage = "auto";
 | 
			
		||||
  const QString translationLanguage = "ru";
 | 
			
		||||
  const int translationTimeout = 15; // secs
 | 
			
		||||
  const bool translationDebugMode = false;
 | 
			
		||||
  const QString translators = "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // SETTINGS_H
 | 
			
		||||
 | 
			
		||||
@ -1,133 +1,288 @@
 | 
			
		||||
#include "SettingsEditor.h"
 | 
			
		||||
#include "ui_SettingsEditor.h"
 | 
			
		||||
#include "LanguageHelper.h"
 | 
			
		||||
#include "TranslatorHelper.h"
 | 
			
		||||
#include "RecognizerHelper.h"
 | 
			
		||||
#include "StAssert.h"
 | 
			
		||||
#include "Utils.h"
 | 
			
		||||
 | 
			
		||||
#include <QSettings>
 | 
			
		||||
#include <QFileDialog>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
#include <QRegExpValidator>
 | 
			
		||||
#include <QNetworkProxy>
 | 
			
		||||
 | 
			
		||||
#include "Settings.h"
 | 
			
		||||
 | 
			
		||||
SettingsEditor::SettingsEditor(const LanguageHelper &dictionary, QWidget *parent) :
 | 
			
		||||
  QDialog(parent),
 | 
			
		||||
  ui(new Ui::SettingsEditor), dictionary_ (dictionary),
 | 
			
		||||
  buttonGroup_ (new QButtonGroup (this))
 | 
			
		||||
{
 | 
			
		||||
  ui->setupUi(this);
 | 
			
		||||
SettingsEditor::SettingsEditor (const LanguageHelper &dictionary, QWidget *parent) :
 | 
			
		||||
  QDialog (parent),
 | 
			
		||||
  ui (new Ui::SettingsEditor), translatorHelper_ (new TranslatorHelper),
 | 
			
		||||
  recognizerHelper_ (new RecognizerHelper), dictionary_ (dictionary),
 | 
			
		||||
  buttonGroup_ (new QButtonGroup (this)) {
 | 
			
		||||
  ui->setupUi (this);
 | 
			
		||||
 | 
			
		||||
  buttonGroup_->addButton (ui->trayRadio, 0);
 | 
			
		||||
  buttonGroup_->addButton (ui->dialogRadio, 1);
 | 
			
		||||
  connect (ui->updateButton, SIGNAL (clicked (bool)), SIGNAL (updateCheckRequested ()));
 | 
			
		||||
  QStringList updateTypes = QStringList () << tr ("Никогда") << tr ("Ежедневно")
 | 
			
		||||
                                           << tr ("Еженедельно") << tr ("Ежемесячно");
 | 
			
		||||
  ui->updateCombo->addItems (updateTypes);
 | 
			
		||||
 | 
			
		||||
  connect (ui->tessdataButton, SIGNAL (clicked ()), SLOT (openTessdataDialog ()));
 | 
			
		||||
  connect (ui->tessdataEdit, SIGNAL (textChanged (const QString&)),
 | 
			
		||||
           SLOT (initOcrLangCombo (const QString&)));
 | 
			
		||||
  connect (ui->tessdataEdit, SIGNAL (textChanged (const QString &)),
 | 
			
		||||
           SLOT (initOcrLangCombo (const QString &)));
 | 
			
		||||
 | 
			
		||||
  connect (ui->recognizerFixTable, SIGNAL (itemChanged (QTableWidgetItem *)),
 | 
			
		||||
           SLOT (recognizerFixTableItemChanged (QTableWidgetItem *)));
 | 
			
		||||
 | 
			
		||||
  ui->translateLangCombo->addItems (dictionary_.translateLanguagesUi ());
 | 
			
		||||
 | 
			
		||||
  typedef QNetworkProxy::ProxyType ProxyType;
 | 
			
		||||
  QMap<ProxyType, QString> proxyTypeNames;
 | 
			
		||||
  proxyTypeNames.insert (QNetworkProxy::NoProxy, tr ("Нет"));
 | 
			
		||||
  proxyTypeNames.insert (QNetworkProxy::Socks5Proxy, tr ("SOCKS 5"));
 | 
			
		||||
  proxyTypeNames.insert (QNetworkProxy::HttpProxy, tr ("HTTP"));
 | 
			
		||||
  QList<int> proxyOrder = proxyTypeOrder ();
 | 
			
		||||
  foreach (int type, proxyOrder) {
 | 
			
		||||
    ui->proxyTypeCombo->addItem (proxyTypeNames.value (QNetworkProxy::ProxyType (type)));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  QRegExp urlRegexp (R"(^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$)");
 | 
			
		||||
  ui->proxyHostEdit->setValidator (new QRegExpValidator (urlRegexp, ui->proxyHostEdit));
 | 
			
		||||
  ui->proxyPassEdit->setEchoMode (QLineEdit::PasswordEchoOnEdit);
 | 
			
		||||
 | 
			
		||||
  loadSettings ();
 | 
			
		||||
  loadState ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SettingsEditor::~SettingsEditor()
 | 
			
		||||
{
 | 
			
		||||
SettingsEditor::~SettingsEditor () {
 | 
			
		||||
  saveState ();
 | 
			
		||||
  delete recognizerHelper_;
 | 
			
		||||
  delete translatorHelper_;
 | 
			
		||||
  delete ui;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SettingsEditor::done(int result)
 | 
			
		||||
{
 | 
			
		||||
  if (result == QDialog::Accepted)
 | 
			
		||||
  {
 | 
			
		||||
void SettingsEditor::done (int result) {
 | 
			
		||||
  if (result == QDialog::Accepted) {
 | 
			
		||||
    saveSettings ();
 | 
			
		||||
    emit settingsEdited ();
 | 
			
		||||
  }
 | 
			
		||||
  QDialog::done (result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SettingsEditor::saveSettings() const
 | 
			
		||||
{
 | 
			
		||||
void SettingsEditor::saveSettings () const {
 | 
			
		||||
  using namespace settings_names;
 | 
			
		||||
  QSettings settings;
 | 
			
		||||
  settings.beginGroup (settings_names::guiGroup);
 | 
			
		||||
  settings.setValue (settings_names::captureHotkey, ui->captureEdit->text ());
 | 
			
		||||
  settings.setValue (settings_names::repeatHotkey, ui->repeatEdit->text ());
 | 
			
		||||
  settings.setValue (settings_names::clipboardHotkey, ui->clipboardEdit->text ());
 | 
			
		||||
  settings.setValue (settings_names::resultShowType, buttonGroup_->checkedId ());
 | 
			
		||||
  settings.beginGroup (guiGroup);
 | 
			
		||||
  settings.setValue (captureHotkey, ui->captureEdit->keySequence ().toString ());
 | 
			
		||||
  settings.setValue (repeatCaptureHotkey, ui->repeatCaptureEdit->keySequence ().toString ());
 | 
			
		||||
  settings.setValue (repeatHotkey, ui->repeatEdit->keySequence ().toString ());
 | 
			
		||||
  settings.setValue (clipboardHotkey, ui->clipboardEdit->keySequence ().toString ());
 | 
			
		||||
  settings.setValue (resultShowType, buttonGroup_->checkedId ());
 | 
			
		||||
  settings.setValue (proxyType, ui->proxyTypeCombo->currentIndex ());
 | 
			
		||||
  settings.setValue (proxyHostName, ui->proxyHostEdit->text ());
 | 
			
		||||
  settings.setValue (proxyPort, ui->proxyPortSpin->value ());
 | 
			
		||||
  settings.setValue (proxyUser, ui->proxyUserEdit->text ());
 | 
			
		||||
  if (ui->proxySaveCheck->isChecked ()) {
 | 
			
		||||
    settings.setValue (proxyPassword, encode (ui->proxyPassEdit->text ()));
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    settings.remove (proxyPassword);
 | 
			
		||||
    QNetworkProxy proxy = QNetworkProxy::applicationProxy ();
 | 
			
		||||
    proxy.setPassword (ui->proxyPassEdit->text ());
 | 
			
		||||
    QNetworkProxy::setApplicationProxy (proxy);
 | 
			
		||||
  }
 | 
			
		||||
  settings.setValue (proxySavePassword, ui->proxySaveCheck->isChecked ());
 | 
			
		||||
  settings.setValue (autoUpdateType, ui->updateCombo->currentIndex ());
 | 
			
		||||
  settings.endGroup ();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  settings.beginGroup (settings_names::recogntionGroup);
 | 
			
		||||
  settings.setValue (settings_names::tessDataPlace, ui->tessdataEdit->text ());
 | 
			
		||||
  QString ocrLanguage = dictionary_.ocrUiToCode (ui->ocrLangCombo->currentText ());
 | 
			
		||||
  settings.setValue (settings_names::ocrLanguage, ocrLanguage);
 | 
			
		||||
  settings.setValue (settings_names::imageScale, ui->imageScaleSpin->value ());
 | 
			
		||||
  settings.beginGroup (recogntionGroup);
 | 
			
		||||
  settings.setValue (tessDataPlace, ui->tessdataEdit->text ());
 | 
			
		||||
  QString ocrLanguageVal = dictionary_.ocrUiToCode (ui->ocrLangCombo->currentText ());
 | 
			
		||||
  settings.setValue (ocrLanguage, ocrLanguageVal);
 | 
			
		||||
  settings.setValue (imageScale, ui->imageScaleSpin->value ());
 | 
			
		||||
 | 
			
		||||
  {  //Recognizer substitutions
 | 
			
		||||
    RecognizerHelper::Subs subs;
 | 
			
		||||
    QTableWidget *t = ui->recognizerFixTable; // Shortcut
 | 
			
		||||
    for (int i = 0, end = t->rowCount () - 1; i < end; ++i) {
 | 
			
		||||
      QComboBox *combo = static_cast<QComboBox *>(t->cellWidget (i, SubsColLanguage));
 | 
			
		||||
      QString langUi = combo->currentText ();
 | 
			
		||||
      RecognizerHelper::Sub sub;
 | 
			
		||||
      sub.language = dictionary_.ocrUiToCode (langUi);
 | 
			
		||||
#define GET(COL) (t->item (i, COL) ? t->item (i, COL)->text () : QString ())
 | 
			
		||||
      sub.source = GET (SubsColSource);
 | 
			
		||||
      sub.target = GET (SubsColTarget);
 | 
			
		||||
#undef GET
 | 
			
		||||
      if (langUi.isEmpty () || sub.language == langUi || sub.source.isEmpty ()) {
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
      subs.append (sub);
 | 
			
		||||
    }
 | 
			
		||||
    recognizerHelper_->setSubs (subs);
 | 
			
		||||
    recognizerHelper_->save ();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  settings.endGroup ();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  settings.beginGroup (settings_names::translationGroup);
 | 
			
		||||
  settings.beginGroup (translationGroup);
 | 
			
		||||
  settings.setValue (doTranslation, ui->doTranslationCheck->isChecked ());
 | 
			
		||||
  settings.setValue (translationDebugMode, ui->translatorDebugCheck->isChecked ());
 | 
			
		||||
  QString trLanguage = dictionary_.translateUiToCode (ui->translateLangCombo->currentText ());
 | 
			
		||||
  settings.setValue (settings_names::translationLanguage, trLanguage);
 | 
			
		||||
  QString sourceLanguage = dictionary_.translateForOcrCode (ocrLanguage);
 | 
			
		||||
  settings.setValue (settings_names::sourceLanguage, sourceLanguage);
 | 
			
		||||
  settings.setValue (translationLanguage, trLanguage);
 | 
			
		||||
  QString sourceLanguageVal = dictionary_.ocrToTranslateCodes (ocrLanguage);
 | 
			
		||||
  settings.setValue (sourceLanguage, sourceLanguageVal);
 | 
			
		||||
  settings.setValue (translationTimeout, ui->translateTimeoutSpin->value ());
 | 
			
		||||
 | 
			
		||||
  {//Translators
 | 
			
		||||
    QStringList enabled;
 | 
			
		||||
    for (int i = 0, end = ui->translatorList->count (); i < end; ++i) {
 | 
			
		||||
      QListWidgetItem *item = ui->translatorList->item (i);
 | 
			
		||||
      if (item->checkState () == Qt::Checked) {
 | 
			
		||||
        enabled << item->text ();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    translatorHelper_->setEnabledTranslators (enabled);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  settings.endGroup ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SettingsEditor::openTessdataDialog()
 | 
			
		||||
{
 | 
			
		||||
void SettingsEditor::openTessdataDialog () {
 | 
			
		||||
  QString path = QFileDialog::getExistingDirectory (this, tr ("Путь к tessdata"));
 | 
			
		||||
  if (path.isEmpty ())
 | 
			
		||||
  {
 | 
			
		||||
  if (path.isEmpty ()) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  QDir dir (path);
 | 
			
		||||
  if (dir.dirName () == QString ("tessdata"))
 | 
			
		||||
  {
 | 
			
		||||
  if (dir.dirName () == QString ("tessdata")) {
 | 
			
		||||
    dir.cdUp ();
 | 
			
		||||
  }
 | 
			
		||||
  ui->tessdataEdit->setText (dir.path ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SettingsEditor::loadSettings()
 | 
			
		||||
{
 | 
			
		||||
void SettingsEditor::loadSettings () {
 | 
			
		||||
#define GET(FIELD) settings.value (settings_names::FIELD, settings_values::FIELD)
 | 
			
		||||
  QSettings settings;
 | 
			
		||||
 | 
			
		||||
  settings.beginGroup (settings_names::guiGroup);
 | 
			
		||||
  ui->captureEdit->setText (GET(captureHotkey).toString ());
 | 
			
		||||
  ui->repeatEdit->setText (GET(repeatHotkey).toString ());
 | 
			
		||||
  ui->clipboardEdit->setText (GET(clipboardHotkey).toString ());
 | 
			
		||||
  QAbstractButton* button = buttonGroup_->button (GET(resultShowType).toInt ());
 | 
			
		||||
  ui->captureEdit->setKeySequence (QKeySequence (GET (captureHotkey).toString ()));
 | 
			
		||||
  ui->repeatCaptureEdit->setKeySequence (QKeySequence (GET (repeatCaptureHotkey).toString ()));
 | 
			
		||||
  ui->repeatEdit->setKeySequence (QKeySequence (GET (repeatHotkey).toString ()));
 | 
			
		||||
  ui->clipboardEdit->setKeySequence (QKeySequence (GET (clipboardHotkey).toString ()));
 | 
			
		||||
  QAbstractButton *button = buttonGroup_->button (GET (resultShowType).toInt ());
 | 
			
		||||
  Q_CHECK_PTR (button);
 | 
			
		||||
  button->setChecked (true);
 | 
			
		||||
  ui->proxyTypeCombo->setCurrentIndex (GET (proxyType).toInt ());
 | 
			
		||||
  ui->proxyHostEdit->setText (GET (proxyHostName).toString ());
 | 
			
		||||
  ui->proxyPortSpin->setValue (GET (proxyPort).toInt ());
 | 
			
		||||
  ui->proxyUserEdit->setText (GET (proxyUser).toString ());
 | 
			
		||||
  ui->proxySaveCheck->setChecked (GET (proxySavePassword).toBool ());
 | 
			
		||||
  if (ui->proxySaveCheck->isChecked ()) {
 | 
			
		||||
    ui->proxyPassEdit->setText (encode (GET (proxyPassword).toString ()));
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    ui->proxyPassEdit->setText (QNetworkProxy::applicationProxy ().password ());
 | 
			
		||||
  }
 | 
			
		||||
  ui->updateCombo->setCurrentIndex (GET (autoUpdateType).toInt ());
 | 
			
		||||
  settings.endGroup ();
 | 
			
		||||
 | 
			
		||||
  settings.beginGroup (settings_names::recogntionGroup);
 | 
			
		||||
  ui->tessdataEdit->setText (GET(tessDataPlace).toString ());
 | 
			
		||||
  QString ocrLanguage = dictionary_.ocrCodeToUi (GET(ocrLanguage).toString ());
 | 
			
		||||
  ui->tessdataEdit->setText (GET (tessDataPlace).toString ());
 | 
			
		||||
  QString ocrLanguage = dictionary_.ocrCodeToUi (GET (ocrLanguage).toString ());
 | 
			
		||||
  ui->ocrLangCombo->setCurrentText (ocrLanguage);
 | 
			
		||||
  ui->imageScaleSpin->setValue (GET(imageScale).toInt ());
 | 
			
		||||
  ui->imageScaleSpin->setValue (GET (imageScale).toInt ());
 | 
			
		||||
 | 
			
		||||
  {//Recognizer substitutions
 | 
			
		||||
    recognizerHelper_->load ();
 | 
			
		||||
    RecognizerHelper::Subs subs = recognizerHelper_->subs ();
 | 
			
		||||
    ui->recognizerFixTable->setRowCount (subs.size ());
 | 
			
		||||
    int row = 0;
 | 
			
		||||
    foreach (const RecognizerHelper::Sub & sub, subs) {
 | 
			
		||||
      if (!initSubsTableRow (row, sub.language)) {
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
      ui->recognizerFixTable->setItem (row, SubsColSource, new QTableWidgetItem (sub.source));
 | 
			
		||||
      ui->recognizerFixTable->setItem (row, SubsColTarget, new QTableWidgetItem (sub.target));
 | 
			
		||||
      ++row;
 | 
			
		||||
    }
 | 
			
		||||
    ui->recognizerFixTable->setRowCount (row + 1);
 | 
			
		||||
    initSubsTableRow (row);
 | 
			
		||||
    ui->recognizerFixTable->resizeColumnsToContents ();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  settings.endGroup ();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  settings.beginGroup (settings_names::translationGroup);
 | 
			
		||||
  QString trLanguage = dictionary_.translateCodeToUi (GET(translationLanguage).toString ());
 | 
			
		||||
  ui->doTranslationCheck->setChecked (GET (doTranslation).toBool ());
 | 
			
		||||
  ui->translatorDebugCheck->setChecked (GET (translationDebugMode).toBool ());
 | 
			
		||||
  QString trLanguage = dictionary_.translateCodeToUi (GET (translationLanguage).toString ());
 | 
			
		||||
  ui->translateLangCombo->setCurrentText (trLanguage);
 | 
			
		||||
  ui->translateTimeoutSpin->setValue (GET (translationTimeout).toInt ());
 | 
			
		||||
 | 
			
		||||
  {// Translators
 | 
			
		||||
    QStringList enabled;
 | 
			
		||||
    ui->translatorList->addItems (translatorHelper_->possibleTranslators (enabled));
 | 
			
		||||
    for (int i = 0, end = ui->translatorList->count (); i < end; ++i) {
 | 
			
		||||
      QListWidgetItem *item = ui->translatorList->item (i);
 | 
			
		||||
      Qt::CheckState state = enabled.contains (item->text ()) ? Qt::Checked : Qt::Unchecked;
 | 
			
		||||
      item->setCheckState (state);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  settings.endGroup ();
 | 
			
		||||
#undef GET
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SettingsEditor::saveState() const
 | 
			
		||||
{
 | 
			
		||||
bool SettingsEditor::initSubsTableRow (int row, const QString &languageCode) {
 | 
			
		||||
  QString lang = dictionary_.ocrCodeToUi (languageCode);
 | 
			
		||||
  if (!languageCode.isEmpty () && lang == languageCode) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  QComboBox *langCombo = new QComboBox (ui->recognizerFixTable);
 | 
			
		||||
  langCombo->setModel (ui->ocrLangCombo->model ());
 | 
			
		||||
  if (!languageCode.isEmpty ()) {
 | 
			
		||||
    langCombo->setCurrentText (lang);
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    langCombo->setCurrentIndex (ui->ocrLangCombo->currentIndex ());
 | 
			
		||||
  }
 | 
			
		||||
  ui->recognizerFixTable->setCellWidget (row, SubsColLanguage, langCombo);
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SettingsEditor::saveState () const {
 | 
			
		||||
  QSettings settings;
 | 
			
		||||
  settings.beginGroup (settings_names::guiGroup);
 | 
			
		||||
  settings.setValue (objectName () + "_" + settings_names::geometry, saveGeometry ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SettingsEditor::loadState()
 | 
			
		||||
{
 | 
			
		||||
void SettingsEditor::loadState () {
 | 
			
		||||
  QSettings settings;
 | 
			
		||||
  settings.beginGroup (settings_names::guiGroup);
 | 
			
		||||
  restoreGeometry (settings.value (objectName () + "_" + settings_names::geometry).toByteArray ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SettingsEditor::initOcrLangCombo(const QString &path)
 | 
			
		||||
{
 | 
			
		||||
void SettingsEditor::initOcrLangCombo (const QString &path) {
 | 
			
		||||
  ui->ocrLangCombo->clear ();
 | 
			
		||||
  ui->ocrLangCombo->addItems (dictionary_.availableOcrLanguagesUi (path));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SettingsEditor::recognizerFixTableItemChanged (QTableWidgetItem *item) {
 | 
			
		||||
  ST_ASSERT (item->column () < 3);
 | 
			
		||||
  int row = item->row ();
 | 
			
		||||
  QTableWidget *t = ui->recognizerFixTable;
 | 
			
		||||
#define CHECK(COL) (!t->item (row, COL) || t->item (row, COL)->text ().isEmpty ())
 | 
			
		||||
  bool isRowEmpty = CHECK (SubsColSource) && CHECK (SubsColTarget);
 | 
			
		||||
#undef CHECK
 | 
			
		||||
  int lastRow = ui->recognizerFixTable->rowCount () - 1;
 | 
			
		||||
  if (isRowEmpty && row != lastRow) {
 | 
			
		||||
    ui->recognizerFixTable->removeRow (row);
 | 
			
		||||
  }
 | 
			
		||||
  else if (!isRowEmpty && row == lastRow) {
 | 
			
		||||
    int newRow = lastRow + 1;
 | 
			
		||||
    ui->recognizerFixTable->insertRow (newRow);
 | 
			
		||||
    initSubsTableRow (newRow);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -5,21 +5,28 @@
 | 
			
		||||
#include <QButtonGroup>
 | 
			
		||||
#include <QMap>
 | 
			
		||||
 | 
			
		||||
class QTableWidgetItem;
 | 
			
		||||
namespace Ui {
 | 
			
		||||
  class SettingsEditor;
 | 
			
		||||
}
 | 
			
		||||
class LanguageHelper;
 | 
			
		||||
class TranslatorHelper;
 | 
			
		||||
class RecognizerHelper;
 | 
			
		||||
 | 
			
		||||
class SettingsEditor : public QDialog
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
class SettingsEditor : public QDialog {
 | 
			
		||||
  Q_OBJECT
 | 
			
		||||
 | 
			
		||||
  enum SubsCol {
 | 
			
		||||
    SubsColLanguage = 0, SubsColSource, SubsColTarget
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    explicit SettingsEditor(const LanguageHelper& dictionary, QWidget *parent = 0);
 | 
			
		||||
    ~SettingsEditor();
 | 
			
		||||
    explicit SettingsEditor (const LanguageHelper &dictionary, QWidget *parent = 0);
 | 
			
		||||
    ~SettingsEditor ();
 | 
			
		||||
 | 
			
		||||
  signals:
 | 
			
		||||
    void settingsEdited ();
 | 
			
		||||
    void updateCheckRequested ();
 | 
			
		||||
 | 
			
		||||
  public slots:
 | 
			
		||||
    void done (int result);
 | 
			
		||||
@ -27,17 +34,21 @@ class SettingsEditor : public QDialog
 | 
			
		||||
  private slots:
 | 
			
		||||
    void saveSettings () const;
 | 
			
		||||
    void openTessdataDialog ();
 | 
			
		||||
    void initOcrLangCombo (const QString& path);
 | 
			
		||||
    void initOcrLangCombo (const QString &path);
 | 
			
		||||
    void recognizerFixTableItemChanged (QTableWidgetItem *item);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    void loadSettings ();
 | 
			
		||||
    void saveState () const;
 | 
			
		||||
    void loadState ();
 | 
			
		||||
    bool initSubsTableRow (int row, const QString &languageCode = QString ());
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    Ui::SettingsEditor *ui;
 | 
			
		||||
    const LanguageHelper& dictionary_;
 | 
			
		||||
    QButtonGroup* buttonGroup_;
 | 
			
		||||
    TranslatorHelper *translatorHelper_;
 | 
			
		||||
    RecognizerHelper *recognizerHelper_;
 | 
			
		||||
    const LanguageHelper &dictionary_;
 | 
			
		||||
    QButtonGroup *buttonGroup_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // SETTINGSEDITOR_H
 | 
			
		||||
 | 
			
		||||
@ -6,213 +6,15 @@
 | 
			
		||||
   <rect>
 | 
			
		||||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>435</width>
 | 
			
		||||
    <height>221</height>
 | 
			
		||||
    <width>553</width>
 | 
			
		||||
    <height>456</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="windowTitle">
 | 
			
		||||
   <string>Настройки</string>
 | 
			
		||||
  </property>
 | 
			
		||||
  <layout class="QGridLayout" name="gridLayout_5">
 | 
			
		||||
   <item row="0" column="0">
 | 
			
		||||
    <widget class="QGroupBox" name="groupBox">
 | 
			
		||||
     <property name="title">
 | 
			
		||||
      <string>Горячие клавиши</string>
 | 
			
		||||
     </property>
 | 
			
		||||
     <layout class="QGridLayout" name="gridLayout">
 | 
			
		||||
      <item row="0" column="0">
 | 
			
		||||
       <widget class="QLabel" name="label">
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string><html><head/><body><p>Сочетание клавиш для перехода в режим захвата.</p></body></html></string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Захватить</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="buddy">
 | 
			
		||||
         <cstring>captureEdit</cstring>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="0" column="1" colspan="2">
 | 
			
		||||
       <widget class="QLineEdit" name="captureEdit"/>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="2" column="0">
 | 
			
		||||
       <widget class="QLabel" name="label_7">
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string><html><head/><body><p>Сочетание клавиш для перехода в режим захвата.</p></body></html></string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Скопировать</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="buddy">
 | 
			
		||||
         <cstring>captureEdit</cstring>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="2" column="1" colspan="2">
 | 
			
		||||
       <widget class="QLineEdit" name="clipboardEdit"/>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="1" column="0">
 | 
			
		||||
       <widget class="QLabel" name="label_3">
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string><html><head/><body><p>Сочетание клавиш для перехода в режим захвата.</p></body></html></string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Повторить</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="buddy">
 | 
			
		||||
         <cstring>captureEdit</cstring>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="1" column="1" colspan="2">
 | 
			
		||||
       <widget class="QLineEdit" name="repeatEdit"/>
 | 
			
		||||
      </item>
 | 
			
		||||
     </layout>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item row="0" column="1">
 | 
			
		||||
    <widget class="QGroupBox" name="groupBox_2">
 | 
			
		||||
     <property name="title">
 | 
			
		||||
      <string>Распознавание</string>
 | 
			
		||||
     </property>
 | 
			
		||||
     <layout class="QGridLayout" name="gridLayout_3">
 | 
			
		||||
      <item row="0" column="0">
 | 
			
		||||
       <widget class="QLabel" name="label_2">
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string><html><head/><body><p>Необходимо для распознавания.</p><p>Скачивается отсюда: <a href="https://code.google.com/p/tesseract-ocr/downloads/list"><span style=" text-decoration: underline; color:#0000ff;">https://code.google.com/p/tesseract-ocr/downloads/list</span></a></p></body></html></string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Путь к tessdata</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="buddy">
 | 
			
		||||
         <cstring>tessdataEdit</cstring>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="0" column="1">
 | 
			
		||||
       <widget class="QLineEdit" name="tessdataEdit"/>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="0" column="2">
 | 
			
		||||
       <widget class="QToolButton" name="tessdataButton">
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>...</string>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="1" column="0">
 | 
			
		||||
       <widget class="QLabel" name="label_4">
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string><html><head/><body><p>Заполняется на основании содержания tessdata</p></body></html></string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Язык распознавания</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="buddy">
 | 
			
		||||
         <cstring>ocrLangCombo</cstring>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="2" column="0">
 | 
			
		||||
       <widget class="QLabel" name="label_5">
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string><html><head/><body><p>Масштабирование изображения для улучшения распознания. Больше - лучше (до определенных пределов), но медленнее.</p></body></html></string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Увеличение масштаба</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="buddy">
 | 
			
		||||
         <cstring>imageScaleSpin</cstring>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="1" column="1" colspan="2">
 | 
			
		||||
       <widget class="QComboBox" name="ocrLangCombo"/>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="2" column="1" colspan="2">
 | 
			
		||||
       <widget class="QSpinBox" name="imageScaleSpin"/>
 | 
			
		||||
      </item>
 | 
			
		||||
     </layout>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item row="0" column="2">
 | 
			
		||||
    <spacer name="horizontalSpacer">
 | 
			
		||||
     <property name="orientation">
 | 
			
		||||
      <enum>Qt::Horizontal</enum>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="sizeHint" stdset="0">
 | 
			
		||||
      <size>
 | 
			
		||||
       <width>0</width>
 | 
			
		||||
       <height>20</height>
 | 
			
		||||
      </size>
 | 
			
		||||
     </property>
 | 
			
		||||
    </spacer>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item row="1" column="0">
 | 
			
		||||
    <widget class="QGroupBox" name="resultGroup">
 | 
			
		||||
     <property name="title">
 | 
			
		||||
      <string>Вывод результата</string>
 | 
			
		||||
     </property>
 | 
			
		||||
     <layout class="QGridLayout" name="gridLayout_4">
 | 
			
		||||
      <item row="0" column="1">
 | 
			
		||||
       <widget class="QRadioButton" name="trayRadio">
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Трей</string>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="0" column="2">
 | 
			
		||||
       <widget class="QRadioButton" name="dialogRadio">
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Окно</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="checked">
 | 
			
		||||
         <bool>true</bool>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
     </layout>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item row="1" column="1">
 | 
			
		||||
    <widget class="QGroupBox" name="groupBox_3">
 | 
			
		||||
     <property name="title">
 | 
			
		||||
      <string>Перевод</string>
 | 
			
		||||
     </property>
 | 
			
		||||
     <layout class="QGridLayout" name="gridLayout_2">
 | 
			
		||||
      <item row="0" column="0">
 | 
			
		||||
       <widget class="QLabel" name="label_6">
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string><html><head/><body><p>Язык, на который осуществляется перевод.</p></body></html></string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Язык результата</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="buddy">
 | 
			
		||||
         <cstring>translateLangCombo</cstring>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="0" column="1">
 | 
			
		||||
       <widget class="QComboBox" name="translateLangCombo"/>
 | 
			
		||||
      </item>
 | 
			
		||||
     </layout>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item row="2" column="0">
 | 
			
		||||
    <spacer name="verticalSpacer">
 | 
			
		||||
     <property name="orientation">
 | 
			
		||||
      <enum>Qt::Vertical</enum>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="sizeHint" stdset="0">
 | 
			
		||||
      <size>
 | 
			
		||||
       <width>20</width>
 | 
			
		||||
       <height>1</height>
 | 
			
		||||
      </size>
 | 
			
		||||
     </property>
 | 
			
		||||
    </spacer>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item row="3" column="1">
 | 
			
		||||
  <layout class="QGridLayout" name="gridLayout_6">
 | 
			
		||||
   <item row="1" column="0" colspan="2">
 | 
			
		||||
    <widget class="QDialogButtonBox" name="buttonBox">
 | 
			
		||||
     <property name="orientation">
 | 
			
		||||
      <enum>Qt::Horizontal</enum>
 | 
			
		||||
@ -222,16 +24,459 @@
 | 
			
		||||
     </property>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item row="0" column="0" colspan="2">
 | 
			
		||||
    <widget class="QTabWidget" name="tabWidget">
 | 
			
		||||
     <property name="currentIndex">
 | 
			
		||||
      <number>0</number>
 | 
			
		||||
     </property>
 | 
			
		||||
     <widget class="QWidget" name="commonTab">
 | 
			
		||||
      <attribute name="title">
 | 
			
		||||
       <string>Общее</string>
 | 
			
		||||
      </attribute>
 | 
			
		||||
      <layout class="QGridLayout" name="gridLayout_8">
 | 
			
		||||
       <item row="0" column="0">
 | 
			
		||||
        <widget class="QGroupBox" name="groupBox">
 | 
			
		||||
         <property name="title">
 | 
			
		||||
          <string>Горячие клавиши</string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <layout class="QGridLayout" name="gridLayout">
 | 
			
		||||
          <item row="0" column="0">
 | 
			
		||||
           <widget class="QLabel" name="label">
 | 
			
		||||
            <property name="toolTip">
 | 
			
		||||
             <string><html><head/><body><p>Сочетание клавиш для перехода в режим захвата.</p></body></html></string>
 | 
			
		||||
            </property>
 | 
			
		||||
            <property name="text">
 | 
			
		||||
             <string>Захватить</string>
 | 
			
		||||
            </property>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="0" column="1">
 | 
			
		||||
           <widget class="QKeySequenceEdit" name="captureEdit"/>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="1" column="0">
 | 
			
		||||
           <widget class="QLabel" name="label_8">
 | 
			
		||||
            <property name="toolTip">
 | 
			
		||||
             <string><html><head/><body><p>Сочетание клавиш для перехода в режим захвата, но с использованием последнего использованного, а не текущего, изображения.</p></body></html></string>
 | 
			
		||||
            </property>
 | 
			
		||||
            <property name="text">
 | 
			
		||||
             <string>Захватить повторно</string>
 | 
			
		||||
            </property>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="1" column="1">
 | 
			
		||||
           <widget class="QKeySequenceEdit" name="repeatCaptureEdit"/>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="2" column="0">
 | 
			
		||||
           <widget class="QLabel" name="label_3">
 | 
			
		||||
            <property name="toolTip">
 | 
			
		||||
             <string><html><head/><body><p>Сочетание клавиш для повторного отображения последнего результата.</p></body></html></string>
 | 
			
		||||
            </property>
 | 
			
		||||
            <property name="text">
 | 
			
		||||
             <string>Показать</string>
 | 
			
		||||
            </property>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="2" column="1">
 | 
			
		||||
           <widget class="QKeySequenceEdit" name="repeatEdit"/>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="3" column="0">
 | 
			
		||||
           <widget class="QLabel" name="label_7">
 | 
			
		||||
            <property name="toolTip">
 | 
			
		||||
             <string><html><head/><body><p>Сочетание клавиш для копирования последнего результата в буфер обмена.</p></body></html></string>
 | 
			
		||||
            </property>
 | 
			
		||||
            <property name="text">
 | 
			
		||||
             <string>Скопировать</string>
 | 
			
		||||
            </property>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="3" column="1">
 | 
			
		||||
           <widget class="QKeySequenceEdit" name="clipboardEdit"/>
 | 
			
		||||
          </item>
 | 
			
		||||
         </layout>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="1" column="0">
 | 
			
		||||
        <widget class="QGroupBox" name="groupBox_2">
 | 
			
		||||
         <property name="title">
 | 
			
		||||
          <string>Прокси</string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <layout class="QGridLayout" name="gridLayout_3">
 | 
			
		||||
          <item row="0" column="0">
 | 
			
		||||
           <widget class="QLabel" name="label_12">
 | 
			
		||||
            <property name="text">
 | 
			
		||||
             <string>Тип:</string>
 | 
			
		||||
            </property>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="0" column="1">
 | 
			
		||||
           <widget class="QComboBox" name="proxyTypeCombo"/>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="0" column="2">
 | 
			
		||||
           <widget class="QLabel" name="label_15">
 | 
			
		||||
            <property name="text">
 | 
			
		||||
             <string>Пользователь:</string>
 | 
			
		||||
            </property>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="0" column="3">
 | 
			
		||||
           <widget class="QLineEdit" name="proxyUserEdit"/>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="1" column="0">
 | 
			
		||||
           <widget class="QLabel" name="label_13">
 | 
			
		||||
            <property name="text">
 | 
			
		||||
             <string>Адрес:</string>
 | 
			
		||||
            </property>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="1" column="1">
 | 
			
		||||
           <widget class="QLineEdit" name="proxyHostEdit"/>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="1" column="2">
 | 
			
		||||
           <widget class="QLabel" name="label_16">
 | 
			
		||||
            <property name="text">
 | 
			
		||||
             <string>Пароль:</string>
 | 
			
		||||
            </property>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="1" column="3">
 | 
			
		||||
           <widget class="QLineEdit" name="proxyPassEdit"/>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="2" column="0">
 | 
			
		||||
           <widget class="QLabel" name="label_14">
 | 
			
		||||
            <property name="text">
 | 
			
		||||
             <string>Порт:</string>
 | 
			
		||||
            </property>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="2" column="1">
 | 
			
		||||
           <widget class="QSpinBox" name="proxyPortSpin">
 | 
			
		||||
            <property name="minimum">
 | 
			
		||||
             <number>1</number>
 | 
			
		||||
            </property>
 | 
			
		||||
            <property name="maximum">
 | 
			
		||||
             <number>65535</number>
 | 
			
		||||
            </property>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="2" column="2" colspan="2">
 | 
			
		||||
           <widget class="QCheckBox" name="proxySaveCheck">
 | 
			
		||||
            <property name="text">
 | 
			
		||||
             <string>Сохранять пароль (небезопасно)</string>
 | 
			
		||||
            </property>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
         </layout>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="2" column="0">
 | 
			
		||||
        <layout class="QHBoxLayout" name="horizontalLayout">
 | 
			
		||||
         <item>
 | 
			
		||||
          <widget class="QGroupBox" name="resultGroup">
 | 
			
		||||
           <property name="sizePolicy">
 | 
			
		||||
            <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
 | 
			
		||||
             <horstretch>0</horstretch>
 | 
			
		||||
             <verstretch>0</verstretch>
 | 
			
		||||
            </sizepolicy>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="title">
 | 
			
		||||
            <string>Вывод результата</string>
 | 
			
		||||
           </property>
 | 
			
		||||
           <layout class="QGridLayout" name="gridLayout_4">
 | 
			
		||||
            <item row="0" column="0">
 | 
			
		||||
             <widget class="QRadioButton" name="trayRadio">
 | 
			
		||||
              <property name="sizePolicy">
 | 
			
		||||
               <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
 | 
			
		||||
                <horstretch>0</horstretch>
 | 
			
		||||
                <verstretch>0</verstretch>
 | 
			
		||||
               </sizepolicy>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="text">
 | 
			
		||||
               <string>Трей</string>
 | 
			
		||||
              </property>
 | 
			
		||||
             </widget>
 | 
			
		||||
            </item>
 | 
			
		||||
            <item row="0" column="1">
 | 
			
		||||
             <widget class="QRadioButton" name="dialogRadio">
 | 
			
		||||
              <property name="sizePolicy">
 | 
			
		||||
               <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
 | 
			
		||||
                <horstretch>0</horstretch>
 | 
			
		||||
                <verstretch>0</verstretch>
 | 
			
		||||
               </sizepolicy>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="text">
 | 
			
		||||
               <string>Окно</string>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="checked">
 | 
			
		||||
               <bool>true</bool>
 | 
			
		||||
              </property>
 | 
			
		||||
             </widget>
 | 
			
		||||
            </item>
 | 
			
		||||
           </layout>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item>
 | 
			
		||||
          <widget class="QGroupBox" name="groupBox_3">
 | 
			
		||||
           <property name="title">
 | 
			
		||||
            <string>Обновление</string>
 | 
			
		||||
           </property>
 | 
			
		||||
           <layout class="QGridLayout" name="gridLayout_5">
 | 
			
		||||
            <item row="0" column="0">
 | 
			
		||||
             <widget class="QLabel" name="label_17">
 | 
			
		||||
              <property name="text">
 | 
			
		||||
               <string>Проверять обновления:</string>
 | 
			
		||||
              </property>
 | 
			
		||||
             </widget>
 | 
			
		||||
            </item>
 | 
			
		||||
            <item row="0" column="1">
 | 
			
		||||
             <widget class="QComboBox" name="updateCombo"/>
 | 
			
		||||
            </item>
 | 
			
		||||
            <item row="0" column="2">
 | 
			
		||||
             <widget class="QPushButton" name="updateButton">
 | 
			
		||||
              <property name="sizePolicy">
 | 
			
		||||
               <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
 | 
			
		||||
                <horstretch>0</horstretch>
 | 
			
		||||
                <verstretch>0</verstretch>
 | 
			
		||||
               </sizepolicy>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="text">
 | 
			
		||||
               <string>Проверить</string>
 | 
			
		||||
              </property>
 | 
			
		||||
             </widget>
 | 
			
		||||
            </item>
 | 
			
		||||
           </layout>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
        </layout>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="3" column="0">
 | 
			
		||||
        <spacer name="verticalSpacer">
 | 
			
		||||
         <property name="orientation">
 | 
			
		||||
          <enum>Qt::Vertical</enum>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="sizeHint" stdset="0">
 | 
			
		||||
          <size>
 | 
			
		||||
           <width>20</width>
 | 
			
		||||
           <height>270</height>
 | 
			
		||||
          </size>
 | 
			
		||||
         </property>
 | 
			
		||||
        </spacer>
 | 
			
		||||
       </item>
 | 
			
		||||
      </layout>
 | 
			
		||||
     </widget>
 | 
			
		||||
     <widget class="QWidget" name="recognizeTab">
 | 
			
		||||
      <attribute name="title">
 | 
			
		||||
       <string>Распознавание</string>
 | 
			
		||||
      </attribute>
 | 
			
		||||
      <layout class="QGridLayout" name="gridLayout_2">
 | 
			
		||||
       <item row="0" column="0">
 | 
			
		||||
        <widget class="QLabel" name="label_2">
 | 
			
		||||
         <property name="toolTip">
 | 
			
		||||
          <string><html><head/><body><p>Необходимо для распознавания.</p><p>Скачивается отсюда: <a href="https://github.com/tesseract-ocr/tessdata"><span style=" text-decoration: underline; color:#7593bc;">https://github.com/tesseract-ocr/tessdata</span></a></p><p>&quot;./&quot; означает, что папка &quot;tessdata&quot; находится в одной директории с исполняемым файлом программы.</p></body></html></string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Путь к tessdata</string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="buddy">
 | 
			
		||||
          <cstring>tessdataEdit</cstring>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="0" column="1">
 | 
			
		||||
        <widget class="QLineEdit" name="tessdataEdit"/>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="0" column="2">
 | 
			
		||||
        <widget class="QToolButton" name="tessdataButton">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>...</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="1" column="0">
 | 
			
		||||
        <widget class="QLabel" name="label_4">
 | 
			
		||||
         <property name="toolTip">
 | 
			
		||||
          <string><html><head/><body><p>Заполняется на основании содержания tessdata</p></body></html></string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Язык распознавания</string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="buddy">
 | 
			
		||||
          <cstring>ocrLangCombo</cstring>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="1" column="1" colspan="2">
 | 
			
		||||
        <widget class="QComboBox" name="ocrLangCombo"/>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="2" column="0">
 | 
			
		||||
        <widget class="QLabel" name="label_5">
 | 
			
		||||
         <property name="toolTip">
 | 
			
		||||
          <string><html><head/><body><p>Масштабирование изображения для улучшения распознания. Больше - лучше (до определенных пределов), но медленнее и потребляет больше памяти.</p><p>Рекомендуемые значения от 5 до 10.</p></body></html></string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Увеличение масштаба</string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="buddy">
 | 
			
		||||
          <cstring>imageScaleSpin</cstring>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="2" column="1" colspan="2">
 | 
			
		||||
        <widget class="QSpinBox" name="imageScaleSpin"/>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="3" column="0" colspan="3">
 | 
			
		||||
        <widget class="QLabel" name="label_11">
 | 
			
		||||
         <property name="toolTip">
 | 
			
		||||
          <string><html><head/><body><p>Символы, регулярно распознаваемые с ошибками. При обнаружении будут заменены на указанные.</p></body></html></string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Исправления:</string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="alignment">
 | 
			
		||||
          <set>Qt::AlignCenter</set>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="4" column="0" colspan="3">
 | 
			
		||||
        <widget class="QTableWidget" name="recognizerFixTable">
 | 
			
		||||
         <property name="selectionBehavior">
 | 
			
		||||
          <enum>QAbstractItemView::SelectRows</enum>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="sortingEnabled">
 | 
			
		||||
          <bool>true</bool>
 | 
			
		||||
         </property>
 | 
			
		||||
         <column>
 | 
			
		||||
          <property name="text">
 | 
			
		||||
           <string>Язык</string>
 | 
			
		||||
          </property>
 | 
			
		||||
         </column>
 | 
			
		||||
         <column>
 | 
			
		||||
          <property name="text">
 | 
			
		||||
           <string>Исходный текст</string>
 | 
			
		||||
          </property>
 | 
			
		||||
         </column>
 | 
			
		||||
         <column>
 | 
			
		||||
          <property name="text">
 | 
			
		||||
           <string>Исправление</string>
 | 
			
		||||
          </property>
 | 
			
		||||
         </column>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
      </layout>
 | 
			
		||||
     </widget>
 | 
			
		||||
     <widget class="QWidget" name="translateTab">
 | 
			
		||||
      <attribute name="title">
 | 
			
		||||
       <string>Перевод</string>
 | 
			
		||||
      </attribute>
 | 
			
		||||
      <layout class="QGridLayout" name="gridLayout_7">
 | 
			
		||||
       <item row="0" column="0">
 | 
			
		||||
        <widget class="QCheckBox" name="doTranslationCheck">
 | 
			
		||||
         <property name="toolTip">
 | 
			
		||||
          <string><html><head/><body><p>Необходимо ли переводить (вкл) распознанный текст.</p></body></html></string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Переводить текст</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="0" column="1" colspan="2">
 | 
			
		||||
        <widget class="QCheckBox" name="translatorDebugCheck">
 | 
			
		||||
         <property name="toolTip">
 | 
			
		||||
          <string><html><head/><body><p>Отображает окно переводчика. Следует использовать только для разработки переводчиков.</p></body></html></string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Режим отладки</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="1" column="0">
 | 
			
		||||
        <widget class="QLabel" name="label_9">
 | 
			
		||||
         <property name="toolTip">
 | 
			
		||||
          <string><html><head/><body><p>Максимальное время, которое может быть затрачено на перевод, чтобы он не считался &quot;зависшим&quot;.</p></body></html></string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Максимальное время перевода:</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="2" column="0">
 | 
			
		||||
        <widget class="QLabel" name="label_6">
 | 
			
		||||
         <property name="toolTip">
 | 
			
		||||
          <string><html><head/><body><p>Язык, на который осуществляется перевод.</p></body></html></string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Язык результата:</string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="buddy">
 | 
			
		||||
          <cstring>translateLangCombo</cstring>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="3" column="0" colspan="3">
 | 
			
		||||
        <widget class="QLabel" name="label_10">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Переводчики:</string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="alignment">
 | 
			
		||||
          <set>Qt::AlignCenter</set>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="2" column="1" colspan="2">
 | 
			
		||||
        <widget class="QComboBox" name="translateLangCombo"/>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="1" column="1" colspan="2">
 | 
			
		||||
        <widget class="QSpinBox" name="translateTimeoutSpin">
 | 
			
		||||
         <property name="suffix">
 | 
			
		||||
          <string> сек.</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="4" column="0" colspan="3">
 | 
			
		||||
        <widget class="QListWidget" name="translatorList">
 | 
			
		||||
         <property name="toolTip">
 | 
			
		||||
          <string><html><head/><body><p>Отображены в порядке убывания приоритета.</p></body></html></string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="editTriggers">
 | 
			
		||||
          <set>QAbstractItemView::NoEditTriggers</set>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="dragDropMode">
 | 
			
		||||
          <enum>QAbstractItemView::InternalMove</enum>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="defaultDropAction">
 | 
			
		||||
          <enum>Qt::MoveAction</enum>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
      </layout>
 | 
			
		||||
     </widget>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
  </layout>
 | 
			
		||||
 </widget>
 | 
			
		||||
 <tabstops>
 | 
			
		||||
  <tabstop>tabWidget</tabstop>
 | 
			
		||||
  <tabstop>captureEdit</tabstop>
 | 
			
		||||
  <tabstop>translateLangCombo</tabstop>
 | 
			
		||||
  <tabstop>repeatCaptureEdit</tabstop>
 | 
			
		||||
  <tabstop>repeatEdit</tabstop>
 | 
			
		||||
  <tabstop>clipboardEdit</tabstop>
 | 
			
		||||
  <tabstop>trayRadio</tabstop>
 | 
			
		||||
  <tabstop>dialogRadio</tabstop>
 | 
			
		||||
  <tabstop>proxyTypeCombo</tabstop>
 | 
			
		||||
  <tabstop>proxyHostEdit</tabstop>
 | 
			
		||||
  <tabstop>proxyPortSpin</tabstop>
 | 
			
		||||
  <tabstop>proxyUserEdit</tabstop>
 | 
			
		||||
  <tabstop>proxyPassEdit</tabstop>
 | 
			
		||||
  <tabstop>proxySaveCheck</tabstop>
 | 
			
		||||
  <tabstop>tessdataEdit</tabstop>
 | 
			
		||||
  <tabstop>tessdataButton</tabstop>
 | 
			
		||||
  <tabstop>ocrLangCombo</tabstop>
 | 
			
		||||
  <tabstop>imageScaleSpin</tabstop>
 | 
			
		||||
  <tabstop>buttonBox</tabstop>
 | 
			
		||||
  <tabstop>recognizerFixTable</tabstop>
 | 
			
		||||
  <tabstop>doTranslationCheck</tabstop>
 | 
			
		||||
  <tabstop>translatorDebugCheck</tabstop>
 | 
			
		||||
  <tabstop>translateTimeoutSpin</tabstop>
 | 
			
		||||
  <tabstop>translateLangCombo</tabstop>
 | 
			
		||||
  <tabstop>translatorList</tabstop>
 | 
			
		||||
 </tabstops>
 | 
			
		||||
 <resources/>
 | 
			
		||||
 <connections>
 | 
			
		||||
@ -242,8 +487,8 @@
 | 
			
		||||
   <slot>accept()</slot>
 | 
			
		||||
   <hints>
 | 
			
		||||
    <hint type="sourcelabel">
 | 
			
		||||
     <x>248</x>
 | 
			
		||||
     <y>254</y>
 | 
			
		||||
     <x>256</x>
 | 
			
		||||
     <y>447</y>
 | 
			
		||||
    </hint>
 | 
			
		||||
    <hint type="destinationlabel">
 | 
			
		||||
     <x>157</x>
 | 
			
		||||
@ -258,8 +503,8 @@
 | 
			
		||||
   <slot>reject()</slot>
 | 
			
		||||
   <hints>
 | 
			
		||||
    <hint type="sourcelabel">
 | 
			
		||||
     <x>316</x>
 | 
			
		||||
     <y>260</y>
 | 
			
		||||
     <x>324</x>
 | 
			
		||||
     <y>447</y>
 | 
			
		||||
    </hint>
 | 
			
		||||
    <hint type="destinationlabel">
 | 
			
		||||
     <x>286</x>
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@
 | 
			
		||||
#  if defined(ST_NO_ASSERT)
 | 
			
		||||
#    define ST_ASSERT(CONDITION)
 | 
			
		||||
#  else
 | 
			
		||||
#    define ST_ASSERT(CONDITION) assert(CONDITION)
 | 
			
		||||
#    define ST_ASSERT(CONDITION) assert (CONDITION)
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										121
									
								
								Translator.cpp
									
									
									
									
									
								
							
							
						
						@ -1,121 +0,0 @@
 | 
			
		||||
#include "Translator.h"
 | 
			
		||||
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QNetworkRequest>
 | 
			
		||||
#include <QNetworkReply>
 | 
			
		||||
#include <QJsonDocument>
 | 
			
		||||
#include <QJsonArray>
 | 
			
		||||
#include <QJsonParseError>
 | 
			
		||||
#include <QSettings>
 | 
			
		||||
 | 
			
		||||
#include "Settings.h"
 | 
			
		||||
#include "GoogleWebTranslator.h"
 | 
			
		||||
#include "StAssert.h"
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
  const QString translateBaseUrl = "http://translate.google.com/translate_a/"
 | 
			
		||||
                                   "t?client=t&text=%1&sl=%2&tl=%3";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Translator::Translator(QObject *parent) :
 | 
			
		||||
  QObject(parent),
 | 
			
		||||
  network_ (this),
 | 
			
		||||
  useAlternativeTranslation_ (false)
 | 
			
		||||
{
 | 
			
		||||
  connect (&network_, SIGNAL (finished (QNetworkReply*)),
 | 
			
		||||
           SLOT (replyFinished (QNetworkReply*)));
 | 
			
		||||
 | 
			
		||||
  GoogleWebTranslator* googleWeb = new GoogleWebTranslator;
 | 
			
		||||
  connect (this, SIGNAL (translateAlternative (ProcessingItem)),
 | 
			
		||||
           googleWeb, SLOT (translate (ProcessingItem)));
 | 
			
		||||
  connect (googleWeb, SIGNAL (translated (ProcessingItem, bool)),
 | 
			
		||||
           this, SLOT (translatedAlternative(ProcessingItem, bool)));
 | 
			
		||||
  connect (googleWeb, SIGNAL (error (QString)), this, SIGNAL (error (QString)));
 | 
			
		||||
 | 
			
		||||
  applySettings ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Translator::applySettings()
 | 
			
		||||
{
 | 
			
		||||
  QSettings settings;
 | 
			
		||||
  settings.beginGroup (settings_names::translationGroup);
 | 
			
		||||
  translationLanguage_ = settings.value (settings_names::translationLanguage,
 | 
			
		||||
                                         settings_values::translationLanguage).toString ();
 | 
			
		||||
  sourceLanguage_ = settings.value (settings_names::sourceLanguage,
 | 
			
		||||
                                    settings_values::sourceLanguage).toString ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Translator::translate(ProcessingItem item)
 | 
			
		||||
{
 | 
			
		||||
  if (useAlternativeTranslation_) {
 | 
			
		||||
    emit translateAlternative(item);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  ST_ASSERT (!item.recognized.isEmpty ());
 | 
			
		||||
  QString sourceLanguage = item.sourceLanguage.isEmpty () ? sourceLanguage_ :
 | 
			
		||||
                                                            item.sourceLanguage;
 | 
			
		||||
  if (translationLanguage_.isEmpty () || sourceLanguage.isEmpty ())
 | 
			
		||||
  {
 | 
			
		||||
    emit error (tr ("Неверные парметры для перевода."));
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  QUrl url (translateBaseUrl.arg (item.recognized, sourceLanguage, translationLanguage_));
 | 
			
		||||
  QNetworkReply* reply = network_.get (QNetworkRequest (url));
 | 
			
		||||
  items_.insert (reply, item);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Translator::translatedAlternative(ProcessingItem item, bool success)
 | 
			
		||||
{
 | 
			
		||||
  if (success)
 | 
			
		||||
  {
 | 
			
		||||
    emit translated(item);
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    emit error (tr ("Ошибка альтернативного перевода текста: %1").arg (item.recognized));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Translator::replyFinished(QNetworkReply* reply)
 | 
			
		||||
{
 | 
			
		||||
  ST_ASSERT (items_.contains (reply));
 | 
			
		||||
  ProcessingItem item = items_.take (reply);
 | 
			
		||||
  ST_ASSERT (reply->isFinished ());
 | 
			
		||||
  if (reply->error () != QNetworkReply::NoError)
 | 
			
		||||
  {
 | 
			
		||||
    useAlternativeTranslation_ = true;
 | 
			
		||||
    emit translateAlternative(item);
 | 
			
		||||
    reply->deleteLater ();
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  QByteArray data = reply->readAll ();
 | 
			
		||||
  reply->deleteLater ();
 | 
			
		||||
 | 
			
		||||
  while (data.indexOf (",,") != -1)//make json valid
 | 
			
		||||
  {
 | 
			
		||||
    data.replace (",,", ",");
 | 
			
		||||
  }
 | 
			
		||||
  QJsonParseError parseError;
 | 
			
		||||
  QJsonDocument document = QJsonDocument::fromJson (data, &parseError);
 | 
			
		||||
  if (document.isEmpty ())
 | 
			
		||||
  {
 | 
			
		||||
    useAlternativeTranslation_ = true;
 | 
			
		||||
    emit translateAlternative(item);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  QJsonArray answerArray = document.array ();
 | 
			
		||||
  QJsonArray fullTranslation = answerArray.first ().toArray ();
 | 
			
		||||
  QString translation = "";
 | 
			
		||||
  foreach (QJsonValue part, fullTranslation)
 | 
			
		||||
  {
 | 
			
		||||
    QJsonArray partTranslation = part.toArray ();
 | 
			
		||||
    if (partTranslation.isEmpty ())
 | 
			
		||||
    {
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    translation += partTranslation.at (0).toString ();
 | 
			
		||||
  }
 | 
			
		||||
  item.translated = translation;
 | 
			
		||||
  emit translated (item);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								Translator.h
									
									
									
									
									
								
							
							
						
						@ -1,36 +0,0 @@
 | 
			
		||||
#ifndef TRANSLATOR_H
 | 
			
		||||
#define TRANSLATOR_H
 | 
			
		||||
 | 
			
		||||
#include <QNetworkAccessManager>
 | 
			
		||||
 | 
			
		||||
#include "ProcessingItem.h"
 | 
			
		||||
 | 
			
		||||
class Translator : public QObject
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
  public:
 | 
			
		||||
    explicit Translator(QObject *parent = 0);
 | 
			
		||||
 | 
			
		||||
  signals:
 | 
			
		||||
    void translated (ProcessingItem item);
 | 
			
		||||
    void translateAlternative (ProcessingItem item);
 | 
			
		||||
    void error (QString text);
 | 
			
		||||
 | 
			
		||||
  public slots:
 | 
			
		||||
    void translate (ProcessingItem item);
 | 
			
		||||
    void translatedAlternative (ProcessingItem item, bool success);
 | 
			
		||||
    void applySettings ();
 | 
			
		||||
 | 
			
		||||
  private slots:
 | 
			
		||||
    void replyFinished (QNetworkReply* reply);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    QNetworkAccessManager network_;
 | 
			
		||||
    QString translationLanguage_;
 | 
			
		||||
    QString sourceLanguage_;
 | 
			
		||||
    QHash<QNetworkReply*, ProcessingItem> items_;
 | 
			
		||||
    bool useAlternativeTranslation_;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // TRANSLATOR_H
 | 
			
		||||
							
								
								
									
										76
									
								
								TranslatorHelper.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,76 @@
 | 
			
		||||
#include <QSettings>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
#include <QFile>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
 | 
			
		||||
#include "TranslatorHelper.h"
 | 
			
		||||
#include "Settings.h"
 | 
			
		||||
 | 
			
		||||
TranslatorHelper::TranslatorHelper ()
 | 
			
		||||
  : translatorsDir_ ("translators"), currentIndex_ (0) {
 | 
			
		||||
  translatorsDir_ = QApplication::applicationDirPath () + QDir::separator () + translatorsDir_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TranslatorHelper::setEnabledTranslators (const QStringList &enabled) const {
 | 
			
		||||
  QSettings settings;
 | 
			
		||||
  settings.beginGroup (settings_names::translationGroup);
 | 
			
		||||
  settings.setValue (settings_names::translators, enabled.join ("|"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList TranslatorHelper::possibleTranslators (QStringList &enabled) const {
 | 
			
		||||
#define GET(FIELD) settings.value (settings_names::FIELD, settings_values::FIELD)
 | 
			
		||||
  QSettings settings;
 | 
			
		||||
  settings.beginGroup (settings_names::translationGroup);
 | 
			
		||||
  QStringList exist = QDir (translatorsDir_).entryList (QStringList () << "*.js", QDir::Files);
 | 
			
		||||
  QStringList saved = GET (translators).toString ().split ("|", QString::SkipEmptyParts);
 | 
			
		||||
  QStringList on, off;
 | 
			
		||||
  std::copy_if (saved.begin (), saved.end (), std::back_inserter (on), [&](const QString &i) {
 | 
			
		||||
    return exist.contains (i);
 | 
			
		||||
  });
 | 
			
		||||
  on = on.isEmpty () ? exist : on;
 | 
			
		||||
 | 
			
		||||
  std::copy_if (exist.begin (), exist.end (), std::back_inserter (off), [&](const QString &i) {
 | 
			
		||||
    return !on.contains (i);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  enabled = on;
 | 
			
		||||
  return (on + off);
 | 
			
		||||
#undef GET
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList TranslatorHelper::enabledTranslatorScripts () const {
 | 
			
		||||
  QStringList enabled;
 | 
			
		||||
  possibleTranslators (enabled);
 | 
			
		||||
  QStringList scripts;
 | 
			
		||||
  foreach (const QString &name, enabled) {
 | 
			
		||||
    QFile f (translatorsDir_ + QDir::separator () + name);
 | 
			
		||||
    if (f.open (QFile::ReadOnly)) {
 | 
			
		||||
      QString script = QString::fromUtf8 (f.readAll ());
 | 
			
		||||
      if (!script.isEmpty ()) {
 | 
			
		||||
        scripts << script;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return scripts;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TranslatorHelper::loadScripts () {
 | 
			
		||||
  scripts_ = enabledTranslatorScripts ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TranslatorHelper::newItem () {
 | 
			
		||||
  currentIndex_ = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString TranslatorHelper::currentScript () const {
 | 
			
		||||
  return (currentIndex_ < scripts_.size () ? scripts_.at (currentIndex_) : QString ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString TranslatorHelper::nextScript () {
 | 
			
		||||
  ++currentIndex_;
 | 
			
		||||
  return currentScript ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool TranslatorHelper::gotScripts () const {
 | 
			
		||||
  return !scripts_.isEmpty ();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								TranslatorHelper.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,27 @@
 | 
			
		||||
#ifndef TRANSLATORHELPER_H
 | 
			
		||||
#define TRANSLATORHELPER_H
 | 
			
		||||
 | 
			
		||||
#include <QStringList>
 | 
			
		||||
 | 
			
		||||
class TranslatorHelper {
 | 
			
		||||
  public:
 | 
			
		||||
    TranslatorHelper ();
 | 
			
		||||
 | 
			
		||||
    QStringList possibleTranslators (QStringList &enabled) const;
 | 
			
		||||
    QStringList enabledTranslatorScripts () const;
 | 
			
		||||
 | 
			
		||||
    void setEnabledTranslators (const QStringList &enabled) const;
 | 
			
		||||
 | 
			
		||||
    void loadScripts ();
 | 
			
		||||
    void newItem ();
 | 
			
		||||
    QString currentScript () const;
 | 
			
		||||
    QString nextScript ();
 | 
			
		||||
    bool gotScripts () const;
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    QString translatorsDir_;
 | 
			
		||||
    QStringList scripts_;
 | 
			
		||||
    int currentIndex_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // TRANSLATORHELPER_H
 | 
			
		||||
							
								
								
									
										264
									
								
								Updater.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,264 @@
 | 
			
		||||
#include <QDir>
 | 
			
		||||
#include <QFile>
 | 
			
		||||
#include <QJsonDocument>
 | 
			
		||||
#include <QJsonArray>
 | 
			
		||||
#include <QNetworkRequest>
 | 
			
		||||
#include <QNetworkReply>
 | 
			
		||||
#include <QMessageBox>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
 | 
			
		||||
#include "Updater.h"
 | 
			
		||||
#include "StAssert.h"
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
#define FIELD(NAME) const QString _ ## NAME = #NAME
 | 
			
		||||
  FIELD (Application);
 | 
			
		||||
 | 
			
		||||
  FIELD (name);
 | 
			
		||||
  FIELD (version);
 | 
			
		||||
  FIELD (compatibleVersion);
 | 
			
		||||
  FIELD (built_in);
 | 
			
		||||
  FIELD (versionString);
 | 
			
		||||
  FIELD (permissions);
 | 
			
		||||
  FIELD (url);
 | 
			
		||||
  FIELD (path);
 | 
			
		||||
#undef FIELD
 | 
			
		||||
 | 
			
		||||
#if defined(Q_OS_WIN)
 | 
			
		||||
  const QString _platform = "_win";
 | 
			
		||||
#elif defined(Q_OS_LINUX)
 | 
			
		||||
  const QString _platform = "_linux";
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  QString versionField (const QJsonObject &component, const QString &field) {
 | 
			
		||||
    return component.contains (field + _platform)
 | 
			
		||||
           ? component[field + _platform].toVariant ().toString ()
 | 
			
		||||
           : component[field].toVariant ().toString ();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  QFileInfo fileDir (const QString &fileName) {
 | 
			
		||||
    return QFileInfo (fileName).absolutePath ();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Updater::Updater (QObject *parent)
 | 
			
		||||
  : QObject (parent),
 | 
			
		||||
  network_ (new QNetworkAccessManager (this)),
 | 
			
		||||
  componentsUpdating_ (0) {
 | 
			
		||||
  updatesFileName_ = QApplication::applicationDirPath () + QDir::separator () + "updates.json";
 | 
			
		||||
  backupSuffix_ = "_backup";
 | 
			
		||||
  connect (network_, SIGNAL (finished (QNetworkReply *)),
 | 
			
		||||
           SLOT (replyFinished (QNetworkReply *)));
 | 
			
		||||
 | 
			
		||||
  getCurrentVersion ();
 | 
			
		||||
  updateCurrentVersion ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QDateTime Updater::nextCheckTime (const QDateTime &lastCheckTime, int updateType) const {
 | 
			
		||||
  QDateTime nextTime;
 | 
			
		||||
  switch (updateType) {
 | 
			
		||||
    case UpdateTypeDaily:
 | 
			
		||||
      nextTime = lastCheckTime.addDays (1);
 | 
			
		||||
      break;
 | 
			
		||||
    case UpdateTypeWeekly:
 | 
			
		||||
      nextTime =  lastCheckTime.addDays (7);
 | 
			
		||||
      break;
 | 
			
		||||
    case UpdateTypeMonthly:
 | 
			
		||||
      nextTime =  lastCheckTime.addDays (30);
 | 
			
		||||
      break;
 | 
			
		||||
    case UpdateTypeNever:
 | 
			
		||||
    default:
 | 
			
		||||
      return QDateTime ();
 | 
			
		||||
  }
 | 
			
		||||
  if (nextTime < QDateTime::currentDateTime ()) {
 | 
			
		||||
    return QDateTime::currentDateTime ().addSecs (5);
 | 
			
		||||
  }
 | 
			
		||||
  return nextTime;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Updater::getCurrentVersion () {
 | 
			
		||||
  QFile f (":/version.json");
 | 
			
		||||
  if (f.open (QFile::ReadOnly)) {
 | 
			
		||||
    currentVersion_ = QJsonDocument::fromJson (f.readAll ()).object ();
 | 
			
		||||
    f.close ();
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    emit error (tr ("Ошибка определения текущей версии. Обновление недоступно."));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Updater::updateCurrentVersion () {
 | 
			
		||||
  QFile f (updatesFileName_);
 | 
			
		||||
  if (!f.open (QFile::ReadOnly)) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  QJsonObject updated = QJsonDocument::fromJson (f.readAll ()).object ();
 | 
			
		||||
  f.close ();
 | 
			
		||||
  foreach (const QString &component, updated.keys ()) {
 | 
			
		||||
    QJsonObject current = currentVersion_[component].toObject ();
 | 
			
		||||
    int updatedVersion = updated[component].toInt ();
 | 
			
		||||
    if (current[_built_in].toBool () || current[_version].toInt () >= updatedVersion) {
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    current[_version] = updatedVersion;
 | 
			
		||||
    currentVersion_[component] = current;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Updater::currentAppVersion () const {
 | 
			
		||||
  return currentVersion_[_Application].toObject ()[_versionString].toString ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Updater::checkForUpdates () {
 | 
			
		||||
  getAvailableVersion ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Updater::getAvailableVersion () {
 | 
			
		||||
  QNetworkRequest request (versionField (currentVersion_, _url));
 | 
			
		||||
  request.setAttribute (QNetworkRequest::User, _version);
 | 
			
		||||
  network_->get (request);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Updater::replyFinished (QNetworkReply *reply) {
 | 
			
		||||
  if (reply->error () != QNetworkReply::NoError) {
 | 
			
		||||
    emit tr ("Ошибка загрузки информации для обновления.");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  QByteArray content = reply->readAll ();
 | 
			
		||||
  QString component = reply->request ().attribute (QNetworkRequest::User).toString ();
 | 
			
		||||
  if (component == _version) {
 | 
			
		||||
    availableVersion_ = QJsonDocument::fromJson (content).object ();
 | 
			
		||||
    parseAvailableVersion ();
 | 
			
		||||
  }
 | 
			
		||||
  else if (availableVersion_.contains (component) && !content.isEmpty ()) {
 | 
			
		||||
    installComponent (component, content);
 | 
			
		||||
  }
 | 
			
		||||
  reply->deleteLater ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Updater::parseAvailableVersion () {
 | 
			
		||||
  QStringList inaccessible, incompatible;
 | 
			
		||||
  QStringList updateList;
 | 
			
		||||
  QDir currentDir;
 | 
			
		||||
  foreach (const QString &component, availableVersion_.keys ()) {
 | 
			
		||||
    QJsonObject available = availableVersion_[component].toObject ();
 | 
			
		||||
    QJsonObject current = currentVersion_[component].toObject ();
 | 
			
		||||
    QString path = versionField (available, _path);
 | 
			
		||||
    if (path.isEmpty ()) {
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QFileInfo installDir = fileDir (path);
 | 
			
		||||
    if (!installDir.exists ()) {
 | 
			
		||||
      currentDir.mkpath (installDir.absoluteFilePath ());
 | 
			
		||||
    }
 | 
			
		||||
    if (!installDir.isWritable ()) { // check dir because install = remove + make new
 | 
			
		||||
      inaccessible << installDir.absoluteFilePath ();
 | 
			
		||||
    }
 | 
			
		||||
    if (current[_version].toInt () < versionField (available, _compatibleVersion).toInt ()) {
 | 
			
		||||
      incompatible << component;
 | 
			
		||||
    }
 | 
			
		||||
    if (!QFile::exists (path) || current[_version].toInt () < available[_version].toInt ()) {
 | 
			
		||||
      updateList << component;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (updateList.isEmpty ()) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  QFileInfo updateFileDir = fileDir (updatesFileName_);
 | 
			
		||||
  if (!updateFileDir.isWritable ()) {
 | 
			
		||||
    inaccessible << updateFileDir.absoluteFilePath ();
 | 
			
		||||
  }
 | 
			
		||||
  inaccessible.removeDuplicates ();
 | 
			
		||||
 | 
			
		||||
  QString message = tr ("Доступно обновлений: %1.\n").arg (updateList.size ());
 | 
			
		||||
  QMessageBox::StandardButtons buttons = QMessageBox::Ok;
 | 
			
		||||
  if (!incompatible.isEmpty ()) {
 | 
			
		||||
    message += tr ("Несовместимых обновлений: %1.\nВыполните обновление вручную.")
 | 
			
		||||
               .arg (incompatible.size ());
 | 
			
		||||
  }
 | 
			
		||||
  else if (!inaccessible.isEmpty ()) {
 | 
			
		||||
    message += tr ("Недоступных для записи директорий: %1.\n%2\nИзмените права доступа и "
 | 
			
		||||
                   "повторите попытку или выполните обновление вручную.")
 | 
			
		||||
               .arg (inaccessible.size ()).arg (inaccessible.join ("\n"));
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    message += tr ("Обновить?");
 | 
			
		||||
    buttons = QMessageBox::Yes | QMessageBox::No;
 | 
			
		||||
  }
 | 
			
		||||
  int result = QMessageBox::question (NULL, tr ("Обновление"), message, buttons);
 | 
			
		||||
  if (result == QMessageBox::Yes) {
 | 
			
		||||
    componentsUpdating_ = updateList.size ();
 | 
			
		||||
    foreach (const QString &component, updateList) {
 | 
			
		||||
      getComponent (component);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Updater::getComponent (const QString &component) {
 | 
			
		||||
  QJsonObject available = availableVersion_[component].toObject ();
 | 
			
		||||
  QString path = versionField (available, _path);
 | 
			
		||||
  if (path.isEmpty ()) {
 | 
			
		||||
    --componentsUpdating_;
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  QString url = versionField (available, _url);
 | 
			
		||||
  if (url.isEmpty ()) { // just remove component
 | 
			
		||||
    installComponent (component, QByteArray ());
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    QNetworkRequest request (url);
 | 
			
		||||
    request.setAttribute (QNetworkRequest::User, component);
 | 
			
		||||
    network_->get (request);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Updater::installComponent (const QString &component, const QByteArray &newContent) {
 | 
			
		||||
  --componentsUpdating_;
 | 
			
		||||
  ST_ASSERT (availableVersion_.contains (component));
 | 
			
		||||
  QJsonObject available = availableVersion_[component].toObject ();
 | 
			
		||||
  QString path = versionField (available, _path);
 | 
			
		||||
  ST_ASSERT (!path.isEmpty ());
 | 
			
		||||
 | 
			
		||||
  QString backup = path + backupSuffix_;
 | 
			
		||||
  QFile::remove (backup);
 | 
			
		||||
  QFile::rename (path, backup);
 | 
			
		||||
 | 
			
		||||
  if (!newContent.isEmpty ()) {
 | 
			
		||||
    QFile f (path);
 | 
			
		||||
    if (!f.open (QFile::WriteOnly)) {
 | 
			
		||||
      emit error (tr ("Ошибка обновления файла (%1).").arg (path));
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    f.write (newContent);
 | 
			
		||||
    f.close ();
 | 
			
		||||
    bool ok;
 | 
			
		||||
    QFileDevice::Permissions perm (available[_permissions].toString ().toUInt (&ok, 16));
 | 
			
		||||
    if (ok) {
 | 
			
		||||
      f.setPermissions (perm);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  updateVersionInfo (component, available[_version].toInt ());
 | 
			
		||||
 | 
			
		||||
  if (componentsUpdating_ == 0) {
 | 
			
		||||
    emit updated ();
 | 
			
		||||
    QString message = tr ("Обновление завершено. Для активации некоторых компонентов "
 | 
			
		||||
                          "может потребоваться перезапуск.");
 | 
			
		||||
    QMessageBox::information (NULL, tr ("Обновление"), message, QMessageBox::Ok);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Updater::updateVersionInfo (const QString &component, int version) {
 | 
			
		||||
  QFile f (updatesFileName_);
 | 
			
		||||
  if (!f.open (QFile::ReadWrite)) {
 | 
			
		||||
    emit error (tr ("Ошибка обновления файла с текущей версией."));
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  QJsonObject updated = QJsonDocument::fromJson (f.readAll ()).object ();
 | 
			
		||||
  updated[component] = version;
 | 
			
		||||
  f.seek (0);
 | 
			
		||||
  f.write (QJsonDocument (updated).toJson ());
 | 
			
		||||
  f.close ();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										65
									
								
								Updater.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,65 @@
 | 
			
		||||
#ifndef UPDATER_H
 | 
			
		||||
#define UPDATER_H
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QJsonObject>
 | 
			
		||||
#include <QNetworkAccessManager>
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * \brief The Updater class.
 | 
			
		||||
 *
 | 
			
		||||
 * Allows to download and copy files from remote source to local machine.
 | 
			
		||||
 */
 | 
			
		||||
class Updater : public QObject {
 | 
			
		||||
  Q_OBJECT
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    enum UpdateType {
 | 
			
		||||
      UpdateTypeNever, UpdateTypeDaily, UpdateTypeWeekly, UpdateTypeMonthly
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    explicit Updater (QObject *parent = 0);
 | 
			
		||||
 | 
			
		||||
    QString currentAppVersion () const;
 | 
			
		||||
 | 
			
		||||
    //! Initiate updates check.
 | 
			
		||||
    void checkForUpdates ();
 | 
			
		||||
 | 
			
		||||
    //! Get nearest update check time based on given settings.
 | 
			
		||||
    QDateTime nextCheckTime (const QDateTime &lastCheckTime, int updateType) const;
 | 
			
		||||
 | 
			
		||||
  signals:
 | 
			
		||||
    void error (const QString &message);
 | 
			
		||||
    //! Emited after all components updated.
 | 
			
		||||
    void updated ();
 | 
			
		||||
 | 
			
		||||
  private slots:
 | 
			
		||||
    //! Handle remote downloads finish.
 | 
			
		||||
    void replyFinished (QNetworkReply *reply);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    //! Load current version info (built-in).
 | 
			
		||||
    void getCurrentVersion ();
 | 
			
		||||
    //! Update current version info with information about preformed updates.
 | 
			
		||||
    void updateCurrentVersion ();
 | 
			
		||||
    //! Load latest available version info from remote source.
 | 
			
		||||
    void getAvailableVersion ();
 | 
			
		||||
    //! Check is updates available, prompt user and start update.
 | 
			
		||||
    void parseAvailableVersion ();
 | 
			
		||||
    //! Start update of given component.
 | 
			
		||||
    void getComponent (const QString &component);
 | 
			
		||||
    //! Finalize update of given component with given new content.
 | 
			
		||||
    void installComponent (const QString &component, const QByteArray &newContent);
 | 
			
		||||
    //! Save information about component update on disk (for updateCurrentVersion()).
 | 
			
		||||
    void updateVersionInfo (const QString &component, int version);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    QNetworkAccessManager *network_;
 | 
			
		||||
    QJsonObject availableVersion_;
 | 
			
		||||
    QJsonObject currentVersion_;
 | 
			
		||||
    QString updatesFileName_;
 | 
			
		||||
    int componentsUpdating_;
 | 
			
		||||
    QString backupSuffix_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // UPDATER_H
 | 
			
		||||
							
								
								
									
										21
									
								
								Utils.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,21 @@
 | 
			
		||||
#include <QNetworkProxy>
 | 
			
		||||
 | 
			
		||||
#include "Utils.h"
 | 
			
		||||
 | 
			
		||||
QString encode (const QString &source) {
 | 
			
		||||
  if (source.isEmpty ()) {
 | 
			
		||||
    return source;
 | 
			
		||||
  }
 | 
			
		||||
  char encKeys[] = {14, 26, 99, 43};
 | 
			
		||||
  std::string result = source.toStdString ();
 | 
			
		||||
  for (int i = 0, end = result.size (); i < end; ++i) {
 | 
			
		||||
    result [i] = result[i] ^ encKeys[ i % sizeof(encKeys)];
 | 
			
		||||
  }
 | 
			
		||||
  return QString::fromUtf8 (result.data ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QList<int> proxyTypeOrder () {
 | 
			
		||||
  QList<int> proxyOrder;
 | 
			
		||||
  proxyOrder << QNetworkProxy::NoProxy << QNetworkProxy::Socks5Proxy << QNetworkProxy::HttpProxy;
 | 
			
		||||
  return proxyOrder;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								Utils.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,10 @@
 | 
			
		||||
#ifndef UTILS_H
 | 
			
		||||
#define UTILS_H
 | 
			
		||||
 | 
			
		||||
#include <QString>
 | 
			
		||||
 | 
			
		||||
QString encode (const QString &source);
 | 
			
		||||
 | 
			
		||||
QList<int> proxyTypeOrder ();
 | 
			
		||||
 | 
			
		||||
#endif // UTILS_H
 | 
			
		||||
							
								
								
									
										142
									
								
								WebTranslator.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,142 @@
 | 
			
		||||
#include <QWebView>
 | 
			
		||||
#include <QWebFrame>
 | 
			
		||||
#include <QSettings>
 | 
			
		||||
#include <QNetworkReply>
 | 
			
		||||
#include <QFile>
 | 
			
		||||
 | 
			
		||||
#include "WebTranslator.h"
 | 
			
		||||
#include "ProcessingItem.h"
 | 
			
		||||
#include "Settings.h"
 | 
			
		||||
#include "StAssert.h"
 | 
			
		||||
#include "WebTranslatorProxy.h"
 | 
			
		||||
#include "TranslatorHelper.h"
 | 
			
		||||
 | 
			
		||||
WebTranslator::WebTranslator ()
 | 
			
		||||
  : QObject (),
 | 
			
		||||
  proxy_ (new WebTranslatorProxy (this)), view_ (new QWebView),
 | 
			
		||||
  translatorHelper_ (new TranslatorHelper), isReady_ (true) {
 | 
			
		||||
 | 
			
		||||
  view_->settings ()->setAttribute (QWebSettings::AutoLoadImages, false);
 | 
			
		||||
  view_->settings ()->setAttribute (QWebSettings::DeveloperExtrasEnabled, true);
 | 
			
		||||
  view_->settings ()->setAttribute (QWebSettings::LocalStorageEnabled, true);
 | 
			
		||||
 | 
			
		||||
  connect (view_, SIGNAL (loadFinished (bool)), SLOT (loadFinished (bool)));
 | 
			
		||||
  connect (view_->page ()->mainFrame (), SIGNAL (javaScriptWindowObjectCleared ()),
 | 
			
		||||
           this, SLOT (addProxyToView ()));
 | 
			
		||||
  connect (view_->page ()->networkAccessManager (), SIGNAL (finished (QNetworkReply *)),
 | 
			
		||||
           this, SLOT (replyFinished (QNetworkReply *)));
 | 
			
		||||
 | 
			
		||||
  translationTimeout_.setSingleShot (true);
 | 
			
		||||
  connect (&translationTimeout_, SIGNAL (timeout ()), SLOT (abortTranslation ()));
 | 
			
		||||
 | 
			
		||||
  connect (proxy_, SIGNAL (translated (QString)), SLOT (proxyTranslated (QString)));
 | 
			
		||||
 | 
			
		||||
  // Delay because it can emit signal that is not connected yet.
 | 
			
		||||
  QTimer::singleShot (500, this, SLOT (applySettings ()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WebTranslator::~WebTranslator () {
 | 
			
		||||
  delete translatorHelper_;
 | 
			
		||||
  delete view_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebTranslator::addProxyToView () {
 | 
			
		||||
  view_->page ()->mainFrame ()->addToJavaScriptWindowObject ("st_wtp", proxy_);
 | 
			
		||||
  view_->page ()->mainFrame ()->evaluateJavaScript (translatorHelper_->currentScript ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebTranslator::translate (ProcessingItem item) {
 | 
			
		||||
  if (!item.isValid () || item.translateLanguage.isEmpty ()) {
 | 
			
		||||
    emit translated (item);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  queue_.push_back (item);
 | 
			
		||||
  translateQueued ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebTranslator::translateQueued () {
 | 
			
		||||
  if (isReady_ && !queue_.isEmpty ()) {
 | 
			
		||||
    translatorHelper_->newItem ();
 | 
			
		||||
    proxy_->setItem (queue_.first ());
 | 
			
		||||
    if (!tryNextTranslator (true)) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebTranslator::proxyTranslated (const QString &text) {
 | 
			
		||||
  if (!queue_.isEmpty () && queue_.first ().recognized == proxy_->sourceText ()) {
 | 
			
		||||
    if (text.isEmpty () && tryNextTranslator ()) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    ProcessingItem &item = queue_.first ();
 | 
			
		||||
    item.translated = text;
 | 
			
		||||
    emit translated (item);
 | 
			
		||||
  }
 | 
			
		||||
  finishTranslation (false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebTranslator::abortTranslation () {
 | 
			
		||||
  if (!tryNextTranslator ()) {
 | 
			
		||||
    emit error (tr ("Перевод отменен по таймауту."));
 | 
			
		||||
    finishTranslation ();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebTranslator::loadFinished (bool ok) {
 | 
			
		||||
  if (!ok && !tryNextTranslator ()) {
 | 
			
		||||
    QString url = view_->url ().toString ();
 | 
			
		||||
    emit error (tr ("Ошибка загрузки страницы (%1) для перевода.").arg (url));
 | 
			
		||||
    finishTranslation ();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebTranslator::finishTranslation (bool markAsTranslated) {
 | 
			
		||||
  translationTimeout_.stop ();
 | 
			
		||||
  view_->stop ();
 | 
			
		||||
  if (!queue_.isEmpty ()) {
 | 
			
		||||
    if (markAsTranslated) {
 | 
			
		||||
      emit translated (queue_.first ());
 | 
			
		||||
    }
 | 
			
		||||
    queue_.pop_front ();
 | 
			
		||||
  }
 | 
			
		||||
  isReady_ = true;
 | 
			
		||||
  translateQueued ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool WebTranslator::tryNextTranslator (bool firstTime) {
 | 
			
		||||
  QString script = firstTime ? translatorHelper_->currentScript ()
 | 
			
		||||
                   : translatorHelper_->nextScript ();
 | 
			
		||||
  if (script.isEmpty ()) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  translationTimeout_.stop ();
 | 
			
		||||
  view_->stop ();
 | 
			
		||||
  addProxyToView ();
 | 
			
		||||
  view_->page ()->mainFrame ()->evaluateJavaScript ("translate();");
 | 
			
		||||
  isReady_ = false;
 | 
			
		||||
  translationTimeout_.start ();
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebTranslator::replyFinished (QNetworkReply *reply) {
 | 
			
		||||
  emit proxy_->resourceLoaded (reply->url ().toString ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebTranslator::applySettings () {
 | 
			
		||||
  QSettings settings;
 | 
			
		||||
  settings.beginGroup (settings_names::translationGroup);
 | 
			
		||||
#define GET(NAME) settings.value (settings_names::NAME, settings_values::NAME)
 | 
			
		||||
  translationTimeout_.setInterval (GET (translationTimeout).toInt () * 1000);
 | 
			
		||||
  translatorHelper_->loadScripts ();
 | 
			
		||||
  if (!translatorHelper_->gotScripts ()) {
 | 
			
		||||
    emit error (tr ("Нет сценариев для перевода. Измените настройки."));
 | 
			
		||||
  }
 | 
			
		||||
  bool debugMode = GET (translationDebugMode).toBool ();
 | 
			
		||||
  setDebugMode (debugMode);
 | 
			
		||||
#undef GET
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebTranslator::setDebugMode (bool isOn) {
 | 
			
		||||
  view_->setVisible (isOn);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										53
									
								
								WebTranslator.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,53 @@
 | 
			
		||||
#ifndef WEBTRANSLATOR_H
 | 
			
		||||
#define WEBTRANSLATOR_H
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QMap>
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
 | 
			
		||||
#include "ProcessingItem.h"
 | 
			
		||||
 | 
			
		||||
class QWebView;
 | 
			
		||||
class QNetworkReply;
 | 
			
		||||
 | 
			
		||||
class WebTranslatorProxy;
 | 
			
		||||
class TranslatorHelper;
 | 
			
		||||
 | 
			
		||||
class WebTranslator : public QObject {
 | 
			
		||||
  Q_OBJECT
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    explicit WebTranslator ();
 | 
			
		||||
    ~WebTranslator ();
 | 
			
		||||
 | 
			
		||||
  signals:
 | 
			
		||||
    void translated (ProcessingItem item);
 | 
			
		||||
    void error (QString text);
 | 
			
		||||
 | 
			
		||||
  public slots:
 | 
			
		||||
    void translate (ProcessingItem item);
 | 
			
		||||
    void applySettings ();
 | 
			
		||||
    void setDebugMode (bool isOn);
 | 
			
		||||
 | 
			
		||||
  private slots:
 | 
			
		||||
    void loadFinished (bool ok);
 | 
			
		||||
    void replyFinished (QNetworkReply *reply);
 | 
			
		||||
    void addProxyToView ();
 | 
			
		||||
    void abortTranslation ();
 | 
			
		||||
    void proxyTranslated (const QString &text);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    void translateQueued ();
 | 
			
		||||
    void finishTranslation (bool markAsTranslated = true);
 | 
			
		||||
    bool tryNextTranslator (bool firstTime = false);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    WebTranslatorProxy *proxy_;
 | 
			
		||||
    QWebView *view_;
 | 
			
		||||
    TranslatorHelper *translatorHelper_;
 | 
			
		||||
    QVector<ProcessingItem> queue_;
 | 
			
		||||
    bool isReady_;
 | 
			
		||||
    QTimer translationTimeout_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // WEBTRANSLATOR_H
 | 
			
		||||
							
								
								
									
										25
									
								
								WebTranslatorProxy.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,25 @@
 | 
			
		||||
#include "WebTranslatorProxy.h"
 | 
			
		||||
#include "ProcessingItem.h"
 | 
			
		||||
 | 
			
		||||
WebTranslatorProxy::WebTranslatorProxy (QObject *parent)
 | 
			
		||||
  : QObject (parent) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WebTranslatorProxy::setItem (const ProcessingItem &item) {
 | 
			
		||||
  sourceText_ = item.recognized;
 | 
			
		||||
  sourceLanguage_ = item.ocrLanguage;
 | 
			
		||||
  resultLanguage_ = item.translateLanguage;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const QString &WebTranslatorProxy::sourceText () const {
 | 
			
		||||
  return sourceText_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const QString &WebTranslatorProxy::sourceLanguage () const {
 | 
			
		||||
  return sourceLanguage_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const QString &WebTranslatorProxy::resultLanguage () const {
 | 
			
		||||
  return resultLanguage_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										37
									
								
								WebTranslatorProxy.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,37 @@
 | 
			
		||||
#ifndef WEBTRANSLATORPROXY_H
 | 
			
		||||
#define WEBTRANSLATORPROXY_H
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
 | 
			
		||||
class ProcessingItem;
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * \brief Proxy class between WebTranslator and QWebView.
 | 
			
		||||
 */
 | 
			
		||||
class WebTranslatorProxy : public QObject {
 | 
			
		||||
  Q_OBJECT
 | 
			
		||||
  Q_PROPERTY (QString sourceText READ sourceText)
 | 
			
		||||
  Q_PROPERTY (QString sourceLanguage READ sourceLanguage)
 | 
			
		||||
  Q_PROPERTY (QString resultLanguage READ resultLanguage)
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    explicit WebTranslatorProxy (QObject *parent = 0);
 | 
			
		||||
 | 
			
		||||
    void setItem (const ProcessingItem &item);
 | 
			
		||||
 | 
			
		||||
    const QString &sourceText () const;
 | 
			
		||||
    const QString &sourceLanguage () const;
 | 
			
		||||
    const QString &resultLanguage () const;
 | 
			
		||||
 | 
			
		||||
  signals:
 | 
			
		||||
    void translated (const QString &text);
 | 
			
		||||
 | 
			
		||||
    void resourceLoaded (const QString &url);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    QString sourceText_;
 | 
			
		||||
    QString sourceLanguage_;
 | 
			
		||||
    QString resultLanguage_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // WEBTRANSLATORPROXY_H
 | 
			
		||||
@ -1,4 +1,21 @@
 | 
			
		||||
Changes.
 | 
			
		||||
2.0.0:
 | 
			
		||||
* Added a version for linux.
 | 
			
		||||
* Added support for multiple monitors.
 | 
			
		||||
* Added ability of recognition without translation.
 | 
			
		||||
* Added ability to recapture from old image.
 | 
			
		||||
* Added ability to recapture without closing capture window.
 | 
			
		||||
* Added ability to re-recognize other language.
 | 
			
		||||
* Added ability to display intermediate result when error occured.
 | 
			
		||||
* Added support for different translation services.
 | 
			
		||||
* Added ability to copy image to clipboard.
 | 
			
		||||
* Added ability to edit recognized text.
 | 
			
		||||
* Added ability to automatically correct common recognition mistakes.
 | 
			
		||||
* Added ability to use a proxy.
 | 
			
		||||
* Added ability to swap translation and recognition languages.
 | 
			
		||||
* Updated icons.
 | 
			
		||||
* Show progress on icon.
 | 
			
		||||
* Added ability to automatically update.
 | 
			
		||||
1.2.3:
 | 
			
		||||
* Fixed possible crash.
 | 
			
		||||
* Added version information and some error messages.
 | 
			
		||||
@ -23,4 +40,4 @@ Changes.
 | 
			
		||||
* Fixed an issue with incorrect window size when display results. 
 | 
			
		||||
1.1.0: 
 | 
			
		||||
+ Displays the result in the window, along with the picture. 
 | 
			
		||||
+ Context menu expanded. Added buttons display the last result and copy it to the clipboard.
 | 
			
		||||
+ Context menu expanded. Added buttons display the last result and copy it to the clipboard.
 | 
			
		||||
@ -1,4 +1,21 @@
 | 
			
		||||
Изменения.
 | 
			
		||||
2.0.0:
 | 
			
		||||
* Добавлена версия под linux.
 | 
			
		||||
* Добавлена поддержка нескольких мониторов.
 | 
			
		||||
* Добавлеа возможность распознание без перевода.
 | 
			
		||||
* Добавлена возможность вызова старого рисунка для выделения.
 | 
			
		||||
* Добавлена возможность повторного выделения без закрытия окна захвата.
 | 
			
		||||
* Добавлена возможность повторного распознания на другом языке.
 | 
			
		||||
* Добавлена возможность отображения промежуточного результата при ошибке перевода.
 | 
			
		||||
* Добавлена поддержка разных сервисов перевода.
 | 
			
		||||
* Добавлена возможность копирования изображения в буфер.
 | 
			
		||||
* Добавлена возможность редакции распознанного текста.
 | 
			
		||||
* Добавлена возможность автоматической коррекции частых ошибок распознавания.
 | 
			
		||||
* Добавлена возможность использования прокси.
 | 
			
		||||
* Добавлена возможность разовой смена языка перевода и распознавания.
 | 
			
		||||
* Обновлены иконки.
 | 
			
		||||
* Добавлено отображение статуса работы на иконке.
 | 
			
		||||
* Добавлена возможность автоматического обновления.
 | 
			
		||||
1.2.3:
 | 
			
		||||
* Устранена возможная причина падения.
 | 
			
		||||
* Добавлена информация о версии и некоторые сообщения об ошибках.
 | 
			
		||||
@ -23,4 +40,4 @@
 | 
			
		||||
- Пофиксен баг с неверным размером окна отображения результатов.
 | 
			
		||||
1.1.0:
 | 
			
		||||
- Отображение результата в окошке, вместе с картинкой.
 | 
			
		||||
- Контекстное меню расширено. Добавлены кнопки отображения последнего результата и копирования его в буфер обмена.
 | 
			
		||||
- Контекстное меню расширено. Добавлены кнопки отображения последнего результата и копирования его в буфер обмена.
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								distr/Files.xlsx
									
									
									
									
									
								
							
							
						
						@ -1,269 +0,0 @@
 | 
			
		||||
; Script generated by the Inno Setup Script Wizard.
 | 
			
		||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
 | 
			
		||||
 | 
			
		||||
#define MyAppName "Screen Translator"
 | 
			
		||||
#define MyAppVersion "1.2.3"
 | 
			
		||||
#define MyAppPublisher "Gres"
 | 
			
		||||
#define MyAppURL "http://gres.biz/screen-translator/"
 | 
			
		||||
#define MyAppExeName "ScreenTranslator.exe"    
 | 
			
		||||
#define MyAppDescription "Screen capture and translation tool"
 | 
			
		||||
 | 
			
		||||
[Setup]
 | 
			
		||||
; NOTE: The value of AppId uniquely identifies this application.
 | 
			
		||||
; Do not use the same AppId value in installers for other applications.
 | 
			
		||||
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
 | 
			
		||||
AppId={{016F399E-0EED-476C-AB00-8AD0FF5BFD77}
 | 
			
		||||
AppName={#MyAppName}
 | 
			
		||||
AppVersion={#MyAppVersion}
 | 
			
		||||
;AppVerName={#MyAppName} {#MyAppVersion}
 | 
			
		||||
AppPublisher={#MyAppPublisher}
 | 
			
		||||
AppPublisherURL={#MyAppURL}
 | 
			
		||||
AppSupportURL={#MyAppURL}
 | 
			
		||||
AppUpdatesURL={#MyAppURL}
 | 
			
		||||
DefaultDirName={pf}\{#MyAppName}
 | 
			
		||||
DefaultGroupName={#MyAppName}
 | 
			
		||||
AllowNoIcons=yes   
 | 
			
		||||
PrivilegesRequired=admin
 | 
			
		||||
CloseApplications=yes
 | 
			
		||||
OutputDir=.
 | 
			
		||||
OutputBaseFilename=ScreenTranslator-{#MyAppVersion}
 | 
			
		||||
SetupIconFile=..\images\icon.ico
 | 
			
		||||
SolidCompression=yes
 | 
			
		||||
RestartIfNeededByRun=False
 | 
			
		||||
ShowLanguageDialog=auto
 | 
			
		||||
VersionInfoCompany={#MyAppPublisher}
 | 
			
		||||
VersionInfoDescription={#MyAppDescription}
 | 
			
		||||
VersionInfoProductName={#MyAppName}
 | 
			
		||||
VersionInfoProductVersion={#MyAppVersion}
 | 
			
		||||
VersionInfoVersion={#MyAppVersion}
 | 
			
		||||
Compression=lzma2/ultra64
 | 
			
		||||
InternalCompressLevel=max
 | 
			
		||||
 | 
			
		||||
[Languages]
 | 
			
		||||
Name: "english"; MessagesFile: "compiler:Default.isl"; InfoBeforeFile: "eng\Changelog.txt"
 | 
			
		||||
Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl,ru\Russian.isl"; InfoBeforeFile: "ru\Changelog.txt"
 | 
			
		||||
 | 
			
		||||
[Tasks]
 | 
			
		||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked        
 | 
			
		||||
Name: "startupicon"; Description: "{cm:CreateStartupIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
 | 
			
		||||
Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1  
 | 
			
		||||
 | 
			
		||||
[Icons]
 | 
			
		||||
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
 | 
			
		||||
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
 | 
			
		||||
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
 | 
			
		||||
Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: quicklaunchicon      
 | 
			
		||||
Name: "{commonstartup}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: startupicon   
 | 
			
		||||
 | 
			
		||||
[Run]
 | 
			
		||||
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
 | 
			
		||||
 | 
			
		||||
[Files]
 | 
			
		||||
Source: "content\ScreenTranslator.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: Executable
 | 
			
		||||
 | 
			
		||||
Source: "content\*.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: Libraries
 | 
			
		||||
Source: "content\platforms\*"; DestDir: "{app}\platforms"; Flags: ignoreversion; Components: Libraries
 | 
			
		||||
 | 
			
		||||
Source: "content\tessdata\afr.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Afrikaans
 | 
			
		||||
Source: "content\tessdata\sqi.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Albanian
 | 
			
		||||
Source: "content\tessdata\grc.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\AncientGreek
 | 
			
		||||
Source: "content\tessdata\ara.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Arabic
 | 
			
		||||
Source: "content\tessdata\aze.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Azerbaijani
 | 
			
		||||
Source: "content\tessdata\eus.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Basque
 | 
			
		||||
Source: "content\tessdata\bel.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Belarusian
 | 
			
		||||
Source: "content\tessdata\ben.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Bengali
 | 
			
		||||
Source: "content\tessdata\bul.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Bulgarian
 | 
			
		||||
Source: "content\tessdata\cat.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Catalan
 | 
			
		||||
Source: "content\tessdata\chr.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Cherokee
 | 
			
		||||
Source: "content\tessdata\chi_sim.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\ChineseSimplified
 | 
			
		||||
Source: "content\tessdata\chi_tra.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\ChineseTraditional
 | 
			
		||||
Source: "content\tessdata\hrv.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Croatian
 | 
			
		||||
Source: "content\tessdata\ces.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Czech
 | 
			
		||||
Source: "content\tessdata\dan.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Danish
 | 
			
		||||
Source: "content\tessdata\nld.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Dutch
 | 
			
		||||
Source: "content\tessdata\eng.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\English
 | 
			
		||||
Source: "content\tessdata\epo.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Esperanto
 | 
			
		||||
Source: "content\tessdata\epo_alt.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Esperantoalternative
 | 
			
		||||
Source: "content\tessdata\est.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Estonian
 | 
			
		||||
Source: "content\tessdata\fin.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Finnish
 | 
			
		||||
Source: "content\tessdata\frk.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Frankish
 | 
			
		||||
Source: "content\tessdata\fra.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\French
 | 
			
		||||
Source: "content\tessdata\glg.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Galician
 | 
			
		||||
Source: "content\tessdata\deu.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\German
 | 
			
		||||
Source: "content\tessdata\ell.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Greek
 | 
			
		||||
Source: "content\tessdata\heb.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Hebrew
 | 
			
		||||
Source: "content\tessdata\hin.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Hindi
 | 
			
		||||
Source: "content\tessdata\hun.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Hungarian
 | 
			
		||||
Source: "content\tessdata\isl.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Icelandic
 | 
			
		||||
Source: "content\tessdata\ind.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Indonesian
 | 
			
		||||
Source: "content\tessdata\ita.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Italian
 | 
			
		||||
Source: "content\tessdata\jpn.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Japanese
 | 
			
		||||
Source: "content\tessdata\kan.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Kannada
 | 
			
		||||
Source: "content\tessdata\kor.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Korean
 | 
			
		||||
Source: "content\tessdata\lav.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Latvian
 | 
			
		||||
Source: "content\tessdata\lit.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Lithuanian
 | 
			
		||||
Source: "content\tessdata\mkd.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Macedonian
 | 
			
		||||
Source: "content\tessdata\msa.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Malay
 | 
			
		||||
Source: "content\tessdata\mal.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Malayalam
 | 
			
		||||
Source: "content\tessdata\mlt.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Maltese
 | 
			
		||||
Source: "content\tessdata\equ.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\MathEquation
 | 
			
		||||
Source: "content\tessdata\enm.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\MiddleEnglish
 | 
			
		||||
Source: "content\tessdata\frm.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\MiddleFrench
 | 
			
		||||
Source: "content\tessdata\nor.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Norwegian
 | 
			
		||||
Source: "content\tessdata\pol.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Polish
 | 
			
		||||
Source: "content\tessdata\por.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Portuguese
 | 
			
		||||
Source: "content\tessdata\ron.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Romanian
 | 
			
		||||
Source: "content\tessdata\rus.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Russian
 | 
			
		||||
Source: "content\tessdata\srp.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Serbian
 | 
			
		||||
Source: "content\tessdata\slk.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Slovakian
 | 
			
		||||
Source: "content\tessdata\slv.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Slovenian
 | 
			
		||||
Source: "content\tessdata\spa.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Spanish
 | 
			
		||||
Source: "content\tessdata\swa.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Swahili
 | 
			
		||||
Source: "content\tessdata\swe.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Swedish
 | 
			
		||||
Source: "content\tessdata\tgl.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Tagalog
 | 
			
		||||
Source: "content\tessdata\tam.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Tamil
 | 
			
		||||
Source: "content\tessdata\tel.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Telugu
 | 
			
		||||
Source: "content\tessdata\tha.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Thai
 | 
			
		||||
Source: "content\tessdata\tur.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Turkish
 | 
			
		||||
Source: "content\tessdata\ukr.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Ukrainian
 | 
			
		||||
Source: "content\tessdata\vie.*"; DestDir: "{app}\tessdata"; Flags: ignoreversion; Components: Languages\Vietnamese
 | 
			
		||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
 | 
			
		||||
 | 
			
		||||
[CustomMessages]
 | 
			
		||||
english.CreateStartupIcon=Create autostart icon
 | 
			
		||||
english.Executables=Executables 
 | 
			
		||||
english.Libraries=Libraries
 | 
			
		||||
english.Languages=OCR Languages
 | 
			
		||||
 | 
			
		||||
english.Afrikaans=Afrikaans
 | 
			
		||||
english.Albanian=Albanian
 | 
			
		||||
english.AncientGreek=AncientGreek
 | 
			
		||||
english.Arabic=Arabic
 | 
			
		||||
english.Azerbaijani=Azerbaijani
 | 
			
		||||
english.Basque=Basque
 | 
			
		||||
english.Belarusian=Belarusian
 | 
			
		||||
english.Bengali=Bengali
 | 
			
		||||
english.Bulgarian=Bulgarian
 | 
			
		||||
english.Catalan=Catalan
 | 
			
		||||
english.Cherokee=Cherokee
 | 
			
		||||
english.ChineseSimplified=ChineseSimplified
 | 
			
		||||
english.ChineseTraditional=ChineseTraditional
 | 
			
		||||
english.Croatian=Croatian
 | 
			
		||||
english.Czech=Czech
 | 
			
		||||
english.Danish=Danish
 | 
			
		||||
english.Dutch=Dutch
 | 
			
		||||
english.English=English
 | 
			
		||||
english.Esperanto=Esperanto
 | 
			
		||||
english.Esperantoalternative=Esperantoalternative
 | 
			
		||||
english.Estonian=Estonian
 | 
			
		||||
english.Finnish=Finnish
 | 
			
		||||
english.Frankish=Frankish
 | 
			
		||||
english.French=French
 | 
			
		||||
english.Galician=Galician
 | 
			
		||||
english.German=German
 | 
			
		||||
english.Greek=Greek
 | 
			
		||||
english.Hebrew=Hebrew
 | 
			
		||||
english.Hindi=Hindi
 | 
			
		||||
english.Hungarian=Hungarian
 | 
			
		||||
english.Icelandic=Icelandic
 | 
			
		||||
english.Indonesian=Indonesian
 | 
			
		||||
english.Italian=Italian
 | 
			
		||||
english.Japanese=Japanese
 | 
			
		||||
english.Kannada=Kannada
 | 
			
		||||
english.Korean=Korean
 | 
			
		||||
english.Latvian=Latvian
 | 
			
		||||
english.Lithuanian=Lithuanian
 | 
			
		||||
english.Macedonian=Macedonian
 | 
			
		||||
english.Malay=Malay
 | 
			
		||||
english.Malayalam=Malayalam
 | 
			
		||||
english.Maltese=Maltese
 | 
			
		||||
english.MathEquation=MathEquation
 | 
			
		||||
english.MiddleEnglish=MiddleEnglish
 | 
			
		||||
english.MiddleFrench=MiddleFrench
 | 
			
		||||
english.Norwegian=Norwegian
 | 
			
		||||
english.Polish=Polish
 | 
			
		||||
english.Portuguese=Portuguese
 | 
			
		||||
english.Romanian=Romanian
 | 
			
		||||
english.Russian=Russian
 | 
			
		||||
english.Serbian=Serbian
 | 
			
		||||
english.Slovakian=Slovakian
 | 
			
		||||
english.Slovenian=Slovenian
 | 
			
		||||
english.Spanish=Spanish
 | 
			
		||||
english.Swahili=Swahili
 | 
			
		||||
english.Swedish=Swedish
 | 
			
		||||
english.Tagalog=Tagalog
 | 
			
		||||
english.Tamil=Tamil
 | 
			
		||||
english.Telugu=Telugu
 | 
			
		||||
english.Thai=Thai
 | 
			
		||||
english.Turkish=Turkish
 | 
			
		||||
english.Ukrainian=Ukrainian
 | 
			
		||||
english.Vietnamese=Vietnamese
 | 
			
		||||
    
 | 
			
		||||
[Components]
 | 
			
		||||
Name: "Executable"; Description: "{cm:Executables}"; Types: compact custom full; Flags: fixed;
 | 
			
		||||
Name: "Libraries"; Description: "{cm:Libraries}"; Types: compact custom full; Flags: fixed;
 | 
			
		||||
Name: "Languages"; Description: "{cm:Languages}"; Types: custom full
 | 
			
		||||
 | 
			
		||||
Name: "Languages\Afrikaans"; Description: "{cm:Afrikaans}"; Types: full
 | 
			
		||||
Name: "Languages\Albanian"; Description: "{cm:Albanian}"; Types: full
 | 
			
		||||
Name: "Languages\AncientGreek"; Description: "{cm:AncientGreek}"; Types: full
 | 
			
		||||
Name: "Languages\Arabic"; Description: "{cm:Arabic}"; Types: full
 | 
			
		||||
Name: "Languages\Azerbaijani"; Description: "{cm:Azerbaijani}"; Types: full
 | 
			
		||||
Name: "Languages\Basque"; Description: "{cm:Basque}"; Types: full
 | 
			
		||||
Name: "Languages\Belarusian"; Description: "{cm:Belarusian}"; Types: full
 | 
			
		||||
Name: "Languages\Bengali"; Description: "{cm:Bengali}"; Types: full
 | 
			
		||||
Name: "Languages\Bulgarian"; Description: "{cm:Bulgarian}"; Types: full
 | 
			
		||||
Name: "Languages\Catalan"; Description: "{cm:Catalan}"; Types: full
 | 
			
		||||
Name: "Languages\Cherokee"; Description: "{cm:Cherokee}"; Types: full
 | 
			
		||||
Name: "Languages\ChineseSimplified"; Description: "{cm:ChineseSimplified}"; Types: full
 | 
			
		||||
Name: "Languages\ChineseTraditional"; Description: "{cm:ChineseTraditional}"; Types: compact custom full
 | 
			
		||||
Name: "Languages\Croatian"; Description: "{cm:Croatian}"; Types: full
 | 
			
		||||
Name: "Languages\Czech"; Description: "{cm:Czech}"; Types: full
 | 
			
		||||
Name: "Languages\Danish"; Description: "{cm:Danish}"; Types: full
 | 
			
		||||
Name: "Languages\Dutch"; Description: "{cm:Dutch}"; Types: full
 | 
			
		||||
Name: "Languages\English"; Description: "{cm:English}"; Types: compact custom full
 | 
			
		||||
Name: "Languages\Esperanto"; Description: "{cm:Esperanto}"; Types: full
 | 
			
		||||
Name: "Languages\Esperantoalternative"; Description: "{cm:Esperantoalternative}"; Types: full
 | 
			
		||||
Name: "Languages\Estonian"; Description: "{cm:Estonian}"; Types: full
 | 
			
		||||
Name: "Languages\Finnish"; Description: "{cm:Finnish}"; Types: full
 | 
			
		||||
Name: "Languages\Frankish"; Description: "{cm:Frankish}"; Types: full
 | 
			
		||||
Name: "Languages\French"; Description: "{cm:French}"; Types: compact custom full
 | 
			
		||||
Name: "Languages\Galician"; Description: "{cm:Galician}"; Types: full
 | 
			
		||||
Name: "Languages\German"; Description: "{cm:German}"; Types: compact custom full
 | 
			
		||||
Name: "Languages\Greek"; Description: "{cm:Greek}"; Types: full
 | 
			
		||||
Name: "Languages\Hebrew"; Description: "{cm:Hebrew}"; Types: full
 | 
			
		||||
Name: "Languages\Hindi"; Description: "{cm:Hindi}"; Types: full
 | 
			
		||||
Name: "Languages\Hungarian"; Description: "{cm:Hungarian}"; Types: full
 | 
			
		||||
Name: "Languages\Icelandic"; Description: "{cm:Icelandic}"; Types: full
 | 
			
		||||
Name: "Languages\Indonesian"; Description: "{cm:Indonesian}"; Types: full
 | 
			
		||||
Name: "Languages\Italian"; Description: "{cm:Italian}"; Types: full
 | 
			
		||||
Name: "Languages\Japanese"; Description: "{cm:Japanese}"; Types: compact custom full
 | 
			
		||||
Name: "Languages\Kannada"; Description: "{cm:Kannada}"; Types: full
 | 
			
		||||
Name: "Languages\Korean"; Description: "{cm:Korean}"; Types: compact custom full
 | 
			
		||||
Name: "Languages\Latvian"; Description: "{cm:Latvian}"; Types: full
 | 
			
		||||
Name: "Languages\Lithuanian"; Description: "{cm:Lithuanian}"; Types: full
 | 
			
		||||
Name: "Languages\Macedonian"; Description: "{cm:Macedonian}"; Types: full
 | 
			
		||||
Name: "Languages\Malay"; Description: "{cm:Malay}"; Types: full
 | 
			
		||||
Name: "Languages\Malayalam"; Description: "{cm:Malayalam}"; Types: full
 | 
			
		||||
Name: "Languages\Maltese"; Description: "{cm:Maltese}"; Types: full
 | 
			
		||||
Name: "Languages\MathEquation"; Description: "{cm:MathEquation}"; Types: compact custom full
 | 
			
		||||
Name: "Languages\MiddleEnglish"; Description: "{cm:MiddleEnglish}"; Types: full
 | 
			
		||||
Name: "Languages\MiddleFrench"; Description: "{cm:MiddleFrench}"; Types: full
 | 
			
		||||
Name: "Languages\Norwegian"; Description: "{cm:Norwegian}"; Types: full
 | 
			
		||||
Name: "Languages\Polish"; Description: "{cm:Polish}"; Types: full
 | 
			
		||||
Name: "Languages\Portuguese"; Description: "{cm:Portuguese}"; Types: full
 | 
			
		||||
Name: "Languages\Romanian"; Description: "{cm:Romanian}"; Types: full
 | 
			
		||||
Name: "Languages\Russian"; Description: "{cm:Russian}"; Types: compact custom full
 | 
			
		||||
Name: "Languages\Serbian"; Description: "{cm:Serbian}"; Types: full
 | 
			
		||||
Name: "Languages\Slovakian"; Description: "{cm:Slovakian}"; Types: full
 | 
			
		||||
Name: "Languages\Slovenian"; Description: "{cm:Slovenian}"; Types: full
 | 
			
		||||
Name: "Languages\Spanish"; Description: "{cm:Spanish}"; Types: compact custom full
 | 
			
		||||
Name: "Languages\Swahili"; Description: "{cm:Swahili}"; Types: full
 | 
			
		||||
Name: "Languages\Swedish"; Description: "{cm:Swedish}"; Types: full
 | 
			
		||||
Name: "Languages\Tagalog"; Description: "{cm:Tagalog}"; Types: full
 | 
			
		||||
Name: "Languages\Tamil"; Description: "{cm:Tamil}"; Types: full
 | 
			
		||||
Name: "Languages\Telugu"; Description: "{cm:Telugu}"; Types: full
 | 
			
		||||
Name: "Languages\Thai"; Description: "{cm:Thai}"; Types: full
 | 
			
		||||
Name: "Languages\Turkish"; Description: "{cm:Turkish}"; Types: full
 | 
			
		||||
Name: "Languages\Ukrainian"; Description: "{cm:Ukrainian}"; Types: full
 | 
			
		||||
Name: "Languages\Vietnamese"; Description: "{cm:Vietnamese}"; Types: full
 | 
			
		||||
							
								
								
									
										16
									
								
								distr/deb/DEBIAN/control
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,16 @@
 | 
			
		||||
Package: screen-translator
 | 
			
		||||
Version: 1
 | 
			
		||||
Section: graphics
 | 
			
		||||
Architecture: amd64
 | 
			
		||||
Depends: libtesseract3, libqt5webkit5, libqt5x11extras5 
 | 
			
		||||
Recommends: tesseract-ocr-eng, tesseract-ocr-rus, tesseract-ocr-deu, tesseract-ocr-spa, tesseract-ocr-chi-sim, tesseract-ocr-fra, tesseract-ocr-jpn
 | 
			
		||||
Installed-Size: 1
 | 
			
		||||
Priority: optional
 | 
			
		||||
Maintainer: Gres <translator@gres.biz>
 | 
			
		||||
Homepage: https://github.com/OneMoreGres/ScreenTranslator
 | 
			
		||||
Description: Screen capture, OCR and translation tool.
 | 
			
		||||
 This software allows to translate any text on screen.
 | 
			
		||||
 Basically it is a combination of screen capture, 
 | 
			
		||||
 OCR and translation tools.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,9 @@
 | 
			
		||||
[Desktop Entry]
 | 
			
		||||
Version=1
 | 
			
		||||
Name=Screen Translator
 | 
			
		||||
Comment=Screen capture, OCR and translation tool.
 | 
			
		||||
Exec=/opt/ScreenTranslator/ScreenTranslator
 | 
			
		||||
Icon=ScreenTranslator.png
 | 
			
		||||
Terminal=false
 | 
			
		||||
Type=Application
 | 
			
		||||
Categories=Graphics;
 | 
			
		||||
							
								
								
									
										145
									
								
								distr/iss/InnoSetup.iss
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,145 @@
 | 
			
		||||
; Script generated by the Inno Setup Script Wizard.
 | 
			
		||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
 | 
			
		||||
             
 | 
			
		||||
#define MyAppName "Screen Translator"
 | 
			
		||||
#define MyAppVersion "2.0.0"
 | 
			
		||||
#define MyAppPublisher "Gres"
 | 
			
		||||
#define MyAppURL "http://gres.biz/screen-translator/"
 | 
			
		||||
#define MyAppExeName "ScreenTranslator.exe"    
 | 
			
		||||
#define MyAppDescription "Screen capture and translation tool"  
 | 
			
		||||
 | 
			
		||||
[Setup]
 | 
			
		||||
; NOTE: The value of AppId uniquely identifies this application.
 | 
			
		||||
; Do not use the same AppId value in installers for other applications.
 | 
			
		||||
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
 | 
			
		||||
AppId={{016F399E-0EED-476C-AB00-8AD0FF5BFD77}
 | 
			
		||||
AppName={#MyAppName}
 | 
			
		||||
AppVersion={#MyAppVersion}
 | 
			
		||||
;AppVerName={#MyAppName} {#MyAppVersion}
 | 
			
		||||
AppPublisher={#MyAppPublisher}
 | 
			
		||||
AppPublisherURL={#MyAppURL}
 | 
			
		||||
AppSupportURL={#MyAppURL}
 | 
			
		||||
AppUpdatesURL={#MyAppURL}
 | 
			
		||||
DefaultDirName={pf}\{#MyAppName}
 | 
			
		||||
DefaultGroupName={#MyAppName}
 | 
			
		||||
AllowNoIcons=yes   
 | 
			
		||||
PrivilegesRequired=admin
 | 
			
		||||
CloseApplications=yes
 | 
			
		||||
OutputDir=..
 | 
			
		||||
OutputBaseFilename=screen-translator-{#MyAppVersion}
 | 
			
		||||
SetupIconFile=icon.ico
 | 
			
		||||
RestartIfNeededByRun=False
 | 
			
		||||
ShowLanguageDialog=auto             
 | 
			
		||||
VersionInfoCompany={#MyAppPublisher}
 | 
			
		||||
VersionInfoDescription={#MyAppDescription}
 | 
			
		||||
VersionInfoProductName={#MyAppName}
 | 
			
		||||
VersionInfoProductVersion={#MyAppVersion}
 | 
			
		||||
VersionInfoVersion={#MyAppVersion}
 | 
			
		||||
Compression=lzma2/ultra64
 | 
			
		||||
InternalCompressLevel=ultra   
 | 
			
		||||
SolidCompression=yes     
 | 
			
		||||
 | 
			
		||||
[Languages]
 | 
			
		||||
Name: "en"; MessagesFile: "compiler:Default.isl"; LicenseFile: "LICENSE_en.md"; InfoBeforeFile: "Changelog_en.txt"
 | 
			
		||||
Name: "ru"; MessagesFile: "compiler:Languages\Russian.isl"; LicenseFile: "LICENSE_ru.md"; InfoBeforeFile: "Changelog_ru.txt"  
 | 
			
		||||
 | 
			
		||||
[Tasks]
 | 
			
		||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked        
 | 
			
		||||
Name: "startupicon"; Description: "{cm:CreateStartupIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
 | 
			
		||||
Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1  
 | 
			
		||||
 | 
			
		||||
[Icons]
 | 
			
		||||
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
 | 
			
		||||
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
 | 
			
		||||
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
 | 
			
		||||
Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: quicklaunchicon      
 | 
			
		||||
Name: "{commonstartup}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: startupicon   
 | 
			
		||||
 | 
			
		||||
[Run]
 | 
			
		||||
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
 | 
			
		||||
 | 
			
		||||
[Files]
 | 
			
		||||
Source: "content\ScreenTranslator.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: Executable  
 | 
			
		||||
Source: "content\*.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: Libraries
 | 
			
		||||
Source: "content\platforms\*"; DestDir: "{app}\platforms"; Flags: ignoreversion; Components: Libraries  
 | 
			
		||||
Source: "content\translators\*"; DestDir: "{app}\translators"; Flags: ignoreversion; Components: Translators
 | 
			
		||||
 | 
			
		||||
[Components]
 | 
			
		||||
Name: "Executable"; Description: "{cm:Executables}"; Types: compact custom full; Flags: fixed;
 | 
			
		||||
Name: "Libraries"; Description: "{cm:Libraries}"; Types: compact custom full; Flags: fixed;   
 | 
			
		||||
Name: "Translators"; Description: "{cm:Translators}"; Types: compact custom full; Flags: fixed;
 | 
			
		||||
 | 
			
		||||
[CustomMessages]
 | 
			
		||||
en.CreateStartupIcon=Create autostart icon
 | 
			
		||||
en.Executables=Executables 
 | 
			
		||||
en.Libraries=Libraries     
 | 
			
		||||
en.Translators=Translators
 | 
			
		||||
 | 
			
		||||
ru.CreateStartupIcon=Äîáàâèòü â àâòîçàïóñê
 | 
			
		||||
ru.Executables=Èñïîëíÿåìûå ôàéëû
 | 
			
		||||
ru.Libraries=Áèáëèîòåêè
 | 
			
		||||
ru.Translators=Ïåðåâîä÷èêè
 | 
			
		||||
 | 
			
		||||
#include "tessdata.iss"
 | 
			
		||||
 | 
			
		||||
[UninstallDelete]
 | 
			
		||||
Type: files; Name: "{app}\updates.json"    
 | 
			
		||||
Type: files; Name: "{app}\st_subs.csv"
 | 
			
		||||
 | 
			
		||||
[UninstallRun]
 | 
			
		||||
Filename: "taskkill.exe"; Parameters: "/IM ScreenTranslator.exe /T /F"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[Code]               
 | 
			
		||||
#define DwinsHs_Use_Predefined_Downloading_WizardPage
 | 
			
		||||
#define DwinsHs_Auto_Continue
 | 
			
		||||
#include "dwinshs.iss"
 | 
			
		||||
 | 
			
		||||
procedure InitializeWizard();
 | 
			
		||||
begin
 | 
			
		||||
  DwinsHs_InitializeWizard(wpPreparing);
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
procedure CurPageChanged(CurPageID: Integer);
 | 
			
		||||
begin
 | 
			
		||||
  DwinsHs_CurPageChanged(CurPageID, nil, nil);
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
function ShouldSkipPage(CurPageId: Integer): Boolean;
 | 
			
		||||
begin
 | 
			
		||||
  Result := False;
 | 
			
		||||
  DwinsHs_ShouldSkipPage(CurPageId, Result);
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
function BackButtonClick(CurPageID: Integer): Boolean;
 | 
			
		||||
begin
 | 
			
		||||
  Result := True;
 | 
			
		||||
  DwinsHs_BackButtonClick(CurPageID);
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
function NextButtonClick(CurPageID: Integer): Boolean;
 | 
			
		||||
begin
 | 
			
		||||
  Result := True;
 | 
			
		||||
  DwinsHs_NextButtonClick(CurPageID, Result);
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
 | 
			
		||||
begin
 | 
			
		||||
  DwinsHs_CancelButtonClick(CurPageID, Cancel, Confirm);
 | 
			
		||||
end;
 | 
			
		||||
  
 | 
			
		||||
[CustomMessages]
 | 
			
		||||
ru.DwinsHs_PageCaption =Çàãðóçêà ôàéëîâ
 | 
			
		||||
ru.DwinsHs_PageDescription =Ïîæàëóéñòà, äîæäèòåñü îêîí÷àíèÿ çàãðóçêè...
 | 
			
		||||
ru.DwinsHs_TotalProgress =Îáùèé ïðîãðåññ:
 | 
			
		||||
ru.DwinsHs_CurrentFile =Òåêóùèé ôàéë:
 | 
			
		||||
ru.DwinsHs_File =Ôàéë:
 | 
			
		||||
ru.DwinsHs_Speed =Ñêîðîñòü:
 | 
			
		||||
ru.DwinsHs_Status =Ñòàòóñ:
 | 
			
		||||
ru.DwinsHs_ElapsedTime =Çàòðà÷åííîå âðåìÿ:
 | 
			
		||||
ru.DwinsHs_RemainingTime =Îñòàâøååñÿ âðåìÿ:
 | 
			
		||||
 | 
			
		||||
ru.DwinsHs_Status_GetFileInformation =Ïîëó÷åíèÿ ðàçìåðà ôàéëà
 | 
			
		||||
ru.DwinsHs_Status_StartingDownload =Íà÷àëî çàãðóçêè
 | 
			
		||||
ru.DwinsHs_Status_Downloading =Çàãðóçêà
 | 
			
		||||
ru.DwinsHs_Status_DownlaodComplete =Çàãðóçêà çàâåðøåíà          
 | 
			
		||||
							
								
								
									
										9
									
								
								distr/iss/LICENSE_ru.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,9 @@
 | 
			
		||||
Лицензия MIT
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2015 Gres (gres@gres.biz)
 | 
			
		||||
 | 
			
		||||
Данная лицензия разрешает лицам, получившим копию данного программного обеспечения и сопутствующей документации (в дальнейшем именуемыми «Программное Обеспечение»), безвозмездно использовать Программное Обеспечение без ограничений, включая неограниченное право на использование, копирование, изменение, добавление, публикацию, распространение, сублицензирование и/или продажу копий Программного Обеспечения, а также лицам, которым предоставляется данное Программное Обеспечение, при соблюдении следующих условий:
 | 
			
		||||
 | 
			
		||||
Указанное выше уведомление об авторском праве и данные условия должны быть включены во все копии или значимые части данного Программного Обеспечения.
 | 
			
		||||
 | 
			
		||||
ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ПО КАКИМ-ЛИБО ИСКАМ, ЗА УЩЕРБ ИЛИ ПО ИНЫМ ТРЕБОВАНИЯМ, В ТОМ ЧИСЛЕ, ПРИ ДЕЙСТВИИ КОНТРАКТА, ДЕЛИКТЕ ИЛИ ИНОЙ СИТУАЦИИ, ВОЗНИКШИМ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.
 | 
			
		||||
							
								
								
									
										109
									
								
								distr/iss/code2langTr.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,109 @@
 | 
			
		||||
#iso-639-3 standard code to names
 | 
			
		||||
afr Afrikaans Африкаанс 
 | 
			
		||||
amh Amharic Амхарский 
 | 
			
		||||
ara Arabic Арабский 
 | 
			
		||||
asm Assamese Ассамский 
 | 
			
		||||
aze Azerbaijani Азербайджанский 
 | 
			
		||||
#aze_cyrl aze_cyrl 
 | 
			
		||||
bel Belarusian Белорусский 
 | 
			
		||||
ben Bengali Бенгальский 
 | 
			
		||||
bod Tibetan Тибетский 
 | 
			
		||||
bos Bosnian Боснийский 
 | 
			
		||||
bul Bulgarian Болгарии 
 | 
			
		||||
cat Catalan Каталонский 
 | 
			
		||||
ceb Cebuano Кебуано 
 | 
			
		||||
ces Czech Чешский 
 | 
			
		||||
chi_sim Chineese_simplified Китайский_упрощенный 
 | 
			
		||||
chi_tra Chineese_traditional Китайский_традиционный 
 | 
			
		||||
chr Cherokee Чероки 
 | 
			
		||||
cym Welsh Валлийский 
 | 
			
		||||
dan Danish Датский 
 | 
			
		||||
#dan_frak dan_frak 
 | 
			
		||||
deu German Немецкий 
 | 
			
		||||
#deu_frak deu_frak 
 | 
			
		||||
dzo Dzongkha Джонгкха 
 | 
			
		||||
ell Modern_Greek Новогреческий 
 | 
			
		||||
eng English Английский 
 | 
			
		||||
enm Middle_English Средневековый_английский 
 | 
			
		||||
epo Esperanto Эсперанто 
 | 
			
		||||
equ Math Математика 
 | 
			
		||||
est Estonian Эстонский 
 | 
			
		||||
eus Basque Басков 
 | 
			
		||||
fas Persian Персидский 
 | 
			
		||||
fin Finnish Финский 
 | 
			
		||||
fra French Французский 
 | 
			
		||||
frk Frankish Франкский 
 | 
			
		||||
frm Middle_French Средневековый_французский 
 | 
			
		||||
gle Irish Ирландский 
 | 
			
		||||
glg Galician Галисийский 
 | 
			
		||||
grc Ancient_Greek Древнегреческий 
 | 
			
		||||
guj Gujarati Гуджарати 
 | 
			
		||||
hat Haitian Гаити 
 | 
			
		||||
heb Hebrew Иврит 
 | 
			
		||||
hin Hindi Хинди 
 | 
			
		||||
hrv Croatian Хорватский 
 | 
			
		||||
hun Hungarian Венгерский 
 | 
			
		||||
iku Inuktitut Инуктитут 
 | 
			
		||||
ind Indonesian Индонезийский 
 | 
			
		||||
isl Icelandic Исландский 
 | 
			
		||||
ita Italian Итальянский 
 | 
			
		||||
#ita_old ita_old 
 | 
			
		||||
jav Javanese Яванский 
 | 
			
		||||
jpn Japanese Японский 
 | 
			
		||||
kan Kannada Каннада 
 | 
			
		||||
kat Georgian Грузинский 
 | 
			
		||||
#kat_old kat_old 
 | 
			
		||||
kaz Kazakh Казахский 
 | 
			
		||||
khm Khmer Кхмерский 
 | 
			
		||||
kir Kirghiz Киргизский 
 | 
			
		||||
kor Korean Корейский 
 | 
			
		||||
kur Kurdish Курдский 
 | 
			
		||||
lao Lao Лао 
 | 
			
		||||
lat Latin Латинский 
 | 
			
		||||
lav Latvian Латышский 
 | 
			
		||||
lit Lithuanian Литовский 
 | 
			
		||||
mal Malayalam Малаялам 
 | 
			
		||||
mar Marathi Маратхи 
 | 
			
		||||
mkd Macedonian Македонский 
 | 
			
		||||
mlt Maltese Мальтийский 
 | 
			
		||||
msa Malay Малайский 
 | 
			
		||||
mya Burmese Бирманский 
 | 
			
		||||
nep Nepali Непальский 
 | 
			
		||||
nld Dutch Голландский 
 | 
			
		||||
nor Norwegian Норвежский 
 | 
			
		||||
ori Oriya Ория 
 | 
			
		||||
#osd OSD OSD 
 | 
			
		||||
pan Panjabi Панджаби 
 | 
			
		||||
pol Polish Польский 
 | 
			
		||||
por Portuguese Португальский 
 | 
			
		||||
pus Pushto Пушту 
 | 
			
		||||
ron Romanian Румынский 
 | 
			
		||||
rus Russian Русский 
 | 
			
		||||
san Sanskrit Санскрит 
 | 
			
		||||
sin Sinhala Сингальский 
 | 
			
		||||
slk Slovak Словацкий 
 | 
			
		||||
#slk_frak slk_frak 
 | 
			
		||||
slv Slovenian Словенский 
 | 
			
		||||
spa Spanish Испанский 
 | 
			
		||||
#spa_old spa_old 
 | 
			
		||||
sqi Albanian Албанский 
 | 
			
		||||
srp Serbian Сербский 
 | 
			
		||||
#srp_latn srp_latn 
 | 
			
		||||
swa Swahili Суахили 
 | 
			
		||||
swe Swedish Шведский 
 | 
			
		||||
syr Syriac Сирийский 
 | 
			
		||||
tam Tamil Тамил 
 | 
			
		||||
tel Telugu Телугу 
 | 
			
		||||
tgk Tajik Таджикиский 
 | 
			
		||||
tgl Tagalog Тагальский 
 | 
			
		||||
tha Thai Тайский 
 | 
			
		||||
tir Tigrinya Тиграи 
 | 
			
		||||
tur Turkish Турецкий 
 | 
			
		||||
uig Uighur Уйгурский 
 | 
			
		||||
ukr Ukrainian Украинский 
 | 
			
		||||
urd Urdu Урду 
 | 
			
		||||
uzb Uzbek Узбекский 
 | 
			
		||||
#uzb_cyrl uzb_cyrl 
 | 
			
		||||
vie Vietnamese Вьетнамский 
 | 
			
		||||
yid Yiddish Идиш 
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1266
									
								
								distr/iss/dwinshs.iss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										230
									
								
								distr/iss/make_tess_iss.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						@ -0,0 +1,230 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
TESSDATA_DIR="../../../tessdata"
 | 
			
		||||
TESSDATA_TAG="3.04.00"
 | 
			
		||||
for arg in ${@}; do
 | 
			
		||||
  case "$arg" in
 | 
			
		||||
    "tessdata" ) TESSDATA_DIR="$arg";;
 | 
			
		||||
    "tag="* ) TESSDATA_TAG=${arg:4};;
 | 
			
		||||
  esac
 | 
			
		||||
done
 | 
			
		||||
TESSDATA_DIR=`readlink -e $TESSDATA_DIR`
 | 
			
		||||
OUT_FILE="tessdata.iss"
 | 
			
		||||
OUT_FILE=`readlink -m $OUT_FILE`
 | 
			
		||||
LANGS_FILE="code2langTr.txt"
 | 
			
		||||
 | 
			
		||||
function getLangsOrder {
 | 
			
		||||
  local FIELD=$1
 | 
			
		||||
  local ORDER=`cat $LANGS_FILE | cut -d' ' -f$FIELD | sort`
 | 
			
		||||
  local FNAMES=""
 | 
			
		||||
  for i in $ORDER; do
 | 
			
		||||
    local FNAME=`grep "$i" $LANGS_FILE | cut -d' ' -f1`
 | 
			
		||||
    if [[ -z "$FNAME" || "${FNAME:0:1}" == "#" ]]; then
 | 
			
		||||
      continue;
 | 
			
		||||
    fi
 | 
			
		||||
    FNAMES=$FNAMES" $FNAME"
 | 
			
		||||
  done
 | 
			
		||||
  echo $FNAMES
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FILES="[Files]\n"
 | 
			
		||||
COMPONENTS="[Components]\nName: \"Languages\"; Description: \"{cm:Languages}\"; Types: custom full\n"
 | 
			
		||||
MESSAGES_EN="\n[CustomMessages]\nen.Languages=OCR Languages\n"
 | 
			
		||||
MESSAGES_RU="\n[CustomMessages]\nru.Languages=Языки распознавания\n"
 | 
			
		||||
PREV_LANG=""
 | 
			
		||||
COMPACT_LANGS="eng rus deu spa chi_sim fra jpn"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function fillIss {
 | 
			
		||||
  local LANG_FIELD=$1
 | 
			
		||||
  local COMPONENT_LANG=$2
 | 
			
		||||
  local ONLY_COMPONENTS=$3
 | 
			
		||||
  COMPONENTS=$COMPONENTS"\n"
 | 
			
		||||
  local ORDER=`cat $LANGS_FILE | cut -d' ' -f$LANG_FIELD | sort`
 | 
			
		||||
  for i in $ORDER; do
 | 
			
		||||
    local LANG_LINE=$(grep " $i " $LANGS_FILE)
 | 
			
		||||
    local FNAME=$(echo "$LANG_LINE" | cut -d' ' -f1)
 | 
			
		||||
    local LANG_EN=$(echo "$LANG_LINE" | cut -d' ' -f2)
 | 
			
		||||
    local LANG_RU=$(echo "$LANG_LINE" | cut -d' ' -f3)
 | 
			
		||||
    if [[ -z "$FNAME" || "${FNAME:0:1}" == "#" ]]; then
 | 
			
		||||
      continue;
 | 
			
		||||
    fi
 | 
			
		||||
    
 | 
			
		||||
    local CUR_LANG_FILES=`find $TESSDATA_DIR -name "$FNAME.*"`
 | 
			
		||||
    if [ -z "$CUR_LANG_FILES" ]; then
 | 
			
		||||
      echo "no lang"
 | 
			
		||||
      continue
 | 
			
		||||
    fi    
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    local COMPONENT_SIZE=0
 | 
			
		||||
    for s in `find $TESSDATA_DIR -name "$FNAME.*" -exec wc -c {} \; | cut -d' ' -f1`; do
 | 
			
		||||
      COMPONENT_SIZE=$(expr $COMPONENT_SIZE + $s)
 | 
			
		||||
    done
 | 
			
		||||
    TYPES="full"
 | 
			
		||||
    if [[ $COMPACT_LANGS =~ $FNAME ]]; then
 | 
			
		||||
      TYPES="compact custom $TYPES"
 | 
			
		||||
    fi
 | 
			
		||||
    COMPONENTS=$COMPONENTS"Name: \"Languages\\\\$LANG_EN\"; Description: \"{cm:$LANG_EN}\"; Languages: $COMPONENT_LANG; 
 | 
			
		||||
      Types: $TYPES; ExtraDiskSpaceRequired: $COMPONENT_SIZE\n"      
 | 
			
		||||
      
 | 
			
		||||
      
 | 
			
		||||
    if $ONLY_COMPONENTS; then
 | 
			
		||||
      continue;
 | 
			
		||||
    fi    
 | 
			
		||||
    MESSAGES_EN=$MESSAGES_EN"en.$LANG_EN=$(echo "$LANG_EN" | sed 's/_/ /g')\n"
 | 
			
		||||
    MESSAGES_RU=$MESSAGES_RU"ru.$LANG_EN=$(echo "$LANG_RU" | sed 's/_/ /g')\n"
 | 
			
		||||
    
 | 
			
		||||
    for f in $CUR_LANG_FILES; do
 | 
			
		||||
      local FNAME=$(basename "$f")
 | 
			
		||||
      FILES=$FILES"Source: \"{tmp}\\\\$FNAME\"; DestDir: \"{app}\\\\tessdata\"; Components: Languages\\\\$LANG_EN; 
 | 
			
		||||
	Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\\\\$FNAME'), 
 | 
			
		||||
	  'https://cdn.rawgit.com/tesseract-ocr/tessdata/$TESSDATA_TAG/$FNAME', 'ST_setup', 'Get', 0);\n"
 | 
			
		||||
    done
 | 
			
		||||
  done
 | 
			
		||||
}
 | 
			
		||||
fillIss 2 "en" false
 | 
			
		||||
fillIss 3 "ru" true
 | 
			
		||||
 | 
			
		||||
echo -e $FILES > $OUT_FILE
 | 
			
		||||
echo -e $COMPONENTS >> $OUT_FILE
 | 
			
		||||
echo -e $MESSAGES_EN >> $OUT_FILE
 | 
			
		||||
echo -e $MESSAGES_RU >> $OUT_FILE
 | 
			
		||||
iconv -f utf8 -t cp1251 $OUT_FILE -o $OUT_FILE.1
 | 
			
		||||
mv $OUT_FILE.1 $OUT_FILE
 | 
			
		||||
 | 
			
		||||
exit 0
 | 
			
		||||
function fillIss {
 | 
			
		||||
  local ORDER=$1
 | 
			
		||||
  local FIELD=$2
 | 
			
		||||
  local ONLY_COMPONENTS=$3
 | 
			
		||||
  local FILES=""
 | 
			
		||||
  for i in $ORDER; do
 | 
			
		||||
    local CUR_LANG_FILES=`find $TESSDATA_DIR -name \"$i.*\"`
 | 
			
		||||
    if [ -z "$CUR_LANG_FILES" ]; then
 | 
			
		||||
      continue
 | 
			
		||||
    fi
 | 
			
		||||
    FILES=$FILES" `find $TESSDATA_DIR -name \"$i.*\"`"
 | 
			
		||||
  done
 | 
			
		||||
  for i in $FILES; do
 | 
			
		||||
  local fName=$(basename "$i")
 | 
			
		||||
  local LANG=$(echo "$fName" | cut -d'.' -f1)
 | 
			
		||||
  LANG_LINE=$(grep "$lang " $LANGS_FILE)
 | 
			
		||||
  if [[ -z "$LANG_LINE" || "${LANG_LINE:0:1}" == "#" ]]; then
 | 
			
		||||
    continue;
 | 
			
		||||
  fi
 | 
			
		||||
  LANG_EN=$(echo "$LANG_LINE" | cut -d' ' -f2)
 | 
			
		||||
  LANG_RU=$(echo "$LANG_LINE" | cut -d' ' -f3)
 | 
			
		||||
  if ! $ONLY_COMP; then
 | 
			
		||||
  FILES=$FILES"Source: \"{tmp}\\\\$fName\"; DestDir: \"{app}\\\\tessdata\"; Components: Languages\\\\$LANG_EN; 
 | 
			
		||||
  Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\\\\$fName'), 
 | 
			
		||||
    'https://cdn.rawgit.com/tesseract-ocr/tessdata/$TESSDATA_TAG/$fName', 'ST_setup', 'Get', 0);\n"
 | 
			
		||||
  fi
 | 
			
		||||
  if [ "$PREV_LANG" != "$LANG_EN" ]; then
 | 
			
		||||
    PREV_LANG="$LANG_EN"
 | 
			
		||||
    SIZE=0
 | 
			
		||||
    for s in `find $TESSDATA_DIR -name "$lang.*" -exec wc -c {} \; | cut -d' ' -f1`; do
 | 
			
		||||
      SIZE=$(expr $SIZE + $s)
 | 
			
		||||
    done
 | 
			
		||||
    TYPES="full"
 | 
			
		||||
    if [[ $COMPACT_LANGS =~ $lang ]]; then
 | 
			
		||||
      TYPES="compact custom $TYPES"
 | 
			
		||||
    fi
 | 
			
		||||
    COMPONENTS=$COMPONENTS"Name: \"Languages\\\\$LANG_EN\"; Description: \"{cm:$LANG_EN}\"; Languages: $LLANG; Types: $TYPES; ExtraDiskSpaceRequired: $SIZE\n"
 | 
			
		||||
    
 | 
			
		||||
  if ! $ONLY_COMP; then
 | 
			
		||||
    MESSAGES_EN=$MESSAGES_EN"en.$LANG_EN=$(echo "$LANG_EN" | sed 's/_/ /g')\n"
 | 
			
		||||
    MESSAGES_RU=$MESSAGES_RU"ru.$LANG_EN=$(echo "$LANG_RU" | sed 's/_/ /g')\n"
 | 
			
		||||
  fi
 | 
			
		||||
  fi
 | 
			
		||||
  done
 | 
			
		||||
}
 | 
			
		||||
echo $(fillIss "$(getLangsOrder 2)" "en" false)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function doJob {
 | 
			
		||||
LLANG=$2
 | 
			
		||||
ONLY_COMP=$3
 | 
			
		||||
for fff in $1; do
 | 
			
		||||
  for f in `find $TESSDATA_DIR -name "$fff.*"`; do
 | 
			
		||||
  f=$(basename "$f")
 | 
			
		||||
  lang=$(echo "$f" | cut -d'.' -f1)
 | 
			
		||||
  LANG_LINE=$(grep "$lang " $LANGS_FILE)
 | 
			
		||||
  if [[ -z "$LANG_LINE" || "${LANG_LINE:0:1}" == "#" ]]; then
 | 
			
		||||
    continue;
 | 
			
		||||
  fi
 | 
			
		||||
  LANG_EN=$(echo "$LANG_LINE" | cut -d' ' -f2)
 | 
			
		||||
  LANG_RU=$(echo "$LANG_LINE" | cut -d' ' -f3)
 | 
			
		||||
  if ! $ONLY_COMP; then
 | 
			
		||||
  FILES=$FILES"Source: \"{tmp}\\\\$f\"; DestDir: \"{app}\\\\tessdata\"; Components: Languages\\\\$LANG_EN; 
 | 
			
		||||
  Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\\\\$f'), 
 | 
			
		||||
    'https://cdn.rawgit.com/tesseract-ocr/tessdata/$TESSDATA_TAG/$f', 'ST_setup', 'Get', 0);\n"
 | 
			
		||||
  fi
 | 
			
		||||
  if [ "$PREV_LANG" != "$LANG_EN" ]; then
 | 
			
		||||
    PREV_LANG="$LANG_EN"
 | 
			
		||||
    SIZE=0
 | 
			
		||||
    for s in `find $TESSDATA_DIR -name "$lang.*" -exec wc -c {} \; | cut -d' ' -f1`; do
 | 
			
		||||
      SIZE=$(expr $SIZE + $s)
 | 
			
		||||
    done
 | 
			
		||||
    TYPES="full"
 | 
			
		||||
    if [[ $COMPACT_LANGS =~ $lang ]]; then
 | 
			
		||||
      TYPES="compact custom $TYPES"
 | 
			
		||||
    fi
 | 
			
		||||
    COMPONENTS=$COMPONENTS"Name: \"Languages\\\\$LANG_EN\"; Description: \"{cm:$LANG_EN}\"; Languages: $LLANG; Types: $TYPES; ExtraDiskSpaceRequired: $SIZE\n"
 | 
			
		||||
    
 | 
			
		||||
  if ! $ONLY_COMP; then
 | 
			
		||||
    MESSAGES_EN=$MESSAGES_EN"en.$LANG_EN=$(echo "$LANG_EN" | sed 's/_/ /g')\n"
 | 
			
		||||
    MESSAGES_RU=$MESSAGES_RU"ru.$LANG_EN=$(echo "$LANG_RU" | sed 's/_/ /g')\n"
 | 
			
		||||
  fi
 | 
			
		||||
  fi
 | 
			
		||||
  done
 | 
			
		||||
done
 | 
			
		||||
}
 | 
			
		||||
doJob "$(getOrder 2)" "en" false
 | 
			
		||||
doJob "$(getOrder 3)" "ru" true
 | 
			
		||||
echo $COMPONENTS
 | 
			
		||||
echo -e $FILES > $OUT_FILE
 | 
			
		||||
echo -e $COMPONENTS >> $OUT_FILE
 | 
			
		||||
echo -e $MESSAGES_EN >> $OUT_FILE
 | 
			
		||||
echo -e $MESSAGES_RU >> $OUT_FILE
 | 
			
		||||
iconv -f utf8 -t cp1251 $OUT_FILE -o $OUT_FILE.1
 | 
			
		||||
mv $OUT_FILE.1 $OUT_FILE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
exit 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
for f in `ls $TESSDATA_DIR | sort`; do
 | 
			
		||||
  lang=$(echo "$f" | cut -d'.' -f1)
 | 
			
		||||
  LANG_LINE=$(grep "$lang " $LANGS_FILE)
 | 
			
		||||
  if [[ -z "$LANG_LINE" || "${LANG_LINE:0:1}" == "#" ]]; then
 | 
			
		||||
    continue;
 | 
			
		||||
  fi
 | 
			
		||||
  LANG_EN=$(echo "$LANG_LINE" | cut -d' ' -f2)
 | 
			
		||||
  LANG_RU=$(echo "$LANG_LINE" | cut -d' ' -f3)
 | 
			
		||||
  FILES=$FILES"Source: \"{tmp}\\\\$f\"; DestDir: \"{app}\\\\tessdata\"; Components: Languages\\\\$LANG_EN; 
 | 
			
		||||
  Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\\\\$f'), 
 | 
			
		||||
    'https://cdn.rawgit.com/tesseract-ocr/tessdata/$TESSDATA_TAG/$f', 'ST_setup', 'Get', 0);\n"
 | 
			
		||||
  if [ "$PREV_LANG" != "$LANG_EN" ]; then
 | 
			
		||||
    PREV_LANG="$LANG_EN"
 | 
			
		||||
    SIZE=0
 | 
			
		||||
    for s in `find $TESSDATA_DIR -name "$lang.*" -exec wc -c {} \; | cut -d' ' -f1`; do
 | 
			
		||||
      SIZE=$(expr $SIZE + $s)
 | 
			
		||||
    done
 | 
			
		||||
    TYPES="full"
 | 
			
		||||
    if [[ $COMPACT_LANGS =~ $lang ]]; then
 | 
			
		||||
      TYPES="compact custom $TYPES"
 | 
			
		||||
    fi
 | 
			
		||||
    COMPONENTS=$COMPONENTS"Name: \"Languages\\\\$LANG_EN\"; Description: \"{cm:$LANG_EN}\"; Types: $TYPES; ExtraDiskSpaceRequired: $SIZE\n"
 | 
			
		||||
    MESSAGES_EN=$MESSAGES_EN"en.$LANG_EN=$(echo "$LANG_EN" | sed 's/_/ /g')\n"
 | 
			
		||||
    MESSAGES_RU=$MESSAGES_RU"ru.$LANG_EN=$(echo "$LANG_RU" | sed 's/_/ /g')\n"
 | 
			
		||||
  fi
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
echo -e $FILES > $OUT_FILE
 | 
			
		||||
echo -e $COMPONENTS >> $OUT_FILE
 | 
			
		||||
echo -e $MESSAGES_EN >> $OUT_FILE
 | 
			
		||||
echo -e $MESSAGES_RU >> $OUT_FILE
 | 
			
		||||
iconv -f utf8 -t cp1251 $OUT_FILE -o $OUT_FILE.1
 | 
			
		||||
mv $OUT_FILE.1 $OUT_FILE
 | 
			
		||||
							
								
								
									
										551
									
								
								distr/iss/tessdata.iss
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,551 @@
 | 
			
		||||
[Files]
 | 
			
		||||
Source: "{tmp}\afr.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Afrikaans; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\afr.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/afr.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\sqi.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Albanian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\sqi.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/sqi.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\amh.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Amharic; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\amh.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/amh.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\grc.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Ancient_Greek; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\grc.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/grc.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ara.cube.lm"; DestDir: "{app}\tessdata"; Components: Languages\Arabic; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ara.cube.lm'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ara.cube.lm', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ara.cube.params"; DestDir: "{app}\tessdata"; Components: Languages\Arabic; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ara.cube.params'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ara.cube.params', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ara.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Arabic; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ara.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ara.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ara.cube.size"; DestDir: "{app}\tessdata"; Components: Languages\Arabic; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ara.cube.size'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ara.cube.size', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ara.cube.bigrams"; DestDir: "{app}\tessdata"; Components: Languages\Arabic; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ara.cube.bigrams'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ara.cube.bigrams', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ara.cube.nn"; DestDir: "{app}\tessdata"; Components: Languages\Arabic; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ara.cube.nn'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ara.cube.nn', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ara.cube.word-freq"; DestDir: "{app}\tessdata"; Components: Languages\Arabic; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ara.cube.word-freq'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ara.cube.word-freq', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ara.cube.fold"; DestDir: "{app}\tessdata"; Components: Languages\Arabic; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ara.cube.fold'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ara.cube.fold', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\asm.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Assamese; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\asm.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/asm.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\aze.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Azerbaijani; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\aze.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/aze.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\eus.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Basque; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\eus.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/eus.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\bel.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Belarusian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\bel.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/bel.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ben.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Bengali; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ben.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ben.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\bos.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Bosnian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\bos.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/bos.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\bul.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Bulgarian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\bul.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/bul.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\mya.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Burmese; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\mya.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/mya.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\cat.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Catalan; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\cat.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/cat.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ceb.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Cebuano; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ceb.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ceb.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\chr.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Cherokee; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\chr.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/chr.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\chi_sim.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Chineese_simplified; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\chi_sim.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/chi_sim.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\chi_tra.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Chineese_traditional; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\chi_tra.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/chi_tra.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\hrv.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Croatian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\hrv.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/hrv.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ces.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Czech; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ces.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ces.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\dan.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Danish; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\dan.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/dan.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\nld.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Dutch; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\nld.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/nld.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\dzo.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Dzongkha; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\dzo.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/dzo.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\eng.cube.size"; DestDir: "{app}\tessdata"; Components: Languages\English; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\eng.cube.size'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/eng.cube.size', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\eng.tesseract_cube.nn"; DestDir: "{app}\tessdata"; Components: Languages\English; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\eng.tesseract_cube.nn'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/eng.tesseract_cube.nn', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\eng.cube.lm"; DestDir: "{app}\tessdata"; Components: Languages\English; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\eng.cube.lm'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/eng.cube.lm', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\eng.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\English; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\eng.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/eng.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\eng.cube.word-freq"; DestDir: "{app}\tessdata"; Components: Languages\English; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\eng.cube.word-freq'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/eng.cube.word-freq', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\eng.cube.nn"; DestDir: "{app}\tessdata"; Components: Languages\English; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\eng.cube.nn'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/eng.cube.nn', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\eng.cube.fold"; DestDir: "{app}\tessdata"; Components: Languages\English; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\eng.cube.fold'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/eng.cube.fold', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\eng.cube.bigrams"; DestDir: "{app}\tessdata"; Components: Languages\English; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\eng.cube.bigrams'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/eng.cube.bigrams', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\eng.cube.params"; DestDir: "{app}\tessdata"; Components: Languages\English; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\eng.cube.params'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/eng.cube.params', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\epo.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Esperanto; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\epo.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/epo.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\est.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Estonian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\est.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/est.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\fin.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Finnish; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\fin.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/fin.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\frk.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Frankish; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\frk.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/frk.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\fra.cube.size"; DestDir: "{app}\tessdata"; Components: Languages\French; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\fra.cube.size'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/fra.cube.size', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\fra.cube.nn"; DestDir: "{app}\tessdata"; Components: Languages\French; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\fra.cube.nn'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/fra.cube.nn', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\fra.cube.params"; DestDir: "{app}\tessdata"; Components: Languages\French; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\fra.cube.params'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/fra.cube.params', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\fra.tesseract_cube.nn"; DestDir: "{app}\tessdata"; Components: Languages\French; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\fra.tesseract_cube.nn'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/fra.tesseract_cube.nn', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\fra.cube.fold"; DestDir: "{app}\tessdata"; Components: Languages\French; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\fra.cube.fold'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/fra.cube.fold', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\fra.cube.lm"; DestDir: "{app}\tessdata"; Components: Languages\French; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\fra.cube.lm'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/fra.cube.lm', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\fra.cube.word-freq"; DestDir: "{app}\tessdata"; Components: Languages\French; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\fra.cube.word-freq'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/fra.cube.word-freq', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\fra.cube.bigrams"; DestDir: "{app}\tessdata"; Components: Languages\French; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\fra.cube.bigrams'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/fra.cube.bigrams', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\fra.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\French; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\fra.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/fra.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\glg.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Galician; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\glg.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/glg.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\kat.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Georgian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\kat.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/kat.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\deu.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\German; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\deu.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/deu.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\guj.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Gujarati; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\guj.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/guj.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\hat.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Haitian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\hat.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/hat.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\heb.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Hebrew; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\heb.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/heb.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\hin.cube.fold"; DestDir: "{app}\tessdata"; Components: Languages\Hindi; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\hin.cube.fold'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/hin.cube.fold', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\hin.cube.lm"; DestDir: "{app}\tessdata"; Components: Languages\Hindi; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\hin.cube.lm'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/hin.cube.lm', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\hin.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Hindi; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\hin.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/hin.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\hin.cube.nn"; DestDir: "{app}\tessdata"; Components: Languages\Hindi; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\hin.cube.nn'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/hin.cube.nn', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\hin.tesseract_cube.nn"; DestDir: "{app}\tessdata"; Components: Languages\Hindi; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\hin.tesseract_cube.nn'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/hin.tesseract_cube.nn', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\hin.cube.params"; DestDir: "{app}\tessdata"; Components: Languages\Hindi; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\hin.cube.params'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/hin.cube.params', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\hin.cube.word-freq"; DestDir: "{app}\tessdata"; Components: Languages\Hindi; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\hin.cube.word-freq'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/hin.cube.word-freq', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\hin.cube.bigrams"; DestDir: "{app}\tessdata"; Components: Languages\Hindi; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\hin.cube.bigrams'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/hin.cube.bigrams', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\hun.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Hungarian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\hun.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/hun.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\isl.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Icelandic; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\isl.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/isl.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ind.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Indonesian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ind.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ind.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\iku.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Inuktitut; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\iku.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/iku.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\gle.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Irish; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\gle.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/gle.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ita.cube.fold"; DestDir: "{app}\tessdata"; Components: Languages\Italian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ita.cube.fold'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ita.cube.fold', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ita.cube.size"; DestDir: "{app}\tessdata"; Components: Languages\Italian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ita.cube.size'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ita.cube.size', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ita.cube.word-freq"; DestDir: "{app}\tessdata"; Components: Languages\Italian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ita.cube.word-freq'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ita.cube.word-freq', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ita.cube.params"; DestDir: "{app}\tessdata"; Components: Languages\Italian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ita.cube.params'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ita.cube.params', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ita.cube.lm"; DestDir: "{app}\tessdata"; Components: Languages\Italian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ita.cube.lm'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ita.cube.lm', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ita.cube.bigrams"; DestDir: "{app}\tessdata"; Components: Languages\Italian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ita.cube.bigrams'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ita.cube.bigrams', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ita.tesseract_cube.nn"; DestDir: "{app}\tessdata"; Components: Languages\Italian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ita.tesseract_cube.nn'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ita.tesseract_cube.nn', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ita.cube.nn"; DestDir: "{app}\tessdata"; Components: Languages\Italian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ita.cube.nn'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ita.cube.nn', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ita.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Italian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ita.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ita.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\jpn.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Japanese; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\jpn.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/jpn.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\jav.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Javanese; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\jav.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/jav.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\kan.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Kannada; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\kan.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/kan.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\kaz.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Kazakh; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\kaz.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/kaz.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\khm.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Khmer; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\khm.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/khm.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\kir.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Kirghiz; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\kir.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/kir.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\kor.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Korean; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\kor.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/kor.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\kur.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Kurdish; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\kur.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/kur.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\lao.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Lao; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\lao.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/lao.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\lat.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Latin; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\lat.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/lat.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\lav.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Latvian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\lav.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/lav.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\lit.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Lithuanian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\lit.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/lit.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\mkd.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Macedonian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\mkd.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/mkd.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\msa.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Malay; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\msa.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/msa.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\mal.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Malayalam; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\mal.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/mal.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\mlt.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Maltese; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\mlt.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/mlt.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\mar.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Marathi; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\mar.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/mar.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\equ.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Math; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\equ.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/equ.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\enm.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Middle_English; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\enm.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/enm.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\frm.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Middle_French; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\frm.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/frm.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ell.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Modern_Greek; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ell.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ell.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\nep.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Nepali; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\nep.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/nep.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\nor.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Norwegian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\nor.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/nor.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ori.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Oriya; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ori.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ori.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\pan.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Panjabi; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\pan.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/pan.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\fas.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Persian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\fas.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/fas.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\pol.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Polish; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\pol.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/pol.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\por.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Portuguese; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\por.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/por.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\pus.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Pushto; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\pus.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/pus.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ron.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Romanian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ron.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ron.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\rus.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Russian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\rus.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/rus.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\rus.cube.nn"; DestDir: "{app}\tessdata"; Components: Languages\Russian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\rus.cube.nn'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/rus.cube.nn', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\rus.cube.fold"; DestDir: "{app}\tessdata"; Components: Languages\Russian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\rus.cube.fold'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/rus.cube.fold', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\rus.cube.lm"; DestDir: "{app}\tessdata"; Components: Languages\Russian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\rus.cube.lm'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/rus.cube.lm', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\rus.cube.size"; DestDir: "{app}\tessdata"; Components: Languages\Russian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\rus.cube.size'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/rus.cube.size', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\rus.cube.params"; DestDir: "{app}\tessdata"; Components: Languages\Russian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\rus.cube.params'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/rus.cube.params', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\rus.cube.word-freq"; DestDir: "{app}\tessdata"; Components: Languages\Russian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\rus.cube.word-freq'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/rus.cube.word-freq', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\san.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Sanskrit; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\san.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/san.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\srp.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Serbian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\srp.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/srp.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\sin.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Sinhala; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\sin.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/sin.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\slk.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Slovak; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\slk.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/slk.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\slv.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Slovenian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\slv.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/slv.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\spa.cube.fold"; DestDir: "{app}\tessdata"; Components: Languages\Spanish; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\spa.cube.fold'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/spa.cube.fold', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\spa.cube.nn"; DestDir: "{app}\tessdata"; Components: Languages\Spanish; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\spa.cube.nn'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/spa.cube.nn', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\spa.cube.lm"; DestDir: "{app}\tessdata"; Components: Languages\Spanish; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\spa.cube.lm'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/spa.cube.lm', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\spa.cube.bigrams"; DestDir: "{app}\tessdata"; Components: Languages\Spanish; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\spa.cube.bigrams'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/spa.cube.bigrams', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\spa.cube.size"; DestDir: "{app}\tessdata"; Components: Languages\Spanish; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\spa.cube.size'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/spa.cube.size', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\spa.cube.word-freq"; DestDir: "{app}\tessdata"; Components: Languages\Spanish; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\spa.cube.word-freq'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/spa.cube.word-freq', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\spa.cube.params"; DestDir: "{app}\tessdata"; Components: Languages\Spanish; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\spa.cube.params'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/spa.cube.params', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\spa.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Spanish; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\spa.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/spa.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\swa.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Swahili; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\swa.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/swa.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\swe.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Swedish; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\swe.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/swe.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\syr.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Syriac; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\syr.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/syr.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\tgl.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Tagalog; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\tgl.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/tgl.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\tgk.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Tajik; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\tgk.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/tgk.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\tam.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Tamil; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\tam.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/tam.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\tel.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Telugu; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\tel.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/tel.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\tha.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Thai; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\tha.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/tha.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\bod.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Tibetan; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\bod.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/bod.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\tir.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Tigrinya; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\tir.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/tir.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\tur.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Turkish; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\tur.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/tur.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\uig.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Uighur; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\uig.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/uig.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\ukr.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Ukrainian; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\ukr.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/ukr.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\urd.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Urdu; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\urd.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/urd.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\uzb.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Uzbek; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\uzb.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/uzb.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\vie.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Vietnamese; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\vie.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/vie.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\cym.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Welsh; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\cym.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/cym.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
Source: "{tmp}\yid.traineddata"; DestDir: "{app}\tessdata"; Components: Languages\Yiddish; Flags: external; Check: DwinsHs_Check(ExpandConstant('{tmp}\yid.traineddata'), 'https://cdn.rawgit.com/tesseract-ocr/tessdata/3.04.00/yid.traineddata', 'ST_setup', 'Get', 0);
 | 
			
		||||
 | 
			
		||||
[Components]
 | 
			
		||||
Name: "Languages"; Description: "{cm:Languages}"; Types: custom full
 | 
			
		||||
 | 
			
		||||
Name: "Languages\Afrikaans"; Description: "{cm:Afrikaans}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 5198548
 | 
			
		||||
Name: "Languages\Albanian"; Description: "{cm:Albanian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 6587325
 | 
			
		||||
Name: "Languages\Amharic"; Description: "{cm:Amharic}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 2953500
 | 
			
		||||
Name: "Languages\Ancient_Greek"; Description: "{cm:Ancient_Greek}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 5182527
 | 
			
		||||
Name: "Languages\Arabic"; Description: "{cm:Arabic}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 28534834
 | 
			
		||||
Name: "Languages\Assamese"; Description: "{cm:Assamese}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 15827072
 | 
			
		||||
Name: "Languages\Azerbaijani"; Description: "{cm:Azerbaijani}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 6615244
 | 
			
		||||
Name: "Languages\Basque"; Description: "{cm:Basque}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 4969647
 | 
			
		||||
Name: "Languages\Belarusian"; Description: "{cm:Belarusian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 6822594
 | 
			
		||||
Name: "Languages\Bengali"; Description: "{cm:Bengali}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 15552533
 | 
			
		||||
Name: "Languages\Bosnian"; Description: "{cm:Bosnian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 5432328
 | 
			
		||||
Name: "Languages\Bulgarian"; Description: "{cm:Bulgarian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 6026234
 | 
			
		||||
Name: "Languages\Burmese"; Description: "{cm:Burmese}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 69770179
 | 
			
		||||
Name: "Languages\Catalan"; Description: "{cm:Catalan}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 5356190
 | 
			
		||||
Name: "Languages\Cebuano"; Description: "{cm:Cebuano}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 1686752
 | 
			
		||||
Name: "Languages\Cherokee"; Description: "{cm:Cherokee}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 1083194
 | 
			
		||||
Name: "Languages\Chineese_simplified"; Description: "{cm:Chineese_simplified}"; Languages: en; Types: compact custom full; ExtraDiskSpaceRequired: 42089623
 | 
			
		||||
Name: "Languages\Chineese_traditional"; Description: "{cm:Chineese_traditional}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 56692327
 | 
			
		||||
Name: "Languages\Croatian"; Description: "{cm:Croatian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 9135966
 | 
			
		||||
Name: "Languages\Czech"; Description: "{cm:Czech}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 11896327
 | 
			
		||||
Name: "Languages\Danish"; Description: "{cm:Danish}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 7340575
 | 
			
		||||
Name: "Languages\Dutch"; Description: "{cm:Dutch}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 17098919
 | 
			
		||||
Name: "Languages\Dzongkha"; Description: "{cm:Dzongkha}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 3310882
 | 
			
		||||
Name: "Languages\English"; Description: "{cm:English}"; Languages: en; Types: compact custom full; ExtraDiskSpaceRequired: 38371506
 | 
			
		||||
Name: "Languages\Esperanto"; Description: "{cm:Esperanto}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 6602178
 | 
			
		||||
Name: "Languages\Estonian"; Description: "{cm:Estonian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 9644486
 | 
			
		||||
Name: "Languages\Finnish"; Description: "{cm:Finnish}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 13274908
 | 
			
		||||
Name: "Languages\Frankish"; Description: "{cm:Frankish}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 16451109
 | 
			
		||||
Name: "Languages\French"; Description: "{cm:French}"; Languages: en; Types: compact custom full; ExtraDiskSpaceRequired: 37350210
 | 
			
		||||
Name: "Languages\Galician"; Description: "{cm:Galician}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 5520499
 | 
			
		||||
Name: "Languages\Georgian"; Description: "{cm:Georgian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 6219735
 | 
			
		||||
Name: "Languages\German"; Description: "{cm:German}"; Languages: en; Types: compact custom full; ExtraDiskSpaceRequired: 13367187
 | 
			
		||||
Name: "Languages\Gujarati"; Description: "{cm:Gujarati}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 10622356
 | 
			
		||||
Name: "Languages\Haitian"; Description: "{cm:Haitian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 1349947
 | 
			
		||||
Name: "Languages\Hebrew"; Description: "{cm:Hebrew}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 4339016
 | 
			
		||||
Name: "Languages\Hindi"; Description: "{cm:Hindi}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 22717250
 | 
			
		||||
Name: "Languages\Hungarian"; Description: "{cm:Hungarian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 12213770
 | 
			
		||||
Name: "Languages\Icelandic"; Description: "{cm:Icelandic}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 6098683
 | 
			
		||||
Name: "Languages\Indonesian"; Description: "{cm:Indonesian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 6503178
 | 
			
		||||
Name: "Languages\Inuktitut"; Description: "{cm:Inuktitut}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 995246
 | 
			
		||||
Name: "Languages\Irish"; Description: "{cm:Irish}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 3482557
 | 
			
		||||
Name: "Languages\Italian"; Description: "{cm:Italian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 32720949
 | 
			
		||||
Name: "Languages\Japanese"; Description: "{cm:Japanese}"; Languages: en; Types: compact custom full; ExtraDiskSpaceRequired: 33072615
 | 
			
		||||
Name: "Languages\Javanese"; Description: "{cm:Javanese}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 4404351
 | 
			
		||||
Name: "Languages\Kannada"; Description: "{cm:Kannada}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 35657050
 | 
			
		||||
Name: "Languages\Kazakh"; Description: "{cm:Kazakh}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 4529022
 | 
			
		||||
Name: "Languages\Khmer"; Description: "{cm:Khmer}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 48851416
 | 
			
		||||
Name: "Languages\Kirghiz"; Description: "{cm:Kirghiz}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 5502225
 | 
			
		||||
Name: "Languages\Korean"; Description: "{cm:Korean}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 13309831
 | 
			
		||||
Name: "Languages\Kurdish"; Description: "{cm:Kurdish}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 2020502
 | 
			
		||||
Name: "Languages\Lao"; Description: "{cm:Lao}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 21118927
 | 
			
		||||
Name: "Languages\Latin"; Description: "{cm:Latin}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 6028030
 | 
			
		||||
Name: "Languages\Latvian"; Description: "{cm:Latvian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 7802105
 | 
			
		||||
Name: "Languages\Lithuanian"; Description: "{cm:Lithuanian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 8916163
 | 
			
		||||
Name: "Languages\Macedonian"; Description: "{cm:Macedonian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 3837583
 | 
			
		||||
Name: "Languages\Malay"; Description: "{cm:Malay}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 6495742
 | 
			
		||||
Name: "Languages\Malayalam"; Description: "{cm:Malayalam}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 8786470
 | 
			
		||||
Name: "Languages\Maltese"; Description: "{cm:Maltese}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 5118233
 | 
			
		||||
Name: "Languages\Marathi"; Description: "{cm:Marathi}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 14237379
 | 
			
		||||
Name: "Languages\Math"; Description: "{cm:Math}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 2251826
 | 
			
		||||
Name: "Languages\Middle_English"; Description: "{cm:Middle_English}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 2105888
 | 
			
		||||
Name: "Languages\Middle_French"; Description: "{cm:Middle_French}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 15831815
 | 
			
		||||
Name: "Languages\Modern_Greek"; Description: "{cm:Modern_Greek}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 5422512
 | 
			
		||||
Name: "Languages\Nepali"; Description: "{cm:Nepali}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 15862542
 | 
			
		||||
Name: "Languages\Norwegian"; Description: "{cm:Norwegian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 8262167
 | 
			
		||||
Name: "Languages\Oriya"; Description: "{cm:Oriya}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 7900659
 | 
			
		||||
Name: "Languages\Panjabi"; Description: "{cm:Panjabi}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 10212006
 | 
			
		||||
Name: "Languages\Persian"; Description: "{cm:Persian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 4803733
 | 
			
		||||
Name: "Languages\Polish"; Description: "{cm:Polish}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 13918058
 | 
			
		||||
Name: "Languages\Portuguese"; Description: "{cm:Portuguese}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 12914622
 | 
			
		||||
Name: "Languages\Pushto"; Description: "{cm:Pushto}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 2493826
 | 
			
		||||
Name: "Languages\Romanian"; Description: "{cm:Romanian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 7957608
 | 
			
		||||
Name: "Languages\Russian"; Description: "{cm:Russian}"; Languages: en; Types: compact custom full; ExtraDiskSpaceRequired: 39371802
 | 
			
		||||
Name: "Languages\Sanskrit"; Description: "{cm:Sanskrit}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 22747749
 | 
			
		||||
Name: "Languages\Serbian"; Description: "{cm:Serbian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 4611681
 | 
			
		||||
Name: "Languages\Sinhala"; Description: "{cm:Sinhala}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 6793740
 | 
			
		||||
Name: "Languages\Slovak"; Description: "{cm:Slovak}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 9126966
 | 
			
		||||
Name: "Languages\Slovenian"; Description: "{cm:Slovenian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 6824064
 | 
			
		||||
Name: "Languages\Spanish"; Description: "{cm:Spanish}"; Languages: en; Types: compact custom full; ExtraDiskSpaceRequired: 39171233
 | 
			
		||||
Name: "Languages\Swahili"; Description: "{cm:Swahili}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 3861506
 | 
			
		||||
Name: "Languages\Swedish"; Description: "{cm:Swedish}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 9460295
 | 
			
		||||
Name: "Languages\Syriac"; Description: "{cm:Syriac}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 2734020
 | 
			
		||||
Name: "Languages\Tagalog"; Description: "{cm:Tagalog}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 4114554
 | 
			
		||||
Name: "Languages\Tajik"; Description: "{cm:Tajik}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 1119022
 | 
			
		||||
Name: "Languages\Tamil"; Description: "{cm:Tamil}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 5118600
 | 
			
		||||
Name: "Languages\Telugu"; Description: "{cm:Telugu}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 39318860
 | 
			
		||||
Name: "Languages\Thai"; Description: "{cm:Thai}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 13565168
 | 
			
		||||
Name: "Languages\Tibetan"; Description: "{cm:Tibetan}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 25231676
 | 
			
		||||
Name: "Languages\Tigrinya"; Description: "{cm:Tigrinya}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 1806235
 | 
			
		||||
Name: "Languages\Turkish"; Description: "{cm:Turkish}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 14069931
 | 
			
		||||
Name: "Languages\Uighur"; Description: "{cm:Uighur}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 2017575
 | 
			
		||||
Name: "Languages\Ukrainian"; Description: "{cm:Ukrainian}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 8043189
 | 
			
		||||
Name: "Languages\Urdu"; Description: "{cm:Urdu}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 4825658
 | 
			
		||||
Name: "Languages\Uzbek"; Description: "{cm:Uzbek}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 4286554
 | 
			
		||||
Name: "Languages\Vietnamese"; Description: "{cm:Vietnamese}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 6096118
 | 
			
		||||
Name: "Languages\Welsh"; Description: "{cm:Welsh}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 3789352
 | 
			
		||||
Name: "Languages\Yiddish"; Description: "{cm:Yiddish}"; Languages: en; Types: full; ExtraDiskSpaceRequired: 4238718
 | 
			
		||||
 | 
			
		||||
Name: "Languages\Azerbaijani"; Description: "{cm:Azerbaijani}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 6615244
 | 
			
		||||
Name: "Languages\Albanian"; Description: "{cm:Albanian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 6587325
 | 
			
		||||
Name: "Languages\Amharic"; Description: "{cm:Amharic}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 2953500
 | 
			
		||||
Name: "Languages\English"; Description: "{cm:English}"; Languages: ru; Types: compact custom full; ExtraDiskSpaceRequired: 38371506
 | 
			
		||||
Name: "Languages\Arabic"; Description: "{cm:Arabic}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 28534834
 | 
			
		||||
Name: "Languages\Assamese"; Description: "{cm:Assamese}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 15827072
 | 
			
		||||
Name: "Languages\Afrikaans"; Description: "{cm:Afrikaans}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 5198548
 | 
			
		||||
Name: "Languages\Basque"; Description: "{cm:Basque}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 4969647
 | 
			
		||||
Name: "Languages\Belarusian"; Description: "{cm:Belarusian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 6822594
 | 
			
		||||
Name: "Languages\Bengali"; Description: "{cm:Bengali}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 15552533
 | 
			
		||||
Name: "Languages\Burmese"; Description: "{cm:Burmese}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 69770179
 | 
			
		||||
Name: "Languages\Bulgarian"; Description: "{cm:Bulgarian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 6026234
 | 
			
		||||
Name: "Languages\Bosnian"; Description: "{cm:Bosnian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 5432328
 | 
			
		||||
Name: "Languages\Welsh"; Description: "{cm:Welsh}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 3789352
 | 
			
		||||
Name: "Languages\Hungarian"; Description: "{cm:Hungarian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 12213770
 | 
			
		||||
Name: "Languages\Vietnamese"; Description: "{cm:Vietnamese}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 6096118
 | 
			
		||||
Name: "Languages\Haitian"; Description: "{cm:Haitian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 1349947
 | 
			
		||||
Name: "Languages\Galician"; Description: "{cm:Galician}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 5520499
 | 
			
		||||
Name: "Languages\Dutch"; Description: "{cm:Dutch}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 17098919
 | 
			
		||||
Name: "Languages\Georgian"; Description: "{cm:Georgian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 6219735
 | 
			
		||||
Name: "Languages\Gujarati"; Description: "{cm:Gujarati}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 10622356
 | 
			
		||||
Name: "Languages\Danish"; Description: "{cm:Danish}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 7340575
 | 
			
		||||
Name: "Languages\Dzongkha"; Description: "{cm:Dzongkha}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 3310882
 | 
			
		||||
Name: "Languages\Ancient_Greek"; Description: "{cm:Ancient_Greek}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 5182527
 | 
			
		||||
Name: "Languages\Hebrew"; Description: "{cm:Hebrew}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 4339016
 | 
			
		||||
Name: "Languages\Yiddish"; Description: "{cm:Yiddish}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 4238718
 | 
			
		||||
Name: "Languages\Indonesian"; Description: "{cm:Indonesian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 6503178
 | 
			
		||||
Name: "Languages\Inuktitut"; Description: "{cm:Inuktitut}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 995246
 | 
			
		||||
Name: "Languages\Irish"; Description: "{cm:Irish}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 3482557
 | 
			
		||||
Name: "Languages\Icelandic"; Description: "{cm:Icelandic}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 6098683
 | 
			
		||||
Name: "Languages\Spanish"; Description: "{cm:Spanish}"; Languages: ru; Types: compact custom full; ExtraDiskSpaceRequired: 39171233
 | 
			
		||||
Name: "Languages\Italian"; Description: "{cm:Italian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 32720949
 | 
			
		||||
Name: "Languages\Kazakh"; Description: "{cm:Kazakh}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 4529022
 | 
			
		||||
Name: "Languages\Kannada"; Description: "{cm:Kannada}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 35657050
 | 
			
		||||
Name: "Languages\Catalan"; Description: "{cm:Catalan}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 5356190
 | 
			
		||||
Name: "Languages\Cebuano"; Description: "{cm:Cebuano}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 1686752
 | 
			
		||||
Name: "Languages\Kirghiz"; Description: "{cm:Kirghiz}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 5502225
 | 
			
		||||
Name: "Languages\Chineese_traditional"; Description: "{cm:Chineese_traditional}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 56692327
 | 
			
		||||
Name: "Languages\Chineese_simplified"; Description: "{cm:Chineese_simplified}"; Languages: ru; Types: compact custom full; ExtraDiskSpaceRequired: 42089623
 | 
			
		||||
Name: "Languages\Korean"; Description: "{cm:Korean}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 13309831
 | 
			
		||||
Name: "Languages\Kurdish"; Description: "{cm:Kurdish}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 2020502
 | 
			
		||||
Name: "Languages\Khmer"; Description: "{cm:Khmer}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 48851416
 | 
			
		||||
Name: "Languages\Lao"; Description: "{cm:Lao}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 21118927
 | 
			
		||||
Name: "Languages\Latin"; Description: "{cm:Latin}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 6028030
 | 
			
		||||
Name: "Languages\Latvian"; Description: "{cm:Latvian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 7802105
 | 
			
		||||
Name: "Languages\Lithuanian"; Description: "{cm:Lithuanian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 8916163
 | 
			
		||||
Name: "Languages\Macedonian"; Description: "{cm:Macedonian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 3837583
 | 
			
		||||
Name: "Languages\Malay"; Description: "{cm:Malay}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 6495742
 | 
			
		||||
Name: "Languages\Malayalam"; Description: "{cm:Malayalam}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 8786470
 | 
			
		||||
Name: "Languages\Maltese"; Description: "{cm:Maltese}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 5118233
 | 
			
		||||
Name: "Languages\Marathi"; Description: "{cm:Marathi}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 14237379
 | 
			
		||||
Name: "Languages\Math"; Description: "{cm:Math}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 2251826
 | 
			
		||||
Name: "Languages\German"; Description: "{cm:German}"; Languages: ru; Types: compact custom full; ExtraDiskSpaceRequired: 13367187
 | 
			
		||||
Name: "Languages\Nepali"; Description: "{cm:Nepali}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 15862542
 | 
			
		||||
Name: "Languages\Modern_Greek"; Description: "{cm:Modern_Greek}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 5422512
 | 
			
		||||
Name: "Languages\Norwegian"; Description: "{cm:Norwegian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 8262167
 | 
			
		||||
Name: "Languages\Oriya"; Description: "{cm:Oriya}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 7900659
 | 
			
		||||
Name: "Languages\Panjabi"; Description: "{cm:Panjabi}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 10212006
 | 
			
		||||
Name: "Languages\Persian"; Description: "{cm:Persian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 4803733
 | 
			
		||||
Name: "Languages\Polish"; Description: "{cm:Polish}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 13918058
 | 
			
		||||
Name: "Languages\Portuguese"; Description: "{cm:Portuguese}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 12914622
 | 
			
		||||
Name: "Languages\Pushto"; Description: "{cm:Pushto}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 2493826
 | 
			
		||||
Name: "Languages\Romanian"; Description: "{cm:Romanian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 7957608
 | 
			
		||||
Name: "Languages\Russian"; Description: "{cm:Russian}"; Languages: ru; Types: compact custom full; ExtraDiskSpaceRequired: 39371802
 | 
			
		||||
Name: "Languages\Sanskrit"; Description: "{cm:Sanskrit}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 22747749
 | 
			
		||||
Name: "Languages\Serbian"; Description: "{cm:Serbian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 4611681
 | 
			
		||||
Name: "Languages\Sinhala"; Description: "{cm:Sinhala}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 6793740
 | 
			
		||||
Name: "Languages\Syriac"; Description: "{cm:Syriac}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 2734020
 | 
			
		||||
Name: "Languages\Slovak"; Description: "{cm:Slovak}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 9126966
 | 
			
		||||
Name: "Languages\Slovenian"; Description: "{cm:Slovenian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 6824064
 | 
			
		||||
Name: "Languages\Middle_English"; Description: "{cm:Middle_English}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 2105888
 | 
			
		||||
Name: "Languages\Middle_French"; Description: "{cm:Middle_French}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 15831815
 | 
			
		||||
Name: "Languages\Swahili"; Description: "{cm:Swahili}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 3861506
 | 
			
		||||
Name: "Languages\Tagalog"; Description: "{cm:Tagalog}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 4114554
 | 
			
		||||
Name: "Languages\Tajik"; Description: "{cm:Tajik}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 1119022
 | 
			
		||||
Name: "Languages\Thai"; Description: "{cm:Thai}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 13565168
 | 
			
		||||
Name: "Languages\Tamil"; Description: "{cm:Tamil}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 5118600
 | 
			
		||||
Name: "Languages\Telugu"; Description: "{cm:Telugu}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 39318860
 | 
			
		||||
Name: "Languages\Tibetan"; Description: "{cm:Tibetan}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 25231676
 | 
			
		||||
Name: "Languages\Tigrinya"; Description: "{cm:Tigrinya}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 1806235
 | 
			
		||||
Name: "Languages\Turkish"; Description: "{cm:Turkish}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 14069931
 | 
			
		||||
Name: "Languages\Uzbek"; Description: "{cm:Uzbek}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 4286554
 | 
			
		||||
Name: "Languages\Uighur"; Description: "{cm:Uighur}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 2017575
 | 
			
		||||
Name: "Languages\Ukrainian"; Description: "{cm:Ukrainian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 8043189
 | 
			
		||||
Name: "Languages\Urdu"; Description: "{cm:Urdu}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 4825658
 | 
			
		||||
Name: "Languages\Finnish"; Description: "{cm:Finnish}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 13274908
 | 
			
		||||
Name: "Languages\Frankish"; Description: "{cm:Frankish}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 16451109
 | 
			
		||||
Name: "Languages\French"; Description: "{cm:French}"; Languages: ru; Types: compact custom full; ExtraDiskSpaceRequired: 37350210
 | 
			
		||||
Name: "Languages\Hindi"; Description: "{cm:Hindi}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 22717250
 | 
			
		||||
Name: "Languages\Croatian"; Description: "{cm:Croatian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 9135966
 | 
			
		||||
Name: "Languages\Cherokee"; Description: "{cm:Cherokee}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 1083194
 | 
			
		||||
Name: "Languages\Czech"; Description: "{cm:Czech}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 11896327
 | 
			
		||||
Name: "Languages\Swedish"; Description: "{cm:Swedish}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 9460295
 | 
			
		||||
Name: "Languages\Esperanto"; Description: "{cm:Esperanto}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 6602178
 | 
			
		||||
Name: "Languages\Estonian"; Description: "{cm:Estonian}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 9644486
 | 
			
		||||
Name: "Languages\Javanese"; Description: "{cm:Javanese}"; Languages: ru; Types: full; ExtraDiskSpaceRequired: 4404351
 | 
			
		||||
Name: "Languages\Japanese"; Description: "{cm:Japanese}"; Languages: ru; Types: compact custom full; ExtraDiskSpaceRequired: 33072615
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[CustomMessages]
 | 
			
		||||
en.Languages=OCR Languages
 | 
			
		||||
en.Afrikaans=Afrikaans
 | 
			
		||||
en.Albanian=Albanian
 | 
			
		||||
en.Amharic=Amharic
 | 
			
		||||
en.Ancient_Greek=Ancient Greek
 | 
			
		||||
en.Arabic=Arabic
 | 
			
		||||
en.Assamese=Assamese
 | 
			
		||||
en.Azerbaijani=Azerbaijani
 | 
			
		||||
en.Basque=Basque
 | 
			
		||||
en.Belarusian=Belarusian
 | 
			
		||||
en.Bengali=Bengali
 | 
			
		||||
en.Bosnian=Bosnian
 | 
			
		||||
en.Bulgarian=Bulgarian
 | 
			
		||||
en.Burmese=Burmese
 | 
			
		||||
en.Catalan=Catalan
 | 
			
		||||
en.Cebuano=Cebuano
 | 
			
		||||
en.Cherokee=Cherokee
 | 
			
		||||
en.Chineese_simplified=Chineese simplified
 | 
			
		||||
en.Chineese_traditional=Chineese traditional
 | 
			
		||||
en.Croatian=Croatian
 | 
			
		||||
en.Czech=Czech
 | 
			
		||||
en.Danish=Danish
 | 
			
		||||
en.Dutch=Dutch
 | 
			
		||||
en.Dzongkha=Dzongkha
 | 
			
		||||
en.English=English
 | 
			
		||||
en.Esperanto=Esperanto
 | 
			
		||||
en.Estonian=Estonian
 | 
			
		||||
en.Finnish=Finnish
 | 
			
		||||
en.Frankish=Frankish
 | 
			
		||||
en.French=French
 | 
			
		||||
en.Galician=Galician
 | 
			
		||||
en.Georgian=Georgian
 | 
			
		||||
en.German=German
 | 
			
		||||
en.Gujarati=Gujarati
 | 
			
		||||
en.Haitian=Haitian
 | 
			
		||||
en.Hebrew=Hebrew
 | 
			
		||||
en.Hindi=Hindi
 | 
			
		||||
en.Hungarian=Hungarian
 | 
			
		||||
en.Icelandic=Icelandic
 | 
			
		||||
en.Indonesian=Indonesian
 | 
			
		||||
en.Inuktitut=Inuktitut
 | 
			
		||||
en.Irish=Irish
 | 
			
		||||
en.Italian=Italian
 | 
			
		||||
en.Japanese=Japanese
 | 
			
		||||
en.Javanese=Javanese
 | 
			
		||||
en.Kannada=Kannada
 | 
			
		||||
en.Kazakh=Kazakh
 | 
			
		||||
en.Khmer=Khmer
 | 
			
		||||
en.Kirghiz=Kirghiz
 | 
			
		||||
en.Korean=Korean
 | 
			
		||||
en.Kurdish=Kurdish
 | 
			
		||||
en.Lao=Lao
 | 
			
		||||
en.Latin=Latin
 | 
			
		||||
en.Latvian=Latvian
 | 
			
		||||
en.Lithuanian=Lithuanian
 | 
			
		||||
en.Macedonian=Macedonian
 | 
			
		||||
en.Malay=Malay
 | 
			
		||||
en.Malayalam=Malayalam
 | 
			
		||||
en.Maltese=Maltese
 | 
			
		||||
en.Marathi=Marathi
 | 
			
		||||
en.Math=Math
 | 
			
		||||
en.Middle_English=Middle English
 | 
			
		||||
en.Middle_French=Middle French
 | 
			
		||||
en.Modern_Greek=Modern Greek
 | 
			
		||||
en.Nepali=Nepali
 | 
			
		||||
en.Norwegian=Norwegian
 | 
			
		||||
en.Oriya=Oriya
 | 
			
		||||
en.Panjabi=Panjabi
 | 
			
		||||
en.Persian=Persian
 | 
			
		||||
en.Polish=Polish
 | 
			
		||||
en.Portuguese=Portuguese
 | 
			
		||||
en.Pushto=Pushto
 | 
			
		||||
en.Romanian=Romanian
 | 
			
		||||
en.Russian=Russian
 | 
			
		||||
en.Sanskrit=Sanskrit
 | 
			
		||||
en.Serbian=Serbian
 | 
			
		||||
en.Sinhala=Sinhala
 | 
			
		||||
en.Slovak=Slovak
 | 
			
		||||
en.Slovenian=Slovenian
 | 
			
		||||
en.Spanish=Spanish
 | 
			
		||||
en.Swahili=Swahili
 | 
			
		||||
en.Swedish=Swedish
 | 
			
		||||
en.Syriac=Syriac
 | 
			
		||||
en.Tagalog=Tagalog
 | 
			
		||||
en.Tajik=Tajik
 | 
			
		||||
en.Tamil=Tamil
 | 
			
		||||
en.Telugu=Telugu
 | 
			
		||||
en.Thai=Thai
 | 
			
		||||
en.Tibetan=Tibetan
 | 
			
		||||
en.Tigrinya=Tigrinya
 | 
			
		||||
en.Turkish=Turkish
 | 
			
		||||
en.Uighur=Uighur
 | 
			
		||||
en.Ukrainian=Ukrainian
 | 
			
		||||
en.Urdu=Urdu
 | 
			
		||||
en.Uzbek=Uzbek
 | 
			
		||||
en.Vietnamese=Vietnamese
 | 
			
		||||
en.Welsh=Welsh
 | 
			
		||||
en.Yiddish=Yiddish
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[CustomMessages]
 | 
			
		||||
ru.Languages=ßçûêè ðàñïîçíàâàíèÿ
 | 
			
		||||
ru.Afrikaans=Àôðèêààíñ
 | 
			
		||||
ru.Albanian=Àëáàíñêèé
 | 
			
		||||
ru.Amharic=Àìõàðñêèé
 | 
			
		||||
ru.Ancient_Greek=Äðåâíåãðå÷åñêèé
 | 
			
		||||
ru.Arabic=Àðàáñêèé
 | 
			
		||||
ru.Assamese=Àññàìñêèé
 | 
			
		||||
ru.Azerbaijani=Àçåðáàéäæàíñêèé
 | 
			
		||||
ru.Basque=Áàñêîâ
 | 
			
		||||
ru.Belarusian=Áåëîðóññêèé
 | 
			
		||||
ru.Bengali=Áåíãàëüñêèé
 | 
			
		||||
ru.Bosnian=Áîñíèéñêèé
 | 
			
		||||
ru.Bulgarian=Áîëãàðèè
 | 
			
		||||
ru.Burmese=Áèðìàíñêèé
 | 
			
		||||
ru.Catalan=Êàòàëîíñêèé
 | 
			
		||||
ru.Cebuano=Êåáóàíî
 | 
			
		||||
ru.Cherokee=×åðîêè
 | 
			
		||||
ru.Chineese_simplified=Êèòàéñêèé óïðîùåííûé
 | 
			
		||||
ru.Chineese_traditional=Êèòàéñêèé òðàäèöèîííûé
 | 
			
		||||
ru.Croatian=Õîðâàòñêèé
 | 
			
		||||
ru.Czech=×åøñêèé
 | 
			
		||||
ru.Danish=Äàòñêèé
 | 
			
		||||
ru.Dutch=Ãîëëàíäñêèé
 | 
			
		||||
ru.Dzongkha=Äæîíãêõà
 | 
			
		||||
ru.English=Àíãëèéñêèé
 | 
			
		||||
ru.Esperanto=Ýñïåðàíòî
 | 
			
		||||
ru.Estonian=Ýñòîíñêèé
 | 
			
		||||
ru.Finnish=Ôèíñêèé
 | 
			
		||||
ru.Frankish=Ôðàíêñêèé
 | 
			
		||||
ru.French=Ôðàíöóçñêèé
 | 
			
		||||
ru.Galician=Ãàëèñèéñêèé
 | 
			
		||||
ru.Georgian=Ãðóçèíñêèé
 | 
			
		||||
ru.German=Íåìåöêèé
 | 
			
		||||
ru.Gujarati=Ãóäæàðàòè
 | 
			
		||||
ru.Haitian=Ãàèòè
 | 
			
		||||
ru.Hebrew=Èâðèò
 | 
			
		||||
ru.Hindi=Õèíäè
 | 
			
		||||
ru.Hungarian=Âåíãåðñêèé
 | 
			
		||||
ru.Icelandic=Èñëàíäñêèé
 | 
			
		||||
ru.Indonesian=Èíäîíåçèéñêèé
 | 
			
		||||
ru.Inuktitut=Èíóêòèòóò
 | 
			
		||||
ru.Irish=Èðëàíäñêèé
 | 
			
		||||
ru.Italian=Èòàëüÿíñêèé
 | 
			
		||||
ru.Japanese=ßïîíñêèé
 | 
			
		||||
ru.Javanese=ßâàíñêèé
 | 
			
		||||
ru.Kannada=Êàííàäà
 | 
			
		||||
ru.Kazakh=Êàçàõñêèé
 | 
			
		||||
ru.Khmer=Êõìåðñêèé
 | 
			
		||||
ru.Kirghiz=Êèðãèçñêèé
 | 
			
		||||
ru.Korean=Êîðåéñêèé
 | 
			
		||||
ru.Kurdish=Êóðäñêèé
 | 
			
		||||
ru.Lao=Ëàî
 | 
			
		||||
ru.Latin=Ëàòèíñêèé
 | 
			
		||||
ru.Latvian=Ëàòûøñêèé
 | 
			
		||||
ru.Lithuanian=Ëèòîâñêèé
 | 
			
		||||
ru.Macedonian=Ìàêåäîíñêèé
 | 
			
		||||
ru.Malay=Ìàëàéñêèé
 | 
			
		||||
ru.Malayalam=Ìàëàÿëàì
 | 
			
		||||
ru.Maltese=Ìàëüòèéñêèé
 | 
			
		||||
ru.Marathi=Ìàðàòõè
 | 
			
		||||
ru.Math=Ìàòåìàòèêà
 | 
			
		||||
ru.Middle_English=Ñðåäíåâåêîâûé àíãëèéñêèé
 | 
			
		||||
ru.Middle_French=Ñðåäíåâåêîâûé ôðàíöóçñêèé
 | 
			
		||||
ru.Modern_Greek=Íîâîãðå÷åñêèé
 | 
			
		||||
ru.Nepali=Íåïàëüñêèé
 | 
			
		||||
ru.Norwegian=Íîðâåæñêèé
 | 
			
		||||
ru.Oriya=Îðèÿ
 | 
			
		||||
ru.Panjabi=Ïàíäæàáè
 | 
			
		||||
ru.Persian=Ïåðñèäñêèé
 | 
			
		||||
ru.Polish=Ïîëüñêèé
 | 
			
		||||
ru.Portuguese=Ïîðòóãàëüñêèé
 | 
			
		||||
ru.Pushto=Ïóøòó
 | 
			
		||||
ru.Romanian=Ðóìûíñêèé
 | 
			
		||||
ru.Russian=Ðóññêèé
 | 
			
		||||
ru.Sanskrit=Ñàíñêðèò
 | 
			
		||||
ru.Serbian=Ñåðáñêèé
 | 
			
		||||
ru.Sinhala=Ñèíãàëüñêèé
 | 
			
		||||
ru.Slovak=Ñëîâàöêèé
 | 
			
		||||
ru.Slovenian=Ñëîâåíñêèé
 | 
			
		||||
ru.Spanish=Èñïàíñêèé
 | 
			
		||||
ru.Swahili=Ñóàõèëè
 | 
			
		||||
ru.Swedish=Øâåäñêèé
 | 
			
		||||
ru.Syriac=Ñèðèéñêèé
 | 
			
		||||
ru.Tagalog=Òàãàëüñêèé
 | 
			
		||||
ru.Tajik=Òàäæèêèñêèé
 | 
			
		||||
ru.Tamil=Òàìèë
 | 
			
		||||
ru.Telugu=Òåëóãó
 | 
			
		||||
ru.Thai=Òàéñêèé
 | 
			
		||||
ru.Tibetan=Òèáåòñêèé
 | 
			
		||||
ru.Tigrinya=Òèãðàè
 | 
			
		||||
ru.Turkish=Òóðåöêèé
 | 
			
		||||
ru.Uighur=Óéãóðñêèé
 | 
			
		||||
ru.Ukrainian=Óêðàèíñêèé
 | 
			
		||||
ru.Urdu=Óðäó
 | 
			
		||||
ru.Uzbek=Óçáåêñêèé
 | 
			
		||||
ru.Vietnamese=Âüåòíàìñêèé
 | 
			
		||||
ru.Welsh=Âàëëèéñêèé
 | 
			
		||||
ru.Yiddish=Èäèø
 | 
			
		||||
 | 
			
		||||
@ -1,78 +0,0 @@
 | 
			
		||||
[LangOptions]
 | 
			
		||||
LanguageName=<0420><0443><0441><0441><043A><0438><0439>
 | 
			
		||||
LanguageID=$0419
 | 
			
		||||
LanguageCodePage=1251
 | 
			
		||||
 | 
			
		||||
[CustomMessages]
 | 
			
		||||
 | 
			
		||||
; *** Components
 | 
			
		||||
CreateStartupIcon=Äîáàâèòü â àâòîçàïóñê
 | 
			
		||||
Executables=Èñïîëíÿåìûå ôàéëû
 | 
			
		||||
Libraries=Áèáëèîòåêè
 | 
			
		||||
Languages=ßçûêè
 | 
			
		||||
 | 
			
		||||
AncientGreek=Äðåâíåãðå÷åñêèé
 | 
			
		||||
Esperantoalternative=Ýñïåðàíòî àëüòåðíàòèâíûé
 | 
			
		||||
English=Àíãëèéñêèé 
 | 
			
		||||
Ukrainian=Óêðàèíñêèé 
 | 
			
		||||
Turkish=Òóðåöêèé 
 | 
			
		||||
Thai=Òàéñêèé 
 | 
			
		||||
Tagalog=Òàãàëüñêèé 
 | 
			
		||||
Telugu=Òåëóãó 
 | 
			
		||||
Tamil=Òàìèëüñêèé 
 | 
			
		||||
Swedish=Øâåäñêèé 
 | 
			
		||||
Swahili=Ñóàõèëè 
 | 
			
		||||
Serbian=Ñåðáñêèé 
 | 
			
		||||
Albanian=Àëáàíñêèé 
 | 
			
		||||
Spanish=Èñïàíñêèé 
 | 
			
		||||
Slovenian=Ñëîâåíñêèé 
 | 
			
		||||
Slovakian=Ñëîâàöêèé
 | 
			
		||||
Romanian=Ðóìûíñêèé 
 | 
			
		||||
Portuguese=Ïîðòóãàëüñêèé 
 | 
			
		||||
Polish=Ïîëüñêèé 
 | 
			
		||||
Norwegian=Íîðâåæñêèé 
 | 
			
		||||
Dutch=Ãîëëàíäñêèé 
 | 
			
		||||
Malay=Ìàëàéñêèé 
 | 
			
		||||
Maltese=Ìàëüòèéñêèé 
 | 
			
		||||
Macedonian=Ìàêåäîíñêèé 
 | 
			
		||||
Malayalam=Ìàëàÿëàì 
 | 
			
		||||
Lithuanian=Ëèòîâñêèé 
 | 
			
		||||
Latvian=Ëàòûøñêèé 
 | 
			
		||||
Korean=Êîðåéñêèé 
 | 
			
		||||
Kannada=Êàííàäà 
 | 
			
		||||
Italian=Èòàëüÿíñêèé 
 | 
			
		||||
Icelandic=Èñëàíäñêèé 
 | 
			
		||||
Indonesian=Èíäîíåçèéñêèé 
 | 
			
		||||
Cherokee=×åðîêè 
 | 
			
		||||
Hungarian=Âåíãåðñêèé 
 | 
			
		||||
Croatian=Õîðâàòñêèé 
 | 
			
		||||
Hindi=Õèíäè 
 | 
			
		||||
Hebrew=Èâðèò 
 | 
			
		||||
Galician=Ãàëèöêèé
 | 
			
		||||
MiddleFrench=Ñðåäíåâåêîâûé Ôðàíöóçñêèé
 | 
			
		||||
Frankish=Ôðàíêñêèé
 | 
			
		||||
French=Ôðàíöóçñêèé 
 | 
			
		||||
Finnish=Ôèíñêèé 
 | 
			
		||||
Basque=Áàñêñêèé 
 | 
			
		||||
Estonian=Ýñòîíñêèé 
 | 
			
		||||
MathEquation=Ìàòåìàòèêà / óðàâíåíèå 
 | 
			
		||||
Esperanto=Ýñïåðàíòî 
 | 
			
		||||
MiddleEnglish=Ñðåäíåâåêîâûé Àíãëèéñêèé
 | 
			
		||||
Greek=Ãðå÷åñêèé 
 | 
			
		||||
German=Íåìåöêèé 
 | 
			
		||||
Danish=Äàòñêèé 
 | 
			
		||||
Czech=×åøñêèé 
 | 
			
		||||
Catalan=Êàòàëîíñêèé 
 | 
			
		||||
Bulgarian=Áîëãàðñêèé 
 | 
			
		||||
Bengali=Áåíãàëüñêèé 
 | 
			
		||||
Belarusian=Áåëîðóññêèé 
 | 
			
		||||
Azerbaijani=Àçåðáàéäæàíñêèé 
 | 
			
		||||
Arabic=Àðàáñêèé 
 | 
			
		||||
Afrikaans=Àôðèêààíñ 
 | 
			
		||||
Japanese=ßïîíñêèé 
 | 
			
		||||
ChineseSimplified=Êèòàéñêèé (óïðîùåííûé) 
 | 
			
		||||
ChineseTraditional=Êèòàéñêèé (òðàäèöèîííûé) 
 | 
			
		||||
Russian=Ðóññêèé 
 | 
			
		||||
Vietnamese=Âüåòíàìñêèé
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,26 +0,0 @@
 | 
			
		||||
#Changes.
 | 
			
		||||
## 1.2.3:
 | 
			
		||||
* Fixed possible crash.
 | 
			
		||||
* Added version information and some error messages.
 | 
			
		||||
## 1.2.2:
 | 
			
		||||
* Added alternative translation source. 
 | 
			
		||||
## 1.2.1:
 | 
			
		||||
* Fixed the bug with the lack of translation. 
 | 
			
		||||
* Fixed the bug with the use of language recognition by default when you select another one in OCR region selection mode.
 | 
			
		||||
## 1.2.0:
 | 
			
		||||
* Changed installer. 
 | 
			
		||||
* Added all available languages for recognition.
 | 
			
		||||
* Added ability to specify language when selecting the field of recognition using right click. 
 | 
			
		||||
* Human readable language names. 
 | 
			
		||||
* Reduced memory usage. 
 | 
			
		||||
* Updated libraries.
 | 
			
		||||
## 1.1.3: 
 | 
			
		||||
* Added library libgcc_s_dw2-1.dll. 
 | 
			
		||||
* Updated libraries. 
 | 
			
		||||
## 1.1.2: 
 | 
			
		||||
* If you specify in the settings the path to tessdata characters "\" or "/" at the end of the path are no longer required. 
 | 
			
		||||
## 1.1.1: 
 | 
			
		||||
* Fixed an issue with incorrect window size when display results. 
 | 
			
		||||
## 1.1.0: 
 | 
			
		||||
* Displays the result in the window, along with the picture. 
 | 
			
		||||
* Context menu expanded. Added buttons display the last result and copy it to the clipboard.
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								images/STIcon.xcf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								images/STIconBlue.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.9 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								images/STIconGreen.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 4.1 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								images/STIconOrange.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								images/STIconRed.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 4.0 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								images/icon.ico
									
									
									
									
									
								
							
							
						
						| 
		 Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 97 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								images/icon.png
									
									
									
									
									
								
							
							
						
						| 
		 Before Width: | Height: | Size: 6.5 KiB  | 
							
								
								
									
										24
									
								
								main.cpp
									
									
									
									
									
								
							
							
						
						@ -1,12 +1,23 @@
 | 
			
		||||
#ifdef Q_OS_LINUX
 | 
			
		||||
#  include <locale.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QTranslator>
 | 
			
		||||
 | 
			
		||||
#include <qtsingleapplication.h>
 | 
			
		||||
 | 
			
		||||
#include <Manager.h>
 | 
			
		||||
#include <Settings.h>
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
  QApplication a(argc, argv);
 | 
			
		||||
int main (int argc, char *argv[]) {
 | 
			
		||||
  QtSingleApplication a (argc, argv);
 | 
			
		||||
  if (a.sendMessage (QString ())) {
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
#ifdef Q_OS_LINUX
 | 
			
		||||
  setlocale (LC_NUMERIC, "C");
 | 
			
		||||
#endif
 | 
			
		||||
  a.setQuitOnLastWindowClosed (false);
 | 
			
		||||
  a.setApplicationName (settings_values::appName);
 | 
			
		||||
  a.setOrganizationName (settings_values::companyName);
 | 
			
		||||
@ -14,12 +25,11 @@ int main(int argc, char *argv[])
 | 
			
		||||
  QTranslator translator;
 | 
			
		||||
  // Set default to english.
 | 
			
		||||
  if (translator.load (QLocale::system (), "translation", "_", ":/translations") ||
 | 
			
		||||
      translator.load (":/translations/translation_en"))
 | 
			
		||||
  {
 | 
			
		||||
    a.installTranslator(&translator);
 | 
			
		||||
      translator.load (":/translations/translation_en")) {
 | 
			
		||||
    a.installTranslator (&translator);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Manager manager;
 | 
			
		||||
 | 
			
		||||
  return a.exec();
 | 
			
		||||
  return a.exec ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										8
									
								
								scripts/get_deps.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						@ -0,0 +1,8 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
source ./options.sh $@
 | 
			
		||||
 | 
			
		||||
echo "Downloading dependencies"
 | 
			
		||||
wget -O $DOWNLOAD_DIR/leptonica.tar.gz http://www.leptonica.com/source/leptonica-1.72.tar.gz
 | 
			
		||||
wget -O $DOWNLOAD_DIR/tesseract.tar.gz https://github.com/tesseract-ocr/tesseract/archive/3.04.00.tar.gz
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								scripts/get_tessdata.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						@ -0,0 +1,14 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
source ./options.sh $@
 | 
			
		||||
 | 
			
		||||
echo "Downloading and extracting tessdata"
 | 
			
		||||
wget -O $DOWNLOAD_DIR/tessdata.tar.gz https://github.com/tesseract-ocr/tessdata/archive/3.04.00.tar.gz
 | 
			
		||||
EXTRACT_DIR=$DOWNLOAD_DIR/tessdata
 | 
			
		||||
CLEAN=true
 | 
			
		||||
cleanupDirInNeeded $EXTRACT_DIR
 | 
			
		||||
tar zxf $DOWNLOAD_DIR/tessdata.tar.gz -C $EXTRACT_DIR
 | 
			
		||||
EXTRACTED=`ls $EXTRACT_DIR | grep tess`
 | 
			
		||||
mv $EXTRACT_DIR/$EXTRACTED/* $EXTRACT_DIR
 | 
			
		||||
rm -r $EXTRACT_DIR/$EXTRACTED
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										5
									
								
								scripts/install_deps.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						@ -0,0 +1,5 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
sudo apt-get update -q
 | 
			
		||||
sudo apt-get -y install libxcb-util0-dev fakeroot libtesseract-dev libleptonica-dev qt5-qmake libqt5webkit5-dev libqt5x11extras5-dev qttools5-dev-tools g++
 | 
			
		||||
#sudo apt-get -y install tesseract-ocr-eng #for testing
 | 
			
		||||
							
								
								
									
										19
									
								
								scripts/make_all.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						@ -0,0 +1,19 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
source ./options.sh $@
 | 
			
		||||
#cleanupDirInNeeded $WORK_DIR
 | 
			
		||||
 | 
			
		||||
echo "Running all scripts for $PLATFORM"
 | 
			
		||||
#./install_deps $@
 | 
			
		||||
#./get_tessdata.sh $@
 | 
			
		||||
#./get_deps.sh $@
 | 
			
		||||
#./make_deps.sh $@
 | 
			
		||||
./make_app.sh $@
 | 
			
		||||
if [ "$PLATFORM" == "linux" ]; then
 | 
			
		||||
  ./make_deb.sh $@
 | 
			
		||||
fi
 | 
			
		||||
if [ "$PLATFORM" == "mingw" ]; then
 | 
			
		||||
  ./make_iss.sh $@
 | 
			
		||||
fi
 | 
			
		||||
./make_sf.sh $@
 | 
			
		||||
echo "All scripts successfully run"
 | 
			
		||||
							
								
								
									
										12
									
								
								scripts/make_app.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						@ -0,0 +1,12 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
source ./options.sh $@
 | 
			
		||||
 | 
			
		||||
cleanupDirInNeeded $APP_DIR
 | 
			
		||||
 | 
			
		||||
cd $APP_DIR
 | 
			
		||||
echo "Building app"
 | 
			
		||||
lrelease $QT_CHOOSER $SRC_DIR/ScreenTranslator.pro
 | 
			
		||||
$QMAKE $QT_CHOOSER "CONFIG-=debug_and_release" "CONFIG+=release" $SRC_DIR
 | 
			
		||||
make $JOBS
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										59
									
								
								scripts/make_deb.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						@ -0,0 +1,59 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
source ./options.sh $@
 | 
			
		||||
 | 
			
		||||
U_VER="15.04"
 | 
			
		||||
 | 
			
		||||
for arg in ${@}; do
 | 
			
		||||
  case "$arg" in
 | 
			
		||||
    "15.10" ) U_VER=$arg;;
 | 
			
		||||
  esac
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
cleanupDirInNeeded $DEB_DIR
 | 
			
		||||
 | 
			
		||||
cp -r $SRC_DISTR_DIR/deb/* $DEB_DIR
 | 
			
		||||
INSTALL_DIR=/opt/ScreenTranslator
 | 
			
		||||
 | 
			
		||||
function makeChangelog {
 | 
			
		||||
local FOUND=false
 | 
			
		||||
local CHANGELOG="screen-translator ($VERSION) stable; urgency=medium\n\n"
 | 
			
		||||
while read line; do
 | 
			
		||||
  if [[ $line =~ [0-9]+\.[0-9]+\.[0-9]+: ]]; then #version info
 | 
			
		||||
    if [ "$line" == "$VERSION:" ]; then
 | 
			
		||||
      FOUND=true
 | 
			
		||||
      continue
 | 
			
		||||
    elif [ $FOUND == true ]; then
 | 
			
		||||
      break;
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
  if [ $FOUND == true ]; then
 | 
			
		||||
    CHANGELOG="$CHANGELOG$line\n\n"
 | 
			
		||||
  fi
 | 
			
		||||
done < $SRC_DISTR_DIR/Changelog_en.txt
 | 
			
		||||
CHANGELOG="$CHANGELOG--Gres <translator@gres.biz> `date -R`\n\n"
 | 
			
		||||
echo $CHANGELOG
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
echo "Making deb"
 | 
			
		||||
cp $SRC_DIR/LICENSE.md $DEB_DIR/DEBIAN/copyright
 | 
			
		||||
mkdir -p $DEB_DIR/usr/share/pixmaps/
 | 
			
		||||
cp $SRC_DIR/images/STIconBlue.png $DEB_DIR/usr/share/pixmaps/ScreenTranslator.png
 | 
			
		||||
mkdir -p $DEB_DIR/$INSTALL_DIR/
 | 
			
		||||
cp $APP_DIR/ScreenTranslator $DEB_DIR/$INSTALL_DIR/ScreenTranslator
 | 
			
		||||
$STRIP -s $DEB_DIR/$INSTALL_DIR/ScreenTranslator
 | 
			
		||||
cp -r $SRC_DIR/translators $DEB_DIR/$INSTALL_DIR/translators
 | 
			
		||||
 | 
			
		||||
VERSION=`grep "versionString" $SRC_DIR/version.json | cut -d'"' -f4`
 | 
			
		||||
sed "s/Version:.*\+/Version: $VERSION/" -i $DEB_DIR/DEBIAN/control
 | 
			
		||||
sed "s/Version=.*\+/Version=$VERSION/" -i $DEB_DIR/usr/share/applications/ScreenTranslator.desktop
 | 
			
		||||
SIZE=$(expr `du -bs $DEB_DIR | cut -f1` / 1024)
 | 
			
		||||
sed "s/Installed-Size:.*\+/Installed-Size: $SIZE/" -i $DEB_DIR/DEBIAN/control
 | 
			
		||||
echo -e $(makeChangelog) > $DEB_DIR/DEBIAN/changelog
 | 
			
		||||
if [ "$U_VER" == "15.10" ]; then
 | 
			
		||||
  sed "s/libtesseract3/libtesseract3v5/" -i $DEB_DIR/DEBIAN/control
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
fakeroot dpkg-deb --build $DEB_DIR $WORK_DIR/screen-translator-$VERSION-$U_VER.deb
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										54
									
								
								scripts/make_deps.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						@ -0,0 +1,54 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
source ./options.sh $@
 | 
			
		||||
 | 
			
		||||
BUILD_LEPT=false
 | 
			
		||||
BUILD_TESS=false
 | 
			
		||||
 | 
			
		||||
for arg in ${@}; do
 | 
			
		||||
  case "$arg" in
 | 
			
		||||
    "tess" ) BUILD_TESS=true;;
 | 
			
		||||
    "lept" ) BUILD_LEPT=true;;
 | 
			
		||||
  esac
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
if ! $BUILD_LEPT && ! $BUILD_TESS ; then
 | 
			
		||||
  BUILD_LEPT=true
 | 
			
		||||
  BUILD_TESS=true
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
cleanupDirInNeeded $DEPS_DIR
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if $BUILD_LEPT ; then
 | 
			
		||||
  echo "Building Leptonica"
 | 
			
		||||
  tar zxf $DOWNLOAD_DIR/leptonica.tar.gz -C $DEPS_DIR
 | 
			
		||||
  LEPT_DIR=`ls $DEPS_DIR | grep lept`
 | 
			
		||||
  pushd .
 | 
			
		||||
  cd $DEPS_DIR/$LEPT_DIR
 | 
			
		||||
  $CFLAGS ./configure --prefix=$DEPS_DIR --disable-programs "$HOST_ATTR"
 | 
			
		||||
  make $JOBS
 | 
			
		||||
  make install
 | 
			
		||||
  popd
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if $BUILD_TESS ; then
 | 
			
		||||
  echo "Building Tesseract"
 | 
			
		||||
  tar zxf $DOWNLOAD_DIR/tesseract.tar.gz -C $DEPS_DIR
 | 
			
		||||
  TESS_DIR=`ls $DEPS_DIR | grep tess`
 | 
			
		||||
  pushd .
 | 
			
		||||
  cd $DEPS_DIR/$TESS_DIR
 | 
			
		||||
  sed 's/vs2008/vs2010/g' -i ccutil/Makefile.in
 | 
			
		||||
  sed 's/Windows\.h/windows\.h/g' -i opencl/openclwrapper.cpp
 | 
			
		||||
  LIBLEPT_HEADERSDIR=$DEPS_DIR/include LIBS=-L$DEPS_DIR/lib ./configure --prefix=$DEPS_DIR --disable-tessdata-prefix "$HOST_ATTR"
 | 
			
		||||
  make $JOBS
 | 
			
		||||
  make install
 | 
			
		||||
  popd
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ $PLATFORM == 'mingw' ]; then
 | 
			
		||||
  find $DEPS_DIR -name '*.dll' -exec cp {} $DEPS_DIR/lib \;
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
echo "Done"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										49
									
								
								scripts/make_iss.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						@ -0,0 +1,49 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
source ./options.sh $@
 | 
			
		||||
 | 
			
		||||
cleanupDirInNeeded $ISS_DIR
 | 
			
		||||
 | 
			
		||||
cp -r $SRC_DISTR_DIR/iss/* $ISS_DIR
 | 
			
		||||
CONTENT_DIR=$ISS_DIR/content
 | 
			
		||||
mkdir -p $CONTENT_DIR
 | 
			
		||||
 | 
			
		||||
echo "Making ISS"
 | 
			
		||||
TESSDATA_DIR="$DOWNLOAD_DIR/tessdata"
 | 
			
		||||
$(cd $ISS_DIR && ./make_tess_iss.sh $TESSDATA_DIR out="$ISS_DIR/tessdata.iss")
 | 
			
		||||
 | 
			
		||||
#setup
 | 
			
		||||
VERSION=`grep "versionString" $SRC_DIR/version.json | cut -d'"' -f4`
 | 
			
		||||
sed "s/#define MyAppVersion.*$/#define MyAppVersion \"$VERSION\"/" -i $ISS_DIR/InnoSetup.iss
 | 
			
		||||
cp $SRC_DIR/images/icon.ico $ISS_DIR/icon.ico
 | 
			
		||||
cp $SRC_DIR/LICENSE.md $ISS_DIR/LICENSE_en.md
 | 
			
		||||
cp $SRC_DISTR_DIR/Changelog_en.txt $ISS_DIR/Changelog_en.txt
 | 
			
		||||
cp $SRC_DISTR_DIR/Changelog_ru.txt $ISS_DIR/Changelog_ru.txt
 | 
			
		||||
 | 
			
		||||
#app
 | 
			
		||||
cp $APP_DIR/ScreenTranslator.exe $CONTENT_DIR/ScreenTranslator.exe
 | 
			
		||||
cp -r $SRC_DIR/translators $CONTENT_DIR/translators
 | 
			
		||||
 | 
			
		||||
#libs
 | 
			
		||||
QT_LIBS="Qt5WebKitWidgets Qt5Widgets Qt5WebKit Qt5Gui Qt5Network Qt5Core Qt5Sensors Qt5Positioning Qt5PrintSupport 
 | 
			
		||||
Qt5OpenGL Qt5Sql Qt5Quick Qt5Qml Qt5WebChannel Qt5Multimedia Qt5MultimediaWidgets"
 | 
			
		||||
for i in $QT_LIBS; do
 | 
			
		||||
  cp -d $QT_LIB_DIR/$i.dll $CONTENT_DIR
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
mkdir -p $CONTENT_DIR/platforms
 | 
			
		||||
cp -d $QT_LIB_DIR/../plugins/platforms/qwindows.dll $CONTENT_DIR/platforms
 | 
			
		||||
 | 
			
		||||
MINGW_LIBS="libgcc_s_sjlj-1 libstdc++-6 icuin55 icuuc55 icudt55 libwinpthread-1 ssleay32 libeay32"
 | 
			
		||||
for i in $MINGW_LIBS; do
 | 
			
		||||
  cp -d $MINGW_DIR/lib/$i.dll $CONTENT_DIR
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
cp -d $DEPS_DIR/lib/liblept*.dll $CONTENT_DIR
 | 
			
		||||
cp -d $DEPS_DIR/lib/libtesseract*.dll $CONTENT_DIR
 | 
			
		||||
 | 
			
		||||
find $CONTENT_DIR -name '*.exe' -exec $STRIP -s {} \;
 | 
			
		||||
find $CONTENT_DIR -name '*.dll' -exec $STRIP -s {} \;
 | 
			
		||||
 | 
			
		||||
cd $ISS_DIR
 | 
			
		||||
wine "C:\Program Files\Inno Setup 5\iscc.exe" "InnoSetup.iss"
 | 
			
		||||
							
								
								
									
										21
									
								
								scripts/make_sf.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						@ -0,0 +1,21 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
source ./options.sh $@
 | 
			
		||||
 | 
			
		||||
cleanupDirInNeeded $SF_DIR
 | 
			
		||||
 | 
			
		||||
echo "Making SF"
 | 
			
		||||
function format {
 | 
			
		||||
  local FILE=$1
 | 
			
		||||
  sed "s/\(Changes\)/#\1/g" -i $FILE
 | 
			
		||||
  sed "s/\(Изменения\)/#\1/g" -i $FILE
 | 
			
		||||
  sed "s/\([0-9]\+\.[0-9]\+\.[0-9]\+:\)/##\1/g" -i $FILE
 | 
			
		||||
  sed "s/+\s/* /g" -i $FILE
 | 
			
		||||
  sed "s/-\s/* /g" -i $FILE
 | 
			
		||||
}
 | 
			
		||||
cp -f $SRC_DISTR_DIR/Changelog_en.txt $SF_DIR/readme.md
 | 
			
		||||
format $SF_DIR/readme.md
 | 
			
		||||
cp -f $SRC_DISTR_DIR/Changelog_ru.txt $SF_DIR/readme_ru.md
 | 
			
		||||
iconv -f cp1251 -t utf8 $SF_DIR/readme_ru.md -o $SF_DIR/readme_ru.md.u
 | 
			
		||||
mv $SF_DIR/readme_ru.md.u $SF_DIR/readme_ru.md
 | 
			
		||||
format $SF_DIR/readme_ru.md
 | 
			
		||||
							
								
								
									
										56
									
								
								scripts/options.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						@ -0,0 +1,56 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
PLATFORM=linux
 | 
			
		||||
CLEAN=false
 | 
			
		||||
JOBS=""
 | 
			
		||||
QT_CHOOSER="-qt=qt5"
 | 
			
		||||
QMAKE=qmake
 | 
			
		||||
QT_LIB_DIR=/usr/lib/x86_64-linux-gnu
 | 
			
		||||
STRIP=strip
 | 
			
		||||
 | 
			
		||||
for arg in ${@}; do
 | 
			
		||||
  case "$arg" in
 | 
			
		||||
    "linux" ) PLATFORM=linux;;
 | 
			
		||||
    "mingw" ) PLATFORM=mingw;;
 | 
			
		||||
    "clean" ) CLEAN=true;;
 | 
			
		||||
    "-j"* ) JOBS=$arg;;
 | 
			
		||||
    *"qmake" ) QMAKE=$arg
 | 
			
		||||
      QT_LIB_DIR=`readlink -e $(dirname $arg)/../lib`
 | 
			
		||||
      QT_CHOOSER=""
 | 
			
		||||
      ;;
 | 
			
		||||
  esac
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
WORK_DIR=../../build/$PLATFORM
 | 
			
		||||
MINGW_DIR=/opt/mingw-4.9.3/mingw-w64-i686
 | 
			
		||||
if [ "$PLATFORM" == "mingw" ]; then
 | 
			
		||||
  QT_LIB_DIR=`readlink -e $QT_LIB_DIR/../bin`
 | 
			
		||||
  HOST=i686-w64-mingw32
 | 
			
		||||
  HOST_ATTR="--host=$HOST"
 | 
			
		||||
  STRIP=$HOST-strip
 | 
			
		||||
  export PATH="$MINGW_DIR/bin:$PATH"
 | 
			
		||||
  COMPILERS="CC=\"${HOST}-gcc\" AR=\"${HOST}-ar\" RANLIB=\"${HOST}-ranlib\""
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
WORK_DIR=`readlink -m $WORK_DIR`
 | 
			
		||||
DEPS_DIR=`readlink -m $WORK_DIR/deps`
 | 
			
		||||
APP_DIR=`readlink -m $WORK_DIR/app`
 | 
			
		||||
DEB_DIR=`readlink -m $WORK_DIR/deb`
 | 
			
		||||
ISS_DIR=`readlink -m $WORK_DIR/iss`
 | 
			
		||||
SF_DIR=`readlink -m $WORK_DIR/sf`
 | 
			
		||||
DOWNLOAD_DIR=`readlink -m ../../`
 | 
			
		||||
SRC_DIR=`readlink -e ..`
 | 
			
		||||
SRC_DISTR_DIR=$SRC_DIR/distr
 | 
			
		||||
 | 
			
		||||
mkdir -p $WORK_DIR
 | 
			
		||||
 | 
			
		||||
function cleanupDirInNeeded {
 | 
			
		||||
  local DIR=$1
 | 
			
		||||
  if [[ "$CLEAN" == "true" && -d "$DIR" ]]; then    
 | 
			
		||||
    rm -rf $DIR    
 | 
			
		||||
  fi
 | 
			
		||||
  mkdir -p $DIR
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										33
									
								
								translators/bing.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,33 @@
 | 
			
		||||
var isPageLoaded = false;
 | 
			
		||||
var isTranslationFinished = false; // async translation request
 | 
			
		||||
var isScheduled = false;
 | 
			
		||||
 | 
			
		||||
function checkFinished () {
 | 
			
		||||
    if (!isPageLoaded || !isTranslationFinished || isScheduled) return;
 | 
			
		||||
    isScheduled = true;
 | 
			
		||||
    setTimeout(function () {
 | 
			
		||||
        var spans = [].slice.call (document.querySelectorAll ('#OutputText span'));
 | 
			
		||||
        var text = spans.reduce (function (res, i) {
 | 
			
		||||
            return res + i.innerText;
 | 
			
		||||
        }, '');
 | 
			
		||||
        st_wtp.translated (text);
 | 
			
		||||
    }, 2000); // wait for gui fill
 | 
			
		||||
}
 | 
			
		||||
function onResourceLoad (url) {
 | 
			
		||||
    if (url.indexOf ('/api.microsofttranslator.com/') > -1) {
 | 
			
		||||
        isTranslationFinished = true;
 | 
			
		||||
        checkFinished ();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
st_wtp.resourceLoaded.connect (onResourceLoad);
 | 
			
		||||
function onPageLoad () {
 | 
			
		||||
    isPageLoaded = true;
 | 
			
		||||
    checkFinished ();
 | 
			
		||||
}
 | 
			
		||||
window.onload = onPageLoad();
 | 
			
		||||
 | 
			
		||||
function translate (){
 | 
			
		||||
    var url = 'https://bing.com/translator/?text=' + st_wtp.sourceText + '#auto/' +
 | 
			
		||||
            st_wtp.resultLanguage;
 | 
			
		||||
    window.location = encodeURI (url);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								translators/google.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,34 @@
 | 
			
		||||
var isPageLoaded = false;
 | 
			
		||||
var isTranslationFinished = false; // async translation request
 | 
			
		||||
var isScheduled = false;
 | 
			
		||||
 | 
			
		||||
function checkFinished () {
 | 
			
		||||
    if (!isPageLoaded || !isTranslationFinished || isScheduled) return;
 | 
			
		||||
    isScheduled = true;
 | 
			
		||||
    setTimeout(function () {
 | 
			
		||||
        var spans = [].slice.call (document.querySelectorAll ('#result_box > span'));
 | 
			
		||||
        var text = spans.reduce (function (res, i) {
 | 
			
		||||
            return res + ' ' + i.innerText;
 | 
			
		||||
        }, '');
 | 
			
		||||
        st_wtp.translated (text);
 | 
			
		||||
        isTranslationFinished = isScheduled = false;
 | 
			
		||||
    }, 2000); // wait for gui fill
 | 
			
		||||
}
 | 
			
		||||
function onResourceLoad (url) {
 | 
			
		||||
    if (url.indexOf ('/translate_a/single') > -1) {
 | 
			
		||||
        isTranslationFinished = true;
 | 
			
		||||
        checkFinished ();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
st_wtp.resourceLoaded.connect (onResourceLoad);
 | 
			
		||||
function onPageLoad () {
 | 
			
		||||
    isPageLoaded = true;
 | 
			
		||||
    checkFinished ();
 | 
			
		||||
}
 | 
			
		||||
window.onload = onPageLoad();
 | 
			
		||||
 | 
			
		||||
function translate (){
 | 
			
		||||
    var url = 'https://translate.google.com/#auto/' +
 | 
			
		||||
            st_wtp.resultLanguage + '/' + st_wtp.sourceText;
 | 
			
		||||
    window.location = encodeURI (url);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								translators/yandex.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,31 @@
 | 
			
		||||
var isPageLoaded = false;
 | 
			
		||||
var isTranslationFinished = true; // async translation request
 | 
			
		||||
var isScheduled = false;
 | 
			
		||||
 | 
			
		||||
function checkFinished () {
 | 
			
		||||
    if (!isPageLoaded || !isTranslationFinished || isScheduled) return;
 | 
			
		||||
    isScheduled = true;
 | 
			
		||||
    setTimeout(function () {
 | 
			
		||||
        var spans = [].slice.call (document.querySelectorAll ('#translation > span'));
 | 
			
		||||
        var text = spans.reduce (function (res, i) {
 | 
			
		||||
            return res + i.innerText;
 | 
			
		||||
        }, '');
 | 
			
		||||
        st_wtp.translated (text);
 | 
			
		||||
    }, 2000); // wait for gui fill
 | 
			
		||||
}
 | 
			
		||||
function onResourceLoad (url) {
 | 
			
		||||
}
 | 
			
		||||
st_wtp.resourceLoaded.connect (onResourceLoad);
 | 
			
		||||
function onPageLoad () {
 | 
			
		||||
    isPageLoaded = true;
 | 
			
		||||
    checkFinished ();
 | 
			
		||||
}
 | 
			
		||||
window.onload = onPageLoad();
 | 
			
		||||
 | 
			
		||||
function translate (){
 | 
			
		||||
    var url = 'https://translate.yandex.ru/?text=' + st_wtp.sourceText + '&lang=auto-' +
 | 
			
		||||
            st_wtp.resultLanguage;
 | 
			
		||||
    url = url.replace(new RegExp(' ','g') , '%20')
 | 
			
		||||
    console.log(encodeURI(url));
 | 
			
		||||
    window.location = (url);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1578
									
								
								uncrustify.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										31
									
								
								version.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,31 @@
 | 
			
		||||
{
 | 
			
		||||
    "version": 1,
 | 
			
		||||
    "url": "https://cdn.rawgit.com/OneMoreGres/ScreenTranslator/master/version.json",
 | 
			
		||||
    "Application": {
 | 
			
		||||
        "version": 1,
 | 
			
		||||
        "compatibleVersion": 1,
 | 
			
		||||
        "compatibleVersion_linux": 999,
 | 
			
		||||
        "built_in": true,
 | 
			
		||||
        "versionString": "2.0.0",
 | 
			
		||||
        "permissions": "0x7755",
 | 
			
		||||
        "url_win": "https://raw.githubusercontent.com/OneMoreGres/ScreenTranslator/releases/2.0.0/ScreenTranslator.exe",
 | 
			
		||||
        "path_win": "ScreenTranslator.exe",
 | 
			
		||||
        "url_linux": "disabled",
 | 
			
		||||
        "path_linux": "ScreenTranslator"
 | 
			
		||||
    },
 | 
			
		||||
    "Bing translator": {
 | 
			
		||||
        "version": 1,
 | 
			
		||||
        "url": "https://raw.githubusercontent.com/OneMoreGres/ScreenTranslator/master/translators/bing.js",
 | 
			
		||||
        "path": "translators/bing.js"
 | 
			
		||||
    },
 | 
			
		||||
    "Google translator": {
 | 
			
		||||
        "version": 1,
 | 
			
		||||
        "url": "https://raw.githubusercontent.com/OneMoreGres/ScreenTranslator/master/translators/google.js",
 | 
			
		||||
        "path": "translators/google.js"
 | 
			
		||||
    },
 | 
			
		||||
    "Yandex translator": {
 | 
			
		||||
        "version": 1,
 | 
			
		||||
        "url": "https://raw.githubusercontent.com/OneMoreGres/ScreenTranslator/master/translators/yandex.js",
 | 
			
		||||
        "path": "translators/yandex.js"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||