update slic3r

This commit is contained in:
QIDI TECH
2025-08-04 16:30:53 +08:00
parent 8d4d60ec48
commit 661b112a68
287 changed files with 22250 additions and 7322 deletions

View File

@@ -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();
}
}

View File

@@ -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;
};
}

View File

@@ -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 &params)
{
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

View File

@@ -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 &params);
}
}

View 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 &section, 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 &section, 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 &section, 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 &section, 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 &section, 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 &section, 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 &section, 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

View 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_

View File

@@ -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

View File

@@ -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);

View File

@@ -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__

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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));

View File

@@ -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 (...) {}

View File

@@ -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));
}

View 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

View 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

View File

@@ -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;
}

View File

@@ -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 {

View File

@@ -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());
}
}
}

View File

@@ -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()];
}
}

View File

@@ -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