commit
7d6323168d
13 changed files with 258 additions and 136 deletions
|
@ -6,7 +6,7 @@ import "pages"
|
||||||
|
|
||||||
ApplicationWindow
|
ApplicationWindow
|
||||||
{
|
{
|
||||||
initialPage: Component { FirstPage { } }
|
initialPage: Component { FirstPage { selectedFile: Qt.application.arguments[1] ? Qt.application.arguments[1] : "" } }
|
||||||
cover: Qt.resolvedUrl("cover/CoverPage.qml")
|
cover: Qt.resolvedUrl("cover/CoverPage.qml")
|
||||||
allowedOrientations: defaultAllowedOrientations
|
allowedOrientations: defaultAllowedOrientations
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,6 @@ Page {
|
||||||
property string selectedFile: ""
|
property string selectedFile: ""
|
||||||
property string selectedFileType
|
property string selectedFileType
|
||||||
|
|
||||||
IppDiscovery {
|
|
||||||
id: discovery
|
|
||||||
}
|
|
||||||
|
|
||||||
WifiChecker {
|
WifiChecker {
|
||||||
id: wifi
|
id: wifi
|
||||||
onConnectedChanged: {
|
onConnectedChanged: {
|
||||||
|
@ -25,10 +21,10 @@ Page {
|
||||||
if(connected) {
|
if(connected) {
|
||||||
var favourites = db.getFavourites(ssid);
|
var favourites = db.getFavourites(ssid);
|
||||||
console.log(favourites);
|
console.log(favourites);
|
||||||
discovery.favourites = favourites;
|
IppDiscovery.favourites = favourites;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
discovery.favourites = []
|
IppDiscovery.favourites = []
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -39,7 +35,7 @@ Page {
|
||||||
console.log("ssid changed", ssid);
|
console.log("ssid changed", ssid);
|
||||||
if(!initialSSIDchange)
|
if(!initialSSIDchange)
|
||||||
{
|
{
|
||||||
discovery.reset();
|
IppDiscovery.reset();
|
||||||
}
|
}
|
||||||
initialSSIDchange = false;
|
initialSSIDchange = false;
|
||||||
}
|
}
|
||||||
|
@ -48,7 +44,22 @@ Page {
|
||||||
signal refreshed()
|
signal refreshed()
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
discovery.discover();
|
IppDiscovery.discover();
|
||||||
|
if(selectedFile != "")
|
||||||
|
{ // Until i can convince FilePickerPage to do its magic without user interaction
|
||||||
|
if(Utils.endsWith(".pdf", selectedFile))
|
||||||
|
{
|
||||||
|
selectedFileType = "application/pdf"
|
||||||
|
}
|
||||||
|
else if(Utils.endsWith(".jpg", selectedFile) || Utils.endsWith(".jpeg", selectedFile))
|
||||||
|
{
|
||||||
|
selectedFileType = "image/jpeg"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
selectedFile = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// To enable PullDownMenu, place our content in a SilicaFlickable
|
// To enable PullDownMenu, place our content in a SilicaFlickable
|
||||||
|
@ -70,14 +81,14 @@ Page {
|
||||||
dialog.accepted.connect(function() {
|
dialog.accepted.connect(function() {
|
||||||
console.log("add", wifi.ssid, dialog.value);
|
console.log("add", wifi.ssid, dialog.value);
|
||||||
db.addFavourite(wifi.ssid, dialog.value);
|
db.addFavourite(wifi.ssid, dialog.value);
|
||||||
discovery.favourites = db.getFavourites(wifi.ssid);
|
IppDiscovery.favourites = db.getFavourites(wifi.ssid);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: qsTr("Refresh")
|
text: qsTr("Refresh")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
discovery.discover();
|
IppDiscovery.discover();
|
||||||
page.refreshed();
|
page.refreshed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,7 +97,7 @@ Page {
|
||||||
SilicaListView {
|
SilicaListView {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
id: listView
|
id: listView
|
||||||
model: discovery
|
model: IppDiscovery
|
||||||
spacing: Theme.paddingSmall
|
spacing: Theme.paddingSmall
|
||||||
|
|
||||||
|
|
||||||
|
@ -147,7 +158,7 @@ Page {
|
||||||
|
|
||||||
height: Theme.itemSizeLarge
|
height: Theme.itemSizeLarge
|
||||||
width: Theme.itemSizeLarge
|
width: Theme.itemSizeLarge
|
||||||
source: printer.attrs["printer-icons"] ? printer.attrs["printer-icons"].value[0] : "icon-seaprint-nobg.svg"
|
source: printer.attrs["printer-icons"] ? "image://ippdiscovery/"+printer.attrs["printer-icons"].value[0] : "icon-seaprint-nobg.svg"
|
||||||
// Some printers serve their icons over https with invalid certs...
|
// Some printers serve their icons over https with invalid certs...
|
||||||
onStatusChanged: if (status == Image.Error) source = "icon-seaprint-nobg.svg"
|
onStatusChanged: if (status == Image.Error) source = "icon-seaprint-nobg.svg"
|
||||||
}
|
}
|
||||||
|
@ -200,7 +211,7 @@ Page {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
removeRemorse.execute(delegate, qsTr("Removing printer"),
|
removeRemorse.execute(delegate, qsTr("Removing printer"),
|
||||||
function() {db.removeFavourite(wifi.ssid, model.display);
|
function() {db.removeFavourite(wifi.ssid, model.display);
|
||||||
discovery.favourites = db.getFavourites()})
|
IppDiscovery.favourites = db.getFavourites()})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ function supported_formats(printer)
|
||||||
|
|
||||||
if(supported.length == 0)
|
if(supported.length == 0)
|
||||||
{
|
{
|
||||||
supported.push(qsTr("No relevant formats supported"))
|
supported.push(qsTr("No compatible formats supported"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return supported.join(" ");
|
return supported.join(" ");
|
||||||
|
@ -86,3 +86,8 @@ function ippName(name, value)
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function endsWith(ending, string)
|
||||||
|
{
|
||||||
|
return string.lastIndexOf(ending) == (string.length - ending.length);
|
||||||
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@ Name: harbour-seaprint
|
||||||
# << macros
|
# << macros
|
||||||
|
|
||||||
Summary: SeaPrint
|
Summary: SeaPrint
|
||||||
Version: 0.3.1
|
Version: 0.4
|
||||||
Release: 1
|
Release: 3
|
||||||
Group: Qt/Qt
|
Group: Qt/Qt
|
||||||
License: LICENSE
|
License: LICENSE
|
||||||
URL: http://example.org/
|
URL: http://example.org/
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
Name: harbour-seaprint
|
Name: harbour-seaprint
|
||||||
Summary: SeaPrint
|
Summary: SeaPrint
|
||||||
Version: 0.3.1
|
Version: 0.4
|
||||||
Release: 1
|
Release: 3
|
||||||
# The contents of the Group field should be one of the groups listed here:
|
# The contents of the Group field should be one of the groups listed here:
|
||||||
# https://github.com/mer-tools/spectacle/blob/master/data/GROUPS
|
# https://github.com/mer-tools/spectacle/blob/master/data/GROUPS
|
||||||
Group: Qt/Qt
|
Group: Qt/Qt
|
||||||
|
|
|
@ -5,24 +5,32 @@
|
||||||
#include <src/ippdiscovery.h>
|
#include <src/ippdiscovery.h>
|
||||||
#include <src/ippprinter.h>
|
#include <src/ippprinter.h>
|
||||||
|
|
||||||
|
static QObject* ippdiscovery_singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
|
||||||
|
{
|
||||||
|
Q_UNUSED(engine)
|
||||||
|
Q_UNUSED(scriptEngine)
|
||||||
|
|
||||||
|
IppDiscovery *ippdiscovery = IppDiscovery::instance();
|
||||||
|
return ippdiscovery;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QGuiApplication* app = SailfishApp::application(argc, argv);
|
QGuiApplication* app = SailfishApp::application(argc, argv);
|
||||||
|
|
||||||
app->setApplicationVersion(QStringLiteral(SEAPRINT_VERSION));
|
app->setApplicationVersion(QStringLiteral(SEAPRINT_VERSION));
|
||||||
|
|
||||||
qmlRegisterType<IppDiscovery>("seaprint.ippdiscovery", 1, 0, "IppDiscovery");
|
qmlRegisterSingletonType<IppDiscovery>("seaprint.ippdiscovery", 1, 0, "IppDiscovery", ippdiscovery_singletontype_provider);
|
||||||
qmlRegisterType<IppPrinter>("seaprint.ippprinter", 1, 0, "IppPrinter");
|
qmlRegisterType<IppPrinter>("seaprint.ippprinter", 1, 0, "IppPrinter");
|
||||||
|
|
||||||
// SailfishApp::main() will display "qml/harbour-printtool.qml", if you need more
|
QQuickView* view = SailfishApp::createView();
|
||||||
// control over initialization, you can use:
|
|
||||||
//
|
view->engine()->addImportPath(SailfishApp::pathTo("qml/pages").toString());
|
||||||
// - SailfishApp::application(int, char *[]) to get the QGuiApplication *
|
view->engine()->addImageProvider(QLatin1String("ippdiscovery"), IppDiscovery::instance());
|
||||||
// - SailfishApp::createView() to get a new QQuickView * instance
|
|
||||||
// - SailfishApp::pathTo(QString) to get a QUrl to a resource file
|
view->setSource(SailfishApp::pathToMainQml());
|
||||||
// - SailfishApp::pathToMainQml() to get a QUrl to the main QML file
|
view->show();
|
||||||
//
|
return app->exec();
|
||||||
// To display the view, call "show()" (will show fullscreen on device).
|
|
||||||
|
|
||||||
return SailfishApp::main(argc, argv);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ QStringList get_addr(Bytestream& bts)
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
IppDiscovery::IppDiscovery() : QStringListModel()
|
IppDiscovery::IppDiscovery() : QStringListModel(), QQuickImageProvider(QQuickImageProvider::Image)
|
||||||
{
|
{
|
||||||
socket = new QUdpSocket(this);
|
socket = new QUdpSocket(this);
|
||||||
connect(socket, SIGNAL(readyRead()),
|
connect(socket, SIGNAL(readyRead()),
|
||||||
|
@ -57,6 +57,24 @@ IppDiscovery::~IppDiscovery() {
|
||||||
delete socket;
|
delete socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IppDiscovery* IppDiscovery::m_Instance = 0;
|
||||||
|
|
||||||
|
IppDiscovery* IppDiscovery::instance()
|
||||||
|
{
|
||||||
|
static QMutex mutex;
|
||||||
|
if (!m_Instance)
|
||||||
|
{
|
||||||
|
mutex.lock();
|
||||||
|
|
||||||
|
if (!m_Instance)
|
||||||
|
m_Instance = new IppDiscovery;
|
||||||
|
|
||||||
|
mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_Instance;
|
||||||
|
}
|
||||||
|
|
||||||
void IppDiscovery::discover() {
|
void IppDiscovery::discover() {
|
||||||
sendQuery(PTR, {"_ipp","_tcp","local"});
|
sendQuery(PTR, {"_ipp","_tcp","local"});
|
||||||
}
|
}
|
||||||
|
@ -136,69 +154,77 @@ void IppDiscovery::readPendingDatagrams()
|
||||||
sender = QHostAddress(sender.toIPv4Address());
|
sender = QHostAddress(sender.toIPv4Address());
|
||||||
|
|
||||||
quint16 transactionid, flags, questions, answerRRs, authRRs, addRRs;
|
quint16 transactionid, flags, questions, answerRRs, authRRs, addRRs;
|
||||||
resp >> transactionid >> flags >> questions >> answerRRs >> authRRs >> addRRs;
|
|
||||||
|
|
||||||
for(quint16 i = 0; i < questions; i++)
|
try {
|
||||||
{
|
|
||||||
quint16 qtype, qflags;
|
|
||||||
QString qaddr = get_addr(resp).join('.');
|
|
||||||
resp >> qtype >> qflags;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(quint16 i = 0; i < answerRRs; i++)
|
resp >> transactionid >> flags >> questions >> answerRRs >> authRRs >> addRRs;
|
||||||
{
|
|
||||||
quint16 atype, aflags, len;
|
|
||||||
quint32 ttl;
|
|
||||||
|
|
||||||
QString aaddr = get_addr(resp).join('.');
|
for(quint16 i = 0; i < questions; i++)
|
||||||
resp >> atype >> aflags >> ttl >> len;
|
|
||||||
|
|
||||||
quint16 pos_before = resp.pos();
|
|
||||||
if (atype == PTR)
|
|
||||||
{
|
{
|
||||||
QString tmpname = get_addr(resp).join(".");
|
quint16 qtype, qflags;
|
||||||
if(aaddr.endsWith("_ipp._tcp.local"))
|
QString qaddr = get_addr(resp).join('.');
|
||||||
{
|
resp >> qtype >> qflags;
|
||||||
ipp_ptrs.append(tmpname);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if(atype == TXT)
|
|
||||||
|
for(quint16 i = 0; i < answerRRs; i++)
|
||||||
{
|
{
|
||||||
Bytestream tmp;
|
quint16 atype, aflags, len;
|
||||||
while(resp.pos() < pos_before+len)
|
quint32 ttl;
|
||||||
|
|
||||||
|
QString aaddr = get_addr(resp).join('.');
|
||||||
|
resp >> atype >> aflags >> ttl >> len;
|
||||||
|
|
||||||
|
quint16 pos_before = resp.pos();
|
||||||
|
if (atype == PTR)
|
||||||
{
|
{
|
||||||
resp/resp.getU8() >> tmp;
|
QString tmpname = get_addr(resp).join(".");
|
||||||
if(tmp >>= "rp=")
|
if(aaddr.endsWith("_ipp._tcp.local"))
|
||||||
{
|
{
|
||||||
std::string tmprp;
|
ipp_ptrs.append(tmpname);
|
||||||
tmp/tmp.remaining() >> tmprp;
|
|
||||||
_rps[aaddr] = tmprp.c_str();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else if(atype == TXT)
|
||||||
else if (atype == SRV)
|
{
|
||||||
{
|
Bytestream tmp;
|
||||||
quint16 prio, w, port;
|
while(resp.pos() < pos_before+len)
|
||||||
resp >> prio >> w >> port;
|
{
|
||||||
QString target = get_addr(resp).join(".");
|
resp/resp.getU8() >> tmp;
|
||||||
_ports[aaddr] = port;
|
if(tmp >>= "rp=")
|
||||||
_targets[aaddr] = target;
|
{
|
||||||
}
|
std::string tmprp;
|
||||||
else if(atype == A)
|
tmp/tmp.remaining() >> tmprp;
|
||||||
{
|
_rps[aaddr] = tmprp.c_str();
|
||||||
quint32 addr;
|
}
|
||||||
resp >> addr;
|
}
|
||||||
QHostAddress haddr(addr);
|
}
|
||||||
_AAs.insert(aaddr, haddr.toString());
|
else if (atype == SRV)
|
||||||
}
|
{
|
||||||
else
|
quint16 prio, w, port;
|
||||||
{
|
resp >> prio >> w >> port;
|
||||||
resp += len;
|
QString target = get_addr(resp).join(".");
|
||||||
}
|
_ports[aaddr] = port;
|
||||||
Q_ASSERT(resp.pos() == pos_before+len);
|
_targets[aaddr] = target;
|
||||||
|
}
|
||||||
|
else if(atype == A)
|
||||||
|
{
|
||||||
|
quint32 addr;
|
||||||
|
resp >> addr;
|
||||||
|
QHostAddress haddr(addr);
|
||||||
|
_AAs.insert(aaddr, haddr.toString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resp += len;
|
||||||
|
}
|
||||||
|
Q_ASSERT(resp.pos() == pos_before+len);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(std::exception e)
|
||||||
|
{
|
||||||
|
qDebug() << e.what();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "new ipp ptrs" << ipp_ptrs;
|
qDebug() << "new ipp ptrs" << ipp_ptrs;
|
||||||
qDebug() << "ipp ptrs" << _ipp;
|
qDebug() << "ipp ptrs" << _ipp;
|
||||||
qDebug() << "rps" << _rps;
|
qDebug() << "rps" << _rps;
|
||||||
|
@ -223,3 +249,59 @@ void IppDiscovery::readPendingDatagrams()
|
||||||
this->update();
|
this->update();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IppDiscovery::ignoreKnownSslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
|
||||||
|
{
|
||||||
|
QList<QSslError> IgnoredSslErrors = {QSslError::NoError,
|
||||||
|
QSslError::SelfSignedCertificate,
|
||||||
|
QSslError::HostNameMismatch,
|
||||||
|
QSslError::UnableToGetLocalIssuerCertificate,
|
||||||
|
QSslError::UnableToVerifyFirstCertificate
|
||||||
|
};
|
||||||
|
|
||||||
|
qDebug() << errors;
|
||||||
|
for (QList<QSslError>::const_iterator it = errors.constBegin(); it != errors.constEnd(); it++) {
|
||||||
|
if(!IgnoredSslErrors.contains(it->error())) {
|
||||||
|
qDebug() << "Bad error: " << int(it->error()) << it->error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// For whatever reason, it doesn't work to pass IgnoredSslErrors here
|
||||||
|
reply->ignoreSslErrors(errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage IppDiscovery::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
|
||||||
|
{ //TODO: consider caching images (doesn't appear to be needed currently)
|
||||||
|
Q_UNUSED(size);
|
||||||
|
Q_UNUSED(requestedSize);
|
||||||
|
qDebug() << "requesting image" << id;
|
||||||
|
|
||||||
|
QImage img;
|
||||||
|
|
||||||
|
QNetworkAccessManager* nam = new QNetworkAccessManager(this);
|
||||||
|
QUrl url(id);
|
||||||
|
qDebug() << url.host() << _AAs;
|
||||||
|
// TODO IPv6
|
||||||
|
if(_AAs.contains(url.host()))
|
||||||
|
{ // TODO: retry potential other IPs
|
||||||
|
url.setHost(_AAs.value(url.host()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QNetworkReply* reply = nam->get(QNetworkRequest(url));
|
||||||
|
|
||||||
|
QEventLoop el;
|
||||||
|
connect(reply, SIGNAL(finished()),&el,SLOT(quit()));
|
||||||
|
connect(nam, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
|
||||||
|
this, SLOT(ignoreKnownSslErrors(QNetworkReply*, const QList<QSslError>&)));
|
||||||
|
el.exec();
|
||||||
|
|
||||||
|
if (reply->error() == QNetworkReply::NoError)
|
||||||
|
{
|
||||||
|
QImageReader imageReader(reply);
|
||||||
|
img = imageReader.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
delete nam;
|
||||||
|
return img;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -1,15 +1,21 @@
|
||||||
#ifndef IPPDISCOVERY_H
|
#ifndef IPPDISCOVERY_H
|
||||||
#define IPPDISCOVERY_H
|
#define IPPDISCOVERY_H
|
||||||
#include <QStringListModel>
|
#include <QStringListModel>
|
||||||
|
#include <QQuickImageProvider>
|
||||||
#include <QUdpSocket>
|
#include <QUdpSocket>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QImageReader>
|
||||||
|
#include <QtNetwork>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QEventLoop>
|
||||||
#include "bytestream.h"
|
#include "bytestream.h"
|
||||||
|
|
||||||
class IppDiscovery : public QStringListModel
|
class IppDiscovery : public QStringListModel, public QQuickImageProvider
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
IppDiscovery();
|
static IppDiscovery* instance();
|
||||||
~IppDiscovery();
|
|
||||||
Q_PROPERTY(QStringList favourites MEMBER _favourites NOTIFY favouritesChanged)
|
Q_PROPERTY(QStringList favourites MEMBER _favourites NOTIFY favouritesChanged)
|
||||||
Q_INVOKABLE void discover();
|
Q_INVOKABLE void discover();
|
||||||
Q_INVOKABLE void reset();
|
Q_INVOKABLE void reset();
|
||||||
|
@ -20,11 +26,21 @@ signals:
|
||||||
public slots:
|
public slots:
|
||||||
void readPendingDatagrams();
|
void readPendingDatagrams();
|
||||||
void update();
|
void update();
|
||||||
|
void ignoreKnownSslErrors(QNetworkReply *reply, const QList<QSslError> &errors);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
private:
|
private:
|
||||||
|
static IppDiscovery* m_Instance;
|
||||||
|
|
||||||
|
IppDiscovery();
|
||||||
|
~IppDiscovery();
|
||||||
|
IppDiscovery(const IppDiscovery &);
|
||||||
|
IppDiscovery& operator=(const IppDiscovery &);
|
||||||
|
|
||||||
void sendQuery(quint16 qtype, QStringList addr);
|
void sendQuery(quint16 qtype, QStringList addr);
|
||||||
|
|
||||||
|
QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override;
|
||||||
|
|
||||||
QStringList _ipp;
|
QStringList _ipp;
|
||||||
QMap<QString,QString> _rps;
|
QMap<QString,QString> _rps;
|
||||||
QMap<QString,quint16> _ports;
|
QMap<QString,quint16> _ports;
|
||||||
|
|
|
@ -282,7 +282,7 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>No relevant formats supported</source>
|
<source>No compatible formats supported</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
|
|
@ -282,8 +282,8 @@
|
||||||
<translation>ppp</translation>
|
<translation>ppp</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>No relevant formats supported</source>
|
<source>No compatible formats supported</source>
|
||||||
<translation>No hay formatos relevantes compatibles</translation>
|
<translation type="unfinished">No hay formatos compatibles</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
</TS>
|
</TS>
|
||||||
|
|
|
@ -57,11 +57,11 @@
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Code and Testing - Rudi Timmermans</source>
|
<source>Code and Testing - Rudi Timmermans</source>
|
||||||
<translation type="unfinished">Rudi Timmermans - Code et test</translation>
|
<translation>Rudi Timmermans - Code et test</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Spanish</source>
|
<source>Spanish</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>Espagnol</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
@ -84,7 +84,7 @@
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Unknown</source>
|
<source>Unknown</source>
|
||||||
<translation type="unfinished">Inconnu</translation>
|
<translation>Inconnu</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
@ -138,7 +138,7 @@
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Unknown</source>
|
<source>Unknown</source>
|
||||||
<translation type="unfinished">Inconnu</translation>
|
<translation>Inconnu</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
@ -215,74 +215,74 @@
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>processing</source>
|
<source>processing</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>traitement</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>processing-stopped</source>
|
<source>processing-stopped</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>traitement-arrêt</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>canceled</source>
|
<source>canceled</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>annulé</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>aborted</source>
|
<source>aborted</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>abandonné</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>completed</source>
|
<source>completed</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>terminé</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>unknown state </source>
|
<source>unknown state </source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>état inconnu</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>draft</source>
|
<source>draft</source>
|
||||||
<translation type="unfinished">brouillon</translation>
|
<translation>brouillon</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>normal</source>
|
<source>normal</source>
|
||||||
<translation type="unfinished">normale</translation>
|
<translation>normale</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>high</source>
|
<source>high</source>
|
||||||
<translation type="unfinished">haute</translation>
|
<translation>haute</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>unknown quality </source>
|
<source>unknown quality </source>
|
||||||
<translation type="unfinished">qualité inconnue</translation>
|
<translation>qualité inconnue</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>portrait</source>
|
<source>portrait</source>
|
||||||
<translation type="unfinished">portrait</translation>
|
<translation>portrait</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>landscape</source>
|
<source>landscape</source>
|
||||||
<translation type="unfinished">paysage</translation>
|
<translation>paysage</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>reverse landscape</source>
|
<source>reverse landscape</source>
|
||||||
<translation type="unfinished">paysage inversé</translation>
|
<translation>paysage inversé</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>reverse portrait</source>
|
<source>reverse portrait</source>
|
||||||
<translation type="unfinished">portrait inversé</translation>
|
<translation>portrait inversé</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>unknown orientation </source>
|
<source>unknown orientation </source>
|
||||||
<translation type="unfinished">orientation inconnue</translation>
|
<translation>orientation inconnue</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>dpi</source>
|
<source>dpi</source>
|
||||||
<translation type="unfinished">dpi</translation>
|
<translation>dpi</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>dots/cm</source>
|
<source>dots/cm</source>
|
||||||
<translation type="unfinished">pts/cm</translation>
|
<translation>pts/cm</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>No relevant formats supported</source>
|
<source>No compatible formats supported</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Source code is available at GitHub. Translations, bug reports and other contributions are welcome!</source>
|
<source>Source code is available at GitHub. Translations, bug reports and other contributions are welcome!</source>
|
||||||
<translation>源代码位于 Github 。欢迎提供翻译,报告缺陷及其它贡献!</translation>
|
<translation>源代码位于 Github 。欢迎提供翻译、报告缺陷及作出其它贡献!</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>SeaPrint licencing is still TBD, but will be some flavor of open.</source>
|
<source>SeaPrint licencing is still TBD, but will be some flavor of open.</source>
|
||||||
|
@ -57,11 +57,11 @@
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Code and Testing - Rudi Timmermans</source>
|
<source>Code and Testing - Rudi Timmermans</source>
|
||||||
<translation type="unfinished">代码及测试 - Rudi Timmermans</translation>
|
<translation>代码及测试 - Rudi Timmermans</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Spanish</source>
|
<source>Spanish</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>西班牙语</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
@ -84,7 +84,7 @@
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Unknown</source>
|
<source>Unknown</source>
|
||||||
<translation type="unfinished">未知</translation>
|
<translation>未知</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
@ -207,83 +207,83 @@
|
||||||
<name>utils</name>
|
<name>utils</name>
|
||||||
<message>
|
<message>
|
||||||
<source>pending</source>
|
<source>pending</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>等候</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>pending-held</source>
|
<source>pending-held</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>等候保持</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>processing</source>
|
<source>processing</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>正在处理</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>processing-stopped</source>
|
<source>processing-stopped</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>处理已停止</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>canceled</source>
|
<source>canceled</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>已取消</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>aborted</source>
|
<source>aborted</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>已中止</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>completed</source>
|
<source>completed</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>已完成</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>unknown state </source>
|
<source>unknown state </source>
|
||||||
<translation type="unfinished"></translation>
|
<translation>未知状态</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>draft</source>
|
<source>draft</source>
|
||||||
<translation type="unfinished">草稿</translation>
|
<translation>草稿</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>normal</source>
|
<source>normal</source>
|
||||||
<translation type="unfinished">正常</translation>
|
<translation>正常</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>high</source>
|
<source>high</source>
|
||||||
<translation type="unfinished">高质量</translation>
|
<translation>高质量</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>unknown quality </source>
|
<source>unknown quality </source>
|
||||||
<translation type="unfinished">质量未知</translation>
|
<translation>质量未知</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>portrait</source>
|
<source>portrait</source>
|
||||||
<translation type="unfinished">竖屏</translation>
|
<translation>竖屏</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>landscape</source>
|
<source>landscape</source>
|
||||||
<translation type="unfinished">横屏</translation>
|
<translation>横屏</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>reverse landscape</source>
|
<source>reverse landscape</source>
|
||||||
<translation type="unfinished">竖屏可旋转</translation>
|
<translation>竖屏可旋转</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>reverse portrait</source>
|
<source>reverse portrait</source>
|
||||||
<translation type="unfinished">横屏可旋转</translation>
|
<translation>横屏可旋转</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>unknown orientation </source>
|
<source>unknown orientation </source>
|
||||||
<translation type="unfinished">方向位置</translation>
|
<translation>方向位置</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>dpi</source>
|
<source>dpi</source>
|
||||||
<translation type="unfinished">dpi</translation>
|
<translation>dpi</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>dots/cm</source>
|
<source>dots/cm</source>
|
||||||
<translation type="unfinished">点/厘米</translation>
|
<translation>点/厘米</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>No relevant formats supported</source>
|
<source>No compatible formats supported</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished">不支持相关格式</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
</TS>
|
</TS>
|
||||||
|
|
|
@ -282,7 +282,7 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>No relevant formats supported</source>
|
<source>No compatible formats supported</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
|
Loading…
Reference in a new issue