Finish 2.0.0
2
.gitignore
vendored
@ -6,3 +6,5 @@
|
||||
|
||||
*.exe
|
||||
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,39 +1,17 @@
|
||||
#include "GlobalActionHelper.h"
|
||||
|
||||
#include <qt_windows.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QApplication>
|
||||
|
||||
QHash<QPair<quint32, quint32>, QAction *> GlobalActionHelper::actions_;
|
||||
|
||||
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);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GlobalActionHelper::init()
|
||||
{
|
||||
void GlobalActionHelper::init () {
|
||||
qApp->installNativeEventFilter (new GlobalActionHelper);
|
||||
}
|
||||
|
||||
bool GlobalActionHelper::makeGlobal(QAction* action)
|
||||
{
|
||||
bool GlobalActionHelper::makeGlobal (QAction *action) {
|
||||
QKeySequence hotKey = action->shortcut ();
|
||||
if (hotKey.isEmpty ())
|
||||
{
|
||||
if (hotKey.isEmpty ()) {
|
||||
return true;
|
||||
}
|
||||
Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier |
|
||||
@ -47,18 +25,18 @@ bool GlobalActionHelper::makeGlobal(QAction* action)
|
||||
const quint32 nativeKey = nativeKeycode (key);
|
||||
const quint32 nativeMods = nativeModifiers (mods);
|
||||
const bool res = registerHotKey (nativeKey, nativeMods);
|
||||
if (res)
|
||||
if (res) {
|
||||
actions_.insert (qMakePair (nativeKey, nativeMods), action);
|
||||
else
|
||||
}
|
||||
else {
|
||||
qWarning () << "Failed to register global hotkey:" << hotKey.toString ();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool GlobalActionHelper::removeGlobal(QAction *action)
|
||||
{
|
||||
bool GlobalActionHelper::removeGlobal (QAction *action) {
|
||||
QKeySequence hotKey = action->shortcut ();
|
||||
if (hotKey.isEmpty ())
|
||||
{
|
||||
if (hotKey.isEmpty ()) {
|
||||
return true;
|
||||
}
|
||||
Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier |
|
||||
@ -71,22 +49,144 @@ bool GlobalActionHelper::removeGlobal(QAction *action)
|
||||
Qt::KeyboardModifiers (hotKey[0] & allMods);
|
||||
const quint32 nativeKey = nativeKeycode (key);
|
||||
const quint32 nativeMods = nativeModifiers (mods);
|
||||
if (!actions_.contains (qMakePair(nativeKey, nativeMods)))
|
||||
{
|
||||
if (!actions_.contains (qMakePair (nativeKey, nativeMods))) {
|
||||
return true;
|
||||
}
|
||||
const bool res = unregisterHotKey (nativeKey, nativeMods);
|
||||
if (res)
|
||||
if (res) {
|
||||
actions_.remove (qMakePair (nativeKey, nativeMods));
|
||||
else
|
||||
}
|
||||
else {
|
||||
qWarning () << "Failed to unregister global hotkey:" << hotKey.toString ();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
quint32 GlobalActionHelper::nativeKeycode(Qt::Key key)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
quint32 GlobalActionHelper::nativeKeycode (Qt::Key key) {
|
||||
Display *display = QX11Info::display ();
|
||||
KeySym keySym = XStringToKeysym (qPrintable (QKeySequence (key).toString ()));
|
||||
return XKeysymToKeycode (display, keySym);
|
||||
}
|
||||
|
||||
quint32 GlobalActionHelper::nativeModifiers (Qt::KeyboardModifiers modifiers) {
|
||||
quint32 native = 0;
|
||||
if (modifiers & Qt::ShiftModifier) {
|
||||
native |= ShiftMask;
|
||||
}
|
||||
if (modifiers & Qt::ControlModifier) {
|
||||
native |= ControlMask;
|
||||
}
|
||||
if (modifiers & Qt::AltModifier) {
|
||||
native |= Mod1Mask;
|
||||
}
|
||||
if (modifiers & Qt::MetaModifier) {
|
||||
native |= Mod4Mask;
|
||||
}
|
||||
return native;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#elif defined(Q_OS_WIN)
|
||||
# include <qt_windows.h>
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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:
|
||||
@ -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,8 +6,7 @@
|
||||
#include <QAbstractNativeEventFilter>
|
||||
#include <QAction>
|
||||
|
||||
class GlobalActionHelper : public QAbstractNativeEventFilter
|
||||
{
|
||||
class GlobalActionHelper : public QAbstractNativeEventFilter {
|
||||
public:
|
||||
bool nativeEventFilter (const QByteArray &eventType, void *message,
|
||||
long *result);
|
||||
@ -23,6 +22,7 @@ class GlobalActionHelper : public QAbstractNativeEventFilter
|
||||
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,71 +7,78 @@
|
||||
#include "ImageProcessing.h"
|
||||
#include "StAssert.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#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 ()
|
||||
{
|
||||
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];
|
||||
}
|
||||
}
|
||||
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;
|
||||
if (resolutionX < 300) {
|
||||
resolutionX = 300;
|
||||
}
|
||||
if (resolutionY < 300) {
|
||||
resolutionY = 300;
|
||||
}
|
||||
pixSetResolution (pix, resolutionX, resolutionY);
|
||||
|
||||
return pixEndianByteSwapNew(pix);
|
||||
return pix;
|
||||
}
|
||||
|
||||
QImage convertImage(Pix &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(pixEndianByteSwapNew(&image));
|
||||
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);
|
||||
|
||||
@ -108,11 +115,10 @@ QImage convertImage(Pix &image)
|
||||
return none;
|
||||
}
|
||||
|
||||
return result.rgbSwapped();
|
||||
return result;
|
||||
}
|
||||
|
||||
Pix *prepareImage(const QImage &image, int preferredScale)
|
||||
{
|
||||
Pix * prepareImage (const QImage &image, int preferredScale) {
|
||||
Pix *pix = convertImage (image);
|
||||
ST_ASSERT (pix != NULL);
|
||||
|
||||
@ -121,32 +127,30 @@ Pix *prepareImage(const QImage &image, int preferredScale)
|
||||
pixDestroy (&pix);
|
||||
|
||||
Pix *scaled = gray;
|
||||
if (preferredScale > 0)
|
||||
{
|
||||
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;
|
||||
if (availableMemory > 0) {
|
||||
qint32 actualSize = gray->w * gray->h * gray->d / 8;
|
||||
float maxScaleMemory = float (availableMemory) / actualSize;
|
||||
scale = std::min (scale, maxScaleMemory);
|
||||
#endif
|
||||
|
||||
scaled = pixScale (gray, scale, scale);
|
||||
}
|
||||
ST_ASSERT (scaled != NULL);
|
||||
if (scaled != gray)
|
||||
{
|
||||
scaled = pixScale (gray, scale, scale);
|
||||
if (scaled == NULL) {
|
||||
scaled = gray;
|
||||
}
|
||||
}
|
||||
if (scaled != gray) {
|
||||
pixDestroy (&gray);
|
||||
}
|
||||
return scaled;
|
||||
}
|
||||
|
||||
void cleanupImage(Pix **image)
|
||||
{
|
||||
void cleanupImage (Pix **image) {
|
||||
pixDestroy (image);
|
||||
}
|
||||
|
@ -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,8 +105,39 @@ void LanguageHelper::updateAvailableOcrLanguages()
|
||||
availableOcrLanguages_ = availableOcrLanguages (tessDataPlace);
|
||||
}
|
||||
|
||||
void LanguageHelper::initTranslateLanguages()
|
||||
{
|
||||
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::initTranslateLanguages () {
|
||||
translateLanguages_.insert (QObject::tr ("Afrikaans"),"af");
|
||||
translateLanguages_.insert (QObject::tr ("Albanian"),"sq");
|
||||
translateLanguages_.insert (QObject::tr ("Arabic"),"ar");
|
||||
@ -176,8 +198,7 @@ void LanguageHelper::initTranslateLanguages()
|
||||
translateLanguages_.insert (QObject::tr ("Yiddish"),"yi");
|
||||
}
|
||||
|
||||
void LanguageHelper::initOcrLanguages()
|
||||
{
|
||||
void LanguageHelper::initOcrLanguages () {
|
||||
ocrLanguages_.insert (QObject::tr ("Ancient Greek"),"grc");
|
||||
ocrLanguages_.insert (QObject::tr ("Esperanto alternative"),"epo_alt");
|
||||
ocrLanguages_.insert (QObject::tr ("English"),"eng");
|
||||
@ -241,4 +262,40 @@ void LanguageHelper::initOcrLanguages()
|
||||
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,9 +3,9 @@
|
||||
|
||||
#include <QMap>
|
||||
#include <QStringList>
|
||||
#include <QMenu>
|
||||
|
||||
class LanguageHelper
|
||||
{
|
||||
class LanguageHelper {
|
||||
public:
|
||||
LanguageHelper ();
|
||||
|
||||
@ -19,10 +19,14 @@ class LanguageHelper
|
||||
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 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;
|
||||
void init ();
|
||||
|
436
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)),
|
||||
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)),
|
||||
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);
|
||||
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 * 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()
|
||||
{
|
||||
void Manager::checkForUpdates () {
|
||||
updater_->checkForUpdates ();
|
||||
scheduleUpdate (true);
|
||||
}
|
||||
|
||||
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 ();
|
||||
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);
|
||||
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::settings()
|
||||
{
|
||||
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";
|
||||
void Manager::about () {
|
||||
QString text = tr ("Программа для распознавания текста на экране.\n" \
|
||||
"Создана с использованием Qt, tesseract-ocr, Google Translate.\n"
|
||||
"Автор: Gres (translator@gres.biz)\n"
|
||||
"Версия: %1 от %2 %3").arg (version)
|
||||
"Версия: %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));
|
||||
}
|
||||
|
37
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
|
||||
{
|
||||
class Manager : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
enum IconType {
|
||||
IconTypeNormal, IconTypeWorking, IconTypeError, IconTypeSuccess
|
||||
};
|
||||
|
||||
public:
|
||||
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);
|
||||
|
||||
void updateNormalIcon ();
|
||||
|
||||
private:
|
||||
QMenu * trayContextMenu ();
|
||||
void updateActionsState (bool isEnabled = true);
|
||||
void changeIcon (int iconType, int timeoutMsec = 3000);
|
||||
void scheduleUpdate (bool justChecked = false);
|
||||
|
||||
private:
|
||||
QSystemTrayIcon *trayIcon_;
|
||||
LanguageHelper *dictionary_;
|
||||
SelectionDialog* selection_;
|
||||
//! 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_;
|
||||
ProcessingItem lastItem_;
|
||||
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 &= (!ocrLanguage.isEmpty ());
|
||||
if (!checkOnlyInput) {
|
||||
valid &= (!recognized.isEmpty ());
|
||||
valid &= (!translated.isEmpty ());
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
@ -3,8 +3,8 @@
|
||||
|
||||
#include <QPixmap>
|
||||
|
||||
struct ProcessingItem
|
||||
{
|
||||
struct ProcessingItem {
|
||||
ProcessingItem ();
|
||||
QPoint screenPos;
|
||||
QPixmap source;
|
||||
QString recognized;
|
||||
@ -12,8 +12,12 @@ struct ProcessingItem
|
||||
|
||||
QString ocrLanguage;
|
||||
QString sourceLanguage;
|
||||
QString translateLanguage;
|
||||
|
||||
bool isValid () const;
|
||||
Qt::KeyboardModifiers modifiers;
|
||||
bool swapLanguages_;
|
||||
|
||||
bool isValid (bool checkOnlyInput = false) const;
|
||||
};
|
||||
Q_DECLARE_METATYPE (ProcessingItem)
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
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),
|
||||
tesseract::OEM_DEFAULT);
|
||||
if (result != 0)
|
||||
{
|
||||
if (result != 0) {
|
||||
emit error (tr ("Ошибка инициализации OCR: %1").arg (result));
|
||||
delete engine;
|
||||
engine = NULL;
|
||||
@ -59,17 +55,17 @@ 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_);
|
||||
void Recognizer::recognize (ProcessingItem item) {
|
||||
if (!item.isValid (true)) {
|
||||
emit recognized (item);
|
||||
return;
|
||||
}
|
||||
bool isCustomLanguage = (item.ocrLanguage != ocrLanguage_);
|
||||
tesseract::TessBaseAPI *engine = (isCustomLanguage) ? NULL : engine_;
|
||||
if (engine == NULL)
|
||||
{
|
||||
QString language = (isCustomLanguage) ? item.ocrLanguage : ocrLanguage_;
|
||||
if (!initEngine (engine, language))
|
||||
{
|
||||
if (engine == NULL) {
|
||||
if (!initEngine (engine, language)) {
|
||||
emit recognized (item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -83,18 +79,15 @@ void Recognizer::recognize(ProcessingItem item)
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -6,14 +6,14 @@
|
||||
|
||||
#include "ProcessingItem.h"
|
||||
|
||||
namespace tesseract
|
||||
{
|
||||
namespace tesseract {
|
||||
class TessBaseAPI;
|
||||
}
|
||||
class RecognizerHelper;
|
||||
|
||||
class Recognizer : public QObject
|
||||
{
|
||||
class Recognizer : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Recognizer (QObject *parent = 0);
|
||||
|
||||
@ -30,6 +30,7 @@ class Recognizer : public QObject
|
||||
|
||||
private:
|
||||
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>
|
||||
|
114
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) :
|
||||
ResultDialog::ResultDialog (const LanguageHelper &dictionary, QWidget *parent) :
|
||||
QDialog (parent),
|
||||
ui (new Ui::ResultDialog),
|
||||
isShowAtCapturePos_ (true)
|
||||
{
|
||||
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 ();
|
||||
Q_CHECK_PTR (desktop);
|
||||
if (isShowAtCapturePos_)
|
||||
{
|
||||
QPoint correction = QPoint (ui->frame->lineWidth (), ui->frame->lineWidth ());
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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
|
||||
{
|
||||
class ResultDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ResultDialog(QWidget *parent = 0);
|
||||
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
|
||||
|
@ -11,156 +11,112 @@
|
||||
SelectionDialog::SelectionDialog (const LanguageHelper &dictionary, QWidget *parent) :
|
||||
QDialog (parent),
|
||||
ui (new Ui::SelectionDialog), dictionary_ (dictionary),
|
||||
languageMenu_ (new QMenu)
|
||||
{
|
||||
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->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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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 (mouseEvent->button () == Qt::RightButton &&
|
||||
!languageMenu_->children ().isEmpty ())
|
||||
{
|
||||
QAction* action = languageMenu_->exec (QCursor::pos ());
|
||||
if (action == NULL)
|
||||
{
|
||||
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 (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,8 +12,7 @@ namespace Ui {
|
||||
}
|
||||
class LanguageHelper;
|
||||
|
||||
class SelectionDialog : public QDialog
|
||||
{
|
||||
class SelectionDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
@ -24,10 +23,12 @@ class SelectionDialog : public QDialog
|
||||
|
||||
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;
|
||||
@ -36,6 +37,7 @@ class SelectionDialog : public QDialog
|
||||
QPoint currentSelectPos_;
|
||||
QPixmap currentPixmap_;
|
||||
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,101 +1,190 @@
|
||||
#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 (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->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 ());
|
||||
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);
|
||||
@ -103,31 +192,97 @@ void SettingsEditor::loadSettings()
|
||||
QString ocrLanguage = dictionary_.ocrCodeToUi (GET (ocrLanguage).toString ());
|
||||
ui->ocrLangCombo->setCurrentText (ocrLanguage);
|
||||
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);
|
||||
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
|
||||
{
|
||||
class SettingsEditor : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
enum SubsCol {
|
||||
SubsColLanguage = 0, SubsColSource, SubsColTarget
|
||||
};
|
||||
|
||||
public:
|
||||
explicit SettingsEditor (const LanguageHelper &dictionary, QWidget *parent = 0);
|
||||
~SettingsEditor ();
|
||||
|
||||
signals:
|
||||
void settingsEdited ();
|
||||
void updateCheckRequested ();
|
||||
|
||||
public slots:
|
||||
void done (int result);
|
||||
@ -28,14 +35,18 @@ class SettingsEditor : public QDialog
|
||||
void saveSettings () const;
|
||||
void openTessdataDialog ();
|
||||
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;
|
||||
TranslatorHelper *translatorHelper_;
|
||||
RecognizerHelper *recognizerHelper_;
|
||||
const LanguageHelper &dictionary_;
|
||||
QButtonGroup *buttonGroup_;
|
||||
};
|
||||
|
@ -6,14 +6,34 @@
|
||||
<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">
|
||||
<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>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</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">
|
||||
@ -28,59 +48,230 @@
|
||||
<property name="text">
|
||||
<string>Захватить</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>captureEdit</cstring>
|
||||
</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="0" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="captureEdit"/>
|
||||
<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>
|
||||
<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 row="3" column="1">
|
||||
<widget class="QKeySequenceEdit" name="clipboardEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Распознавание</string>
|
||||
<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://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>
|
||||
<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>
|
||||
@ -113,10 +304,13 @@
|
||||
</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></body></html></string>
|
||||
<string><html><head/><body><p>Масштабирование изображения для улучшения распознания. Больше - лучше (до определенных пределов), но медленнее и потребляет больше памяти.</p><p>Рекомендуемые значения от 5 до 10.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Увеличение масштаба</string>
|
||||
@ -126,112 +320,163 @@
|
||||
</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>
|
||||
<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="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>
|
||||
<string>Исправления:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QRadioButton" name="dialogRadio">
|
||||
<property name="text">
|
||||
<string>Окно</string>
|
||||
<item row="4" column="0" colspan="3">
|
||||
<widget class="QTableWidget" name="recognizerFixTable">
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<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>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<widget class="QWidget" name="translateTab">
|
||||
<attribute name="title">
|
||||
<string>Перевод</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
</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>
|
||||
<string>Язык результата:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>translateLangCombo</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<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>
|
||||
</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">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</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>
|
||||
|
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.
|
@ -1,4 +1,21 @@
|
||||
Изменения.
|
||||
2.0.0:
|
||||
* Добавлена версия под linux.
|
||||
* Добавлена поддержка нескольких мониторов.
|
||||
* Добавлеа возможность распознание без перевода.
|
||||
* Добавлена возможность вызова старого рисунка для выделения.
|
||||
* Добавлена возможность повторного выделения без закрытия окна захвата.
|
||||
* Добавлена возможность повторного распознания на другом языке.
|
||||
* Добавлена возможность отображения промежуточного результата при ошибке перевода.
|
||||
* Добавлена поддержка разных сервисов перевода.
|
||||
* Добавлена возможность копирования изображения в буфер.
|
||||
* Добавлена возможность редакции распознанного текста.
|
||||
* Добавлена возможность автоматической коррекции частых ошибок распознавания.
|
||||
* Добавлена возможность использования прокси.
|
||||
* Добавлена возможность разовой смена языка перевода и распознавания.
|
||||
* Обновлены иконки.
|
||||
* Добавлено отображение статуса работы на иконке.
|
||||
* Добавлена возможность автоматического обновления.
|
||||
1.2.3:
|
||||
* Устранена возможная причина падения.
|
||||
* Добавлена информация о версии и некоторые сообщения об ошибках.
|
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 |
20
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,8 +25,7 @@ int main(int argc, char *argv[])
|
||||
QTranslator translator;
|
||||
// Set default to english.
|
||||
if (translator.load (QLocale::system (), "translation", "_", ":/translations") ||
|
||||
translator.load (":/translations/translation_en"))
|
||||
{
|
||||
translator.load (":/translations/translation_en")) {
|
||||
a.installTranslator (&translator);
|
||||
}
|
||||
|
||||
|
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"
|
||||
}
|
||||
}
|