mirror of
https://github.com/QIDITECH/QIDIStudio.git
synced 2026-02-07 12:21:50 +03:00
update slic3r
This commit is contained in:
@@ -7,11 +7,12 @@
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <thread>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/endian/conversion.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_duration.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
|
||||
using boost::optional;
|
||||
using boost::system::error_code;
|
||||
@@ -237,7 +238,6 @@ struct DnsRR_A
|
||||
enum { TAG = 0x1 };
|
||||
|
||||
asio::ip::address_v4 ip;
|
||||
std::string name;
|
||||
|
||||
static void decode(optional<DnsRR_A> &result, const DnsResource &rr)
|
||||
{
|
||||
@@ -255,7 +255,6 @@ struct DnsRR_AAAA
|
||||
enum { TAG = 0x1c };
|
||||
|
||||
asio::ip::address_v6 ip;
|
||||
std::string name;
|
||||
|
||||
static void decode(optional<DnsRR_AAAA> &result, const DnsResource &rr)
|
||||
{
|
||||
@@ -403,7 +402,7 @@ struct DnsMessage
|
||||
|
||||
DnsSDMap sdmap;
|
||||
|
||||
static optional<DnsMessage> decode(const std::vector<char>& buffer, const Bonjour::TxtKeys& txt_keys)
|
||||
static optional<DnsMessage> decode(const std::vector<char> &buffer, const Bonjour::TxtKeys &txt_keys)
|
||||
{
|
||||
const auto size = buffer.size();
|
||||
if (size < DnsHeader::SIZE + DnsQuestion::MIN_SIZE || size > MAX_SIZE) {
|
||||
@@ -436,27 +435,21 @@ struct DnsMessage
|
||||
}
|
||||
|
||||
private:
|
||||
void parse_rr(const std::vector<char>& buffer, DnsResource&& rr, size_t dataoffset, const Bonjour::TxtKeys& txt_keys)
|
||||
void parse_rr(const std::vector<char> &buffer, DnsResource &&rr, size_t dataoffset, const Bonjour::TxtKeys &txt_keys)
|
||||
{
|
||||
switch (rr.type) {
|
||||
case DnsRR_A::TAG:
|
||||
DnsRR_A::decode(this->rr_a, rr);
|
||||
this->rr_a->name = rr.name;
|
||||
break;
|
||||
case DnsRR_AAAA::TAG:
|
||||
DnsRR_AAAA::decode(this->rr_aaaa, rr);
|
||||
this->rr_aaaa->name = rr.name;
|
||||
break;
|
||||
case DnsRR_SRV::TAG: {
|
||||
auto srv = DnsRR_SRV::decode(buffer, rr, dataoffset);
|
||||
if (srv) { this->sdmap.insert_srv(std::move(rr.name), std::move(*srv)); }
|
||||
break;
|
||||
}
|
||||
case DnsRR_TXT::TAG: {
|
||||
auto txt = DnsRR_TXT::decode(rr, txt_keys);
|
||||
if (txt) { this->sdmap.insert_txt(std::move(rr.name), std::move(*txt)); }
|
||||
break;
|
||||
}
|
||||
case DnsRR_A::TAG: DnsRR_A::decode(this->rr_a, rr); break;
|
||||
case DnsRR_AAAA::TAG: DnsRR_AAAA::decode(this->rr_aaaa, rr); break;
|
||||
case DnsRR_SRV::TAG: {
|
||||
auto srv = DnsRR_SRV::decode(buffer, rr, dataoffset);
|
||||
if (srv) { this->sdmap.insert_srv(std::move(rr.name), std::move(*srv)); }
|
||||
break;
|
||||
}
|
||||
case DnsRR_TXT::TAG: {
|
||||
auto txt = DnsRR_TXT::decode(rr, txt_keys);
|
||||
if (txt) { this->sdmap.insert_txt(std::move(rr.name), std::move(*txt)); }
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -487,11 +480,24 @@ std::ostream& operator<<(std::ostream &os, const DnsMessage &msg)
|
||||
return os << "])";
|
||||
}
|
||||
|
||||
const asio::ip::address_v4 BonjourRequest::MCAST_IP4{ 0xe00000fb };
|
||||
const asio::ip::address_v6 BonjourRequest::MCAST_IP6 = asio::ip::make_address_v6("ff02::fb");
|
||||
|
||||
struct BonjourRequest
|
||||
{
|
||||
static const asio::ip::address_v4 MCAST_IP4;
|
||||
static const uint16_t MCAST_PORT;
|
||||
|
||||
std::vector<char> data;
|
||||
|
||||
static optional<BonjourRequest> make(const std::string &service, const std::string &protocol);
|
||||
|
||||
private:
|
||||
BonjourRequest(std::vector<char> &&data) : data(std::move(data)) {}
|
||||
};
|
||||
|
||||
const asio::ip::address_v4 BonjourRequest::MCAST_IP4{0xe00000fb};
|
||||
const uint16_t BonjourRequest::MCAST_PORT = 5353;
|
||||
|
||||
optional<BonjourRequest> BonjourRequest::make_PTR(const std::string &service, const std::string &protocol)
|
||||
optional<BonjourRequest> BonjourRequest::make(const std::string &service, const std::string &protocol)
|
||||
{
|
||||
if (service.size() > 15 || protocol.size() > 15) {
|
||||
return boost::none;
|
||||
@@ -528,227 +534,74 @@ optional<BonjourRequest> BonjourRequest::make_PTR(const std::string &service, co
|
||||
|
||||
return BonjourRequest(std::move(data));
|
||||
}
|
||||
optional<BonjourRequest> BonjourRequest::make_A(const std::string& hostname)
|
||||
|
||||
|
||||
// API - private part
|
||||
|
||||
struct Bonjour::priv
|
||||
{
|
||||
// todo: why is this and what is real max
|
||||
if (hostname.size() > 30) {
|
||||
return boost::none;
|
||||
}
|
||||
const std::string service;
|
||||
std::string protocol;
|
||||
std::string service_dn;
|
||||
TxtKeys txt_keys;
|
||||
unsigned timeout;
|
||||
unsigned retries;
|
||||
|
||||
std::vector<char> data;
|
||||
data.reserve(hostname.size() + 18);
|
||||
std::vector<char> buffer;
|
||||
std::thread io_thread;
|
||||
Bonjour::ReplyFn replyfn;
|
||||
Bonjour::CompleteFn completefn;
|
||||
|
||||
// Add metadata
|
||||
static const unsigned char rq_meta[] = {
|
||||
0x00, 0x00, // Query ID (zero for mDNS)
|
||||
0x00, 0x00, // Flags
|
||||
0x00, 0x01, // One query
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Zero Answer, Authority, and Additional RRs
|
||||
};
|
||||
std::copy(rq_meta, rq_meta + sizeof(rq_meta), std::back_inserter(data));
|
||||
priv(std::string &&service);
|
||||
|
||||
// Add hostname without .local
|
||||
data.push_back(hostname.size());
|
||||
data.insert(data.end(), hostname.begin(), hostname.end());
|
||||
|
||||
// Add the rest of A record
|
||||
static const unsigned char ptr_tail[] = {
|
||||
0x05, // length of "local"
|
||||
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00,// "local" string and terminator
|
||||
0x00, 0x01, // Type A
|
||||
0x00, 0xff, // Class - 01 is internet 0xff is any
|
||||
};
|
||||
std::copy(ptr_tail, ptr_tail + sizeof(ptr_tail), std::back_inserter(data));
|
||||
std::string strip_service_dn(const std::string &service_name) const;
|
||||
void udp_receive(udp::endpoint from, size_t bytes);
|
||||
void lookup_perform();
|
||||
};
|
||||
|
||||
return BonjourRequest(std::move(data));
|
||||
Bonjour::priv::priv(std::string &&service)
|
||||
: service(std::move(service))
|
||||
, protocol("tcp")
|
||||
, timeout(10)
|
||||
, retries(1)
|
||||
{
|
||||
buffer.resize(DnsMessage::MAX_SIZE);
|
||||
}
|
||||
|
||||
optional<BonjourRequest> BonjourRequest::make_AAAA(const std::string& hostname)
|
||||
{
|
||||
// todo: why is this and what is real max
|
||||
if (hostname.size() > 30) {
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
std::vector<char> data;
|
||||
data.reserve(hostname.size() + 18);
|
||||
|
||||
// Add metadata
|
||||
static const unsigned char rq_meta[] = {
|
||||
0x00, 0x00, // Query ID (zero for mDNS)
|
||||
0x00, 0x00, // Flags
|
||||
0x00, 0x01, // One query
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Zero Answer, Authority, and Additional RRs
|
||||
};
|
||||
std::copy(rq_meta, rq_meta + sizeof(rq_meta), std::back_inserter(data));
|
||||
|
||||
// Add hostname without .local
|
||||
data.push_back(hostname.size());
|
||||
data.insert(data.end(), hostname.begin(), hostname.end());
|
||||
|
||||
// Add the rest of A record
|
||||
static const unsigned char ptr_tail[] = {
|
||||
0x05, // length of "local"
|
||||
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, // "local" string and terminator
|
||||
0x00, 0x1c, // Type AAAA
|
||||
0x00, 0xff, // Class - 01 is internet 0xff is any
|
||||
};
|
||||
std::copy(ptr_tail, ptr_tail + sizeof(ptr_tail), std::back_inserter(data));
|
||||
|
||||
return BonjourRequest(std::move(data));
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::string strip_service_dn(const std::string& service_name, const std::string& service_dn)
|
||||
std::string Bonjour::priv::strip_service_dn(const std::string &service_name) const
|
||||
{
|
||||
if (service_name.size() <= service_dn.size()) {
|
||||
return std::string();
|
||||
return service_name;
|
||||
}
|
||||
|
||||
auto needle = service_name.rfind(service_dn);
|
||||
if (needle == service_name.size() - service_dn.size()) {
|
||||
return service_name.substr(0, needle - 1);
|
||||
} else {
|
||||
return std::string();
|
||||
return service_name;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
UdpSession::UdpSession(Bonjour::ReplyFn rfn) : replyfn(rfn)
|
||||
void Bonjour::priv::udp_receive(udp::endpoint from, size_t bytes)
|
||||
{
|
||||
buffer.resize(DnsMessage::MAX_SIZE);
|
||||
}
|
||||
|
||||
UdpSocket::UdpSocket( Bonjour::ReplyFn replyfn, const asio::ip::address& multicast_address, const asio::ip::address& interface_address, std::shared_ptr< boost::asio::io_service > io_service)
|
||||
: replyfn(replyfn)
|
||||
, multicast_address(multicast_address)
|
||||
, socket(*io_service)
|
||||
, io_service(io_service)
|
||||
{
|
||||
try {
|
||||
// open socket
|
||||
boost::asio::ip::udp::endpoint listen_endpoint(multicast_address.is_v4() ? udp::v4() : udp::v6(), BonjourRequest::MCAST_PORT);
|
||||
socket.open(listen_endpoint.protocol());
|
||||
// set socket to listen
|
||||
socket.set_option(udp::socket::reuse_address(true));
|
||||
socket.bind(listen_endpoint);
|
||||
if (interface_address.is_v4()) {
|
||||
// listen for multicast on given interface
|
||||
socket.set_option(boost::asio::ip::multicast::join_group(multicast_address.to_v4(), interface_address.to_v4()));
|
||||
// send to interface
|
||||
socket.set_option(asio::ip::multicast::outbound_interface(interface_address.to_v4()));
|
||||
} else {
|
||||
// listen for multicast on given interface
|
||||
socket.set_option(boost::asio::ip::multicast::join_group(multicast_address.to_v6(), interface_address.to_v6().scope_id()));
|
||||
// send to interface
|
||||
socket.set_option(asio::ip::multicast::outbound_interface(interface_address.to_v6().scope_id()));
|
||||
}
|
||||
mcast_endpoint = udp::endpoint(multicast_address, BonjourRequest::MCAST_PORT);
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Socket created. Multicast: " << multicast_address << ". Interface: " << interface_address;
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UdpSocket::UdpSocket( Bonjour::ReplyFn replyfn, const asio::ip::address& multicast_address, std::shared_ptr< boost::asio::io_service > io_service)
|
||||
: replyfn(replyfn)
|
||||
, multicast_address(multicast_address)
|
||||
, socket(*io_service)
|
||||
, io_service(io_service)
|
||||
{
|
||||
try {
|
||||
// open socket
|
||||
boost::asio::ip::udp::endpoint listen_endpoint(multicast_address.is_v4() ? udp::v4() : udp::v6(), BonjourRequest::MCAST_PORT);
|
||||
socket.open(listen_endpoint.protocol());
|
||||
// set socket to listen
|
||||
socket.set_option(udp::socket::reuse_address(true));
|
||||
socket.bind(listen_endpoint);
|
||||
socket.set_option(boost::asio::ip::multicast::join_group(multicast_address));
|
||||
mcast_endpoint = udp::endpoint(multicast_address, BonjourRequest::MCAST_PORT);
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Socket created. Multicast: " << multicast_address;
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
void UdpSocket::send()
|
||||
{
|
||||
try {
|
||||
for (const auto& request : requests)
|
||||
socket.send_to(asio::buffer(request.m_data), mcast_endpoint);
|
||||
|
||||
// Should we care if this is called while already receiving? (async_receive call from receive_handler)
|
||||
async_receive();
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
void UdpSocket::async_receive()
|
||||
{
|
||||
try {
|
||||
// our session to hold the buffer + endpoint
|
||||
auto session = create_session();
|
||||
socket.async_receive_from(asio::buffer(session->buffer, session->buffer.size())
|
||||
, session->remote_endpoint
|
||||
, boost::bind(&UdpSocket::receive_handler, this, session, asio::placeholders::error, asio::placeholders::bytes_transferred));
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
void UdpSocket::receive_handler(SharedSession session, const boost::system::error_code& error, size_t bytes)
|
||||
{
|
||||
// let io_service to handle the datagram on session
|
||||
// from boost documentation io_service::post:
|
||||
// The io_service guarantees that the handler will only be called in a thread in which the run(), run_one(), poll() or poll_one() member functions is currently being invoked.
|
||||
io_service->post(boost::bind(&UdpSession::handle_receive, session, error, bytes));
|
||||
// immediately accept new datagrams
|
||||
async_receive();
|
||||
}
|
||||
|
||||
SharedSession LookupSocket::create_session() const
|
||||
{
|
||||
return std::shared_ptr< LookupSession >(new LookupSession(this, replyfn));
|
||||
}
|
||||
|
||||
|
||||
void LookupSession::handle_receive(const error_code& error, size_t bytes)
|
||||
{
|
||||
assert(socket);
|
||||
|
||||
if (error) {
|
||||
BOOST_LOG_TRIVIAL(error) << error.message();
|
||||
return;
|
||||
}
|
||||
if (bytes == 0 || !replyfn) {
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.resize(bytes);
|
||||
auto dns_msg = DnsMessage::decode(buffer, socket->get_txt_keys());
|
||||
auto dns_msg = DnsMessage::decode(buffer, txt_keys);
|
||||
if (dns_msg) {
|
||||
asio::ip::address ip = remote_endpoint.address();
|
||||
asio::ip::address ip = from.address();
|
||||
if (dns_msg->rr_a) { ip = dns_msg->rr_a->ip; }
|
||||
else if (dns_msg->rr_aaaa) { ip = dns_msg->rr_aaaa->ip; }
|
||||
|
||||
for (auto& sdpair : dns_msg->sdmap) {
|
||||
if (!sdpair.second.srv) {
|
||||
for (auto &sdpair : dns_msg->sdmap) {
|
||||
if (! sdpair.second.srv) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto& srv = *sdpair.second.srv;
|
||||
|
||||
auto service_name = strip_service_dn(sdpair.first, socket->get_service_dn());
|
||||
if (service_name.empty())
|
||||
continue;
|
||||
const auto &srv = *sdpair.second.srv;
|
||||
auto service_name = strip_service_dn(sdpair.first);
|
||||
|
||||
std::string path;
|
||||
std::string version;
|
||||
@@ -764,282 +617,64 @@ void LookupSession::handle_receive(const error_code& error, size_t bytes)
|
||||
}
|
||||
}
|
||||
|
||||
SharedSession ResolveSocket::create_session() const
|
||||
{
|
||||
return std::shared_ptr< ResolveSession > (new ResolveSession(this, replyfn));
|
||||
}
|
||||
|
||||
|
||||
void ResolveSession::handle_receive(const error_code& error, size_t bytes)
|
||||
{
|
||||
assert(socket);
|
||||
if (error) {
|
||||
// todo: what level? do we even log? There might be callbacks when timer runs out
|
||||
BOOST_LOG_TRIVIAL(info) << error.message();
|
||||
return;
|
||||
}
|
||||
if (bytes == 0 || !replyfn) {
|
||||
// todo: log something?
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.resize(bytes);
|
||||
#if 0
|
||||
std::string str;
|
||||
char const hex_chars[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
for (size_t i = 0; i < buffer.size(); i++) {
|
||||
const char ch = buffer[i];
|
||||
str += hex_chars[(ch & 0xF0) >> 4];
|
||||
str += hex_chars[(ch & 0x0F) >> 0];
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(debug) << remote_endpoint.address()<< " " << str;
|
||||
#endif
|
||||
// decode buffer, txt keys are not needed for A / AAAA answer
|
||||
auto dns_msg = DnsMessage::decode(buffer, Bonjour::TxtKeys());
|
||||
if (dns_msg) {
|
||||
asio::ip::address ip;
|
||||
std::string answer_name;
|
||||
if (dns_msg->rr_a) {
|
||||
ip = dns_msg->rr_a->ip;
|
||||
answer_name = dns_msg->rr_a->name;
|
||||
}
|
||||
else if (dns_msg->rr_aaaa) {
|
||||
ip = dns_msg->rr_aaaa->ip;
|
||||
answer_name = dns_msg->rr_aaaa->name;
|
||||
}
|
||||
else
|
||||
return; // not matching query type with answer type
|
||||
|
||||
if (!answer_name.empty()) {
|
||||
// transform both strings to lower. Should we really do it?
|
||||
std::string name_tolower = answer_name;
|
||||
std::transform(name_tolower.begin(), name_tolower.end(), name_tolower.begin(),
|
||||
[](unsigned char c) { return std::tolower(c); });
|
||||
std::string hostname_tolower = socket->get_hostname();
|
||||
std::transform(hostname_tolower.begin(), hostname_tolower.end(), hostname_tolower.begin(),
|
||||
[](unsigned char c) { return std::tolower(c); });
|
||||
if (name_tolower == hostname_tolower) {
|
||||
BonjourReply reply(ip, 0, std::string(), answer_name, BonjourReply::TxtData());
|
||||
replyfn(std::move(reply));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// API - private part
|
||||
|
||||
struct Bonjour::priv
|
||||
{
|
||||
const std::string service;
|
||||
std::string protocol;
|
||||
std::string service_dn;
|
||||
TxtKeys txt_keys;
|
||||
unsigned timeout;
|
||||
unsigned retries;
|
||||
std::string hostname;
|
||||
|
||||
// std::vector<BonjourReply> replies;
|
||||
|
||||
std::vector<char> buffer;
|
||||
std::thread io_thread;
|
||||
Bonjour::ReplyFn replyfn;
|
||||
Bonjour::CompleteFn completefn;
|
||||
Bonjour::ResolveFn resolvefn;
|
||||
|
||||
priv(std::string&& service);
|
||||
|
||||
// void udp_receive_lookup(udp::endpoint from, size_t bytes);
|
||||
void lookup_perform();
|
||||
void resolve_perform();
|
||||
};
|
||||
|
||||
Bonjour::priv::priv(std::string&& service)
|
||||
: service(std::move(service))
|
||||
, protocol("tcp")
|
||||
, timeout(10)
|
||||
, retries(1)
|
||||
{
|
||||
buffer.resize(DnsMessage::MAX_SIZE);
|
||||
}
|
||||
|
||||
void Bonjour::priv::lookup_perform()
|
||||
{
|
||||
service_dn = (boost::format("_%1%._%2%.local") % service % protocol).str();
|
||||
|
||||
std::shared_ptr< boost::asio::io_service > io_service(new boost::asio::io_service);
|
||||
|
||||
std::vector<LookupSocket*> sockets;
|
||||
|
||||
// resolve intefaces - from PR#6646
|
||||
std::vector<boost::asio::ip::address> interfaces;
|
||||
asio::ip::udp::resolver resolver(*io_service);
|
||||
boost::system::error_code ec;
|
||||
// ipv4 interfaces
|
||||
auto results = resolver.resolve(udp::v4(), asio::ip::host_name(), "", ec);
|
||||
if (!ec) {
|
||||
for (const auto & r : results) {
|
||||
const auto addr = r.endpoint().address();
|
||||
if (addr.is_loopback()) continue;
|
||||
interfaces.emplace_back(std::move(addr));
|
||||
}
|
||||
// create ipv4 socket for each interface
|
||||
// each will send to querry to for both ipv4 and ipv6
|
||||
for (const auto& intrfc : interfaces)
|
||||
sockets.emplace_back(new LookupSocket(txt_keys, service, service_dn, protocol, replyfn, BonjourRequest::MCAST_IP4, intrfc, io_service));
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << "Failed to resolve ipv4 interfaces: " << ec.message();
|
||||
}
|
||||
if (sockets.empty())
|
||||
sockets.emplace_back(new LookupSocket(txt_keys, service, service_dn, protocol, replyfn, BonjourRequest::MCAST_IP4, io_service));
|
||||
// ipv6 interfaces
|
||||
interfaces.clear();
|
||||
//udp::resolver::query query(host, PORT, boost::asio::ip::resolver_query_base::numeric_service);
|
||||
results = resolver.resolve(udp::v6(), asio::ip::host_name(), "", ec);
|
||||
if (!ec)
|
||||
{
|
||||
for (const auto& r : results) {
|
||||
const auto addr = r.endpoint().address();
|
||||
if (addr.is_loopback()) continue;
|
||||
interfaces.emplace_back(std::move(addr));
|
||||
}
|
||||
// create ipv6 socket for each interface
|
||||
// each will send to querry to for both ipv4 and ipv6
|
||||
for (const auto& intrfc : interfaces)
|
||||
sockets.emplace_back(new LookupSocket(txt_keys, service, service_dn, protocol, replyfn, BonjourRequest::MCAST_IP6, intrfc, io_service));
|
||||
if (interfaces.empty())
|
||||
sockets.emplace_back(new LookupSocket(txt_keys, service, service_dn, protocol, replyfn, BonjourRequest::MCAST_IP6, io_service));
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info)<< "Failed to resolve ipv6 interfaces: " << ec.message();
|
||||
const auto brq = BonjourRequest::make(service, protocol);
|
||||
if (!brq) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto self = this;
|
||||
|
||||
try {
|
||||
// send first queries
|
||||
for (auto * socket : sockets)
|
||||
socket->send();
|
||||
boost::asio::io_service io_service;
|
||||
udp::socket socket(io_service);
|
||||
socket.open(udp::v4());
|
||||
socket.set_option(udp::socket::reuse_address(true));
|
||||
udp::endpoint mcast(BonjourRequest::MCAST_IP4, BonjourRequest::MCAST_PORT);
|
||||
socket.send_to(asio::buffer(brq->data), mcast);
|
||||
|
||||
// timer settings
|
||||
asio::deadline_timer timer(*io_service);
|
||||
bool expired = false;
|
||||
bool retry = false;
|
||||
asio::deadline_timer timer(io_service);
|
||||
retries--;
|
||||
std::function<void(const error_code&)> timer_handler = [&](const error_code& error) {
|
||||
// end
|
||||
std::function<void(const error_code &)> timer_handler = [&](const error_code &error) {
|
||||
if (retries == 0 || error) {
|
||||
// is this correct ending?
|
||||
io_service->stop();
|
||||
if (completefn) {
|
||||
completefn();
|
||||
expired = true;
|
||||
if (self->completefn) {
|
||||
self->completefn();
|
||||
}
|
||||
// restart timer
|
||||
} else {
|
||||
retry = true;
|
||||
retries--;
|
||||
timer.expires_from_now(boost::posix_time::seconds(timeout));
|
||||
timer.async_wait(timer_handler);
|
||||
// trigger another round of queries
|
||||
for (auto * socket : sockets)
|
||||
socket->send();
|
||||
}
|
||||
};
|
||||
// start timer
|
||||
|
||||
timer.expires_from_now(boost::posix_time::seconds(timeout));
|
||||
timer.async_wait(timer_handler);
|
||||
// start io_service, it will run until it has something to do - so in this case until stop is called in timer
|
||||
io_service->run();
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
void Bonjour::priv::resolve_perform()
|
||||
{
|
||||
// reply callback is shared to every UDPSession which is called on same thread as io_service->run();
|
||||
// thus no need to mutex replies in reply_callback, same should go with the timer
|
||||
std::vector<BonjourReply> replies;
|
||||
// examples would store [self] to the lambda (and the timer one), is it ok not to do it? (Should be c++03)
|
||||
const auto reply_callback = [&rpls = replies](BonjourReply&& reply)
|
||||
{
|
||||
if (std::find(rpls.begin(), rpls.end(), reply) == rpls.end())
|
||||
rpls.push_back(reply);
|
||||
};
|
||||
udp::endpoint recv_from;
|
||||
const auto recv_handler = [&](const error_code &error, size_t bytes) {
|
||||
if (!error) { self->udp_receive(recv_from, bytes); }
|
||||
};
|
||||
socket.async_receive_from(asio::buffer(buffer, buffer.size()), recv_from, recv_handler);
|
||||
|
||||
std::shared_ptr< boost::asio::io_service > io_service(new boost::asio::io_service);
|
||||
std::vector<ResolveSocket*> sockets;
|
||||
|
||||
// resolve interfaces - from PR#6646
|
||||
std::vector<boost::asio::ip::address> interfaces;
|
||||
asio::ip::udp::resolver resolver(*io_service);
|
||||
boost::system::error_code ec;
|
||||
// ipv4 interfaces
|
||||
auto results = resolver.resolve(udp::v4(), asio::ip::host_name(), "", ec);
|
||||
if (!ec) {
|
||||
for (auto const& r : results) {
|
||||
auto const addr = r.endpoint().address();
|
||||
if (addr.is_loopback()) continue;
|
||||
interfaces.emplace_back(addr);
|
||||
}
|
||||
// create ipv4 socket for each interface
|
||||
// each will send to querry to for both ipv4 and ipv6
|
||||
for (const auto& intrfc : interfaces)
|
||||
sockets.emplace_back(new ResolveSocket(hostname, reply_callback, BonjourRequest::MCAST_IP4, intrfc, io_service));
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << "Failed to resolve ipv4 interfaces: " << ec.message();
|
||||
}
|
||||
if (sockets.empty())
|
||||
sockets.emplace_back(new ResolveSocket(hostname, reply_callback, BonjourRequest::MCAST_IP4, io_service));
|
||||
|
||||
// ipv6 interfaces
|
||||
interfaces.clear();
|
||||
results = resolver.resolve(udp::v6(), asio::ip::host_name(), "", ec);
|
||||
if (!ec) {
|
||||
for (auto const& r : results) {
|
||||
auto const addr = r.endpoint().address();
|
||||
if (addr.is_loopback()) continue;
|
||||
interfaces.emplace_back(addr);
|
||||
}
|
||||
// create ipv6 socket for each interface
|
||||
// each will send to querry to for both ipv4 and ipv6
|
||||
for (const auto& intrfc : interfaces)
|
||||
sockets.emplace_back(new ResolveSocket(hostname, reply_callback, BonjourRequest::MCAST_IP6, intrfc, io_service));
|
||||
if (interfaces.empty())
|
||||
sockets.emplace_back(new ResolveSocket(hostname, reply_callback, BonjourRequest::MCAST_IP6, io_service));
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << "Failed to resolve ipv6 interfaces: " << ec.message();
|
||||
}
|
||||
|
||||
try {
|
||||
// send first queries
|
||||
for (auto * socket : sockets)
|
||||
socket->send();
|
||||
|
||||
// timer settings
|
||||
asio::deadline_timer timer(*io_service);
|
||||
retries--;
|
||||
std::function<void(const error_code&)> timer_handler = [&](const error_code& error) {
|
||||
int replies_count = replies.size();
|
||||
// end
|
||||
if (retries == 0 || error || replies_count > 0) {
|
||||
// is this correct ending?
|
||||
io_service->stop();
|
||||
if (replies_count > 0 && resolvefn) {
|
||||
resolvefn(replies);
|
||||
}
|
||||
// restart timer
|
||||
while (io_service.run_one()) {
|
||||
if (expired) {
|
||||
socket.cancel();
|
||||
} else if (retry) {
|
||||
retry = false;
|
||||
socket.send_to(asio::buffer(brq->data), mcast);
|
||||
} else {
|
||||
retries--;
|
||||
timer.expires_from_now(boost::posix_time::seconds(timeout));
|
||||
timer.async_wait(timer_handler);
|
||||
// trigger another round of queries
|
||||
for (auto * socket : sockets)
|
||||
socket->send();
|
||||
buffer.resize(DnsMessage::MAX_SIZE);
|
||||
socket.async_receive_from(asio::buffer(buffer, buffer.size()), recv_from, recv_handler);
|
||||
}
|
||||
};
|
||||
// start timer
|
||||
timer.expires_from_now(boost::posix_time::seconds(timeout));
|
||||
timer.async_wait(timer_handler);
|
||||
// start io_service, it will run until it has something to do - so in this case until stop is called in timer
|
||||
io_service->run();
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << e.what();
|
||||
}
|
||||
} catch (std::exception& /* e */) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1135,12 +770,6 @@ Bonjour& Bonjour::set_timeout(unsigned timeout)
|
||||
return *this;
|
||||
}
|
||||
|
||||
Bonjour& Bonjour::set_hostname(const std::string& hostname)
|
||||
{
|
||||
if (p) { p->hostname = hostname; }
|
||||
return *this;
|
||||
}
|
||||
|
||||
Bonjour& Bonjour::set_retries(unsigned retries)
|
||||
{
|
||||
if (p && retries > 0) { p->retries = retries; }
|
||||
@@ -1159,12 +788,6 @@ Bonjour& Bonjour::on_complete(CompleteFn fn)
|
||||
return *this;
|
||||
}
|
||||
|
||||
Bonjour& Bonjour::on_resolve(ResolveFn fn)
|
||||
{
|
||||
if (p) { p->resolvefn = std::move(fn); }
|
||||
return *this;
|
||||
}
|
||||
|
||||
Bonjour::Ptr Bonjour::lookup()
|
||||
{
|
||||
auto self = std::make_shared<Bonjour>(std::move(*this));
|
||||
@@ -1178,24 +801,6 @@ Bonjour::Ptr Bonjour::lookup()
|
||||
|
||||
return self;
|
||||
}
|
||||
Bonjour::Ptr Bonjour::resolve()
|
||||
{
|
||||
auto self = std::make_shared<Bonjour>(std::move(*this));
|
||||
|
||||
if (self->p) {
|
||||
auto io_thread = std::thread([self]() {
|
||||
self->p->resolve_perform();
|
||||
});
|
||||
self->p->io_thread = std::move(io_thread);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
void Bonjour::resolve_sync()
|
||||
{
|
||||
if (p)
|
||||
p->resolve_perform();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -7,17 +7,12 @@
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <functional>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/ip/address.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
||||
|
||||
struct BonjourReply
|
||||
{
|
||||
typedef std::unordered_map<std::string, std::string> TxtData;
|
||||
@@ -45,6 +40,7 @@ struct BonjourReply
|
||||
|
||||
std::ostream& operator<<(std::ostream &, const BonjourReply &);
|
||||
|
||||
|
||||
/// Bonjour lookup performer
|
||||
class Bonjour : public std::enable_shared_from_this<Bonjour> {
|
||||
private:
|
||||
@@ -53,7 +49,6 @@ public:
|
||||
typedef std::shared_ptr<Bonjour> Ptr;
|
||||
typedef std::function<void(BonjourReply &&)> ReplyFn;
|
||||
typedef std::function<void()> CompleteFn;
|
||||
typedef std::function<void(const std::vector<BonjourReply>&)> ResolveFn;
|
||||
typedef std::set<std::string> TxtKeys;
|
||||
|
||||
Bonjour(std::string service);
|
||||
@@ -71,215 +66,14 @@ public:
|
||||
// Timeout is per one retry, ie. total time spent listening = retries * timeout.
|
||||
// If retries > 1, then care needs to be taken as more than one reply from the same service may be received.
|
||||
|
||||
// sets hostname queried by resolve()
|
||||
Bonjour& set_hostname(const std::string& hostname);
|
||||
|
||||
Bonjour& on_reply(ReplyFn fn);
|
||||
Bonjour& on_complete(CompleteFn fn);
|
||||
|
||||
Bonjour& on_resolve(ResolveFn fn);
|
||||
// lookup all devices by given TxtKeys
|
||||
// each correct reply is passed back in ReplyFn, finishes with CompleteFn
|
||||
Ptr lookup();
|
||||
// performs resolving of hostname into vector of ip adresses passed back by ResolveFn
|
||||
// needs set_hostname and on_resolve to be called before.
|
||||
Ptr resolve();
|
||||
// resolve on the current thread
|
||||
void resolve_sync();
|
||||
private:
|
||||
std::unique_ptr<priv> p;
|
||||
};
|
||||
struct BonjourRequest
|
||||
{
|
||||
static const boost::asio::ip::address_v4 MCAST_IP4;
|
||||
static const boost::asio::ip::address_v6 MCAST_IP6;
|
||||
static const uint16_t MCAST_PORT;
|
||||
|
||||
std::vector<char> m_data;
|
||||
|
||||
static boost::optional<BonjourRequest> make_PTR(const std::string& service, const std::string& protocol);
|
||||
static boost::optional<BonjourRequest> make_A(const std::string& hostname);
|
||||
static boost::optional<BonjourRequest> make_AAAA(const std::string& hostname);
|
||||
private:
|
||||
BonjourRequest(std::vector<char>&& data) : m_data(std::move(data)) {}
|
||||
};
|
||||
|
||||
|
||||
class LookupSocket;
|
||||
class ResolveSocket;
|
||||
|
||||
// Session is created for each async_receive of socket. On receive, its handle_receive method is called (Thru io_service->post).
|
||||
// ReplyFn is called if correct datagram was received.
|
||||
class UdpSession
|
||||
{
|
||||
public:
|
||||
UdpSession(Bonjour::ReplyFn rfn);
|
||||
virtual void handle_receive(const boost::system::error_code& error, size_t bytes) = 0;
|
||||
std::vector<char> buffer;
|
||||
boost::asio::ip::udp::endpoint remote_endpoint;
|
||||
protected:
|
||||
Bonjour::ReplyFn replyfn;
|
||||
};
|
||||
typedef std::shared_ptr<UdpSession> SharedSession;
|
||||
// Session for LookupSocket
|
||||
class LookupSession : public UdpSession
|
||||
{
|
||||
public:
|
||||
LookupSession(const LookupSocket* sckt, Bonjour::ReplyFn rfn) : UdpSession(rfn), socket(sckt) {}
|
||||
void handle_receive(const boost::system::error_code& error, size_t bytes) override;
|
||||
protected:
|
||||
// const pointer to socket to get needed data as txt_keys etc.
|
||||
const LookupSocket* socket;
|
||||
};
|
||||
// Session for ResolveSocket
|
||||
class ResolveSession : public UdpSession
|
||||
{
|
||||
public:
|
||||
ResolveSession(const ResolveSocket* sckt, Bonjour::ReplyFn rfn) : UdpSession(rfn), socket(sckt) {}
|
||||
void handle_receive(const boost::system::error_code& error, size_t bytes) override;
|
||||
protected:
|
||||
// const pointer to seocket to get hostname during handle_receive
|
||||
const ResolveSocket* socket;
|
||||
};
|
||||
|
||||
// Udp socket, starts receiving answers after first send() call until io_service is stopped.
|
||||
class UdpSocket
|
||||
{
|
||||
public:
|
||||
// Two constructors: 1st is with interface which must be resolved before calling this
|
||||
UdpSocket(Bonjour::ReplyFn replyfn
|
||||
, const boost::asio::ip::address& multicast_address
|
||||
, const boost::asio::ip::address& interface_address
|
||||
, std::shared_ptr< boost::asio::io_service > io_service);
|
||||
|
||||
UdpSocket(Bonjour::ReplyFn replyfn
|
||||
, const boost::asio::ip::address& multicast_address
|
||||
, std::shared_ptr< boost::asio::io_service > io_service);
|
||||
|
||||
void send();
|
||||
void async_receive();
|
||||
void cancel() { socket.cancel(); }
|
||||
protected:
|
||||
void receive_handler(SharedSession session, const boost::system::error_code& error, size_t bytes);
|
||||
virtual SharedSession create_session() const = 0;
|
||||
|
||||
Bonjour::ReplyFn replyfn;
|
||||
boost::asio::ip::address multicast_address;
|
||||
boost::asio::ip::udp::socket socket;
|
||||
boost::asio::ip::udp::endpoint mcast_endpoint;
|
||||
std::shared_ptr< boost::asio::io_service > io_service;
|
||||
std::vector<BonjourRequest> requests;
|
||||
};
|
||||
|
||||
class LookupSocket : public UdpSocket
|
||||
{
|
||||
public:
|
||||
LookupSocket(Bonjour::TxtKeys txt_keys
|
||||
, std::string service
|
||||
, std::string service_dn
|
||||
, std::string protocol
|
||||
, Bonjour::ReplyFn replyfn
|
||||
, const boost::asio::ip::address& multicast_address
|
||||
, const boost::asio::ip::address& interface_address
|
||||
, std::shared_ptr< boost::asio::io_service > io_service)
|
||||
: UdpSocket(replyfn, multicast_address, interface_address, io_service)
|
||||
, txt_keys(txt_keys)
|
||||
, service(service)
|
||||
, service_dn(service_dn)
|
||||
, protocol(protocol)
|
||||
{
|
||||
assert(!service.empty() && replyfn);
|
||||
create_request();
|
||||
}
|
||||
|
||||
LookupSocket(Bonjour::TxtKeys txt_keys
|
||||
, std::string service
|
||||
, std::string service_dn
|
||||
, std::string protocol
|
||||
, Bonjour::ReplyFn replyfn
|
||||
, const boost::asio::ip::address& multicast_address
|
||||
, std::shared_ptr< boost::asio::io_service > io_service)
|
||||
: UdpSocket(replyfn, multicast_address, io_service)
|
||||
, txt_keys(txt_keys)
|
||||
, service(service)
|
||||
, service_dn(service_dn)
|
||||
, protocol(protocol)
|
||||
{
|
||||
assert(!service.empty() && replyfn);
|
||||
create_request();
|
||||
}
|
||||
|
||||
const Bonjour::TxtKeys get_txt_keys() const { return txt_keys; }
|
||||
const std::string get_service() const { return service; }
|
||||
const std::string get_service_dn() const { return service_dn; }
|
||||
|
||||
protected:
|
||||
SharedSession create_session() const override;
|
||||
void create_request()
|
||||
{
|
||||
requests.clear();
|
||||
// create PTR request
|
||||
if (auto rqst = BonjourRequest::make_PTR(service, protocol); rqst)
|
||||
requests.push_back(std::move(rqst.get()));
|
||||
}
|
||||
boost::optional<BonjourRequest> request;
|
||||
Bonjour::TxtKeys txt_keys;
|
||||
std::string service;
|
||||
std::string service_dn;
|
||||
std::string protocol;
|
||||
};
|
||||
|
||||
class ResolveSocket : public UdpSocket
|
||||
{
|
||||
public:
|
||||
ResolveSocket(const std::string& hostname
|
||||
, Bonjour::ReplyFn replyfn
|
||||
, const boost::asio::ip::address& multicast_address
|
||||
, const boost::asio::ip::address& interface_address
|
||||
, std::shared_ptr< boost::asio::io_service > io_service)
|
||||
: UdpSocket(replyfn, multicast_address, interface_address, io_service)
|
||||
, hostname(hostname)
|
||||
|
||||
{
|
||||
assert(!hostname.empty() && replyfn);
|
||||
create_requests();
|
||||
}
|
||||
|
||||
ResolveSocket(const std::string& hostname
|
||||
, Bonjour::ReplyFn replyfn
|
||||
, const boost::asio::ip::address& multicast_address
|
||||
, std::shared_ptr< boost::asio::io_service > io_service)
|
||||
: UdpSocket(replyfn, multicast_address, io_service)
|
||||
, hostname(hostname)
|
||||
|
||||
{
|
||||
assert(!hostname.empty() && replyfn);
|
||||
create_requests();
|
||||
}
|
||||
|
||||
std::string get_hostname() const { return hostname; }
|
||||
protected:
|
||||
SharedSession create_session() const override;
|
||||
void create_requests()
|
||||
{
|
||||
requests.clear();
|
||||
// BonjourRequest::make_A / AAAA is now implemented to add .local correctly after the hostname.
|
||||
// If that is unsufficient, we need to change make_A / AAAA and pass full hostname.
|
||||
std::string trimmed_hostname = hostname;
|
||||
if (size_t dot_pos = trimmed_hostname.find_first_of('.'); dot_pos != std::string::npos)
|
||||
trimmed_hostname = trimmed_hostname.substr(0, dot_pos);
|
||||
if (auto rqst = BonjourRequest::make_A(trimmed_hostname); rqst)
|
||||
requests.push_back(std::move(rqst.get()));
|
||||
|
||||
trimmed_hostname = hostname;
|
||||
if (size_t dot_pos = trimmed_hostname.find_first_of('.'); dot_pos != std::string::npos)
|
||||
trimmed_hostname = trimmed_hostname.substr(0, dot_pos);
|
||||
if (auto rqst = BonjourRequest::make_AAAA(trimmed_hostname); rqst)
|
||||
requests.push_back(std::move(rqst.get()));
|
||||
}
|
||||
|
||||
std::string hostname;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -8,12 +8,14 @@
|
||||
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "../GUI/MsgDialog.hpp"
|
||||
#include "QDTUtil.hpp"
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
const float MIN_PA_K_VALUE = 0.0;
|
||||
const float MAX_PA_K_VALUE = 2.0;
|
||||
static const float MIN_PA_K_VALUE_STEP = 0.001;
|
||||
|
||||
std::shared_ptr<PrintJob> CalibUtils::print_job;
|
||||
wxString wxstr_temp_dir = fs::path(fs::temp_directory_path() / "calib").wstring();
|
||||
@@ -74,6 +76,19 @@ wxString get_nozzle_volume_type_name(NozzleVolumeType type)
|
||||
return wxString();
|
||||
}
|
||||
|
||||
bool is_pa_params_valid(const Calib_Params ¶ms)
|
||||
{
|
||||
if (params.start < MIN_PA_K_VALUE || params.end > MAX_PA_K_VALUE || params.step < MIN_PA_K_VALUE_STEP || params.end < params.start + params.step) {
|
||||
MessageDialog msg_dlg(nullptr,
|
||||
wxString::Format(_L("Please input valid values:\nStart value: >= %.1f\nEnd value: <= %.1f\nEnd value: > Start value\nValue step: >= %.3f)"),
|
||||
MIN_PA_K_VALUE, MAX_PA_K_VALUE, MIN_PA_K_VALUE_STEP),
|
||||
wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void get_tray_ams_and_slot_id(MachineObject* obj, int in_tray_id, int &ams_id, int &slot_id, int &tray_id)
|
||||
{
|
||||
assert(obj);
|
||||
@@ -970,6 +985,7 @@ void CalibUtils::calib_max_vol_speed(const CalibInfo &calib_info, wxString &erro
|
||||
filament_config.set_key_value("curr_bed_type", new ConfigOptionEnum<BedType>(calib_info.bed_type));
|
||||
|
||||
print_config.set_key_value("enable_overhang_speed", new ConfigOptionBoolsNullable{false});
|
||||
print_config.set_key_value("enable_height_slowdown", new ConfigOptionBoolsNullable{ false });
|
||||
print_config.set_key_value("timelapse_type", new ConfigOptionEnum<TimelapseType>(tlTraditional));
|
||||
print_config.set_key_value("wall_loops", new ConfigOptionInt(1));
|
||||
print_config.set_key_value("top_shell_layers", new ConfigOptionInt(0));
|
||||
@@ -1035,6 +1051,7 @@ void CalibUtils::calib_VFA(const CalibInfo &calib_info, wxString &error_message)
|
||||
filament_config.set_key_value("curr_bed_type", new ConfigOptionEnum<BedType>(calib_info.bed_type));
|
||||
|
||||
print_config.set_key_value("enable_overhang_speed", new ConfigOptionBoolsNullable{false});
|
||||
print_config.set_key_value("enable_height_slowdown", new ConfigOptionBoolsNullable{ false });
|
||||
print_config.set_key_value("timelapse_type", new ConfigOptionEnum<TimelapseType>(tlTraditional));
|
||||
print_config.set_key_value("wall_loops", new ConfigOptionInt(1));
|
||||
print_config.set_key_value("top_shell_layers", new ConfigOptionInt(0));
|
||||
@@ -1456,7 +1473,7 @@ void CalibUtils::send_to_print(const CalibInfo &calib_info, wxString &error_mess
|
||||
j["print"]["print_numbers"] = calib_info.params.print_numbers;
|
||||
j["print"]["flow_ratio_mode"] = flow_ratio_mode;
|
||||
j["print"]["tray_id"] = calib_info.select_ams;
|
||||
j["print"]["dev_id"] = calib_info.dev_id;
|
||||
j["print"]["dev_id"] = QDTCrossTalk::Crosstalk_DevId(calib_info.dev_id);
|
||||
j["print"]["bed_type"] = calib_info.bed_type;
|
||||
j["print"]["printer_prest"] = calib_info.printer_prest ? calib_info.printer_prest->name : "";
|
||||
j["print"]["filament_prest"] = calib_info.filament_prest ? calib_info.filament_prest->name : "";
|
||||
@@ -1551,7 +1568,7 @@ void CalibUtils::send_to_print(const CalibInfo &calib_info, wxString &error_mess
|
||||
print_job->set_calibration_task(true);
|
||||
|
||||
print_job->has_sdcard = obj_->get_sdcard_state() == MachineObject::SdcardState::HAS_SDCARD_NORMAL;
|
||||
print_job->set_print_config(MachineBedTypeString[bed_type], true, false, false, false, true, 0, 0, 0);
|
||||
print_job->set_print_config(MachineBedTypeString[bed_type], true, false, false, false, true, false, 0, 0, 0);
|
||||
print_job->set_print_job_finished_event(wxGetApp().plater()->get_send_calibration_finished_event(), print_job->m_project_name);
|
||||
|
||||
{ // after send: record the print job
|
||||
|
||||
@@ -88,6 +88,8 @@ extern void get_tray_ams_and_slot_id(MachineObject* obj, int in_tray_id, int &am
|
||||
|
||||
extern void get_default_k_n_value(const std::string &filament_id, float &k, float &n);
|
||||
extern wxString get_nozzle_volume_type_name(NozzleVolumeType type);
|
||||
extern bool is_pa_params_valid(const Calib_Params ¶ms);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
864
src/slic3r/Utils/EmbossStyleManager.cpp
Normal file
864
src/slic3r/Utils/EmbossStyleManager.cpp
Normal file
@@ -0,0 +1,864 @@
|
||||
#include "EmbossStyleManager.hpp"
|
||||
#include <optional>
|
||||
#include <GL/glew.h> // Imgui texture
|
||||
#include <imgui/imgui_internal.h> // ImTextCharFromUtf8
|
||||
#include <libslic3r/AppConfig.hpp>
|
||||
#include <libslic3r/Utils.hpp> // ScopeGuard
|
||||
|
||||
#include "WxFontUtils.hpp"
|
||||
#include "slic3r/GUI/3DScene.hpp" // ::glsafe
|
||||
#include "slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp"
|
||||
#include "slic3r/GUI/Jobs/CreateFontNameImageJob.hpp"
|
||||
#include "slic3r/GUI/ImGuiWrapper.hpp" // check of font ranges
|
||||
#include "slic3r/GUI/OpenGLManager.hpp"
|
||||
#include <boost/assign.hpp>
|
||||
#include <boost/bimap.hpp>
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::Emboss;
|
||||
using namespace Slic3r::GUI::Emboss;
|
||||
|
||||
StyleManager::StyleManager(const ImWchar *language_glyph_range, const std::function<EmbossStyles()>& create_default_styles)
|
||||
: m_create_default_styles(create_default_styles)
|
||||
, m_imgui_init_glyph_range(language_glyph_range)
|
||||
{}
|
||||
|
||||
StyleManager::~StyleManager() {
|
||||
clear_imgui_font();
|
||||
free_style_images();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For store/load emboss style to/from AppConfig
|
||||
/// </summary>
|
||||
namespace {
|
||||
void store_style_index(AppConfig &cfg, size_t index);
|
||||
::std::optional<size_t> load_style_index(const AppConfig &cfg);
|
||||
|
||||
StyleManager::Styles load_styles(const AppConfig &cfg);
|
||||
void store_styles(AppConfig &cfg, const StyleManager::Styles &styles);
|
||||
void make_unique_name(const StyleManager::Styles &styles, std::string &name);
|
||||
|
||||
// Enum map to string and vice versa
|
||||
using HorizontalAlignToName = boost::bimap<FontProp::HorizontalAlign, std::string_view>;
|
||||
const HorizontalAlignToName horizontal_align_to_name =
|
||||
boost::assign::list_of<HorizontalAlignToName::relation>
|
||||
(FontProp::HorizontalAlign::left, "left")
|
||||
(FontProp::HorizontalAlign::center, "center")
|
||||
(FontProp::HorizontalAlign::right, "right");
|
||||
using VerticalAlignToName = boost::bimap<FontProp::VerticalAlign, std::string_view>;
|
||||
const VerticalAlignToName vertical_align_to_name =
|
||||
boost::assign::list_of<VerticalAlignToName::relation>
|
||||
(FontProp::VerticalAlign::top, "top")
|
||||
(FontProp::VerticalAlign::center, "middle")
|
||||
(FontProp::VerticalAlign::bottom, "bottom");
|
||||
} // namespace
|
||||
|
||||
void StyleManager::init(AppConfig *app_config)
|
||||
{
|
||||
assert(app_config != nullptr);
|
||||
m_app_config = app_config;
|
||||
m_styles = ::load_styles(*app_config);
|
||||
|
||||
if (m_styles.empty()) {
|
||||
// No styles loaded from ini file so use default
|
||||
EmbossStyles styles = m_create_default_styles();
|
||||
for (EmbossStyle &style : styles) {
|
||||
::make_unique_name(m_styles, style.name);
|
||||
m_styles.push_back({style});
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<size_t> active_index_opt = (app_config != nullptr) ?
|
||||
::load_style_index(*app_config) :
|
||||
std::optional<size_t>{};
|
||||
|
||||
size_t active_index = 0;
|
||||
if (active_index_opt.has_value()) active_index = *active_index_opt;
|
||||
if (active_index >= m_styles.size()) active_index = 0;
|
||||
|
||||
// find valid font item
|
||||
if (load_style(active_index))
|
||||
return; // style is loaded
|
||||
|
||||
// Try to fix that style can't be loaded
|
||||
m_styles.erase(m_styles.begin() + active_index);
|
||||
|
||||
load_valid_style();
|
||||
}
|
||||
|
||||
bool StyleManager::store_styles_to_app_config(bool use_modification, bool store_active_index)
|
||||
{
|
||||
assert(m_app_config != nullptr);
|
||||
if (m_app_config == nullptr) return false;
|
||||
if (use_modification) {
|
||||
if (exist_stored_style()) {
|
||||
// update stored item
|
||||
m_styles[m_style_cache.style_index] = m_style_cache.style;
|
||||
} else {
|
||||
// add new into stored list
|
||||
EmbossStyle &style = m_style_cache.style;
|
||||
::make_unique_name(m_styles, style.name);
|
||||
m_style_cache.truncated_name.clear();
|
||||
m_style_cache.style_index = m_styles.size();
|
||||
m_styles.push_back({style});
|
||||
}
|
||||
m_style_cache.stored_wx_font = m_style_cache.wx_font;
|
||||
}
|
||||
|
||||
if (store_active_index)
|
||||
{
|
||||
size_t style_index = exist_stored_style() ?
|
||||
m_style_cache.style_index :
|
||||
m_last_style_index;
|
||||
store_style_index(*m_app_config, style_index);
|
||||
}
|
||||
|
||||
store_styles(*m_app_config, m_styles);
|
||||
return true;
|
||||
}
|
||||
|
||||
void StyleManager::add_style(const std::string &name) {
|
||||
EmbossStyle& style = m_style_cache.style;
|
||||
style.name = name;
|
||||
::make_unique_name(m_styles, style.name);
|
||||
m_style_cache.style_index = m_styles.size();
|
||||
m_style_cache.stored_wx_font = m_style_cache.wx_font;
|
||||
m_style_cache.truncated_name.clear();
|
||||
m_styles.push_back({style});
|
||||
}
|
||||
|
||||
void StyleManager::swap(size_t i1, size_t i2) {
|
||||
if (i1 >= m_styles.size() ||
|
||||
i2 >= m_styles.size()) return;
|
||||
std::swap(m_styles[i1], m_styles[i2]);
|
||||
// fix selected index
|
||||
if (!exist_stored_style()) return;
|
||||
if (m_style_cache.style_index == i1) {
|
||||
m_style_cache.style_index = i2;
|
||||
} else if (m_style_cache.style_index == i2) {
|
||||
m_style_cache.style_index = i1;
|
||||
}
|
||||
}
|
||||
|
||||
void StyleManager::discard_style_changes() {
|
||||
if (exist_stored_style()) {
|
||||
if (load_style(m_style_cache.style_index))
|
||||
return; // correct reload style
|
||||
} else {
|
||||
if(load_style(m_last_style_index))
|
||||
return; // correct load last used style
|
||||
}
|
||||
|
||||
// try to save situation by load some font
|
||||
load_valid_style();
|
||||
}
|
||||
|
||||
void StyleManager::erase(size_t index) {
|
||||
if (index >= m_styles.size()) return;
|
||||
|
||||
// fix selected index
|
||||
if (exist_stored_style()) {
|
||||
size_t &i = m_style_cache.style_index;
|
||||
if (index < i) --i;
|
||||
else if (index == i) i = std::numeric_limits<size_t>::max();
|
||||
}
|
||||
|
||||
m_styles.erase(m_styles.begin() + index);
|
||||
}
|
||||
|
||||
void StyleManager::rename(const std::string& name) {
|
||||
m_style_cache.style.name = name;
|
||||
m_style_cache.truncated_name.clear();
|
||||
if (exist_stored_style()) {
|
||||
Style &it = m_styles[m_style_cache.style_index];
|
||||
it.name = name;
|
||||
it.truncated_name.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void StyleManager::load_valid_style()
|
||||
{
|
||||
// iterate over all known styles
|
||||
while (!m_styles.empty()) {
|
||||
if (load_style(0))
|
||||
return;
|
||||
// can't load so erase it from list
|
||||
m_styles.erase(m_styles.begin());
|
||||
}
|
||||
|
||||
// no one style is loadable
|
||||
// set up default font list
|
||||
EmbossStyles def_style = m_create_default_styles();
|
||||
for (EmbossStyle &style : def_style) {
|
||||
::make_unique_name(m_styles, style.name);
|
||||
m_styles.push_back({std::move(style)});
|
||||
}
|
||||
|
||||
// iterate over default styles
|
||||
// There have to be option to use build in font
|
||||
while (!m_styles.empty()) {
|
||||
if (load_style(0))
|
||||
return;
|
||||
// can't load so erase it from list
|
||||
m_styles.erase(m_styles.begin());
|
||||
}
|
||||
|
||||
// This OS doesn't have TTF as default font,
|
||||
// find some loadable font out of default list
|
||||
assert(false);
|
||||
}
|
||||
|
||||
bool StyleManager::load_style(size_t style_index)
|
||||
{
|
||||
if (style_index >= m_styles.size())
|
||||
return false;
|
||||
if (!load_style(m_styles[style_index]))
|
||||
return false;
|
||||
m_style_cache.style_index = style_index;
|
||||
m_style_cache.stored_wx_font = m_style_cache.wx_font; // copy
|
||||
m_last_style_index = style_index;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StyleManager::load_style(const Style &style) {
|
||||
if (style.type == EmbossStyle::Type::file_path) {
|
||||
std::unique_ptr<FontFile> font_ptr = create_font_file(style.path.c_str());
|
||||
if (font_ptr == nullptr) return false;
|
||||
m_style_cache.wx_font = {};
|
||||
m_style_cache.font_file =
|
||||
FontFileWithCache(std::move(font_ptr));
|
||||
m_style_cache.style = style; // copy
|
||||
m_style_cache.style_index = std::numeric_limits<size_t>::max();
|
||||
m_style_cache.stored_wx_font = {};
|
||||
return true;
|
||||
}
|
||||
if (style.type != WxFontUtils::get_current_type()) return false;
|
||||
std::optional<wxFont> wx_font_opt = WxFontUtils::load_wxFont(style.path);
|
||||
if (!wx_font_opt.has_value()) return false;
|
||||
return load_style(style, *wx_font_opt);
|
||||
}
|
||||
|
||||
bool StyleManager::load_style(const Style &style, const wxFont &font)
|
||||
{
|
||||
m_style_cache.style = style; // copy
|
||||
|
||||
// wx font property has bigger priority to set
|
||||
// it must be after copy of the style
|
||||
if (!set_wx_font(font)) return false;
|
||||
|
||||
m_style_cache.style_index = std::numeric_limits<size_t>::max();
|
||||
m_style_cache.stored_wx_font = {};
|
||||
m_style_cache.truncated_name.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
Slic3r::Emboss::FontFileWithCache Slic3r::GUI::Emboss::StyleManager::get_font_file(wxString name) {
|
||||
for (int i = 0; i < m_styles.size(); i++) {
|
||||
if (m_styles[i].truncated_name == name .utf8_string()) {
|
||||
std::cout << "";
|
||||
}
|
||||
}
|
||||
return Slic3r::Emboss::FontFileWithCache();
|
||||
}
|
||||
|
||||
bool StyleManager::is_font_changed() const
|
||||
{
|
||||
const wxFont &wx_font = get_wx_font();
|
||||
if (!wx_font.IsOk())
|
||||
return false;
|
||||
if (!exist_stored_style())
|
||||
return false;
|
||||
const EmbossStyle *stored_style = get_stored_style();
|
||||
if (stored_style == nullptr)
|
||||
return false;
|
||||
|
||||
const wxFont &wx_font_stored = get_stored_wx_font();
|
||||
if (!wx_font_stored.IsOk())
|
||||
return false;
|
||||
|
||||
const FontProp &prop = get_style().prop;
|
||||
const FontProp &prop_stored = stored_style->prop;
|
||||
|
||||
// Exist change in face name?
|
||||
if(wx_font_stored.GetFaceName() != wx_font.GetFaceName()) return true;
|
||||
|
||||
const std::optional<float> &skew = prop.skew;
|
||||
bool is_italic = skew.has_value() || WxFontUtils::is_italic(wx_font);
|
||||
const std::optional<float> &skew_stored = prop_stored.skew;
|
||||
bool is_stored_italic = skew_stored.has_value() || WxFontUtils::is_italic(wx_font_stored);
|
||||
// is italic changed
|
||||
if (is_italic != is_stored_italic)
|
||||
return true;
|
||||
|
||||
const std::optional<float> &boldness = prop.boldness;
|
||||
bool is_bold = boldness.has_value() || WxFontUtils::is_bold(wx_font);
|
||||
const std::optional<float> &boldness_stored = prop_stored.boldness;
|
||||
bool is_stored_bold = boldness_stored.has_value() || WxFontUtils::is_bold(wx_font_stored);
|
||||
// is bold changed
|
||||
return is_bold != is_stored_bold;
|
||||
}
|
||||
|
||||
bool StyleManager::is_unique_style_name(const std::string &name) const {
|
||||
for (const StyleManager::Style &style : m_styles)
|
||||
if (style.name == name)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StyleManager::is_active_font() { return m_style_cache.font_file.has_value(); }
|
||||
|
||||
const StyleManager::Style *StyleManager::get_stored_style() const
|
||||
{
|
||||
if (m_style_cache.style_index >= m_styles.size()) return nullptr;
|
||||
return &m_styles[m_style_cache.style_index];
|
||||
}
|
||||
|
||||
void StyleManager::clear_glyphs_cache()
|
||||
{
|
||||
FontFileWithCache &ff = m_style_cache.font_file;
|
||||
if (!ff.has_value()) return;
|
||||
ff.cache = std::make_shared<Glyphs>();
|
||||
}
|
||||
|
||||
void StyleManager::clear_imgui_font() { m_style_cache.atlas.Clear(); }
|
||||
|
||||
ImFont *StyleManager::get_imgui_font()
|
||||
{
|
||||
if (!is_active_font()) return nullptr;
|
||||
|
||||
ImVector<ImFont *> &fonts = m_style_cache.atlas.Fonts;
|
||||
if (fonts.empty()) return nullptr;
|
||||
|
||||
// check correct index
|
||||
int f_size = fonts.size();
|
||||
assert(f_size == 1);
|
||||
if (f_size != 1) return nullptr;
|
||||
ImFont *font = fonts.front();
|
||||
if (font == nullptr) return nullptr;
|
||||
return font;
|
||||
}
|
||||
|
||||
const StyleManager::Styles &StyleManager::get_styles() const{ return m_styles; }
|
||||
void StyleManager::init_trunc_names(float max_width) {
|
||||
for (auto &s : m_styles)
|
||||
if (s.truncated_name.empty()) {
|
||||
std::string name = s.name;
|
||||
ImGuiWrapper::escape_double_hash(name);
|
||||
s.truncated_name = ImGuiWrapper::trunc(name, max_width);
|
||||
}
|
||||
}
|
||||
|
||||
// for access to worker
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
|
||||
// for get DPI
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/MainFrame.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GizmoObjectManipulation.hpp"
|
||||
|
||||
void StyleManager::init_style_images(const Vec2i32 &max_size,
|
||||
const std::string &text)
|
||||
{
|
||||
// check already initialized
|
||||
if (m_exist_style_images) return;
|
||||
|
||||
// check is initializing
|
||||
if (m_temp_style_images != nullptr) {
|
||||
// is initialization finished
|
||||
if (!m_temp_style_images->styles.empty()) {
|
||||
assert(m_temp_style_images->images.size() ==
|
||||
m_temp_style_images->styles.size());
|
||||
// copy images into styles
|
||||
for (StyleManager::StyleImage &image : m_temp_style_images->images){
|
||||
size_t index = &image - &m_temp_style_images->images.front();
|
||||
StyleImagesData::Item &style = m_temp_style_images->styles[index];
|
||||
|
||||
// find style in font list and copy to it
|
||||
for (auto &it : m_styles) {
|
||||
if (it.name != style.text ||
|
||||
!(it.prop == style.prop))
|
||||
continue;
|
||||
it.image = image;
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_temp_style_images = nullptr;
|
||||
m_exist_style_images = true;
|
||||
return;
|
||||
}
|
||||
// in process of initialization inside of job
|
||||
return;
|
||||
}
|
||||
|
||||
// create job for init images
|
||||
m_temp_style_images = std::make_shared<StyleImagesData::StyleImages>();
|
||||
StyleImagesData::Items styles;
|
||||
styles.reserve(m_styles.size());
|
||||
for (const Style &style : m_styles) {
|
||||
std::optional<wxFont> wx_font_opt = WxFontUtils::load_wxFont(style.path);
|
||||
if (!wx_font_opt.has_value()) continue;
|
||||
std::unique_ptr<FontFile> font_file =
|
||||
WxFontUtils::create_font_file(*wx_font_opt);
|
||||
if (font_file == nullptr) continue;
|
||||
styles.push_back({
|
||||
FontFileWithCache(std::move(font_file)),
|
||||
style.name,
|
||||
style.prop
|
||||
});
|
||||
}
|
||||
|
||||
auto mf = wxGetApp().mainframe;
|
||||
// dot per inch for monitor
|
||||
int dpi = get_dpi_for_window(mf);
|
||||
// pixel per milimeter
|
||||
double ppm = dpi / GizmoObjectManipulation::in_to_mm;
|
||||
|
||||
auto &worker = wxGetApp().plater()->get_ui_job_worker();
|
||||
StyleImagesData data{std::move(styles), max_size, text, m_temp_style_images, ppm};
|
||||
queue_job(worker, std::make_unique<CreateFontStyleImagesJob>(std::move(data)));
|
||||
}
|
||||
|
||||
void StyleManager::free_style_images() {
|
||||
if (!m_exist_style_images) return;
|
||||
GLuint tex_id = 0;
|
||||
for (Style &it : m_styles) {
|
||||
if (tex_id == 0 && it.image.has_value())
|
||||
tex_id = (GLuint)(intptr_t) it.image->texture_id;
|
||||
it.image.reset();
|
||||
}
|
||||
if (tex_id != 0)
|
||||
glsafe(::glDeleteTextures(1, &tex_id));
|
||||
m_exist_style_images = false;
|
||||
}
|
||||
|
||||
float StyleManager::min_imgui_font_size = 18.f;
|
||||
float StyleManager::max_imgui_font_size = 60.f;
|
||||
float StyleManager::get_imgui_font_size(const FontProp &prop, const FontFile &file, double scale)
|
||||
{
|
||||
const FontFile::Info& info = get_font_info(file, prop);
|
||||
// coeficient for convert line height to font size
|
||||
float c1 = (info.ascent - info.descent + info.linegap) /
|
||||
(float) info.unit_per_em;
|
||||
|
||||
// The point size is defined as 1/72 of the Anglo-Saxon inch (25.4 mm):
|
||||
// It is approximately 0.0139 inch or 352.8 um.
|
||||
return c1 * std::abs(prop.size_in_mm) / 0.3528f * scale;
|
||||
}
|
||||
|
||||
ImFont *StyleManager::create_imgui_font(const std::string &text, double scale, bool support_backup_fonts)
|
||||
{
|
||||
// inspiration inside of ImGuiWrapper::init_font
|
||||
auto& ff = m_style_cache.font_file;
|
||||
if (!ff.has_value()) return nullptr;
|
||||
const FontFile &font_file = *ff.font_file;
|
||||
|
||||
ImFontGlyphRangesBuilder builder;
|
||||
builder.AddRanges(m_imgui_init_glyph_range);
|
||||
if (!text.empty())
|
||||
builder.AddText(text.c_str());
|
||||
|
||||
ImVector<ImWchar> &ranges = m_style_cache.ranges;
|
||||
ranges.clear();
|
||||
builder.BuildRanges(&ranges);
|
||||
|
||||
m_style_cache.atlas.Flags |= ImFontAtlasFlags_NoMouseCursors |
|
||||
ImFontAtlasFlags_NoPowerOfTwoHeight;
|
||||
|
||||
const FontProp &font_prop = m_style_cache.style.prop;
|
||||
float font_size = 36;//use fix font size get_imgui_font_size(font_prop, font_file, scale);
|
||||
if (font_size < min_imgui_font_size)
|
||||
font_size = min_imgui_font_size;
|
||||
if (font_size > max_imgui_font_size)
|
||||
font_size = max_imgui_font_size;
|
||||
|
||||
ImFontConfig font_config;
|
||||
// TODO: start using merge mode
|
||||
int unit_per_em = get_font_info(font_file, font_prop).unit_per_em;
|
||||
float coef = font_size / (double) unit_per_em;
|
||||
if (font_prop.char_gap.has_value())
|
||||
font_config.GlyphExtraSpacing.x = coef * (*font_prop.char_gap);
|
||||
if (font_prop.line_gap.has_value())
|
||||
font_config.GlyphExtraSpacing.y = coef * (*font_prop.line_gap);
|
||||
|
||||
font_config.FontDataOwnedByAtlas = false;
|
||||
ImFont *font{nullptr};
|
||||
const std::vector<unsigned char> &buffer = *font_file.data;
|
||||
font = m_style_cache.atlas.AddFontFromMemoryTTF((void *) buffer.data(), buffer.size(), font_size, &font_config, m_style_cache.ranges.Data);
|
||||
if (support_backup_fonts) {
|
||||
font_config.MergeMode = true;
|
||||
for (int i = 0; i < Slic3r::GUI::BackupFonts::backup_fonts.size(); i++) {
|
||||
if (Slic3r::GUI::BackupFonts::backup_fonts[i].has_value()) {
|
||||
auto & temp_ff = Slic3r::GUI::BackupFonts::backup_fonts[i];
|
||||
const FontFile & temp_font_file = *temp_ff.font_file;
|
||||
const std::vector<unsigned char> &temp_buffer = *temp_font_file.data;
|
||||
font = m_style_cache.atlas.AddFontFromMemoryTTF((void *) temp_buffer.data(), temp_buffer.size(), font_size, &font_config, m_style_cache.ranges.Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char *pixels;
|
||||
int width, height;
|
||||
m_style_cache.atlas.GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||
|
||||
// Upload texture to graphics system
|
||||
GLint last_texture;
|
||||
glsafe(::glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
|
||||
ScopeGuard sg([last_texture]() {
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, last_texture));
|
||||
});
|
||||
|
||||
GLuint font_texture;
|
||||
glsafe(::glGenTextures(1, &font_texture));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, font_texture));
|
||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||
glsafe(::glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
|
||||
if (OpenGLManager::are_compressed_textures_supported())
|
||||
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
|
||||
else
|
||||
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
|
||||
|
||||
// Store our identifier
|
||||
m_style_cache.atlas.TexID = (ImTextureID) (intptr_t) font_texture;
|
||||
assert(!m_style_cache.atlas.Fonts.empty());
|
||||
if (m_style_cache.atlas.Fonts.empty()) return nullptr;
|
||||
assert(font == m_style_cache.atlas.Fonts.back());
|
||||
if (!font->IsLoaded()) return nullptr;
|
||||
assert(font->IsLoaded());
|
||||
return font;
|
||||
}
|
||||
|
||||
bool StyleManager::set_wx_font(const wxFont &wx_font) {
|
||||
std::unique_ptr<FontFile> font_file =
|
||||
WxFontUtils::create_font_file(wx_font);
|
||||
return set_wx_font(wx_font, std::move(font_file));
|
||||
}
|
||||
|
||||
bool StyleManager::set_wx_font(const wxFont &wx_font, std::unique_ptr<FontFile> font_file)
|
||||
{
|
||||
if (font_file == nullptr) return false;
|
||||
m_style_cache.wx_font = wx_font; // copy
|
||||
m_style_cache.font_file =
|
||||
FontFileWithCache(std::move(font_file));
|
||||
|
||||
EmbossStyle &style = m_style_cache.style;
|
||||
style.type = WxFontUtils::get_current_type();
|
||||
// update string path
|
||||
style.path = WxFontUtils::store_wxFont(wx_font);
|
||||
WxFontUtils::update_property(style.prop, wx_font);
|
||||
clear_imgui_font();
|
||||
return true;
|
||||
}
|
||||
|
||||
#include <libslic3r/AppConfig.hpp>
|
||||
#include "WxFontUtils.hpp"
|
||||
#include "fast_float/fast_float.h"
|
||||
|
||||
// StylesSerializable
|
||||
namespace {
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::GUI;
|
||||
using Section = std::map<std::string,std::string>;
|
||||
|
||||
const std::string APP_CONFIG_FONT_NAME = "name";
|
||||
const std::string APP_CONFIG_FONT_DESCRIPTOR = "descriptor";
|
||||
const std::string APP_CONFIG_FONT_LINE_HEIGHT = "line_height";
|
||||
const std::string APP_CONFIG_FONT_DEPTH = "depth";
|
||||
const std::string APP_CONFIG_FONT_USE_SURFACE = "use_surface";
|
||||
const std::string APP_CONFIG_PER_GLYPH = "per_glyph";
|
||||
const std::string APP_CONFIG_VERTICAL_ALIGN = "vertical_align";
|
||||
const std::string APP_CONFIG_HORIZONTAL_ALIGN = "horizontal_align";
|
||||
const std::string APP_CONFIG_FONT_BOLDNESS = "boldness";
|
||||
const std::string APP_CONFIG_FONT_SKEW = "skew";
|
||||
const std::string APP_CONFIG_FONT_DISTANCE = "distance";
|
||||
const std::string APP_CONFIG_FONT_ANGLE = "angle";
|
||||
const std::string APP_CONFIG_FONT_COLLECTION = "collection";
|
||||
const std::string APP_CONFIG_FONT_CHAR_GAP = "char_gap";
|
||||
const std::string APP_CONFIG_FONT_LINE_GAP = "line_gap";
|
||||
|
||||
const std::string APP_CONFIG_ACTIVE_FONT = "active_font";
|
||||
|
||||
std::string create_section_name(unsigned index)
|
||||
{
|
||||
return AppConfig::SECTION_EMBOSS_STYLE + ':' + std::to_string(index);
|
||||
}
|
||||
|
||||
// check only existence of flag
|
||||
bool read(const Section §ion, const std::string &key, bool &value)
|
||||
{
|
||||
auto item = section.find(key);
|
||||
if (item == section.end())
|
||||
return false;
|
||||
|
||||
value = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read(const Section §ion, const std::string &key, Slic3r::FontProp::HorizontalAlign &value) {
|
||||
auto item = section.find(key);
|
||||
if (item == section.end())
|
||||
return false;
|
||||
|
||||
const std::string &data = item->second;
|
||||
if (data.empty())
|
||||
return false;
|
||||
|
||||
const auto& map = horizontal_align_to_name.right;
|
||||
auto it = map.find(data);
|
||||
value = (it != map.end()) ? it->second : Slic3r::FontProp::HorizontalAlign::center;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read(const Section §ion, const std::string &key, Slic3r::FontProp::VerticalAlign &value) {
|
||||
auto item = section.find(key);
|
||||
if (item == section.end())
|
||||
return false;
|
||||
|
||||
const std::string &data = item->second;
|
||||
if (data.empty())
|
||||
return false;
|
||||
|
||||
const auto &map = vertical_align_to_name.right;
|
||||
auto it = map.find(data);
|
||||
value = (it != map.end()) ? it->second : Slic3r::FontProp::VerticalAlign::center;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read(const Section §ion, const std::string &key, float &value)
|
||||
{
|
||||
auto item = section.find(key);
|
||||
if (item == section.end())
|
||||
return false;
|
||||
const std::string &data = item->second;
|
||||
if (data.empty())
|
||||
return false;
|
||||
float value_;
|
||||
fast_float::from_chars(data.c_str(), data.c_str() + data.length(), value_);
|
||||
// read only non zero value
|
||||
if (fabs(value_) <= std::numeric_limits<float>::epsilon())
|
||||
return false;
|
||||
|
||||
value = value_;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read(const Section §ion, const std::string &key, std::optional<int> &value)
|
||||
{
|
||||
auto item = section.find(key);
|
||||
if (item == section.end())
|
||||
return false;
|
||||
const std::string &data = item->second;
|
||||
if (data.empty())
|
||||
return false;
|
||||
int value_ = std::atoi(data.c_str());
|
||||
if (value_ == 0)
|
||||
return false;
|
||||
|
||||
value = value_;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read(const Section §ion, const std::string &key, std::optional<unsigned int> &value)
|
||||
{
|
||||
auto item = section.find(key);
|
||||
if (item == section.end())
|
||||
return false;
|
||||
const std::string &data = item->second;
|
||||
if (data.empty())
|
||||
return false;
|
||||
int value_ = std::atoi(data.c_str());
|
||||
if (value_ <= 0)
|
||||
return false;
|
||||
|
||||
value = static_cast<unsigned int>(value_);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read(const Section §ion, const std::string &key, std::optional<float> &value)
|
||||
{
|
||||
auto item = section.find(key);
|
||||
if (item == section.end())
|
||||
return false;
|
||||
const std::string &data = item->second;
|
||||
if (data.empty())
|
||||
return false;
|
||||
float value_;
|
||||
fast_float::from_chars(data.c_str(), data.c_str() + data.length(), value_);
|
||||
// read only non zero value
|
||||
if (fabs(value_) <= std::numeric_limits<float>::epsilon())
|
||||
return false;
|
||||
|
||||
value = value_;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<StyleManager::Style> load_style(const Section &app_cfg_section)
|
||||
{
|
||||
auto path_it = app_cfg_section.find(APP_CONFIG_FONT_DESCRIPTOR);
|
||||
if (path_it == app_cfg_section.end())
|
||||
return {};
|
||||
|
||||
StyleManager::Style s;
|
||||
EmbossProjection& ep = s.projection;
|
||||
FontProp& fp = s.prop;
|
||||
|
||||
s.path = path_it->second;
|
||||
s.type = WxFontUtils::get_current_type();
|
||||
auto name_it = app_cfg_section.find(APP_CONFIG_FONT_NAME);
|
||||
const std::string default_name = "font_name";
|
||||
s.name = (name_it == app_cfg_section.end()) ? default_name : name_it->second;
|
||||
|
||||
read(app_cfg_section, APP_CONFIG_FONT_LINE_HEIGHT, fp.size_in_mm);
|
||||
float depth = 1.;
|
||||
read(app_cfg_section, APP_CONFIG_FONT_DEPTH, depth);
|
||||
ep.depth = depth;
|
||||
read(app_cfg_section, APP_CONFIG_FONT_USE_SURFACE, ep.use_surface);
|
||||
read(app_cfg_section, APP_CONFIG_PER_GLYPH, fp.per_glyph);
|
||||
read(app_cfg_section, APP_CONFIG_HORIZONTAL_ALIGN, fp.align.first);
|
||||
read(app_cfg_section, APP_CONFIG_VERTICAL_ALIGN, fp.align.second);
|
||||
read(app_cfg_section, APP_CONFIG_FONT_BOLDNESS, fp.boldness);
|
||||
read(app_cfg_section, APP_CONFIG_FONT_SKEW, fp.skew);
|
||||
read(app_cfg_section, APP_CONFIG_FONT_DISTANCE, s.distance);
|
||||
read(app_cfg_section, APP_CONFIG_FONT_ANGLE, s.angle);
|
||||
read(app_cfg_section, APP_CONFIG_FONT_COLLECTION, fp.collection_number);
|
||||
read(app_cfg_section, APP_CONFIG_FONT_CHAR_GAP, fp.char_gap);
|
||||
read(app_cfg_section, APP_CONFIG_FONT_LINE_GAP, fp.line_gap);
|
||||
return s;
|
||||
}
|
||||
|
||||
void store_style(AppConfig &cfg, const StyleManager::Style &s, unsigned index)
|
||||
{
|
||||
const EmbossProjection &ep = s.projection;
|
||||
Section data;
|
||||
data[APP_CONFIG_FONT_NAME] = s.name;
|
||||
data[APP_CONFIG_FONT_DESCRIPTOR] = s.path;
|
||||
const FontProp &fp = s.prop;
|
||||
data[APP_CONFIG_FONT_LINE_HEIGHT] = std::to_string(fp.size_in_mm);
|
||||
data[APP_CONFIG_FONT_DEPTH] = std::to_string(ep.depth);
|
||||
if (ep.use_surface)
|
||||
data[APP_CONFIG_FONT_USE_SURFACE] = "true";
|
||||
if (fp.per_glyph)
|
||||
data[APP_CONFIG_PER_GLYPH] = "true";
|
||||
if (fp.align.first != FontProp::HorizontalAlign::center)
|
||||
data[APP_CONFIG_HORIZONTAL_ALIGN] = horizontal_align_to_name.left.find(fp.align.first)->second;
|
||||
if (fp.align.second != FontProp::VerticalAlign::center)
|
||||
data[APP_CONFIG_VERTICAL_ALIGN] = vertical_align_to_name.left.find(fp.align.second)->second;
|
||||
if (fp.boldness.has_value())
|
||||
data[APP_CONFIG_FONT_BOLDNESS] = std::to_string(*fp.boldness);
|
||||
if (fp.skew.has_value())
|
||||
data[APP_CONFIG_FONT_SKEW] = std::to_string(*fp.skew);
|
||||
if (s.distance.has_value())
|
||||
data[APP_CONFIG_FONT_DISTANCE] = std::to_string(*s.distance);
|
||||
if (s.angle.has_value())
|
||||
data[APP_CONFIG_FONT_ANGLE] = std::to_string(*s.angle);
|
||||
if (fp.collection_number.has_value())
|
||||
data[APP_CONFIG_FONT_COLLECTION] = std::to_string(*fp.collection_number);
|
||||
if (fp.char_gap.has_value())
|
||||
data[APP_CONFIG_FONT_CHAR_GAP] = std::to_string(*fp.char_gap);
|
||||
if (fp.line_gap.has_value())
|
||||
data[APP_CONFIG_FONT_LINE_GAP] = std::to_string(*fp.line_gap);
|
||||
cfg.set_section(create_section_name(index), std::move(data));
|
||||
}
|
||||
|
||||
void store_style_index(AppConfig &cfg, size_t index)
|
||||
{
|
||||
// store actual font index
|
||||
// active font first index is +1 to correspond with section name
|
||||
Section data;
|
||||
data[APP_CONFIG_ACTIVE_FONT] = std::to_string(index);
|
||||
cfg.set_section(AppConfig::SECTION_EMBOSS_STYLE, std::move(data));
|
||||
}
|
||||
|
||||
std::optional<size_t> load_style_index(const AppConfig &cfg)
|
||||
{
|
||||
if (!cfg.has_section(AppConfig::SECTION_EMBOSS_STYLE))
|
||||
return {};
|
||||
|
||||
auto section = cfg.get_section(AppConfig::SECTION_EMBOSS_STYLE);
|
||||
auto it = section.find(APP_CONFIG_ACTIVE_FONT);
|
||||
if (it == section.end())
|
||||
return {};
|
||||
|
||||
size_t active_font = static_cast<size_t>(std::atoi(it->second.c_str()));
|
||||
// order in config starts with number 1
|
||||
return active_font - 1;
|
||||
}
|
||||
|
||||
::StyleManager::Styles load_styles(const AppConfig &cfg)
|
||||
{
|
||||
StyleManager::Styles result;
|
||||
// human readable index inside of config starts from 1 !!
|
||||
unsigned index = 1;
|
||||
std::string section_name = create_section_name(index);
|
||||
while (cfg.has_section(section_name)) {
|
||||
std::optional<StyleManager::Style> style_opt = load_style(cfg.get_section(section_name));
|
||||
if (style_opt.has_value()) {
|
||||
make_unique_name(result, style_opt->name);
|
||||
result.emplace_back(*style_opt);
|
||||
}
|
||||
|
||||
section_name = create_section_name(++index);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void store_styles(AppConfig &cfg, const StyleManager::Styles &styles)
|
||||
{
|
||||
EmbossStyle::Type current_type = WxFontUtils::get_current_type();
|
||||
// store styles
|
||||
unsigned index = 1;
|
||||
for (const StyleManager::Style &style : styles) {
|
||||
// skip file paths + fonts from other OS(loaded from .3mf)
|
||||
assert(style.type == current_type);
|
||||
if (style.type != current_type)
|
||||
continue;
|
||||
store_style(cfg, style, index);
|
||||
++index;
|
||||
}
|
||||
|
||||
// remove rest of font sections (after deletation)
|
||||
std::string section_name = create_section_name(index);
|
||||
while (cfg.has_section(section_name)) {
|
||||
cfg.clear_section(section_name);
|
||||
section_name = create_section_name(index);
|
||||
++index;
|
||||
}
|
||||
cfg.set_dirty();
|
||||
}
|
||||
|
||||
void make_unique_name(const StyleManager::Styles& styles, std::string &name)
|
||||
{
|
||||
auto is_unique = [&styles](const std::string &name){
|
||||
for (const StyleManager::Style &it : styles)
|
||||
if (it.name == name) return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
// Style name can't be empty so default name is set
|
||||
if (name.empty()) name = "Text style";
|
||||
|
||||
// When name is already unique, nothing need to be changed
|
||||
if (is_unique(name)) return;
|
||||
|
||||
// when there is previous version of style name only find number
|
||||
const char *prefix = " (";
|
||||
const char suffix = ')';
|
||||
auto pos = name.find_last_of(prefix);
|
||||
if (name.c_str()[name.size() - 1] == suffix &&
|
||||
pos != std::string::npos) {
|
||||
// short name by ord number
|
||||
name = name.substr(0, pos);
|
||||
}
|
||||
|
||||
int order = 1; // start with value 2 to represents same font name
|
||||
std::string new_name;
|
||||
do {
|
||||
new_name = name + prefix + std::to_string(++order) + suffix;
|
||||
} while (!is_unique(new_name));
|
||||
name = new_name;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
323
src/slic3r/Utils/EmbossStyleManager.hpp
Normal file
323
src/slic3r/Utils/EmbossStyleManager.hpp
Normal file
@@ -0,0 +1,323 @@
|
||||
#ifndef slic3r_EmbossStyleManager_hpp_
|
||||
#define slic3r_EmbossStyleManager_hpp_
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <imgui/imgui.h>
|
||||
#include <wx/font.h>
|
||||
#include <GL/glew.h>
|
||||
#include <libslic3r/BoundingBox.hpp>
|
||||
#include <libslic3r/Emboss.hpp>
|
||||
#include <libslic3r/TextConfiguration.hpp>
|
||||
#include <libslic3r/EmbossShape.hpp>
|
||||
#include <libslic3r/AppConfig.hpp>
|
||||
|
||||
namespace Slic3r::GUI::Emboss {
|
||||
/// <summary>
|
||||
/// Manage Emboss text styles
|
||||
/// Cache actual state of style
|
||||
/// + imgui font
|
||||
/// + wx font
|
||||
/// </summary>
|
||||
class StyleManager
|
||||
{
|
||||
friend class CreateFontStyleImagesJob; // access to StyleImagesData
|
||||
public:
|
||||
/// <param name="language_glyph_range">Character to load for imgui when initialize imgui font</param>
|
||||
/// <param name="create_default_styles">Function to create default styles</param>
|
||||
StyleManager(const ImWchar *language_glyph_range, const std::function<EmbossStyles()>& create_default_styles);
|
||||
|
||||
/// <summary>
|
||||
/// Release imgui font and style images from GPU
|
||||
/// </summary>
|
||||
~StyleManager();
|
||||
|
||||
/// <summary>
|
||||
/// Load font style list from config
|
||||
/// Also select actual activ font
|
||||
/// </summary>
|
||||
/// <param name="app_config">Application configuration loaded from file "PrusaSlicer.ini"
|
||||
/// + cfg is stored to privat variable</param>
|
||||
void init(AppConfig *app_config);
|
||||
|
||||
/// <summary>
|
||||
/// Write font list into AppConfig
|
||||
/// </summary>
|
||||
/// <param name="item_to_store">Configuration</param>
|
||||
/// <param name="use_modification">When true cache state will be used for store</param>
|
||||
/// <param name="use_modification">When true store activ index into configuration</param>
|
||||
/// <returns>True on succes otherwise False.</returns>
|
||||
bool store_styles_to_app_config(bool use_modification = true, bool store_active_index = true);
|
||||
|
||||
/// <summary>
|
||||
/// Append actual style to style list
|
||||
/// </summary>
|
||||
/// <param name="name">New name for style</param>
|
||||
void add_style(const std::string& name);
|
||||
|
||||
/// <summary>
|
||||
/// Change order of style item in m_styles.
|
||||
/// Fix selected font index when (i1 || i2) == m_font_selected
|
||||
/// </summary>
|
||||
/// <param name="i1">First index to m_styles</param>
|
||||
/// <param name="i2">Second index to m_styles</param>
|
||||
void swap(size_t i1, size_t i2);
|
||||
|
||||
/// <summary>
|
||||
/// Discard changes in activ style
|
||||
/// When no activ style use last used OR first loadable
|
||||
/// </summary>
|
||||
void discard_style_changes();
|
||||
|
||||
/// <summary>
|
||||
/// Remove style from m_styles.
|
||||
/// Fix selected font index when index is under m_font_selected
|
||||
/// </summary>
|
||||
/// <param name="index">Index of style to be removed</param>
|
||||
void erase(size_t index);
|
||||
|
||||
/// <summary>
|
||||
/// Rename actual selected font item
|
||||
/// </summary>
|
||||
/// <param name="name">New name</param>
|
||||
void rename(const std::string &name);
|
||||
|
||||
/// <summary>
|
||||
/// load some valid style
|
||||
/// </summary>
|
||||
void load_valid_style();
|
||||
|
||||
/// <summary>
|
||||
/// Change active font
|
||||
/// When font not loaded roll back activ font
|
||||
/// </summary>
|
||||
/// <param name="font_index">New font index(from m_styles range)</param>
|
||||
/// <returns>True on succes. False on fail load font</returns>
|
||||
bool load_style(size_t font_index);
|
||||
// load font style not stored in list
|
||||
struct Style;
|
||||
bool load_style(const Style &style);
|
||||
// fastering load font on index by wxFont, ignore type and descriptor
|
||||
bool load_style(const Style &style, const wxFont &font);
|
||||
|
||||
// clear actual selected glyphs cache
|
||||
void clear_glyphs_cache();
|
||||
|
||||
// remove cached imgui font for actual selected font
|
||||
void clear_imgui_font();
|
||||
|
||||
// getters for private data
|
||||
const Style *get_stored_style() const;
|
||||
|
||||
const Style &get_style() const { return m_style_cache.style; }
|
||||
Style &get_style() { return m_style_cache.style; }
|
||||
size_t get_style_index() const { return m_style_cache.style_index; }
|
||||
std::string &get_truncated_name() { return m_style_cache.truncated_name; }
|
||||
const ImFontAtlas &get_atlas() const { return m_style_cache.atlas; }
|
||||
const FontProp &get_font_prop() const { return get_style().prop; }
|
||||
FontProp &get_font_prop() { return get_style().prop; }
|
||||
const wxFont &get_wx_font() const { return m_style_cache.wx_font; }
|
||||
const wxFont &get_stored_wx_font() const { return m_style_cache.stored_wx_font; }
|
||||
Slic3r::Emboss::FontFileWithCache &get_font_file_with_cache() { return m_style_cache.font_file; }
|
||||
Slic3r::Emboss::FontFileWithCache get_font_file(wxString name);
|
||||
bool has_collections() const { return m_style_cache.font_file.font_file != nullptr &&
|
||||
m_style_cache.font_file.font_file->infos.size() > 1; }
|
||||
|
||||
// True when activ style has same name as some of stored style
|
||||
bool exist_stored_style() const { return m_style_cache.style_index != std::numeric_limits<size_t>::max(); }
|
||||
|
||||
/// <summary>
|
||||
/// check whether current style differ to selected
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
bool is_font_changed() const;
|
||||
|
||||
bool is_unique_style_name(const std::string &name) const;
|
||||
|
||||
/// <summary>
|
||||
/// Setter on wx_font when changed
|
||||
/// </summary>
|
||||
/// <param name="wx_font">new wx font</param>
|
||||
/// <returns>True on success set otherwise FALSE</returns>
|
||||
bool set_wx_font(const wxFont &wx_font);
|
||||
|
||||
/// <summary>
|
||||
/// Faster way of set wx_font when font file is known(do not load font file twice)
|
||||
/// When you not sure that wx_font is made by font_file use only set_wx_font(wx_font)
|
||||
/// </summary>
|
||||
/// <param name="wx_font">Must be source of font file</param>
|
||||
/// <param name="font_file">font file created by WxFontUtils::create_font_file(wx_font)</param>
|
||||
/// <returns>True on success otherwise false</returns>
|
||||
bool set_wx_font(const wxFont &wx_font, std::unique_ptr<Slic3r::Emboss::FontFile> font_file);
|
||||
|
||||
// Getter on acitve font pointer for imgui
|
||||
// Initialize imgui font(generate texture) when doesn't exist yet.
|
||||
// Extend font atlas when not in glyph range
|
||||
ImFont *get_imgui_font();
|
||||
// initialize font range by unique symbols in text
|
||||
ImFont *create_imgui_font(const std::string &text, double scale, bool support_backup_fonts);
|
||||
|
||||
// init truncated names of styles
|
||||
void init_trunc_names(float max_width);
|
||||
|
||||
/// <summary>
|
||||
/// Initialization texture with rendered font style
|
||||
/// </summary>
|
||||
/// <param name="max_size">Maximal width and height of one style texture</param>
|
||||
/// <param name="text">Text to render by style</param>
|
||||
void init_style_images(const Vec2i32& max_size, const std::string &text);
|
||||
void free_style_images();
|
||||
|
||||
// access to all managed font styles
|
||||
const std::vector<Style> &get_styles() const;
|
||||
|
||||
/// <summary>
|
||||
/// Describe image in GPU to show settings of style
|
||||
/// </summary>
|
||||
struct StyleImage
|
||||
{
|
||||
void* texture_id = nullptr; // GLuint
|
||||
BoundingBox bounding_box;
|
||||
ImVec2 tex_size;
|
||||
ImVec2 uv0;
|
||||
ImVec2 uv1;
|
||||
Point offset = Point(0, 0);
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// All connected with one style
|
||||
/// keep temporary data and caches for style
|
||||
/// </summary>
|
||||
struct Style : public EmbossStyle
|
||||
{
|
||||
// Define how to emboss shape
|
||||
EmbossProjection projection;
|
||||
|
||||
// distance from surface point
|
||||
// used for move over model surface
|
||||
// When not set value is zero and is not stored
|
||||
std::optional<float> distance; // [in mm]
|
||||
|
||||
// Angle of rotation around emboss direction (Z axis)
|
||||
// It is calculate on the fly from volume world transformation
|
||||
// only StyleManager keep actual value for comparision with style
|
||||
// When not set value is zero and is not stored
|
||||
std::optional<float> angle; // [in radians] form -Pi to Pi
|
||||
|
||||
bool operator==(const Style &other) const
|
||||
{
|
||||
bool case0 = EmbossStyle::operator==(other);
|
||||
bool case1 = projection == other.projection;
|
||||
return case0 && case1 &&
|
||||
distance == other.distance &&
|
||||
angle == other.angle;
|
||||
}
|
||||
|
||||
// cache for view font name with maximal width in imgui
|
||||
std::string truncated_name;
|
||||
|
||||
// visualization of style
|
||||
std::optional<StyleImage> image;
|
||||
};
|
||||
using Styles = std::vector<Style>;
|
||||
|
||||
// check if exist selected font style in manager
|
||||
bool is_active_font();
|
||||
|
||||
// Limits for imgui loaded font size
|
||||
// Value out of limits is crop
|
||||
static float min_imgui_font_size;
|
||||
static float max_imgui_font_size;
|
||||
static float get_imgui_font_size(const FontProp &prop, const Slic3r::Emboss::FontFile &file, double scale);
|
||||
|
||||
private:
|
||||
// function to create default style list
|
||||
std::function<EmbossStyles()> m_create_default_styles;
|
||||
// keep language dependent glyph range
|
||||
const ImWchar *m_imgui_init_glyph_range;
|
||||
|
||||
/// <summary>
|
||||
/// Cache data from style to reduce amount of:
|
||||
/// 1) loading font from file
|
||||
/// 2) Create atlas of symbols for imgui
|
||||
/// 3) Keep loaded(and modified by style) glyphs from font
|
||||
/// </summary>
|
||||
struct StyleCache
|
||||
{
|
||||
// share font file data with emboss job thread
|
||||
Slic3r::Emboss::FontFileWithCache font_file = {};
|
||||
|
||||
// must live same as imgui_font inside of atlas
|
||||
ImVector<ImWchar> ranges = {};
|
||||
|
||||
// Keep only actual style in atlas
|
||||
ImFontAtlas atlas = {};
|
||||
|
||||
// wx widget font
|
||||
wxFont wx_font = {};
|
||||
|
||||
// cache for view font name with maximal width in imgui
|
||||
std::string truncated_name;
|
||||
|
||||
// actual used font item
|
||||
Style style = {};
|
||||
|
||||
// cache for stored wx font to not create every frame
|
||||
wxFont stored_wx_font = {};
|
||||
|
||||
// index into m_styles
|
||||
size_t style_index = std::numeric_limits<size_t>::max();
|
||||
|
||||
} m_style_cache;
|
||||
|
||||
// Privat member
|
||||
Styles m_styles;
|
||||
AppConfig *m_app_config = nullptr;
|
||||
size_t m_last_style_index = std::numeric_limits<size_t>::max();
|
||||
|
||||
/// <summary>
|
||||
/// Keep data needed to create Font Style Images in Job
|
||||
/// </summary>
|
||||
struct StyleImagesData
|
||||
{
|
||||
struct Item
|
||||
{
|
||||
Slic3r::Emboss::FontFileWithCache font;
|
||||
std::string text;
|
||||
FontProp prop;
|
||||
};
|
||||
using Items = std::vector<Item>;
|
||||
|
||||
// Keep styles to render
|
||||
Items styles;
|
||||
// Maximal width and height in pixels of image
|
||||
Vec2i32 max_size;
|
||||
// Text to render
|
||||
std::string text;
|
||||
|
||||
/// <summary>
|
||||
/// Result of job
|
||||
/// </summary>
|
||||
struct StyleImages
|
||||
{
|
||||
// vector of inputs
|
||||
StyleImagesData::Items styles;
|
||||
// job output
|
||||
std::vector<StyleImage> images;
|
||||
};
|
||||
|
||||
// place to store result in main thread in Finalize
|
||||
std::shared_ptr<StyleImages> result;
|
||||
|
||||
// pixel per milimeter (scaled DPI)
|
||||
double ppm;
|
||||
};
|
||||
std::shared_ptr<StyleImagesData::StyleImages> m_temp_style_images = nullptr;
|
||||
bool m_exist_style_images = false;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_EmbossStyleManager_hpp_
|
||||
@@ -1,7 +1,3 @@
|
||||
///|/ Copyright (c) Prusa Research 2021 - 2022 Filip Sykala @Jony01
|
||||
///|/
|
||||
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
|
||||
///|/
|
||||
#include "FontConfigHelp.hpp"
|
||||
|
||||
#ifdef EXIST_FONT_CONFIG_INCLUDE
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
///|/ Copyright (c) Prusa Research 2021 - 2022 Filip Sykala @Jony01
|
||||
///|/
|
||||
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
|
||||
///|/
|
||||
#ifndef slic3r_FontConfigHelp_hpp_
|
||||
#define slic3r_FontConfigHelp_hpp_
|
||||
|
||||
@@ -11,7 +7,7 @@
|
||||
|
||||
#ifdef EXIST_FONT_CONFIG_INCLUDE
|
||||
#include <wx/font.h>
|
||||
namespace Slic3r::GUI {
|
||||
namespace Slic3r::GUI {
|
||||
|
||||
/// <summary>
|
||||
/// initialize font config
|
||||
@@ -20,7 +16,7 @@ namespace Slic3r::GUI {
|
||||
/// https://github.com/utelle/wxpdfdoc/blob/5bdcdb9953327d06dc50ec312685ccd9bc8400e0/src/pdffontmanager.cpp
|
||||
/// </summary>
|
||||
/// <param name="font">Wx descriptor of font</param>
|
||||
/// <param name="reload_fonts">flag to reinitialize font list</param>
|
||||
/// <param name="reload_fonts">flag to reinitialize font list</param>
|
||||
/// <returns>Font FilePath by FontConfig</returns>
|
||||
std::string get_font_path(const wxFont &font, bool reload_fonts = false);
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ std::string get_file_path(const wxFont &font)
|
||||
const wxString &path = uri.GetPath();
|
||||
wxString path_unescaped = wxURI::Unescape(path);
|
||||
std::string path_str = path_unescaped.ToUTF8().data();
|
||||
BOOST_LOG_TRIVIAL(trace) << "input uri(" << file_uri.c_str() << ") convert to path(" << path.c_str() << ") string(" << path_str << ").";
|
||||
//BOOST_LOG_TRIVIAL(trace) << "input uri(" << file_uri.c_str() << ") convert to path(" << path.c_str() << ") string(" << path_str << ").";
|
||||
return path_str;
|
||||
}
|
||||
#endif // __APPLE__
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "slic3r/Utils/QDTUtil.hpp"
|
||||
#include "NetworkAgent.hpp"
|
||||
|
||||
|
||||
@@ -56,8 +57,6 @@ func_stop_subscribe NetworkAgent::stop_subscribe_ptr = nullptr;
|
||||
func_add_subscribe NetworkAgent::add_subscribe_ptr = nullptr;
|
||||
func_del_subscribe NetworkAgent::del_subscribe_ptr = nullptr;
|
||||
func_enable_multi_machine NetworkAgent::enable_multi_machine_ptr = nullptr;
|
||||
func_start_device_subscribe NetworkAgent::start_device_subscribe_ptr = nullptr;
|
||||
func_stop_device_subscribe NetworkAgent::stop_device_subscribe_ptr = nullptr;
|
||||
func_send_message NetworkAgent::send_message_ptr = nullptr;
|
||||
func_connect_printer NetworkAgent::connect_printer_ptr = nullptr;
|
||||
func_disconnect_printer NetworkAgent::disconnect_printer_ptr = nullptr;
|
||||
@@ -135,7 +134,7 @@ NetworkAgent::NetworkAgent(std::string log_dir)
|
||||
if (create_agent_ptr) {
|
||||
network_agent = create_agent_ptr(log_dir);
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", this %1%, network_agent=%2%, create_agent_ptr=%3%, log_dir=%4%")%this %network_agent %create_agent_ptr %log_dir;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", line %1%, network_agent=%2%, create_agent_ptr=%3%")%__LINE__ %network_agent %create_agent_ptr;
|
||||
}
|
||||
|
||||
NetworkAgent::~NetworkAgent()
|
||||
@@ -144,7 +143,7 @@ NetworkAgent::~NetworkAgent()
|
||||
if (network_agent && destroy_agent_ptr) {
|
||||
ret = destroy_agent_ptr(network_agent);
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", this %1%, network_agent=%2%, destroy_agent_ptr=%3%, ret %4%")%this %network_agent %destroy_agent_ptr %ret;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", line %1%, network_agent=%2%, destroy_agent_ptr=%3%, ret %4%")%__LINE__ %network_agent %destroy_agent_ptr %ret;
|
||||
}
|
||||
|
||||
std::string NetworkAgent::get_libpath_in_current_directory(std::string library_name)
|
||||
@@ -154,7 +153,7 @@ std::string NetworkAgent::get_libpath_in_current_directory(std::string library_n
|
||||
wchar_t file_name[512];
|
||||
DWORD ret = GetModuleFileNameW(NULL, file_name, 512);
|
||||
if (!ret) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", GetModuleFileNameW return error, can not Load Library for %1%") % library_name;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", GetModuleFileNameW return error, can not Load Library for %1%") %library_name;
|
||||
return lib_path;
|
||||
}
|
||||
int size_needed = ::WideCharToMultiByte(0, 0, file_name, wcslen(file_name), nullptr, 0, nullptr, nullptr);
|
||||
@@ -205,7 +204,7 @@ int NetworkAgent::initialize_network_module(bool using_backup)
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", can not get path in current directory for %1%") % QIDI_NETWORK_LIBRARY;
|
||||
return -1;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", current path %1%")%library_path;
|
||||
//BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", current path %1%")%library_path;
|
||||
memset(lib_wstr, 0, sizeof(lib_wstr));
|
||||
::MultiByteToWideChar(CP_UTF8, NULL, library_path.c_str(), strlen(library_path.c_str())+1, lib_wstr, sizeof(lib_wstr) / sizeof(lib_wstr[0]));
|
||||
netwoking_module = LoadLibrary(lib_wstr);
|
||||
@@ -216,7 +215,7 @@ int NetworkAgent::initialize_network_module(bool using_backup)
|
||||
#else
|
||||
library = plugin_folder.string() + "/" + std::string("lib") + std::string(QIDI_NETWORK_LIBRARY) + ".so";
|
||||
#endif
|
||||
printf("loading network module at %s\n", library.c_str());
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", line %1%, loading network module, using_backup %2%\n")%__LINE__ %using_backup;
|
||||
netwoking_module = dlopen( library.c_str(), RTLD_LAZY);
|
||||
if (!netwoking_module) {
|
||||
/*#if defined(__WXMAC__)
|
||||
@@ -227,16 +226,16 @@ int NetworkAgent::initialize_network_module(bool using_backup)
|
||||
//netwoking_module = dlopen( library.c_str(), RTLD_LAZY);
|
||||
char* dll_error = dlerror();
|
||||
printf("error, dlerror is %s\n", dll_error);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", error, dlerror is %1%")%dll_error;
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", error, dlerror is %1%")%dll_error;
|
||||
}
|
||||
printf("after dlopen, network_module is %p\n", netwoking_module);
|
||||
#endif
|
||||
|
||||
if (!netwoking_module) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", can not Load Library for %1%")%library;
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", line %1%, can not Load Library, using_backup %2%\n")%__LINE__ %using_backup;
|
||||
return -1;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", successfully loaded library %1%, module %2%")%library %netwoking_module;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", line %1%, successfully loaded library, using_backup %2%, module %3%")%__LINE__ %using_backup %netwoking_module;
|
||||
|
||||
//load the functions
|
||||
check_debug_consistent_ptr = reinterpret_cast<func_check_debug_consistent>(get_network_function("qidi_network_check_debug_consistent"));
|
||||
@@ -268,8 +267,6 @@ int NetworkAgent::initialize_network_module(bool using_backup)
|
||||
add_subscribe_ptr = reinterpret_cast<func_add_subscribe>(get_network_function("qidi_network_add_subscribe"));
|
||||
del_subscribe_ptr = reinterpret_cast<func_del_subscribe>(get_network_function("qidi_network_del_subscribe"));
|
||||
enable_multi_machine_ptr = reinterpret_cast<func_enable_multi_machine>(get_network_function("qidi_network_enable_multi_machine"));
|
||||
start_device_subscribe_ptr = reinterpret_cast<func_start_device_subscribe>(get_network_function("qidi_network_start_device_subscribe"));
|
||||
stop_device_subscribe_ptr = reinterpret_cast<func_stop_device_subscribe>(get_network_function("qidi_network_stop_device_subscribe"));
|
||||
send_message_ptr = reinterpret_cast<func_send_message>(get_network_function("qidi_network_send_message"));
|
||||
connect_printer_ptr = reinterpret_cast<func_connect_printer>(get_network_function("qidi_network_connect_printer"));
|
||||
disconnect_printer_ptr = reinterpret_cast<func_disconnect_printer>(get_network_function("qidi_network_disconnect_printer"));
|
||||
@@ -494,7 +491,7 @@ void* NetworkAgent::get_qidi_source_entry()
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", can not get path in current directory for %1%") % QIDI_SOURCE_LIBRARY;
|
||||
return source_module;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", current path %1%")%library_path;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", line %1%")%__LINE__;
|
||||
memset(lib_wstr, 0, sizeof(lib_wstr));
|
||||
::MultiByteToWideChar(CP_UTF8, NULL, library_path.c_str(), strlen(library_path.c_str()) + 1, lib_wstr, sizeof(lib_wstr) / sizeof(lib_wstr[0])); //1.9.5
|
||||
source_module = LoadLibrary(lib_wstr);
|
||||
@@ -807,7 +804,7 @@ int NetworkAgent::add_subscribe(std::vector<std::string> dev_list)
|
||||
if (network_agent && add_subscribe_ptr) {
|
||||
ret = add_subscribe_ptr(network_agent, dev_list);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") % network_agent % ret;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") %network_agent %ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -818,7 +815,7 @@ int NetworkAgent::del_subscribe(std::vector<std::string> dev_list)
|
||||
if (network_agent && del_subscribe_ptr) {
|
||||
ret = del_subscribe_ptr(network_agent, dev_list);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") % network_agent % ret;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") %network_agent %ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -830,35 +827,14 @@ void NetworkAgent::enable_multi_machine(bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
int NetworkAgent::start_device_subscribe()
|
||||
{
|
||||
int ret = 0;
|
||||
if (network_agent && start_device_subscribe_ptr) {
|
||||
ret = start_device_subscribe_ptr(network_agent);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") % network_agent % ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int NetworkAgent::stop_device_subscribe()
|
||||
{
|
||||
int ret = 0;
|
||||
if (network_agent && stop_device_subscribe_ptr) {
|
||||
ret = stop_device_subscribe_ptr(network_agent);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") % network_agent % ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int NetworkAgent::send_message(std::string dev_id, std::string json_str, int qos, int flag)
|
||||
{
|
||||
int ret = 0;
|
||||
if (network_agent && send_message_ptr) {
|
||||
ret = send_message_ptr(network_agent, dev_id, json_str, qos, flag);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, dev_id=%3%, json_str=%4%, qos=%5%")%network_agent %ret %dev_id %json_str %qos;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ <<
|
||||
boost::format(" error: network_agent=%1%, ret=%2%, dev_id=%3%, json_str=%4%, qos=%5%") %network_agent %ret %QDTCrossTalk::Crosstalk_DevId(dev_id) %json_str %qos;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -869,8 +845,8 @@ int NetworkAgent::connect_printer(std::string dev_id, std::string dev_ip, std::s
|
||||
if (network_agent && connect_printer_ptr) {
|
||||
ret = connect_printer_ptr(network_agent, dev_id, dev_ip, username, password, use_ssl);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << (boost::format(" error: network_agent=%1%, ret=%2%, dev_id=%3%, dev_ip=%4%, username=%5%, password=%6%")
|
||||
% network_agent % ret % dev_id % dev_ip % username % password).str();
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ <<
|
||||
(boost::format(" error: network_agent=%1%, ret=%2%, dev_id=%3%, dev_ip=%4%, username=%5%, password=%6%") %network_agent %ret %QDTCrossTalk::Crosstalk_DevId(dev_id) %QDTCrossTalk::Crosstalk_DevIP(dev_ip) %username %password).str();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -881,7 +857,7 @@ int NetworkAgent::disconnect_printer()
|
||||
if (network_agent && disconnect_printer_ptr) {
|
||||
ret = disconnect_printer_ptr(network_agent);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%")%network_agent %ret;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") %network_agent %ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -892,8 +868,7 @@ int NetworkAgent::send_message_to_printer(std::string dev_id, std::string json_s
|
||||
if (network_agent && send_message_to_printer_ptr) {
|
||||
ret = send_message_to_printer_ptr(network_agent, dev_id, json_str, qos, flag);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, dev_id=%3%, json_str=%4%, qos=%5%")
|
||||
%network_agent %ret %dev_id %json_str %qos;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, dev_id=%3%, json_str=%4%, qos=%5%") %network_agent %ret %QDTCrossTalk::Crosstalk_DevId(dev_id) %json_str %qos;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -904,7 +879,7 @@ int NetworkAgent::check_cert()
|
||||
if (network_agent && check_cert_ptr) {
|
||||
ret = check_cert_ptr(network_agent);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") % network_agent % ret;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") %network_agent %ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -932,7 +907,7 @@ int NetworkAgent::change_user(std::string user_info)
|
||||
if (network_agent && change_user_ptr) {
|
||||
ret = change_user_ptr(network_agent, user_info);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, user_info=%3%")%network_agent %ret %user_info ;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") %network_agent %ret ;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -952,7 +927,7 @@ int NetworkAgent::user_logout(bool request)
|
||||
if (network_agent && user_logout_ptr) {
|
||||
ret = user_logout_ptr(network_agent, request);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%")%network_agent %ret;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") %network_agent %ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1026,8 +1001,8 @@ int NetworkAgent::ping_bind(std::string ping_code)
|
||||
if (network_agent && ping_bind_ptr) {
|
||||
ret = ping_bind_ptr(network_agent, ping_code);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, pin code=%3%")
|
||||
% network_agent % ret % ping_code;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%")
|
||||
% network_agent % ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1038,8 +1013,7 @@ int NetworkAgent::bind_detect(std::string dev_ip, std::string sec_link, detectRe
|
||||
if (network_agent && bind_detect_ptr) {
|
||||
ret = bind_detect_ptr(network_agent, dev_ip, sec_link, detect);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, dev_ip=%3%")
|
||||
% network_agent % ret % dev_ip;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, dev_ip=%3%") %network_agent %ret %QDTCrossTalk::Crosstalk_DevIP(dev_ip);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1062,8 +1036,7 @@ int NetworkAgent::bind(std::string dev_ip, std::string dev_id, std::string sec_l
|
||||
if (network_agent && bind_ptr) {
|
||||
ret = bind_ptr(network_agent, dev_ip, dev_id, sec_link, timezone, improved, update_fn);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, dev_ip=%3%, timezone=%4%")
|
||||
%network_agent %ret %dev_ip %timezone;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, dev_ip=%3%, timezone=%4%") %network_agent %ret %QDTCrossTalk::Crosstalk_DevIP(dev_ip) %timezone;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1074,7 +1047,7 @@ int NetworkAgent::unbind(std::string dev_id)
|
||||
if (network_agent && unbind_ptr) {
|
||||
ret = unbind_ptr(network_agent, dev_id);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, user_info=%3%")%network_agent %ret %dev_id ;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") %network_agent %ret ;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1103,7 +1076,7 @@ int NetworkAgent::set_user_selected_machine(std::string dev_id)
|
||||
if (network_agent && set_user_selected_machine_ptr) {
|
||||
ret = set_user_selected_machine_ptr(network_agent, dev_id);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, user_info=%3%")%network_agent %ret %dev_id ;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, user_info=%3%") %network_agent %ret %QDTCrossTalk::Crosstalk_DevId(dev_id);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1113,8 +1086,8 @@ int NetworkAgent::start_print(PrintParams params, OnUpdateStatusFn update_fn, Wa
|
||||
int ret = 0;
|
||||
if (network_agent && start_print_ptr) {
|
||||
ret = start_print_ptr(network_agent, params, update_fn, cancel_fn, wait_fn);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" : network_agent=%1%, ret=%2%, dev_id=%3%, task_name=%4%, project_name=%5%")
|
||||
%network_agent %ret %params.dev_id %params.task_name %params.project_name;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__
|
||||
<< boost::format(" : network_agent=%1%, ret=%2%, dev_id=%3%, task_name=%4%, project_name=%5%") %network_agent %ret %QDTCrossTalk::Crosstalk_DevId(params.dev_id) %params.task_name %params.project_name;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1124,8 +1097,7 @@ int NetworkAgent::start_local_print_with_record(PrintParams params, OnUpdateStat
|
||||
int ret = 0;
|
||||
if (network_agent && start_local_print_with_record_ptr) {
|
||||
ret = start_local_print_with_record_ptr(network_agent, params, update_fn, cancel_fn, wait_fn);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" : network_agent=%1%, ret=%2%, dev_id=%3%, task_name=%4%, project_name=%5%")
|
||||
%network_agent %ret %params.dev_id %params.task_name %params.project_name;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" : network_agent=%1%, ret=%2%, dev_id=%3%, task_name=%4%, project_name=%5%") %network_agent %ret %QDTCrossTalk::Crosstalk_DevId(params.dev_id) %params.task_name %params.project_name;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1135,8 +1107,7 @@ int NetworkAgent::start_send_gcode_to_sdcard(PrintParams params, OnUpdateStatusF
|
||||
int ret = 0;
|
||||
if (network_agent && start_send_gcode_to_sdcard_ptr) {
|
||||
ret = start_send_gcode_to_sdcard_ptr(network_agent, params, update_fn, cancel_fn, wait_fn);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" : network_agent=%1%, ret=%2%, dev_id=%3%, task_name=%4%, project_name=%5%")
|
||||
% network_agent % ret % params.dev_id % params.task_name % params.project_name;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" : network_agent=%1%, ret=%2%, dev_id=%3%, task_name=%4%, project_name=%5%") %network_agent %ret %QDTCrossTalk::Crosstalk_DevId(params.dev_id) %params.task_name %params.project_name;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1146,8 +1117,7 @@ int NetworkAgent::start_local_print(PrintParams params, OnUpdateStatusFn update_
|
||||
int ret = 0;
|
||||
if (network_agent && start_local_print_ptr) {
|
||||
ret = start_local_print_ptr(network_agent, params, update_fn, cancel_fn);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" : network_agent=%1%, ret=%2%, dev_id=%3%, task_name=%4%, project_name=%5%")
|
||||
%network_agent %ret %params.dev_id %params.task_name %params.project_name;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" : network_agent=%1%, ret=%2%, dev_id=%3%, task_name=%4%, project_name=%5%") %network_agent %ret %QDTCrossTalk::Crosstalk_DevId(params.dev_id) %params.task_name %params.project_name;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1157,8 +1127,7 @@ int NetworkAgent::start_sdcard_print(PrintParams params, OnUpdateStatusFn update
|
||||
int ret = 0;
|
||||
if (network_agent && start_sdcard_print_ptr) {
|
||||
ret = start_sdcard_print_ptr(network_agent, params, update_fn, cancel_fn);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" : network_agent=%1%, ret=%2%, dev_id=%3%, task_name=%4%, project_name=%5%")
|
||||
% network_agent % ret % params.dev_id % params.task_name % params.project_name;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" : network_agent=%1%, ret=%2%, dev_id=%3%, task_name=%4%, project_name=%5%") %network_agent %ret %QDTCrossTalk::Crosstalk_DevId(params.dev_id) %params.task_name %params.project_name;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1274,7 +1243,7 @@ int NetworkAgent::get_user_print_info(unsigned int* http_code, std::string* http
|
||||
int ret = 0;
|
||||
if (network_agent && get_user_print_info_ptr) {
|
||||
ret = get_user_print_info_ptr(network_agent, http_code, http_body);
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, http_code=%3%, http_body=%4%")%network_agent %ret %(*http_code) %(*http_body);
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, http_code=%3%")%network_agent %ret %(*http_code);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1284,7 +1253,7 @@ int NetworkAgent::get_user_tasks(TaskQueryParams params, std::string* http_body)
|
||||
int ret = 0;
|
||||
if (network_agent && get_user_tasks_ptr) {
|
||||
ret = get_user_tasks_ptr(network_agent, params, http_body);
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, http_body=%3%") % network_agent % ret % (*http_body);
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") %network_agent %ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1294,8 +1263,7 @@ int NetworkAgent::get_printer_firmware(std::string dev_id, unsigned* http_code,
|
||||
int ret = 0;
|
||||
if (network_agent && get_printer_firmware_ptr) {
|
||||
ret = get_printer_firmware_ptr(network_agent, dev_id, http_code, http_body);
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" : network_agent=%1%, ret=%2%, dev_id=%3%, http_code=%4%, http_body=%5%")
|
||||
%network_agent %ret %dev_id %(*http_code) %(*http_body);
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" : network_agent=%1%, ret=%2%, dev_id=%3%") %network_agent %ret %QDTCrossTalk::Crosstalk_DevId(dev_id);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1361,8 +1329,7 @@ int NetworkAgent::query_bind_status(std::vector<std::string> query_list, unsigne
|
||||
if (network_agent && query_bind_status_ptr) {
|
||||
ret = query_bind_status_ptr(network_agent, query_list, http_code, http_body);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, http_code=%3%, http_body=%4%")
|
||||
%network_agent %ret%(*http_code) %(*http_body);
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, http_code=%3%") %network_agent %ret %(*http_code);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1372,7 +1339,7 @@ int NetworkAgent::modify_printer_name(std::string dev_id, std::string dev_name)
|
||||
int ret = 0;
|
||||
if (network_agent && modify_printer_name_ptr) {
|
||||
ret = modify_printer_name_ptr(network_agent, dev_id, dev_name);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" : network_agent=%1%, ret=%2%, dev_id=%3%, dev_name=%4%")%network_agent %ret %dev_id %dev_name;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" : network_agent=%1%, ret=%2%, dev_id=%3%, dev_name=%4%") %network_agent %ret %QDTCrossTalk::Crosstalk_DevId(dev_id) %dev_name;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1383,7 +1350,7 @@ int NetworkAgent::get_camera_url(std::string dev_id, std::function<void(std::str
|
||||
if (network_agent && get_camera_url_ptr) {
|
||||
ret = get_camera_url_ptr(network_agent, dev_id, callback);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, dev_id=%3%")%network_agent %ret %dev_id;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%, dev_id=%3%") %network_agent %ret %QDTCrossTalk::Crosstalk_DevId(dev_id);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -36,8 +36,6 @@ typedef int (*func_stop_subscribe)(void *agent, std::string module);
|
||||
typedef int (*func_add_subscribe)(void *agent, std::vector<std::string> dev_list);
|
||||
typedef int (*func_del_subscribe)(void *agent, std::vector<std::string> dev_list);
|
||||
typedef void (*func_enable_multi_machine)(void *agent, bool enable);
|
||||
typedef int (*func_start_device_subscribe)(void* agent);
|
||||
typedef int (*func_stop_device_subscribe)(void* agent);
|
||||
typedef int (*func_send_message)(void *agent, std::string dev_id, std::string json_str, int qos, int flag);
|
||||
typedef int (*func_connect_printer)(void *agent, std::string dev_id, std::string dev_ip, std::string username, std::string password, bool use_ssl);
|
||||
typedef int (*func_disconnect_printer)(void *agent);
|
||||
@@ -155,8 +153,6 @@ public:
|
||||
int add_subscribe(std::vector<std::string> dev_list);
|
||||
int del_subscribe(std::vector<std::string> dev_list);
|
||||
void enable_multi_machine(bool enable);
|
||||
int start_device_subscribe();
|
||||
int stop_device_subscribe();
|
||||
int send_message(std::string dev_id, std::string json_str, int qos, int flag);
|
||||
int connect_printer(std::string dev_id, std::string dev_ip, std::string username, std::string password, bool use_ssl);
|
||||
int disconnect_printer();
|
||||
@@ -264,8 +260,6 @@ private:
|
||||
static func_add_subscribe add_subscribe_ptr;
|
||||
static func_del_subscribe del_subscribe_ptr;
|
||||
static func_enable_multi_machine enable_multi_machine_ptr;
|
||||
static func_start_device_subscribe start_device_subscribe_ptr;
|
||||
static func_stop_device_subscribe stop_device_subscribe_ptr;
|
||||
static func_send_message send_message_ptr;
|
||||
static func_connect_printer connect_printer_ptr;
|
||||
static func_disconnect_printer disconnect_printer_ptr;
|
||||
|
||||
@@ -126,11 +126,9 @@ bool OctoPrint::test(wxString &msg) const
|
||||
bool res = true;
|
||||
auto url = make_url("api/version");
|
||||
|
||||
// BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url;
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("Before uploading, %1%:Test at: %2%") % name % url;
|
||||
auto http = Http::get(std::move(url));
|
||||
set_auth(http);
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("Before uploading, %1%:Test at: %2%") % name % url;
|
||||
http.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting version: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
|
||||
res = false;
|
||||
@@ -333,11 +331,9 @@ std::string OctoPrint::get_status(wxString& msg) const
|
||||
std::string print_state = "standby";
|
||||
auto url = make_url("printer/objects/query?print_stats=state");
|
||||
|
||||
// BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url;
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url;
|
||||
auto http = Http::get(std::move(url));
|
||||
set_auth(http);
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get status at: %2%") % name % url;
|
||||
//y36
|
||||
http.timeout_connect(4)
|
||||
.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
@@ -406,11 +402,9 @@ float OctoPrint::get_progress(wxString& msg) const
|
||||
bool res = true;
|
||||
auto url = make_url("printer/objects/query?display_status=progress");
|
||||
float process = 0;
|
||||
// BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url;
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url;
|
||||
auto http = Http::get(std::move(url));
|
||||
set_auth(http);
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get progress at: %2%") % name % url;
|
||||
http.timeout_connect(4)
|
||||
.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
if (status == 404)
|
||||
@@ -537,11 +531,9 @@ std::pair<std::string, float> OctoPrint::get_status_progress(wxString& msg) cons
|
||||
float process = 0;
|
||||
auto url = make_url("printer/objects/query?print_stats=state&display_status=progress");
|
||||
|
||||
//BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url;
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("Get status progress, the url is %1%") % url;
|
||||
auto http = Http::get(std::move(url));
|
||||
set_auth(http);
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("Get status progress, the url is %1%") % url;
|
||||
// B64 //y6
|
||||
http.timeout_connect(4)
|
||||
.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
@@ -706,8 +698,7 @@ bool QIDILink::get_storage(wxArrayString& storage_path, wxArrayString& storage_n
|
||||
};
|
||||
std::vector<StorageInfo> storage;
|
||||
|
||||
// BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get storage at: %2%") % name % url;
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get storage at: %2%") % name % url;
|
||||
wxString wlang = GUI::wxGetApp().current_language_code();
|
||||
std::string lang = GUI::format(wlang.SubString(0, 1));
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/string_file.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
@@ -171,7 +170,7 @@ struct Update
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const Update &self)
|
||||
{
|
||||
os << "Update(" << self.source.string() << " -> " << self.target.string() << ')';
|
||||
os << "Update(" << PathSanitizer::sanitize(self.source.string()) << " -> " << PathSanitizer::sanitize(self.target.string()) << ')';
|
||||
return os;
|
||||
}
|
||||
};
|
||||
@@ -320,8 +319,8 @@ bool PresetUpdater::priv::get_file(const std::string &url, const fs::path &targe
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << format("[QDS Updater]download file `%1%`, stored to `%2%`, tmp path `%3%`",
|
||||
url,
|
||||
target_path.string(),
|
||||
tmp_path.string());
|
||||
PathSanitizer::sanitize(target_path),
|
||||
PathSanitizer::sanitize(tmp_path));
|
||||
|
||||
Slic3r::Http::get(url)
|
||||
.on_progress([this](Slic3r::Http::Progress, bool &cancel_http) {
|
||||
@@ -386,11 +385,11 @@ bool PresetUpdater::priv::extract_file(const fs::path &source_path, const fs::pa
|
||||
{
|
||||
res = mz_zip_reader_extract_to_file(&archive, stat.m_file_index, dest_file.c_str(), 0);
|
||||
if (!res) {
|
||||
BOOST_LOG_TRIVIAL(error) << "[QDT Updater]extract file "<<stat.m_filename<<" to dest "<<dest_file<<" failed";
|
||||
BOOST_LOG_TRIVIAL(error) << "[QDT Updater]extract file " << stat.m_filename << " to dest " << PathSanitizer::sanitize(dest_file) << " failed";
|
||||
close_zip_reader(&archive);
|
||||
return res;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << "[QDT Updater]successfully extract file " << stat.m_file_index << " to "<<dest_file;
|
||||
BOOST_LOG_TRIVIAL(info) << "[QDT Updater]successfully extract file " << stat.m_file_index << " to " << PathSanitizer::sanitize(dest_file);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -648,7 +647,7 @@ bool PresetUpdater::priv::sync_resources(std::string http_url, std::map<std::str
|
||||
for (auto sub : resource.sub_caches) {
|
||||
if (fs::exists(cache_path / sub)) {
|
||||
fs::remove_all(cache_path / sub);
|
||||
BOOST_LOG_TRIVIAL(info) << "[QDT Updater]remove cache path " << (cache_path / sub).string();
|
||||
BOOST_LOG_TRIVIAL(info) << "[QDT Updater]remove cache path " << PathSanitizer::sanitize((cache_path / sub).string());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -657,14 +656,14 @@ bool PresetUpdater::priv::sync_resources(std::string http_url, std::map<std::str
|
||||
remove_config_files(resource.vendor, PRESET_SUBPATH);
|
||||
}
|
||||
// extract the file downloaded
|
||||
BOOST_LOG_TRIVIAL(info) << "[QDT Updater]start to unzip the downloaded file " << cache_file_path << " to "<<cache_path;
|
||||
BOOST_LOG_TRIVIAL(info) << "[QDT Updater]start to unzip the downloaded file " << PathSanitizer::sanitize(cache_file_path) << " to "<< PathSanitizer::sanitize(cache_path);
|
||||
if (!fs::exists(cache_path))
|
||||
fs::create_directories(cache_path);
|
||||
if (!extract_file(cache_file_path, cache_path)) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "[QDT Updater]extract resource " << resource_it.first << " failed, path: " << cache_file_path;
|
||||
BOOST_LOG_TRIVIAL(warning) << "[QDT Updater]extract resource " << resource_it.first << " failed, path: " << PathSanitizer::sanitize(cache_file_path);
|
||||
continue;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << "[QDT Updater]finished unzip the downloaded file " << cache_file_path;
|
||||
BOOST_LOG_TRIVIAL(info) << "[QDT Updater]finished unzip the downloaded file " << PathSanitizer::sanitize(cache_file_path);
|
||||
|
||||
// save the description to disk
|
||||
if (changelog_file.empty())
|
||||
@@ -1067,9 +1066,9 @@ void PresetUpdater::priv::sync_tooltip(std::string http_url, std::string languag
|
||||
fs::path cache_root = fs::path(data_dir()) / "resources/tooltip";
|
||||
try {
|
||||
auto vf = cache_root / "common" / "version";
|
||||
if (fs::exists(vf)) fs::load_string_file(vf, common_version);
|
||||
if (fs::exists(vf)) Slic3r::load_string_file(vf, common_version);
|
||||
vf = cache_root / language / "version";
|
||||
if (fs::exists(vf)) fs::load_string_file(vf, language_version);
|
||||
if (fs::exists(vf)) Slic3r::load_string_file(vf, language_version);
|
||||
} catch (...) {}
|
||||
std::map<std::string, Resource> resources
|
||||
{
|
||||
@@ -1154,11 +1153,11 @@ void PresetUpdater::priv::sync_plugins(std::string http_url, std::string plugin_
|
||||
if (need_delete_cache) {
|
||||
if (fs::exists(cache_plugin_folder))
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "[remove_old_networking_plugins] remove the plugins directory "<<cache_plugin_folder.string();
|
||||
BOOST_LOG_TRIVIAL(info) << "[remove_old_networking_plugins] remove the plugins directory " << PathSanitizer::sanitize(cache_plugin_folder);
|
||||
try {
|
||||
fs::remove_all(cache_plugin_folder);
|
||||
} catch (...) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed removing the plugins file " << cache_plugin_folder.string();
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed removing the plugins file " << PathSanitizer::sanitize(cache_plugin_folder);
|
||||
}
|
||||
}
|
||||
//create this directory again
|
||||
@@ -1227,13 +1226,13 @@ void PresetUpdater::priv::sync_printer_config(std::string http_url)
|
||||
|
||||
try {
|
||||
if (fs::exists(config_folder / "version.txt")) {
|
||||
fs::load_string_file(config_folder / "version.txt", curr_version);
|
||||
Slic3r::load_string_file(config_folder / "version.txt", curr_version);
|
||||
boost::algorithm::trim(curr_version);
|
||||
}
|
||||
} catch (...) {}
|
||||
try {
|
||||
if (fs::exists(cache_folder / "version.txt")) {
|
||||
fs::load_string_file(cache_folder / "version.txt", cached_version);
|
||||
Slic3r::load_string_file(cache_folder / "version.txt", cached_version);
|
||||
boost::algorithm::trim(cached_version);
|
||||
}
|
||||
} catch (...) {}
|
||||
@@ -1273,7 +1272,7 @@ void PresetUpdater::priv::sync_printer_config(std::string http_url)
|
||||
bool result = false;
|
||||
try {
|
||||
if (fs::exists(cache_folder / "version.txt")) {
|
||||
fs::load_string_file(cache_folder / "version.txt", cached_version);
|
||||
Slic3r::load_string_file(cache_folder / "version.txt", cached_version);
|
||||
boost::algorithm::trim(cached_version);
|
||||
result = true;
|
||||
}
|
||||
@@ -1404,13 +1403,13 @@ Updates PresetUpdater::priv::get_printer_config_updates(bool update) const
|
||||
std::string resc_version;
|
||||
try {
|
||||
if (fs::exists(resc_folder / "version.txt")) {
|
||||
fs::load_string_file(resc_folder / "version.txt", resc_version);
|
||||
Slic3r::load_string_file(resc_folder / "version.txt", resc_version);
|
||||
boost::algorithm::trim(resc_version);
|
||||
}
|
||||
} catch (...) {}
|
||||
try {
|
||||
if (fs::exists(config_folder / "version.txt")) {
|
||||
fs::load_string_file(config_folder / "version.txt", curr_version);
|
||||
Slic3r::load_string_file(config_folder / "version.txt", curr_version);
|
||||
boost::algorithm::trim(curr_version);
|
||||
}
|
||||
} catch (...) {}
|
||||
|
||||
@@ -180,12 +180,6 @@ void PrintHostJobQueue::priv::bg_thread_main()
|
||||
|
||||
source_to_remove = job.upload_data.source_path;
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("PrintHostJobQueue/bg_thread: Received job: [%1%]: `%2%` -> `%3%`, cancelled: %4%")
|
||||
% job_id
|
||||
% job.upload_data.upload_path
|
||||
% job.printhost->get_host()
|
||||
% job.cancelled;
|
||||
|
||||
if (! job.cancelled) {
|
||||
perform_job(std::move(job));
|
||||
}
|
||||
|
||||
173
src/slic3r/Utils/QDTUtil.cpp
Normal file
173
src/slic3r/Utils/QDTUtil.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
#include "QDTUtil.hpp"
|
||||
#include "libslic3r_version.h"
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#if QDT_RELEASE_TO_PUBLIC
|
||||
static bool s_enable_cross_talk = true;
|
||||
#else
|
||||
static bool s_enable_cross_talk = false;
|
||||
#endif
|
||||
|
||||
namespace Slic3r
|
||||
{
|
||||
|
||||
std::string QDTCrossTalk::Crosstalk_DevId(const std::string& dev_id)
|
||||
{
|
||||
if (!s_enable_cross_talk) { return dev_id; }
|
||||
if (dev_id.size() > 6)
|
||||
{
|
||||
const string& cs_devid = dev_id.substr(0, 3) + std::string(dev_id.size() - 6, '*') + dev_id.substr(dev_id.size() - 3, 3);
|
||||
return cs_devid;
|
||||
}
|
||||
|
||||
return dev_id;
|
||||
}
|
||||
|
||||
std::string QDTCrossTalk::Crosstalk_DevIP(const std::string& str)
|
||||
{
|
||||
if (!s_enable_cross_talk) { return str; }
|
||||
|
||||
std::string format_ip = str;
|
||||
size_t pos_st = 0;
|
||||
size_t pos_en = 0;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
pos_en = format_ip.find('.', pos_st + 1);
|
||||
if (pos_en == std::string::npos) {
|
||||
return str;
|
||||
}
|
||||
format_ip.replace(pos_st, pos_en - pos_st, "***");
|
||||
pos_st = pos_en + 1;
|
||||
}
|
||||
|
||||
return format_ip;
|
||||
}
|
||||
|
||||
std::string QDTCrossTalk::Crosstalk_DevName(const std::string& dev_name)
|
||||
{
|
||||
if (!s_enable_cross_talk) { return dev_name; }
|
||||
|
||||
auto get_name = [](const std::string& dev_name, int count) ->std::string
|
||||
{
|
||||
const string& cs_dev_name = std::string(dev_name.size() - count, '*') + dev_name.substr(dev_name.size() - count, count);
|
||||
return cs_dev_name;
|
||||
};
|
||||
|
||||
if (dev_name.size() > 3)
|
||||
{
|
||||
return get_name(dev_name, 3);
|
||||
}
|
||||
else if(dev_name.size() > 2)
|
||||
{
|
||||
return get_name(dev_name, 2);
|
||||
}
|
||||
else if(dev_name.size() > 1)
|
||||
{
|
||||
return get_name(dev_name, 1);
|
||||
}
|
||||
|
||||
return std::string(dev_name.size(), '*');
|
||||
}
|
||||
|
||||
std::string QDTCrossTalk::Crosstalk_ChannelName(const std::string& channel_name)
|
||||
{
|
||||
if (!s_enable_cross_talk) { return channel_name; }
|
||||
|
||||
int pos = channel_name.find("_");
|
||||
if (pos != std::string::npos && pos < channel_name.size() - 1)
|
||||
{
|
||||
std::string cs_channel_name = Crosstalk_DevId(channel_name.substr(0, pos)) + channel_name.substr(pos, channel_name.size() - pos);
|
||||
return cs_channel_name;
|
||||
}
|
||||
|
||||
return "****";
|
||||
}
|
||||
|
||||
std::string QDTCrossTalk::Crosstalk_JsonLog(const nlohmann::json& json)
|
||||
{
|
||||
if (!s_enable_cross_talk) { return json.dump(1); }// Return the original JSON string if cross-talk is disabled
|
||||
|
||||
nlohmann::json copied_json = json;
|
||||
|
||||
try
|
||||
{
|
||||
std::vector<nlohmann::json*> to_traverse_jsons {&copied_json};
|
||||
while (!to_traverse_jsons.empty())
|
||||
{
|
||||
nlohmann::json* json = to_traverse_jsons.back();
|
||||
to_traverse_jsons.pop_back();
|
||||
|
||||
auto iter = json->begin();
|
||||
while (iter != json->end())
|
||||
{
|
||||
const std::string& key_str = iter.key();
|
||||
if (iter.value().is_string())
|
||||
{
|
||||
if (key_str.find("dev_id") != string::npos || key_str.find("sn") != string::npos)
|
||||
{
|
||||
iter.value() = Crosstalk_DevId(iter.value().get<std::string>());
|
||||
}
|
||||
else if (key_str.find("dev_name") != string::npos)
|
||||
{
|
||||
iter.value() = Crosstalk_DevName(iter.value().get<std::string>());
|
||||
}
|
||||
else if (key_str.find("access_code")!= string::npos)
|
||||
{
|
||||
iter.value() = "******";
|
||||
}
|
||||
else if (key_str.find("url") != string::npos)
|
||||
{
|
||||
iter.value() = "******";
|
||||
}
|
||||
else if (key_str.find("channel_name") != string::npos)
|
||||
{
|
||||
iter.value() = Crosstalk_ChannelName(iter.value().get<std::string>());
|
||||
}
|
||||
else if (key_str.find("ttcode_enc") != string::npos)
|
||||
{
|
||||
iter.value() = "******";
|
||||
}
|
||||
}
|
||||
else if (iter.value().is_object())
|
||||
{
|
||||
to_traverse_jsons.push_back(&iter.value());
|
||||
}
|
||||
else if (iter.value().is_array())
|
||||
{
|
||||
for (auto& array_item : iter.value())
|
||||
{
|
||||
if (array_item.is_object() || array_item.is_array())
|
||||
{
|
||||
to_traverse_jsons.push_back(&array_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const nlohmann::json::exception& e)
|
||||
{
|
||||
// Handle JSON parsing exceptions if necessary
|
||||
BOOST_LOG_TRIVIAL(info) << "Error processing JSON for cross-talk: " << e.what();
|
||||
return std::string();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "Error processing JSON for cross-talk: " << e.what();
|
||||
return std::string();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "Error processing JSON for cross-talk";
|
||||
};
|
||||
|
||||
return copied_json.dump(1);
|
||||
}
|
||||
|
||||
}// End of namespace Slic3r
|
||||
|
||||
23
src/slic3r/Utils/QDTUtil.hpp
Normal file
23
src/slic3r/Utils/QDTUtil.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
namespace Slic3r
|
||||
{
|
||||
|
||||
class QDTCrossTalk
|
||||
{
|
||||
public:
|
||||
QDTCrossTalk() = delete;
|
||||
~QDTCrossTalk() = delete;
|
||||
|
||||
public:
|
||||
static std::string Crosstalk_DevId(const std::string& str);
|
||||
static std::string Crosstalk_DevIP(const std::string& str);
|
||||
static std::string Crosstalk_DevName(const std::string& str);
|
||||
static std::string Crosstalk_JsonLog(const nlohmann::json& json);
|
||||
|
||||
private:
|
||||
static std::string Crosstalk_ChannelName(const std::string& str);
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
@@ -30,11 +30,6 @@ void TCPConsole::transmit_next_command()
|
||||
std::string cmd = m_cmd_queue.front();
|
||||
m_cmd_queue.pop_front();
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("TCPConsole: transmitting '%3%' to %1%:%2%")
|
||||
% m_host_name
|
||||
% m_port_name
|
||||
% cmd;
|
||||
|
||||
m_send_buffer = cmd + m_newline;
|
||||
|
||||
set_deadline_in(m_write_timeout);
|
||||
@@ -72,22 +67,11 @@ void TCPConsole::handle_read(
|
||||
m_error_code = ec;
|
||||
|
||||
if (ec) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("TCPConsole: Can't read from %1%:%2%: %3%")
|
||||
% m_host_name
|
||||
% m_port_name
|
||||
% ec.message();
|
||||
|
||||
m_io_context.stop();
|
||||
}
|
||||
else {
|
||||
std::string line = extract_next_line();
|
||||
boost::trim(line);
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("TCPConsole: received '%3%' from %1%:%2%")
|
||||
% m_host_name
|
||||
% m_port_name
|
||||
% line;
|
||||
|
||||
boost::to_lower(line);
|
||||
|
||||
if (line == m_done_string)
|
||||
@@ -103,11 +87,6 @@ void TCPConsole::handle_write(
|
||||
{
|
||||
m_error_code = ec;
|
||||
if (ec) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("TCPConsole: Can't write to %1%:%2%: %3%")
|
||||
% m_host_name
|
||||
% m_port_name
|
||||
% ec.message();
|
||||
|
||||
m_io_context.stop();
|
||||
}
|
||||
else {
|
||||
@@ -120,19 +99,10 @@ void TCPConsole::handle_connect(const boost::system::error_code& ec)
|
||||
m_error_code = ec;
|
||||
|
||||
if (ec) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("TCPConsole: Can't connect to %1%:%2%: %3%")
|
||||
% m_host_name
|
||||
% m_port_name
|
||||
% ec.message();
|
||||
|
||||
m_io_context.stop();
|
||||
}
|
||||
else {
|
||||
m_is_connected = true;
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("TCPConsole: connected to %1%:%2%")
|
||||
% m_host_name
|
||||
% m_port_name;
|
||||
|
||||
transmit_next_command();
|
||||
}
|
||||
}
|
||||
@@ -190,11 +160,6 @@ bool TCPConsole::run_queue()
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("TCPConsole: Exception while talking with %1%:%2%: %3%")
|
||||
% m_host_name
|
||||
% m_port_name
|
||||
% e.what();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,10 +14,7 @@
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
//B35
|
||||
#if defined __linux__
|
||||
#include <boost/array.hpp>
|
||||
#endif
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
||||
@@ -978,7 +978,7 @@ void StackImpl::reduce_noisy_snapshots(const std::string& new_name)
|
||||
assert(it_last != m_snapshots.begin() && (it_last->snapshot_data.snapshot_type == SnapshotType::LeavingGizmoNoAction || it_last->snapshot_data.snapshot_type == SnapshotType::LeavingGizmoWithAction));
|
||||
if (it_last->snapshot_data.snapshot_type == SnapshotType::LeavingGizmoWithAction) {
|
||||
for (-- it_last; it_last->snapshot_data.snapshot_type != SnapshotType::EnteringGizmo; -- it_last) {
|
||||
if (it_last->snapshot_data.snapshot_type == SnapshotType::GizmoAction) {
|
||||
if (it_last > m_snapshots.begin() && it_last->snapshot_data.snapshot_type == SnapshotType::GizmoAction) {
|
||||
it_last->name = new_name;
|
||||
auto it = it_last;
|
||||
for (-- it; it->snapshot_data.snapshot_type == SnapshotType::GizmoAction; -- it) ;
|
||||
@@ -990,7 +990,6 @@ void StackImpl::reduce_noisy_snapshots(const std::string& new_name)
|
||||
it_last = this->release_snapshots(it + 1, it_last + 1);
|
||||
}
|
||||
}
|
||||
assert(it_last != m_snapshots.begin());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@ int json_diff::diff_objects(json const &in, json &out, json const &base)
|
||||
|
||||
if (!base.contains(el.key()) ) {
|
||||
out[el.key()] = el.value();
|
||||
BOOST_LOG_TRIVIAL(trace) << "json_c diff new key: " << el.key()
|
||||
<< " type: " << el.value().type_name()
|
||||
<< " value: " << el.value();
|
||||
// BOOST_LOG_TRIVIAL(trace) << "json_c diff new key: " << el.key()
|
||||
// << " type: " << el.value().type_name()
|
||||
// << " value: " << el.value();
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -104,10 +104,10 @@ bool json_diff::load_compatible_settings(std::string const &type, std::string co
|
||||
diff2all_base_reset(full_message);
|
||||
return true;
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(error) << "load_compatible_settings failed, file = " << config_file;
|
||||
//BOOST_LOG_TRIVIAL(error) << "load_compatible_settings failed, file = " << config_file;
|
||||
}
|
||||
} catch (...) {
|
||||
BOOST_LOG_TRIVIAL(error) << "load_compatible_settings failed, file = " << config_file;
|
||||
//BOOST_LOG_TRIVIAL(error) << "load_compatible_settings failed, file = " << config_file;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -194,9 +194,9 @@ int json_diff::restore_append_objects(json const &in, json &out)
|
||||
for (auto& el: in.items()) {
|
||||
|
||||
if (!out.contains(el.key()) ) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "json_c append new " << el.key()
|
||||
<< " type: " << el.value().type_name()
|
||||
<< " value: " << el.value();
|
||||
// BOOST_LOG_TRIVIAL(trace) << "json_c append new " << el.key()
|
||||
// << " type: " << el.value().type_name()
|
||||
// << " value: " << el.value();
|
||||
out[el.key()] = el.value();
|
||||
continue;
|
||||
}
|
||||
@@ -205,9 +205,9 @@ int json_diff::restore_append_objects(json const &in, json &out)
|
||||
int recur_ret =
|
||||
restore_append_objects(el.value(), out[el.key()]);
|
||||
if (recur_ret != 0) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "json_c append obj failed"
|
||||
<< " key: " << el.key()
|
||||
<< " value: " << el.value();
|
||||
// BOOST_LOG_TRIVIAL(trace) << "json_c append obj failed"
|
||||
// << " key: " << el.key()
|
||||
// << " value: " << el.value();
|
||||
return recur_ret;
|
||||
}
|
||||
}
|
||||
@@ -253,14 +253,15 @@ int json_diff::diff2all(json const &in, json &out)
|
||||
void json_diff::compare_print(json &a, json &b)
|
||||
{
|
||||
for (auto& e: a.items()) {
|
||||
if (!b.contains(e.key()) ) { BOOST_LOG_TRIVIAL(trace) << "json_c compare loss " << e.key()
|
||||
if (!b.contains(e.key()) ) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "json_c compare loss " << e.key()
|
||||
<< " type: " << e.value().type_name();
|
||||
}
|
||||
if (e.value() != b[e.key()]) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "json_c compare not equal: key: " << e.key()
|
||||
<< " value: " << e.value();
|
||||
BOOST_LOG_TRIVIAL(trace) << "json_c compare vs value "
|
||||
<< " vs value: " << b[e.key()];
|
||||
// BOOST_LOG_TRIVIAL(trace) << "json_c compare not equal: key: " << e.key()
|
||||
// << " value: " << e.value();
|
||||
// BOOST_LOG_TRIVIAL(trace) << "json_c compare vs value "
|
||||
// << " vs value: " << b[e.key()];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace QDT {
|
||||
#define QIDI_NETWORK_LIBRARY "qidi_networking"
|
||||
#define QIDI_NETWORK_AGENT_NAME "qidi_network_agent"
|
||||
|
||||
#define QIDI_NETWORK_AGENT_VERSION "02.01.01.52"
|
||||
#define QIDI_NETWORK_AGENT_VERSION "02.02.00.55"
|
||||
|
||||
//iot preset type strings
|
||||
#define IOT_PRINTER_TYPE_STRING "printer"
|
||||
@@ -233,6 +233,7 @@ struct PrintParams {
|
||||
int auto_bed_leveling{ 0 };
|
||||
int auto_flow_cali{ 0 };
|
||||
int auto_offset_cali{ 0 };
|
||||
bool task_ext_change_assist;
|
||||
};
|
||||
|
||||
struct TaskQueryParams
|
||||
|
||||
Reference in New Issue
Block a user