Compare commits

..
Author SHA1 Message Date
Hanif Koh 3956fcc836 Match Windows Paths in the clang-tidy Ignore List
Header paths use backslashes on Windows, so every / in a pattern is now [/\\]. The Windows SDK headers are ignored alongside the other OS-specific ones, and the list is one pattern per line. Suggested by @raistlin7447 from a Windows clang-cl run.
2026-10-02 03:31:10 +08:00
Hanif Koh f4f43535e5 Add the clang-tidy Configuration That Generated These Includes
Only misc-include-cleaner's missing-include check, with the headers it must never suggest: per-platform, internal and OS-specific ones that would break other platforms or are not meant to be included directly.
2026-10-02 02:13:49 +08:00
Hanif Koh 843e8c40e6 Drop the OS-Specific Includes Added Outside Their Platform Guards
GLib, GTK, D-Bus and POSIX headers are only used inside platform #if blocks, which already include them. Added unconditionally at the top of the file they broke the Windows build.
2026-10-01 23:46:58 +08:00
Hanif Koh db4e2f7ced Add Missing Includes Across src/slic3r/GUI
Every GUI source and header now directly includes the headers declaring what it uses, rather than relying on the precompiled header or transitive includes. Generated with clang-tidy misc-include-cleaner, plus one hand edit making CalibrationPanel.hpp self-contained.
2026-10-01 23:46:58 +08:00
Ian Chua 2f4758446a feat: add foundation for configurable printer agent connection (#16027)
* feat: add foundation for configurable printer agent connection

* fix: regression after merge

* chore: remove duplcate http include

* fix: remove unrelated moonraker.cpp changes

* chore: port add_platform_root_certificates to 15711

* fix: clean diff
2026-10-01 22:50:56 +08:00
HanifKoh c023632a7d Lock Config and Preset Files Across Instances and Write Them Atomically (#15861)
* Lock Config and Preset Files Across Instances and Write Them Atomically

Every running instance shares one OrcaSlicer.conf and one user preset
tree, and nothing kept their writers apart. Two instances saving at the
same moment, or the cloud preset sync thread writing while the GUI thread
saved, could interleave, and a reader in another instance could open a
preset JSON or .info file between truncate and close and get a partial
file, dropping that preset for the session with a parse error.

Add InstanceLock, a scoped guard that serialises the threads of one
process through a recursive mutex and other processes through an advisory
OS file lock: flock on POSIX, held on the guard's own descriptor so no
other close in the process can drop it, and LockFileEx on Windows. The
outermost guard opens the lock file and closes it on release, so nothing
stays open between saves and a data dir can be removed once nothing is
saving into it; the file itself is kept, since deleting it would let a
third instance lock a fresh file while the second still holds the old
one. It is best effort: when the lock file cannot be opened or locked, or
another instance still holds it after a second, the guard logs once and
lets the write proceed, then leaves the file alone for ten seconds, so a
hung instance never blocks every other one and a holder stuck in a
debugger does not cost a stall per save. The guard sits at the leaf
readers and writers: set_sync_info_and_save() calls save_info() under the
preset collection mutex, so a batch lock around save_user_presets() would
invert the order against the sync thread. The user preset scan reads its
files on worker threads without the guard, since the mutex would
serialise them, and takes it per file in the serial commit step, so a
save never waits for the whole scan. Each read keeps the bytes of the
preset and its .info as they were before parsing; commit compares them
with the disk under the guard and reads a file that changed again, so it
never deletes or writes back over another instance's newer save, nor
installs a .json and .info from two different saves; a preset another
instance removed in the meantime is not installed. Without the guard, in
a cool-down, the scan still loads the presets but leaves their files
alone: an unreadable file stays for the next scan, and a derived
compatible printer is not written back. Read-only scans, which is what
the CLI does, take no lock and create no lock file.

AppConfig holds OrcaSlicer.conf.lock in load() and save(); load is
included because the Windows path restores from the .bak copy. Every
user preset writer and reader holds user.lock: Preset::save(), which
writes no .info when the preset itself could not be written, since an
.info without its preset reads as a cloud deletion request, save_info(),
reload() and remove_files(), each preset the scan commits, the
bundle metadata reads and write, the .info removal after a cloud-confirmed
delete, the orphaned-.info scan on the sync thread, the bundle folder
removal on unsubscribe and the physical printer writers and delete
paths. A bundle import extracts under cache/ into a folder per process
and per import, where no scan reads.

Preset JSON, .info, bundle metadata, physical printer and config files,
and the caches and state files that already used a temporary by hand,
now go through write_file_atomically(), which writes <file>.<pid>.<n>.tmp
beside the target and renames it over, so a reader that never waits sees
a complete old or new file. A symlink is followed; a target that is not
a regular file is written in place; and when no temporary can be created
beside an existing target, or the rename itself is refused, by a Windows
reader holding the file open or a mount that cannot replace in one step,
the helper writes in place as before, since losing the save is worse
than a torn read. On POSIX the rename replaces the
target atomically where the old code removed it first and left a window
with no file at all; only a mount that refuses a one-step replace gets
the old remove-then-rename. A crash between temporary and rename leaves
the temporary behind, which no scan reads. Preset::save() returns
whether it wrote the preset, so the scan counts a compatible printer it
could not write back as an error. A failed config write keeps
the config dirty, and the idle handler waits ten seconds before retrying
while an explicit save always tries.

* Run the Cross-Process Lock Test on Every Platform

The test that checks the guard yields to a lock held elsewhere forked a
child to hold it, so it was left out on Windows. The OS lock belongs to
the handle on Windows and to the open file description elsewhere, so a
second handle in the same process is refused like another instance
would be. The test now holds the lock that way and runs everywhere.
2026-10-01 22:18:21 +08:00
710 changed files with 9235 additions and 357 deletions
+47
View File
@@ -0,0 +1,47 @@
# clang-tidy configuration. Only missing includes are reported for now: a file
# should include the header for every symbol it uses, not rely on the
# precompiled header or another header's includes. Run with --fix to add them.
Checks: '-*,misc-include-cleaner'
CheckOptions:
# Missing includes only. Builds without the precompiled header break on these.
misc-include-cleaner.UnusedIncludes: false
# Headers that declare a symbol but are not the one to include: per-platform
# implementations of wxWidgets and Boost.Thread (a Linux run would suggest the
# GTK or pthread one), library internals and forward declarations, CPython's
# headers behind Python.h, curl's behind curl.h, oneTBB's behind tbb/, and
# admesh's stl.h, which the include path also exposes without its directory.
# FFmpeg's C headers are left alone because they are only included inside
# extern "C", which an inserted include would miss. OS-specific headers (GLib,
# GTK, D-Bus, POSIX, the Windows SDK) are only used inside platform #if blocks,
# and an include added at the top of the file would break the other platforms'
# builds. A symbol these provide is not reported missing.
# Write every / as [/\\] so the patterns also match Windows paths.
# No comments inside the block below, because a # there silently becomes part of a pattern.
misc-include-cleaner.IgnoreHeaders: >-
wx[/\\](gtk|gtk1|msw|osx|unix|x11|motif|univ|qt|dfb|generic|private)[/\\].*;
.*[/\\]detail[/\\].*;
.*[/\\]impl[/\\].*;
.*_fwd\.hpp;
python3\.[0-9]+[/\\].*;
bits[/\\].*;
imconfig\.h;
expat_external\.h;
admesh[/\\]stl\.h;
boost[/\\]thread[/\\](pthread|win32)[/\\].*;
boost[/\\]regex[/\\]v[0-9]+[/\\].*;
curl[/\\](easy|multi|system|urlapi|header|options|websockets|mprintf)\.h;
oneapi[/\\]tbb[/\\].*;
opencv2[/\\]core[/\\]hal[/\\].*;
openssl[/\\]ossl_typ\.h;
libav[a-z]+[/\\].*;
libsw[a-z]+[/\\].*;
glib-2\.0[/\\].*;
gtk-3\.0[/\\].*;
dbus-1\.0[/\\].*;
sys[/\\].*;
unistd\.h;
strings\.h;
fcntl\.h;
termios\.h;
[/\\](um|shared)[/\\].*;
sal\.h
+46 -64
View File
@@ -5,6 +5,7 @@
//BBS
#include "Preset.hpp"
#include "Exception.hpp"
#include "InstanceLock.hpp"
#include "LocalesUtils.hpp"
#include "Thread.hpp"
#include "format.hpp"
@@ -743,10 +744,13 @@ static bool verify_config_file_checksum(boost::nowide::ifstream &ifs)
#ifdef USE_JSON_CONFIG
std::string AppConfig::load()
std::string AppConfig::load(bool read_only)
{
json j;
// Keep another instance from replacing or restoring the file mid-read.
InstanceLock instance_lock(read_only ? std::string() : lock_path());
// 1) Read the complete config file into a boost::property_tree.
namespace pt = boost::property_tree;
pt::ptree tree;
@@ -996,7 +1000,6 @@ void AppConfig::save()
// The config is first written to a file with a PID suffix and then moved
// to avoid race conditions with multiple instances of Slic3r
const auto path = config_path();
std::string path_pid = (boost::format("%1%.%2%") % path % get_current_pid()).str();
json j;
@@ -1126,43 +1129,18 @@ void AppConfig::save()
j["local_machines"][local_machine.first] = m_json;
}
boost::nowide::ofstream c;
c.open(path_pid, std::ios::out | std::ios::trunc);
c << j.dump(1, '\t') << std::endl;
#ifdef WIN32
// WIN32 specific: The final "rename_file()" call is not safe in case of an application crash, there is no atomic "rename file" API
// provided by Windows (sic!). Therefore we save a MD5 checksum to be able to verify file corruption. In addition,
// we save the config file into a backup first before moving it to the final destination.
c << appconfig_md5_hash_line(j.dump(1, '\t'));
#endif
c.close();
if (c.fail()) {
BOOST_LOG_TRIVIAL(error) << "Failed to write new configuration to " << path_pid << "; aborting attempt to overwrite original configuration";
return;
}
#ifdef WIN32
// Make a backup of the configuration file before copying it to the final destination.
std::string error_message;
std::string backup_path = (boost::format("%1%.bak") % path).str();
// Copy configuration file with PID suffix into the configuration file with "bak" suffix.
if (copy_file(path_pid, backup_path, error_message, false) != SUCCESS)
BOOST_LOG_TRIVIAL(error) << "Copying from " << path_pid << " to " << backup_path << " failed. Failed to create a backup configuration.";
#endif
// Rename the config atomically.
// On Windows, the rename is likely NOT atomic, thus it may fail if PrusaSlicer crashes on another thread in the meanwhile.
// To cope with that, we already made a backup of the config on Windows.
rename_file(path_pid, path);
const std::string config_str = j.dump(1, '\t');
if (write_config_file(path, config_str + "\n", config_str))
m_dirty = false;
}
#else
std::string AppConfig::load()
std::string AppConfig::load(bool read_only)
{
// Keep another instance from replacing or restoring the file mid-read.
InstanceLock instance_lock(read_only ? std::string() : lock_path());
// 1) Read the complete config file into a boost::property_tree.
namespace pt = boost::property_tree;
pt::ptree tree;
@@ -1300,7 +1278,6 @@ void AppConfig::save()
// The config is first written to a file with a PID suffix and then moved
// to avoid race conditions with multiple instances of Slic3r
const auto path = config_path();
std::string path_pid = (boost::format("%1%.%2%") % path % get_current_pid()).str();
std::stringstream config_ss;
if (m_mode == EAppMode::Editor)
@@ -1336,39 +1313,39 @@ void AppConfig::save()
// One empty line before the MD5 sum.
config_ss << std::endl;
std::string config_str = config_ss.str();
boost::nowide::ofstream c;
c.open(path_pid, std::ios::out | std::ios::trunc);
c << config_str;
#ifdef WIN32
// WIN32 specific: The final "rename_file()" call is not safe in case of an application crash, there is no atomic "rename file" API
// provided by Windows (sic!). Therefore we save a MD5 checksum to be able to verify file corruption. In addition,
// we save the config file into a backup first before moving it to the final destination.
c << appconfig_md5_hash_line(config_str);
#endif
c.close();
if (c.fail()) {
BOOST_LOG_TRIVIAL(error) << "Failed to write new configuration to " << path_pid << "; aborting attempt to overwrite original configuration";
return;
}
#ifdef WIN32
// Make a backup of the configuration file before copying it to the final destination.
std::string error_message;
std::string backup_path = (boost::format("%1%.bak") % path).str();
// Copy configuration file with PID suffix into the configuration file with "bak" suffix.
if (copy_file(path_pid, backup_path, error_message, false) != SUCCESS)
BOOST_LOG_TRIVIAL(error) << "Copying from " << path_pid << " to " << backup_path << " failed. Failed to create a backup configuration.";
#endif
// Rename the config atomically.
// On Windows, the rename is likely NOT atomic, thus it may fail if PrusaSlicer crashes on another thread in the meanwhile.
// To cope with that, we already made a backup of the config on Windows.
rename_file(path_pid, path);
const std::string config_str = config_ss.str();
if (write_config_file(path, config_str, config_str))
m_dirty = false;
}
#endif
bool AppConfig::write_config_file(const std::string &path, std::string body, const std::string &checksum_source)
{
// Everything before this is assembly; only the writes need the other instances kept out.
InstanceLock instance_lock(lock_path());
#ifdef WIN32
// WIN32 specific: the final replace is not safe in case of an application crash, there is no atomic "rename file" API
// provided by Windows (sic!). Therefore we save a MD5 checksum to be able to verify file corruption. In addition,
// we save the config file into a backup first before moving it to the final destination.
body += appconfig_md5_hash_line(checksum_source);
#endif
// Not flushed to the device: the idle handler saves on the GUI thread after
// any change, and the rename already gives a complete old or new file.
if (const std::error_code ec = write_file_atomically(path, body)) {
BOOST_LOG_TRIVIAL(error) << "Failed to write the configuration " << path << ": " << ec.message() << "; trying again in 10 s";
m_retry_save_at = std::chrono::steady_clock::now() + std::chrono::seconds(10);
return false;
}
m_retry_save_at = {};
#ifdef WIN32
// Written after the config, so the backup never holds a state that was not confirmed written.
const std::string backup_path = (boost::format("%1%.bak") % path).str();
if (const std::error_code ec = write_file_atomically(backup_path, body))
BOOST_LOG_TRIVIAL(error) << "Failed to write the backup configuration " << backup_path << ": " << ec.message();
#endif
return true;
}
bool AppConfig::get_variant(const std::string &vendor, const std::string &model, const std::string &variant) const
{
const auto it_v = m_vendors.find(vendor);
@@ -1857,6 +1834,11 @@ void AppConfig::reset_selections()
}
}
std::string AppConfig::lock_path()
{
return Slic3r::data_dir().empty() ? std::string() : config_path() + ".lock";
}
std::string AppConfig::config_path()
{
#ifdef USE_JSON_CONFIG
@@ -1893,7 +1875,7 @@ bool AppConfig::exists()
std::string AppConfig::load_if_exists()
{
return boost::filesystem::exists(loading_path()) ? load() : std::string();
return boost::filesystem::exists(loading_path()) ? load(/*read_only=*/true) : std::string();
}
}; // namespace Slic3r
+16 -1
View File
@@ -2,6 +2,7 @@
#define slic3r_AppConfig_hpp_
#include <set>
#include <chrono>
#include <map>
#include <string>
#include "nlohmann/json.hpp"
@@ -122,14 +123,18 @@ public:
// Load the slic3r.ini from a user profile directory (or a datadir, if configured).
// Return an error string, or an empty string on success.
std::string load();
std::string load(bool read_only = false);
// Treat a missing config as default state; otherwise load it normally.
// The CLI's load: it never saves, so it takes no lock and creates no lock file.
std::string load_if_exists();
// Store the slic3r.ini into a user profile directory (or a datadir, if configured).
void save();
// Does this config need to be saved?
bool dirty() const { return m_dirty; }
// False for ten seconds after a failed write, so the idle handler does not
// repeat a hopeless attempt on every event; an explicit save() always tries.
bool save_due() const { return std::chrono::steady_clock::now() >= m_retry_save_at; }
void set_dirty() { m_dirty = true; }
@@ -339,6 +344,8 @@ public:
// Get the default config path from Slic3r::data_dir().
std::string config_path();
// Lock file guarding config_path() against other running instances; empty without a data dir.
std::string lock_path();
// Returns true if the user's data directory comes from before Slic3r 1.40.0 (no updating)
bool legacy_datadir() const { return m_legacy_datadir; }
@@ -449,8 +456,16 @@ private:
// Preset for each machine
MachineSettingMap m_printer_settings;
// Writes the assembled config text, and on Windows its checksum and a backup copy; false when the
// config itself could not be written, in which case the caller stays dirty and retries. `checksum_source`
// is the text load() will verify, which for the JSON config ends before the trailing newline.
bool write_config_file(const std::string &path, std::string body, const std::string &checksum_source);
// Has any value been modified since the config.ini has been last saved or loaded?
bool m_dirty;
// After a failed write, save_due() is false for the next ten seconds, so the
// idle handler does not repeat a hopeless write on every event.
std::chrono::steady_clock::time_point m_retry_save_at{};
// Original version found in the ini file before it was overwritten
Semver m_orig_version;
// Whether the existing version is before system profiles & configuration updating
+2
View File
@@ -306,6 +306,8 @@ set(lisbslic3r_sources
Geometry/VoronoiUtils.cpp
Geometry/VoronoiUtils.hpp
Geometry/VoronoiVisualUtils.hpp
InstanceLock.cpp
InstanceLock.hpp
Int128.hpp
KDTreeIndirect.hpp
Layer.cpp
+3 -5
View File
@@ -1538,11 +1538,9 @@ void ConfigBase::save_to_json(const std::string &file, const std::string &name,
// Serialize first: if that throws (invalid UTF-8), the existing file stays untouched.
std::ostringstream ss;
this->save_to_json(ss, name, from, version);
boost::nowide::ofstream c;
c.open(file, std::ios::out | std::ios::trunc);
c << ss.str();
c.close();
if (const std::error_code ec = write_file_atomically(file, ss.str()))
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(": failed to save config to %1%: %2%") % file % ec.message();
else
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(", saved config to %1%\n")%file;
}
+165
View File
@@ -0,0 +1,165 @@
#include "InstanceLock.hpp"
#include <map>
#include <memory>
#include <system_error>
#include <thread>
#include <boost/filesystem.hpp>
#include <boost/log/trivial.hpp>
#include <boost/nowide/fstream.hpp>
#ifdef _WIN32
#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/nowide/convert.hpp>
#else
#include <cerrno>
#include <fcntl.h>
#include <sys/file.h>
#include <unistd.h>
#endif
namespace Slic3r {
#ifdef _WIN32
// LockFileEx, held by this handle alone.
using NativeFileLock = boost::interprocess::file_lock;
#else
// flock(2) rather than an fcntl lock: it belongs to this open file description,
// so any other code in the process that opens and closes the lock file, as a
// backup or an export walking the data dir might, cannot drop it. An fcntl
// lock would go with the first such close.
class NativeFileLock
{
public:
explicit NativeFileLock(const char *path) : m_fd(::open(path, O_RDWR | O_CREAT | O_CLOEXEC, 0644))
{
if (m_fd < 0)
throw std::system_error(errno, std::generic_category(), path);
}
~NativeFileLock() { ::close(m_fd); }
bool try_lock()
{
if (::flock(m_fd, LOCK_EX | LOCK_NB) == 0)
return true;
// A signal (a child exiting, for one) interrupts the call like any other; the caller polls again.
if (errno == EWOULDBLOCK || errno == EINTR)
return false;
throw std::system_error(errno, std::generic_category(), "flock");
}
void unlock() { ::flock(m_fd, LOCK_UN); }
private:
int m_fd;
};
#endif
// One slot per lock file, shared by every guard in the process: one lock
// object per path behind a mutex is what makes the guard re-entrant and safe
// to use from the preset sync thread and the GUI thread at once. The lock
// file is opened by the outermost guard and closed when it goes, so the file
// is never held open between guards: whatever is at the path is what gets
// locked, and a data dir can be removed once nothing is saving into it. The
// file is kept rather than deleted on release because the lock state lives in
// the kernel on the open file, and deleting it would let a third instance
// lock a fresh file while the second still holds the old one.
struct InstanceLock::Slot
{
std::recursive_mutex mutex;
// Non-null exactly while this process holds the file lock.
std::unique_ptr<NativeFileLock> file_lock;
int depth{0};
// Until this point, after a guard could not open, lock or wait out the
// file, guards do not touch it.
std::chrono::steady_clock::time_point cooldown_until{};
};
InstanceLock::Slot &InstanceLock::slot_for(const std::string &lock_file_path)
{
// Never freed: a save during static destruction still needs its slot.
static auto *registry_mutex = new std::mutex();
static auto *registry = new std::map<std::string, std::unique_ptr<Slot>>();
std::lock_guard<std::mutex> guard(*registry_mutex);
std::unique_ptr<Slot> &slot = (*registry)[lock_file_path];
if (! slot)
slot = std::make_unique<Slot>();
return *slot;
}
// Starts the cool-down. Called with the slot mutex held.
void InstanceLock::defer(Slot &slot, const std::string &reason)
{
slot.cooldown_until = std::chrono::steady_clock::now() + cooldown;
BOOST_LOG_TRIVIAL(warning) << reason << "; proceeding without the lock for the next " << cooldown.count() << " ms";
}
// Creates the lock file if needed and opens it, or starts the cool-down.
// Called with the slot mutex held.
bool InstanceLock::open_lock_file(Slot &slot, const std::string &lock_file_path)
{
try {
#ifdef _WIN32
// The lock opens an existing file; created once, on the first miss.
const std::wstring wide_path = boost::nowide::widen(lock_file_path);
try {
slot.file_lock = std::make_unique<NativeFileLock>(wide_path.c_str());
} catch (const std::exception &) {
boost::nowide::ofstream(lock_file_path, std::ios::app).close();
slot.file_lock = std::make_unique<NativeFileLock>(wide_path.c_str());
}
#else
slot.file_lock = std::make_unique<NativeFileLock>(lock_file_path.c_str());
#endif
return true;
} catch (const std::exception &e) {
defer(slot, "Cannot open lock file " + lock_file_path + ": " + e.what() + " (check its owner and permissions)");
return false;
}
}
InstanceLock::InstanceLock(const std::string &lock_file_path, std::chrono::milliseconds timeout)
{
if (lock_file_path.empty())
return;
m_slot = &slot_for(lock_file_path);
m_slot_guard = std::unique_lock<std::recursive_mutex>(m_slot->mutex);
const auto now = std::chrono::steady_clock::now();
if (m_slot->depth == 0 && now >= m_slot->cooldown_until && open_lock_file(*m_slot, lock_file_path)) {
const auto deadline = now + timeout;
bool taken = false;
for (;;) {
try {
if ((taken = m_slot->file_lock->try_lock()))
break;
} catch (const std::exception &e) {
defer(*m_slot, "Cannot lock " + lock_file_path + ": " + e.what());
break;
}
if (std::chrono::steady_clock::now() >= deadline) {
defer(*m_slot, "Another instance has held " + lock_file_path + " for over " + std::to_string(timeout.count()) + " ms");
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
if (! taken)
m_slot->file_lock.reset();
}
// Counted last, so a throw above leaves the slot exactly as it was found.
++ m_slot->depth;
m_locked = m_slot->file_lock != nullptr;
}
InstanceLock::~InstanceLock()
{
if (m_slot == nullptr)
return;
if (-- m_slot->depth == 0 && m_slot->file_lock) {
try {
m_slot->file_lock->unlock();
} catch (const std::exception &e) {
BOOST_LOG_TRIVIAL(warning) << "Cannot unlock instance lock: " << e.what();
}
m_slot->file_lock.reset();
}
}
} // namespace Slic3r
+60
View File
@@ -0,0 +1,60 @@
#pragma once
#include <chrono>
#include <mutex>
#include <string>
namespace Slic3r {
// Scoped write lock on a file shared by every running instance of the
// application, such as the app config or the user preset directory: threads
// of this process are serialised through a recursive mutex, other processes
// through an advisory OS file lock on `lock_file_path`. The lock file is
// created on first use and kept; the OS releases the lock when its holder
// exits, so a crashed instance never leaves a stale lock behind.
//
// Best effort: when the lock file cannot be opened or locked, or another
// instance still holds it after `timeout`, the guard keeps only the in-process
// mutex, locked() reports false and the write proceeds, since a hung instance
// must never block another one from saving. For `cooldown` afterwards guards
// leave the file alone. The wait for the in-process mutex is bounded only by
// the longest critical section, so a guard covers a few file operations and
// nothing slower.
//
// Lock order: the preset collection mutex may be held when a guard is taken
// (set_sync_info_and_save() calls save_info() under it), never the reverse;
// that is why the guards sit at the leaf readers and writers and why a guard
// must not be added around save_user_presets(), which takes the collection
// mutex through delete_preset().
class InstanceLock
{
public:
// Long against a critical section of milliseconds, short against the GUI
// thread, which is where most guards are taken.
static constexpr std::chrono::milliseconds default_timeout{1000};
// Long enough that a holder stuck in a debugger does not cost a stall per
// save; mutable so tests can shorten it.
static inline std::chrono::milliseconds cooldown{10000};
// An empty path makes the guard a no-op.
explicit InstanceLock(const std::string &lock_file_path, std::chrono::milliseconds timeout = default_timeout);
~InstanceLock();
InstanceLock(const InstanceLock &) = delete;
InstanceLock &operator=(const InstanceLock &) = delete;
// True while this process holds the cross-process file lock.
bool locked() const { return m_locked; }
private:
struct Slot;
static Slot &slot_for(const std::string &lock_file_path);
static bool open_lock_file(Slot &slot, const std::string &lock_file_path);
static void defer(Slot &slot, const std::string &reason);
Slot *m_slot{nullptr};
std::unique_lock<std::recursive_mutex> m_slot_guard;
bool m_locked{false};
};
} // namespace Slic3r
+126 -25
View File
@@ -51,6 +51,9 @@
#include "libslic3r.h"
#include "LifecycleEvents.hpp"
#include "Utils.hpp"
#include "InstanceLock.hpp"
#include <sstream>
#include "Time.hpp"
#include "PlaceholderParser.hpp"
#include "libslic3r/GCode/Thumbnails.hpp"
@@ -107,6 +110,32 @@ std::string get_preset_canonical_name(const std::string &preset_bare_name, const
}
}
std::string user_presets_lock_path(bool read_only)
{
return read_only || data_dir().empty() ? std::string() : (fs::path(data_dir()) / (PRESET_USER_DIR ".lock")).string();
}
// Removes a preset file the scan could not load, and its .info, under the lock.
// The scan passes read_only when it could not take the lock, since the file may
// then be another instance's fresh write that it merely raced.
static void remove_preset_files(const std::string &preset_file, bool read_only)
{
if (read_only)
return;
InstanceLock instance_lock(user_presets_lock_path());
// A symlink whose target is missing stays, since the target may come back; one
// that cannot even be followed is removed like any other unreadable file.
auto remove = [](const fs::path &file) {
boost::system::error_code ec;
if (fs::status(file, ec).type() != fs::file_not_found)
fs::remove(file, ec);
};
fs::path file_path(preset_file);
remove(file_path);
file_path.replace_extension(".info");
remove(file_path);
}
std::string get_preset_bare_name(const std::string &canonical_name)
{
const auto pos = canonical_name.find_last_of('/');
@@ -649,18 +678,20 @@ void Preset::save_info(std::string file)
file = idx_file.string();
}
boost::nowide::ofstream c;
c.open(file, std::ios::out | std::ios::trunc);
std::string sync_info_to_save;
//BBS: hold is used for stop requesting to server this time
if (this->sync_info.compare("hold") != 0)
sync_info_to_save = this->sync_info;
std::ostringstream c;
c << "sync_info" << " = " << sync_info_to_save << std::endl;
c << "user_id" << " = " << this->user_id << std::endl;
c << "setting_id" << " = " << this->setting_id << std::endl;
c << "base_id" << " = " << this->base_id << std::endl;
c << "updated_time" << " = " << std::to_string(this->updated_time) << std::endl;
c.close();
InstanceLock instance_lock(user_presets_lock_path());
if (const std::error_code ec = write_file_atomically(file, c.str()))
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": failed to save " << file << ": " << ec.message();
}
void Preset::remove_files(bool cloud_already_deleted)
@@ -669,6 +700,7 @@ void Preset::remove_files(bool cloud_already_deleted)
if (this->is_project_embedded) {
return;
}
InstanceLock instance_lock(user_presets_lock_path());
// Erase the preset file.
boost::nowide::remove(this->file.c_str());
fs::path idx_path(this->file);
@@ -686,11 +718,11 @@ void Preset::remove_files(bool cloud_already_deleted)
}
//BBS: add logic for only difference save
void Preset::save(DynamicPrintConfig* parent_config)
bool Preset::save(DynamicPrintConfig* parent_config)
{
//BBS: add project embedded preset logic
if (this->is_project_embedded)
return;
return true;
//BBS: change to json format
//this->config.save(this->file);
std::string from_str;
@@ -705,12 +737,16 @@ void Preset::save(DynamicPrintConfig* parent_config)
else
from_str = std::string("Default");
boost::filesystem::create_directories(fs::path(this->file).parent_path());
const std::string bare_name = get_preset_bare_name(this->name);
// What gets written: the diff against the parent, the config plus its
// filament id, or the config as is. Built before the lock is taken so the
// exclusive window covers only the file writes.
DynamicPrintConfig temp_config;
const DynamicPrintConfig *to_save = &this->config;
//BBS: only save difference if it has parent
if (parent_config) {
DynamicPrintConfig temp_config;
std::vector<std::string> dirty_options = config.diff(*parent_config);
std::string extruder_id_name, extruder_variant_name;
@@ -746,13 +782,22 @@ void Preset::save(DynamicPrintConfig* parent_config)
opt_dst->set(opt_src);
}
}
temp_config.save_to_json(this->file, bare_name, from_str, this->version.to_string());
to_save = &temp_config;
} else if (!filament_id.empty() && inherits().empty()) {
DynamicPrintConfig temp_config = config;
temp_config = config;
temp_config.set_key_value(BBL_JSON_KEY_FILAMENT_ID, new ConfigOptionString(filament_id));
temp_config.save_to_json(this->file, bare_name, from_str, this->version.to_string());
} else {
this->config.save_to_json(this->file, bare_name, from_str, this->version.to_string());
to_save = &temp_config;
}
std::ostringstream json;
to_save->save_to_json(json, bare_name, from_str, this->version.to_string());
InstanceLock instance_lock(user_presets_lock_path());
boost::filesystem::create_directories(fs::path(this->file).parent_path());
if (const std::error_code ec = write_file_atomically(this->file, json.str())) {
// No .info either: one without its preset reads as a cloud deletion request.
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": failed to save " << this->file << ": " << ec.message();
return false;
}
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " save config for: " << this->name << " and filament_id: " << filament_id << " and base_id: " << this->base_id;
@@ -762,6 +807,7 @@ void Preset::save(DynamicPrintConfig* parent_config)
idx_file.replace_extension(".info");
this->save_info(idx_file.string());
}
return true;
}
void Preset::reload(Preset const &parent)
@@ -773,6 +819,7 @@ void Preset::reload(Preset const &parent)
std::string reason;
ForwardCompatibilitySubstitutionRule substitution_rule = ForwardCompatibilitySubstitutionRule::Disable;
try {
InstanceLock instance_lock(user_presets_lock_path());
ConfigSubstitutions config_substitutions = config.load_from_json(file, substitution_rule, key_values, reason);
this->config = parent.config;
this->config.apply(std::move(config));
@@ -1702,6 +1749,22 @@ std::string PresetCollection::canonical_preset_name(const std::string &name, con
return get_preset_canonical_name(parsed.bare, origin);
}
PresetCollection::PresetFilesOnDisk PresetCollection::PresetFilesOnDisk::read(const boost::filesystem::path &file)
{
auto read_if_present = [](const fs::path &path) -> std::optional<std::string> {
std::string bytes;
try {
load_string_file(path, bytes);
} catch (const std::exception &) {
return std::nullopt;
}
return bytes;
};
fs::path info_path(file);
info_path.replace_extension(".info");
return { read_if_present(file), read_if_present(info_path) };
}
PresetCollection::UserPresetLoad PresetCollection::resolve_user_preset(
const boost::filesystem::path &file, const std::string &canonical_name,
const PresetOrigin &load_origin, ForwardCompatibilitySubstitutionRule substitution_rule,
@@ -1713,6 +1776,9 @@ PresetCollection::UserPresetLoad PresetCollection::resolve_user_preset(
Preset &preset = out.preset;
preset.bundle_id = load_origin.bundle_id;
preset.file = file.string();
// Before either file is parsed, so a save that lands during the parse still shows
// up as a difference when commit compares.
out.on_disk = PresetFilesOnDisk::read(file);
// Load the preset file, apply preset values on top of defaults.
try {
fs::path idx_path(preset.file);
@@ -1825,14 +1891,8 @@ void PresetCollection::commit_user_preset(UserPresetLoad &&loaded, std::deque<Pr
++m_errors;
BOOST_LOG_TRIVIAL(error) << error;
}
if (loaded.discard_file && !read_only) {
fs::path file_path(loaded.preset.file);
if (fs::exists(file_path))
fs::remove(file_path);
file_path.replace_extension(".info");
if (fs::exists(file_path))
fs::remove(file_path);
}
if (loaded.discard_file)
remove_preset_files(loaded.preset.file, read_only);
if (!loaded.install)
return;
@@ -1840,9 +1900,12 @@ void PresetCollection::commit_user_preset(UserPresetLoad &&loaded, std::deque<Pr
if (loaded.save_compatible_printers) {
// A filesystem error from the rewrite is counted, and the preset still loads.
try {
if (!read_only)
preset.save(nullptr);
if (read_only)
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " added compatible_printers for preset: " << preset.name << " (not written back)";
else if (preset.save(nullptr))
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " added compatible_printers for preset: " << preset.name;
else
++m_errors; // save() logged why
} catch (const std::runtime_error &err) {
++m_errors;
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " can not write compatible_printers back to " << preset.file << ": " << err.what();
@@ -1928,11 +1991,32 @@ void PresetCollection::load_presets(
return this->resolve_user_preset(files[i].path, files[i].canonical_name, resolved_origin, substitution_rule,
extruder_id_name, extruder_variant_name, key_set1, key_set2);
},
[&](size_t, UserPresetLoad &&loaded) {
[&](size_t i, UserPresetLoad &&loaded) {
// Resolve read the files without the lock, so another instance may have saved
// over them since. A file that changed is resolved again under the lock before
// commit removes or rewrites it, which also keeps its .json and .info from two
// different saves apart. Without the lock nothing is checked, so commit leaves
// the files alone.
const std::string lock_path = user_presets_lock_path(read_only);
InstanceLock instance_lock(lock_path);
if (instance_lock.locked()) {
const PresetFilesOnDisk on_disk = PresetFilesOnDisk::read(files[i].path);
boost::system::error_code ec;
// The link itself, and a stat error counts as present, so a file that is
// there but cannot be read is still counted and removed by commit.
if (! on_disk.json && fs::symlink_status(files[i].path, ec).type() == fs::file_not_found)
return; // removed by another instance since it was read
if (! (on_disk == loaded.on_disk)) {
CNumericLocalesSetter locales_setter;
loaded = this->resolve_user_preset(files[i].path, files[i].canonical_name, resolved_origin, substitution_rule,
extruder_id_name, extruder_variant_name, key_set1, key_set2);
}
}
const bool leave_files = read_only || (! lock_path.empty() && ! instance_lock.locked());
// Committing can remove an unreadable preset's file, and a filesystem error
// there is reported without stopping the rest of the directory.
try {
this->commit_user_preset(std::move(loaded), presets_loaded, substitutions, preset_loaded_fn, read_only);
this->commit_user_preset(std::move(loaded), presets_loaded, substitutions, preset_loaded_fn, leave_files);
} catch (const std::runtime_error &err) {
errors_cummulative += err.what();
errors_cummulative += "\n";
@@ -2242,7 +2326,10 @@ void PresetCollection::set_sync_info_and_save(std::string name, std::string sett
preset->setting_id = setting_id;
if (update_time > 0)
preset->updated_time = update_time;
preset->sync_info == "update" ? preset->save(nullptr) : preset->save_info();
if (preset->sync_info == "update")
preset->save(nullptr);
else
preset->save_info();
break;
}
}
@@ -4311,8 +4398,15 @@ void PhysicalPrinter::update_preset_names_in_config()
}
}
void PhysicalPrinter::save(DynamicPrintConfig* /* parent_config */)
{
InstanceLock instance_lock(user_presets_lock_path());
this->config.save_to_json(this->file, std::string("Physical_Printer"), std::string("User"), std::string(SLIC3R_VERSION));
}
void PhysicalPrinter::save(const std::string& file_name_from, const std::string& file_name_to)
{
InstanceLock instance_lock(user_presets_lock_path());
// rename the file
boost::nowide::rename(file_name_from.data(), file_name_to.data());
this->file = file_name_to;
@@ -4444,6 +4538,7 @@ void PhysicalPrinterCollection::load_printers(
continue;
}
try {
InstanceLock instance_lock(user_presets_lock_path());
PhysicalPrinter printer(name, this->default_config());
printer.file = dir_entry.path().string();
// Load the preset file, apply preset values on top of defaults.
@@ -4636,7 +4731,10 @@ bool PhysicalPrinterCollection::delete_printer(const std::string& name)
const PhysicalPrinter& printer = *it;
// Erase the preset file.
{
InstanceLock instance_lock(user_presets_lock_path());
boost::nowide::remove(printer.file.c_str());
}
m_printers.erase(it);
return true;
}
@@ -4648,7 +4746,10 @@ bool PhysicalPrinterCollection::delete_selected_printer()
const PhysicalPrinter& printer = this->get_selected_printer();
// Erase the preset file.
{
InstanceLock instance_lock(user_presets_lock_path());
boost::nowide::remove(printer.file.c_str());
}
// Remove the preset from the list.
m_printers.erase(m_printers.begin() + m_idx_selected);
// unselect all printers
+23 -2
View File
@@ -8,6 +8,7 @@
#include <unordered_set>
#include <functional>
#include <mutex>
#include <optional>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/property_tree/ptree_fwd.hpp>
@@ -330,7 +331,8 @@ public:
//BBS: add logic for only difference save
//if parent_config is null, save all keys, otherwise, only save difference
void save(DynamicPrintConfig* parent_config);
// Returns false when the preset file could not be written.
bool save(DynamicPrintConfig* parent_config);
void reload(Preset const & parent);
// Return a label of this preset, consisting of a name and a "(modified)" suffix, if this preset is dirty.
@@ -497,6 +499,12 @@ std::string get_preset_canonical_name(const std::string &preset_bare_name, const
// Tail segment of a canonical name — what's written to the bundle's .json filename and JSON "name" field.
std::string get_preset_bare_name(const std::string &canonical_name);
// Lock file guarding every user preset file under data_dir() against other
// running instances and the preset sync thread. Empty without a data dir, and
// for a read-only load (the CLI), which never rewrites or deletes and may run
// many jobs on one data dir.
std::string user_presets_lock_path(bool read_only = false);
// Resolve an origin from a directory path when the caller passes Kind::Auto.
PresetOrigin detect_origin_from_path(const boost::filesystem::path &path, const PresetOrigin &explicit_origin = PresetOrigin());
@@ -906,6 +914,16 @@ protected:
void set_custom_preset_alias(Preset &preset);
private:
// A preset file and its .info as read from disk, std::nullopt for one that is missing.
struct PresetFilesOnDisk
{
std::optional<std::string> json;
std::optional<std::string> info;
static PresetFilesOnDisk read(const boost::filesystem::path &file);
bool operator==(const PresetFilesOnDisk &rhs) const { return json == rhs.json && info == rhs.info; }
};
// One preset file read and flattened against the presets already in this
// collection, before anything the collection shares has been touched.
struct UserPresetLoad
@@ -923,6 +941,9 @@ private:
bool discard_file { false };
// The .info file read beside the preset, which commit logs.
std::string info_file;
// Both files as they were before the preset was read from them. Resolve runs
// without the instance lock, so commit compares this with the disk under it.
PresetFilesOnDisk on_disk;
// Counted and logged by commit, in the order the directory listed the files.
std::vector<std::string> errors;
PresetsConfigSubstitutions substitutions;
@@ -1111,7 +1132,7 @@ public:
//BBS: change to json format
//void save() { this->config.save(this->file); }
void save(DynamicPrintConfig* parent_config) { this->config.save_to_json(this->file, std::string("Physical_Printer"), std::string("User"), std::string(SLIC3R_VERSION)); }
void save(DynamicPrintConfig* parent_config);
void save(const std::string& file_name_from, const std::string& file_name_to);
void update_from_preset(const Preset& preset);
+29 -12
View File
@@ -1,3 +1,4 @@
#include <atomic>
#include <cassert>
#include <chrono>
#include <ctime>
@@ -13,6 +14,7 @@
#include "libslic3r.h"
#include "I18N.hpp"
#include "Utils.hpp"
#include "InstanceLock.hpp"
#include "LocalesUtils.hpp"
#include "Model.hpp"
#include "TriangleSelector.hpp"
@@ -1272,6 +1274,13 @@ PresetsConfigSubstitutions PresetBundle::load_user_presets(std::string user, For
const auto user_load_t0 = std::chrono::steady_clock::now();
// Reads one bundle's metadata under the lock, per file, so the lock is never
// held when bundles.WriteLock() is taken afterwards.
auto load_bundle_metadata = [read_only](const fs::path &metadata_file, BundleMetadata &metadata) {
InstanceLock instance_lock(user_presets_lock_path(read_only));
return metadata.load_from_json(metadata_file.string());
};
// Load bundle metadata from _local directory first
fs::path local_dir(folder / PRESET_LOCAL_DIR);
if (fs::exists(local_dir)) {
@@ -1285,7 +1294,7 @@ PresetsConfigSubstitutions PresetBundle::load_user_presets(std::string user, For
if (!fs::exists(metadata_file)) continue;
BundleMetadata metadata;
if (!metadata.load_from_json(metadata_file.string())) continue;
if (!load_bundle_metadata(metadata_file, metadata)) continue;
metadata.print_presets.clear();
metadata.filament_presets.clear();
metadata.printer_presets.clear();
@@ -1320,7 +1329,7 @@ PresetsConfigSubstitutions PresetBundle::load_user_presets(std::string user, For
if (!fs::exists(metadata_file)) continue;
BundleMetadata metadata;
if (!metadata.load_from_json(metadata_file.string())) continue;
if (!load_bundle_metadata(metadata_file, metadata)) continue;
metadata.print_presets.clear();
metadata.filament_presets.clear();
metadata.printer_presets.clear();
@@ -1654,10 +1663,12 @@ PresetsConfigSubstitutions PresetBundle::import_presets(std::vector<std::string>
if (ec) BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " create directory failed: " << ec.message();
//create temp folder
//std::string user_default_temp_dir = data_dir() + "/" + PRESET_USER_DIR + "/" + DEFAULT_USER_FOLDER_NAME + "/" + "temp";
fs::path temp_folder(configs_folder / "temp");
// Under cache/, per process and per import, so two instances importing
// at once do not clear each other's extraction and no preset scan reads it.
static std::atomic<unsigned> import_counter{0};
fs::path temp_folder(fs::path(data_dir()) / "cache" / ("import." + std::to_string(get_current_pid()) + "." + std::to_string(import_counter++)));
std::string user_default_temp_dir = temp_folder.make_preferred().string();
if (fs::exists(temp_folder)) fs::remove_all(temp_folder);
fs::create_directory(temp_folder, ec);
fs::create_directories(temp_folder, ec);
if (ec) BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " create directory failed: " << ec.message();
file = boost::filesystem::path(file).make_preferred().string();
@@ -1669,6 +1680,9 @@ PresetsConfigSubstitutions PresetBundle::import_presets(std::vector<std::string>
status = mz_zip_reader_init_cfile(&zip_archive, zipFile, 0, MZ_ZIP_FLAG_CASE_SENSITIVE | MZ_ZIP_FLAG_IGNORE_PATH);
if (MZ_FALSE == status) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " Failed to initialize reader ZIP archive";
if (zipFile != nullptr)
std::fclose(zipFile);
fs::remove_all(temp_folder, ec);
return substitutions;
} else {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " Success to initialize reader ZIP archive";
@@ -2276,10 +2290,9 @@ void PresetBundle::remove_user_presets_directory(const std::string preset_folder
return;
}
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" enter, delete directory : %1%") % dir_user_presets;
fs::path folder(dir_user_presets);
if (fs::exists(folder)) {
fs::remove_all(folder);
}
boost::system::error_code ec;
InstanceLock instance_lock(user_presets_lock_path());
fs::remove_all(fs::path(dir_user_presets), ec);
}
void PresetBundle::update_system_preset_setting_ids(std::map<std::string, std::map<std::string, std::string>>& system_presets)
@@ -8213,9 +8226,13 @@ bool BundleMetadata::save_to_json(const std::string& path) const
j["filament_presets"] = strip_prefix(this->filament_presets);
j["printer_presets"] = strip_prefix(this->printer_presets);
boost::nowide::ofstream ofs(path);
ofs << j.dump(4);
return ofs.good();
const std::string content = j.dump(4);
InstanceLock instance_lock(user_presets_lock_path());
if (const std::error_code ec = write_file_atomically(path, content)) {
BOOST_LOG_TRIVIAL(error) << "Failed to save bundle metadata to " << path << ": " << ec.message();
return false;
}
return true;
} catch (const std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "Failed to save bundle metadata to " << path << ": " << e.what();
return false;
+6 -28
View File
@@ -400,46 +400,24 @@ bool write_cache_blob(const std::string& path, const std::string& blob)
{
boost::crc_32_type crc;
crc.process_bytes(blob.data(), blob.size());
// Written beside the target and moved into place, as AppConfig::save does:
// a cache is truncated and rewritten in full, so a write that dies partway
// would otherwise leave a header claiming more body than the file holds.
// The PID suffix also keeps two instances writing the same vendor from
// interleaving.
const std::string tmp_path = path + "." + std::to_string(get_current_pid()) + ".tmp";
// Written beside the target and moved into place: a cache is truncated and
// rewritten in full, so a write that dies partway would otherwise leave a
// header claiming more body than the file holds.
try {
boost::filesystem::create_directories(boost::filesystem::path(path).parent_path());
{
boost::nowide::ofstream ofs(tmp_path, std::ios::binary | std::ios::trunc);
if (!ofs.is_open()) {
BOOST_LOG_TRIVIAL(warning) << "VendorCacheFile: cannot open for writing: " << tmp_path;
return false;
}
CacheFileHeader fhdr;
fhdr.magic = CACHE_MAGIC;
fhdr.version = CACHE_VERSION;
fhdr.data_size = static_cast<uint64_t>(blob.size());
fhdr.crc32 = crc.checksum();
ofs.write(reinterpret_cast<const char*>(&fhdr), sizeof(fhdr));
ofs.write(blob.data(), static_cast<std::streamsize>(blob.size()));
ofs.close(); // flush; close() raises failbit on error
if (! ofs.good()) {
BOOST_LOG_TRIVIAL(warning) << "VendorCacheFile: write failed (" << tmp_path << ")";
boost::system::error_code ec;
boost::filesystem::remove(tmp_path, ec);
return false;
}
}
if (const std::error_code ec = rename_file(tmp_path, path)) {
BOOST_LOG_TRIVIAL(warning) << "VendorCacheFile: could not move " << tmp_path << " into place: " << ec.message();
boost::system::error_code rm;
boost::filesystem::remove(tmp_path, rm);
const std::string_view header(reinterpret_cast<const char*>(&fhdr), sizeof(fhdr));
if (const std::error_code ec = write_file_atomically(path, { header, std::string_view(blob) }, /*binary=*/true)) {
BOOST_LOG_TRIVIAL(warning) << "VendorCacheFile: write failed (" << path << "): " << ec.message();
return false;
}
return true;
} catch (const std::exception& e) {
BOOST_LOG_TRIVIAL(warning) << "VendorCacheFile: write failed (" << path << "): " << e.what();
boost::system::error_code ec;
boost::filesystem::remove(tmp_path, ec);
return false;
}
}
+2 -23
View File
@@ -11582,20 +11582,8 @@ void DynamicPrintConfig::update_diff_values_to_child_config(DynamicPrintConfig&
else
variant_index.resize(1, 0);
// A parent variant the child does not list (the parent gained it after the child was saved, or the
// child lists none) takes the child's first variant of the same extruder, as slicing does in
// get_config_index_base. Left unmatched, the parent's value would silently replace the user's.
auto same_extruder = [&](int i, int child_extruder_id) {
return cur_extruder_ids.empty() || child_extruder_id < 0 ||
(i < int(cur_extruder_ids.size()) && cur_extruder_ids[i] == child_extruder_id);
};
if (target_variant_count == 0) {
// The child's one value belongs to the extruder of the parent's first variant.
const int child_extruder_id = cur_extruder_ids.empty() ? -1 : cur_extruder_ids[0];
for (int i = 0; i < int(variant_index.size()); i++)
if (i == 0 || same_extruder(i, child_extruder_id))
variant_index[i] = 0;
variant_index[0] = 0;
}
else if ((cur_extruder_ids.size() > 0) && cur_variant_count != cur_extruder_ids.size()){
//should not happen
@@ -11613,22 +11601,13 @@ void DynamicPrintConfig::update_diff_values_to_child_config(DynamicPrintConfig&
for (int j = 0; j < target_variant_count; j++)
{
if ((cur_extruder_variants[i] == target_extruder_variants[j])
&&(cur_extruder_ids.empty() || target_extruder_ids.empty() || (cur_extruder_ids[i] == target_extruder_ids[j])))
&&(cur_extruder_ids.empty() || (cur_extruder_ids[i] == target_extruder_ids[j])))
{
variant_index[i] = j;
break;
}
}
}
for (int i = 0; i < cur_variant_count; i++) {
if (variant_index[i] != -1)
continue;
for (int j = 0; j < target_variant_count; j++)
if (same_extruder(i, target_extruder_ids.empty() ? -1 : target_extruder_ids[j])) {
variant_index[i] = j;
break;
}
}
}
const t_config_option_keys &keys = new_config.keys();
+17
View File
@@ -8,6 +8,8 @@
#include <functional>
#include <type_traits>
#include <system_error>
#include <initializer_list>
#include <string_view>
#include <regex>
#include <boost/system/error_code.hpp>
@@ -224,6 +226,21 @@ extern std::vector<std::string> split_string(const std::string &str, char delimi
// On Windows, the file explorer (or anti-virus or whatever else) often locks the file
// for a short while, so the file may not be movable. Retry while we see recoverable errors.
extern std::error_code rename_file(const std::string &from, const std::string &to);
// Write `chunks`, in order, to `path` through a temporary file beside it that is
// then renamed over the target, so a concurrent reader sees the old or the new
// file, never a partial one. The temporary is removed on failure and an existing
// target keeps its permissions. Text mode unless `binary`, so Windows writes CRLF
// as the streams this replaces did. A target that is not a regular file (a
// device or pipe) is written in place, since replacing it would change what it
// is, and so is an existing target beside which no temporary can be created or
// whose replace the filesystem refuses; a symlink is followed and the file it
// names is replaced. On Windows a reader holding the
// target open without sharing its deletion, which the C runtime does not, makes
// the replace fall back to the in-place write too, so an unlocked reader there
// can still see a partial file.
extern std::error_code write_file_atomically(const std::string &path, std::initializer_list<std::string_view> chunks, bool binary = false);
inline std::error_code write_file_atomically(const std::string &path, const std::string &content, bool binary = false)
{ return write_file_atomically(path, { std::string_view(content) }, binary); }
enum CopyFileResult {
SUCCESS = 0,
+90 -2
View File
@@ -9,6 +9,8 @@
#include <stdio.h>
#include <filesystem>
#include <sstream>
#include <cerrno>
#include <mutex>
#include <iomanip>
#include <algorithm>
#include <cmath>
@@ -703,13 +705,99 @@ namespace WindowsSupport
std::error_code rename_file(const std::string &from, const std::string &to)
{
#ifdef _WIN32
// Retries and moves an open destination aside itself.
return WindowsSupport::rename(from, to);
#else
boost::nowide::remove(to.c_str());
return std::make_error_code(static_cast<std::errc>(boost::nowide::rename(from.c_str(), to.c_str())));
// rename(2) replaces an existing target atomically; removing it first would
// leave a window in which the file does not exist at all.
if (boost::nowide::rename(from.c_str(), to.c_str()) == 0)
return {};
const int err = errno;
// Some mounts (sshfs, gvfs, MTP and a few SMB setups) refuse to replace an
// existing target in one step, each with the error it sees fit; every error
// is worth the remove-then-rename this always did, except the ones no retry
// can help: nothing at the source, a different device, or a directory where
// a file was expected and the reverse.
const bool worth_retrying = err != ENOENT && err != EXDEV && err != ENOTDIR && err != EISDIR;
if (worth_retrying && boost::nowide::remove(to.c_str()) == 0 && boost::nowide::rename(from.c_str(), to.c_str()) == 0)
return {};
return std::make_error_code(static_cast<std::errc>(err));
#endif
}
static std::error_code write_whole_file(const std::string &path, std::initializer_list<std::string_view> chunks, bool binary)
{
errno = 0;
FILE *file = boost::nowide::fopen(path.c_str(), binary ? "wb" : "w");
if (file == nullptr)
return std::make_error_code(errno != 0 ? static_cast<std::errc>(errno) : std::errc::io_error);
bool ok = true;
for (const std::string_view chunk : chunks)
ok = ok && std::fwrite(chunk.data(), 1, chunk.size(), file) == chunk.size();
ok = ok && std::fflush(file) == 0;
const int err = ok ? 0 : errno;
ok = std::fclose(file) == 0 && ok;
if (ok)
return {};
return std::make_error_code(err != 0 ? static_cast<std::errc>(err) : std::errc::io_error);
}
// The in-place fallback truncates the target, so two threads of this process
// on the same file must not both be in it. One mutex for all such writes: they
// are the rare case. Never freed, like the InstanceLock registry, so a save
// during static destruction still finds it.
static std::error_code write_in_place(const std::string &path, std::initializer_list<std::string_view> chunks, bool binary)
{
static auto *mutex = new std::mutex();
std::lock_guard<std::mutex> guard(*mutex);
return write_whole_file(path, chunks, binary);
}
std::error_code write_file_atomically(const std::string &path, std::initializer_list<std::string_view> chunks, bool binary)
{
boost::system::error_code bec;
const boost::filesystem::file_status target = boost::filesystem::symlink_status(path, bec);
const bool target_exists = ! bec && boost::filesystem::exists(target);
if (target_exists && boost::filesystem::is_symlink(target)) {
// A config or preset kept in a dotfiles repository: the link stays,
// the file it points to is replaced like any other.
const boost::filesystem::path resolved = boost::filesystem::canonical(path, bec);
if (! bec && boost::filesystem::is_regular_file(resolved, bec))
return write_file_atomically(resolved.string(), chunks, binary);
}
if (target_exists && ! boost::filesystem::is_regular_file(target))
return write_in_place(path, chunks, binary);
// Unique per process and per call, so two threads writing one target
// without a lock never share a temporary.
static std::atomic<unsigned> counter{0};
const std::string tmp_path = path + "." + std::to_string(get_current_pid()) + "." + std::to_string(counter++) + ".tmp";
if (const std::error_code ec = write_whole_file(tmp_path, chunks, binary)) {
boost::nowide::remove(tmp_path.c_str());
if (! target_exists)
return ec;
// A directory that lets this process write its files but not create
// one: losing the save is worse than a reader seeing a partial file.
BOOST_LOG_TRIVIAL(warning) << "Cannot create a temporary beside " << path << " (" << ec.message() << "); writing in place";
return write_in_place(path, chunks, binary);
}
#ifndef _WIN32
// Not on Windows, where a read-only bit on the temporary would stop the rename itself.
if (target_exists)
boost::filesystem::permissions(tmp_path, target.permissions(), bec);
#endif
if (const std::error_code ec = rename_file(tmp_path, path)) {
boost::nowide::remove(tmp_path.c_str());
// A reader on Windows holding the target open without FILE_SHARE_DELETE,
// or a mount that cannot replace a file at all. Losing the save is worse
// than a reader seeing a partial file, so write in place the way this
// used to work before the atomic path existed.
BOOST_LOG_TRIVIAL(warning) << "Cannot replace " << path << " (" << ec.message() << "); writing in place";
return write_in_place(path, chunks, binary);
}
return {};
}
#ifdef __linux__
// Copied from boost::filesystem.
// Called by copy_file_linux() in case linux sendfile() API is not supported.
+18
View File
@@ -4,7 +4,25 @@
#include "3DBed.hpp"
#include "PartPlate.hpp"
#include <vector>
#include "libslic3r/Polyline.hpp"
#include "libslic3r/ExPolygon.hpp"
#include "libslic3r/Point.hpp"
#include "libslic3r/libslic3r.h"
#include <wx/colour.h>
#include <wx/brush.h>
#include <algorithm>
#include "libslic3r/Color.hpp"
#include <string>
#include <cstddef>
#include "slic3r/GUI/Gizmos/GLGizmoBase.hpp"
#include "slic3r/GUI/Widgets/StateColor.hpp"
#include <wx/dcbuffer.h>
#include <wx/panel.h>
#include <wx/wx.h>
#include <wx/gdicmn.h>
#include <wx/peninfobase.h>
#include <wx/font.h>
#include "libslic3r/BoundingBox.hpp"
#include "libslic3r/Geometry.hpp"
+4
View File
@@ -1,6 +1,10 @@
#ifndef slic3r_2DBed_hpp_
#define slic3r_2DBed_hpp_
#include <wx/panel.h>
#include "libslic3r/Point.hpp"
#include "libslic3r/Line.hpp"
#include <vector>
#include <wx/wx.h>
#include "libslic3r/Config.hpp"
#include "libslic3r/ExPolygon.hpp"
+16
View File
@@ -15,11 +15,27 @@
#include "Plater.hpp"
#include "Camera.hpp"
#include <boost/version.hpp>
#include <cstddef>
#include <array>
#include <glad/gl.h>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/log/trivial.hpp>
#include "slic3r/GUI/GLModel.hpp"
#include <vector>
#include "libslic3r/Point.hpp"
#include <utility>
#include "libslic3r/Color.hpp"
#include "slic3r/GUI/ImGuiWrapper.hpp"
#include "slic3r/GUI/GLShader.hpp"
#include "slic3r/GUI/3DScene.hpp"
#include "libslic3r/Geometry.hpp"
#include <math.h>
#include <tuple>
#include "libslic3r/Preset.hpp"
#include "libslic3r/Config.hpp"
#if BOOST_VERSION >= 107800
#include <boost/timer/timer.hpp>
+5
View File
@@ -8,8 +8,13 @@
#include "libslic3r/BuildVolume.hpp"
#include "libslic3r/ExPolygon.hpp"
#include "libslic3r/Color.hpp"
#include "libslic3r/Point.hpp"
#include <string>
#include "libslic3r/BoundingBox.hpp"
#include <tuple>
#include <array>
#include <vector>
namespace Slic3r {
namespace GUI {
+31
View File
@@ -1,3 +1,7 @@
#include <array>
#include <algorithm>
#include <functional>
#include <cmath>
#include <glad/gl.h>
#include "3DScene.hpp"
@@ -25,6 +29,30 @@
#include "libslic3r/Tesselate.hpp"
#include "libslic3r/PrintConfig.hpp"
#include "libslic3r/BoundingBox.hpp"
#include "libslic3r/TriangleMeshSlicer.hpp"
#include "libslic3r/Polygon.hpp"
#include "libslic3r/Point.hpp"
#include "slic3r/GUI/ImGuiWrapper.hpp"
#include "libslic3r/Model.hpp"
#include "libslic3r/Technologies.hpp"
#include <optional>
#include "slic3r/GUI/OpenGLManager.hpp"
#include "libslic3r/Config.hpp"
#include <memory>
#include "slic3r/GUI/MeshUtils.hpp"
#include "libslic3r/TriangleMesh.hpp"
#include <math.h>
#include "libslic3r/ObjectID.hpp"
#include "libslic3r/libslic3r.h"
#include <map>
#include <set>
#include <iterator>
#include "libslic3r/Color.hpp"
#include "slic3r/GUI/GUI_ObjectList.hpp"
#include "libslic3r/Line.hpp"
#include "libslic3r/Polyline.hpp"
#include "libslic3r/Exception.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -36,6 +64,9 @@
#include <boost/algorithm/string/predicate.hpp>
#include <Eigen/Dense>
#include <vector>
#include <utility>
#include <string>
#ifdef HAS_GLSAFE
void glAssertRecentCallImpl(const char* file_name, unsigned int line, const char* function_name)
+9
View File
@@ -16,8 +16,17 @@
#include "GLShader.hpp"
#include "MeshUtils.hpp"
#include <array>
#include <cstddef>
#include <cmath>
#include <functional>
#include <map>
#include "libslic3r/BoundingBox.hpp"
#include <memory>
#include <optional>
#include <vector>
#include <string>
#include <utility>
#ifndef NDEBUG
#define HAS_GLSAFE
+31
View File
@@ -19,7 +19,38 @@
#include "libslic3r/PresetBundle.hpp"
#include "libslic3r/Preset.hpp"
#include <algorithm>
#include <boost/log/trivial.hpp>
#include <string>
#include "slic3r/GUI/DeviceCore/DevDefs.h"
#include <wx/string.h>
#include <wx/event.h>
#include <wx/panel.h>
#include <wx/colour.h>
#include "slic3r/GUI/Widgets/StateColor.hpp"
#include <wx/gdicmn.h>
#include "libslic3r/Exception.hpp"
#include <wx/dcclient.h>
#include "slic3r/GUI/GUI_Utils.hpp"
#include <wx/toplevel.h>
#include <wx/scrolwin.h>
#include "slic3r/GUI/Widgets/AMSItem.hpp"
#include <wx/chartype.h>
#include "slic3r/GUI/Widgets/Button.hpp"
#include <utility>
#include <chrono>
#include <optional>
#include <wx/timer.h>
#include "libslic3r/Utils.hpp"
#include <unordered_set>
#include <vector>
#include <set>
#include <sstream>
#include <ios>
#include <iomanip>
#include "slic3r/GUI/DeviceCore/DevConfigUtil.h"
#include <limits>
#include <memory>
namespace Slic3r { namespace GUI {
+18
View File
@@ -9,7 +9,25 @@
#include "slic3r/GUI/I18N.hpp" // Orca: explicit _L() catalog include
#include <chrono>
#include <memory>
#include "libslic3r/PresetBundle.hpp"
#include <map>
#include <optional>
#include <wx/panel.h>
#include <wx/string.h>
#include <string>
#include <wx/event.h>
#include <vector>
#include "slic3r/GUI/GUI_Utils.hpp"
#include <wx/gdicmn.h>
#include <wx/simplebook.h>
#include "slic3r/GUI/Widgets/ComboBox.hpp"
#include "slic3r/GUI/Widgets/Button.hpp"
#include <wx/timer.h>
#include "slic3r/GUI/DeviceCore/DevDefs.h"
#include <unordered_map>
#include <wx/colour.h>
#include <wx/scrolwin.h>
//Previous defintions
+40
View File
@@ -8,8 +8,48 @@
#include "I18N.hpp"
#include <algorithm>
#include <boost/log/trivial.hpp>
#include <string>
#include <sstream>
#include <ios>
#include <iomanip>
#include <wx/checklst.h>
#include "slic3r/GUI/GUI_Utils.hpp"
#include "slic3r/GUI/Widgets/Button.hpp"
#include "slic3r/GUI/Widgets/Label.hpp"
#include <utility>
#include "slic3r/GUI/wxExtensions.hpp"
#include "slic3r/GUI/Widgets/HyperLink.hpp"
#include <cstdlib>
#include <cstdio>
#include "slic3r/GUI/DeviceCore/DevDefs.h"
#include "libslic3r/calib.hpp"
#include "libslic3r/Config.hpp"
#include <vector>
#include <unordered_map>
#include <wx/arrstr.h>
#include <set>
#include "slic3r/GUI/DeviceCore/DevConfigUtil.h"
#include <cstddef>
#include <climits>
#include "libslic3r/PrintConfig.hpp"
#include <cmath>
#include "slic3r/GUI/Widgets/PopupWindow.hpp"
#include "slic3r/GUI/Widgets/StaticBox.hpp"
#include <wx/colordlg.h>
#include <wx/dcclient.h>
#include <wx/dc.h>
#include <wx/colour.h>
#include <wx/colourdata.h>
#include <wx/dcgraph.h>
#include <wx/event.h>
#include <wx/gdicmn.h>
#include <wx/toplevel.h>
#include <wx/panel.h>
#include <wx/textctrl.h>
#include <wx/string.h>
#include <wx/valtext.h>
#include <wx/sizer.h>
#include <wx/peninfobase.h>
#include "CalibUtils.hpp"
#include "../Utils/ColorSpaceConvert.hpp"
#include "EncodedFilament.hpp"
+15
View File
@@ -16,6 +16,21 @@
#include "Widgets/TextInput.hpp"
#include "Widgets/HyperLink.hpp"
#include "slic3r/Utils/CalibUtils.hpp"
#include <wx/colour.h>
#include <vector>
#include <wx/checklst.h>
#include <wx/gdicmn.h>
#include <wx/event.h>
#include <wx/dc.h>
#include "slic3r/GUI/Widgets/PopupWindow.hpp"
#include "slic3r/GUI/Widgets/StaticBox.hpp"
#include <wx/sizer.h>
#include <wx/string.h>
#include <string>
#include "libslic3r/calib.hpp"
#include "slic3r/GUI/Widgets/StateColor.hpp"
#include <wx/panel.h>
#include <map>
#define AMS_MATERIALS_SETTING_DEF_COLOUR wxColour(255, 255, 255)
#define AMS_MATERIALS_SETTING_GREY900 wxColour(38, 46, 48)
+13
View File
@@ -2,6 +2,7 @@
#include "GUI_App.hpp"
#include "I18N.hpp"
#include "libslic3r_version.h"
#include "slic3r/GUI/DeviceCore/DevExtruderSystem.h"
#include "slic3r/GUI/DeviceCore/DevFilaSystem.h"
#include "slic3r/GUI/DeviceCore/DevManager.h"
@@ -11,6 +12,18 @@
#include "slic3r/GUI/Widgets/AnimaController.hpp"
#include "slic3r/GUI/Widgets/Label.hpp"
#include "slic3r/GUI/Widgets/ComboBox.hpp"
#include <wx/checklst.h>
#include <wx/gdicmn.h>
#include "slic3r/GUI/GUI_Utils.hpp"
#include <wx/string.h>
#include <wx/panel.h>
#include "slic3r/GUI/Widgets/CheckBox.hpp"
#include <wx/tglbtn.h>
#include "slic3r/GUI/wxExtensions.hpp"
#include "slic3r/GUI/DeviceCore/DevFilaAmsSetting.h"
#include "slic3r/GUI/DeviceCore/DevConfigUtil.h"
#include <wx/event.h>
#include <vector>
namespace Slic3r { namespace GUI {
+9
View File
@@ -12,6 +12,15 @@
#include "Widgets/CheckBox.hpp"
#include "slic3r/GUI/DeviceCore/DevFilaAmsSetting.h"
#include <wx/checklst.h>
#include <wx/gdicmn.h>
#include <wx/dialog.h>
#include <string>
#include <wx/event.h>
#include <wx/panel.h>
#include <wx/sizer.h>
#include <memory>
#include <unordered_map>
#define AMS_SETTING_DEF_COLOUR wxColour(255, 255, 255)
#define AMS_SETTING_GREY800 wxColour(50, 58, 61)
+8
View File
@@ -1,6 +1,14 @@
#include "AVVideoDecoder.hpp"
#include <algorithm>
#include <assert.h>
#include "slic3r/GUI/Printer/BambuTunnel.h"
#include <cstdio>
#include <cstring>
#include <cstddef>
#include <wx/image.h>
#include <wx/gdicmn.h>
#include <cstdint>
extern "C"
{
+1
View File
@@ -2,6 +2,7 @@
#define AVVIDEODECODER_HPP
#include "Printer/BambuTunnel.h"
#include <cstdint>
extern "C" {
#include <libavcodec/avcodec.h>
+18
View File
@@ -9,8 +9,26 @@
#include "MainFrame.hpp"
#include "format.hpp"
#include "Widgets/Button.hpp"
#include "libslic3r_version.h"
#include "slic3r/GUI/GUI_Utils.hpp"
#include "libslic3r/libslic3r.h"
#include "slic3r/GUI/wxExtensions.hpp"
#include "slic3r/GUI/Widgets/Label.hpp"
#include <vector>
#include <wx/clipbrd.h>
#include <wx/panel.h>
#include <wx/wx.h>
#include <wx/gdicmn.h>
#include <wx/event.h>
#include <wx/dcclient.h>
#include <wx/dialog.h>
#include <wx/toplevel.h>
#include <wx/sizer.h>
#include <wx/html/htmlwin.h>
#include <wx/string.h>
#include <wx/colour.h>
#include <wx/dataobj.h>
namespace Slic3r {
namespace GUI {
+5
View File
@@ -1,6 +1,11 @@
#ifndef slic3r_GUI_AboutDialog_hpp_
#define slic3r_GUI_AboutDialog_hpp_
#include <wx/panel.h>
#include <wx/event.h>
#include <string>
#include <vector>
#include <wx/string.h>
#include <wx/wx.h>
#include <wx/intl.h>
#include <wx/html/htmlwin.h>
+9
View File
@@ -12,10 +12,19 @@
#include "Tab.hpp"
#include "slic3r/plugin/PluginManager.hpp"
#include <cassert>
#include <boost/filesystem/operations.hpp>
#include <libslic3r/AppConfig.hpp>
#include <libslic3r/Config.hpp>
#include "slic3r/plugin/PluginDescriptor.hpp"
#include <memory>
#include "libslic3r/Preset.hpp"
#include "slic3r/GUI/PartPlate.hpp"
#include <slic3r/plugin/PythonPluginInterface.hpp>
#include <vector>
#include <utility>
#include <wx/app.h>
#include <wx/thread.h>
#include <boost/filesystem.hpp>
+33
View File
@@ -11,6 +11,36 @@
#include "MainFrame.hpp"
#include "format.hpp"
#include "Widgets/ProgressDialog.hpp"
#include <wx/event.h>
#include <wx/colour.h>
#include <string>
#include <wx/panel.h>
#include <wx/gdicmn.h>
#include <vector>
#include <boost/log/trivial.hpp>
#include <wx/dcclient.h>
#include <cstddef>
#include <wx/arrstr.h>
#include "slic3r/GUI/DeviceManager.hpp"
#include <math.h>
#include <cmath>
#include "slic3r/GUI/Widgets/StateColor.hpp"
#include <wx/peninfobase.h>
#include <wx/string.h>
#include "slic3r/GUI/Widgets/PopupWindow.hpp"
#include <wx/popupwin.h>
#include <wx/anybutton.h>
#include <wx/sizer.h>
#include <map>
#include "slic3r/GUI/DeviceCore/DevUtil.h"
#include <cstdlib>
#include "slic3r/GUI/DeviceCore/DevDefs.h"
#include "slic3r/GUI/wxExtensions.hpp"
#include "slic3r/GUI/GUI_Utils.hpp"
#include "slic3r/GUI/Widgets/SwitchButton.hpp"
#include <utility>
#include "slic3r/GUI/Widgets/AMSItem.hpp"
#include <unordered_map>
#include <wx/tooltip.h>
#include "Widgets/RoundedRectangle.hpp"
#include "Widgets/StaticBox.hpp"
@@ -23,6 +53,9 @@
#include <miniz.h>
#include <algorithm>
#include <optional>
#include <wx/wx.h>
#include <wx/toplevel.h>
#include <wx/wrapsizer.h>
#include "Plater.hpp"
#include "BitmapCache.hpp"
#include "BindDialog.hpp"
+10
View File
@@ -1,6 +1,16 @@
#ifndef slic3r_GUI_AmsMappingPopup_hpp_
#define slic3r_GUI_AmsMappingPopup_hpp_
#include <string>
#include <vector>
#include <wx/event.h>
#include <wx/dc.h>
#include <optional>
#include "libslic3r/ProjectTask.hpp"
#include "slic3r/GUI/DeviceCore/DevDefs.h"
#include <map>
#include <functional>
#include <memory>
#include <wx/wx.h>
#include <wx/intl.h>
#include <wx/collpane.h>
+12
View File
@@ -21,6 +21,17 @@
#include "Widgets/RoundedRectangle.hpp"
#include "Widgets/StaticBox.hpp"
#include <list>
#include <vector>
#include "slic3r/GUI/DeviceCore/DevDefs.h"
#include <boost/log/trivial.hpp>
#include <cstddef>
#include <string>
#include <cstdlib>
#include <exception>
#include <map>
#include "libslic3r/Config.hpp"
#include <wx/event.h>
#include <wx/progdlg.h>
#include <wx/clipbrd.h>
#include <wx/dcgraph.h>
@@ -28,6 +39,7 @@
#include <miniz.h>
#include <algorithm>
#include <optional>
#include <wx/wx.h>
#include "Plater.hpp"
#include "BitmapCache.hpp"
+3
View File
@@ -1,7 +1,10 @@
#include "AmsWidgets.hpp"
#include <map>
#include <string>
#include <wx/button.h>
#include <wx/sizer.h>
#include <wx/dataview.h>
#include <wx/variant.h>
#include "GUI_App.hpp"
#include "GUI_ObjectList.hpp"
+2
View File
@@ -2,6 +2,7 @@
#define slic3r_AmsWidgets_hpp_
#include <wx/arrstr.h>
#include <wx/notebook.h>
#include <wx/scrolwin.h>
#include <wx/sizer.h>
@@ -10,6 +11,7 @@
#include <wx/treectrl.h>
#include <wx/imaglist.h>
#include <wx/artprov.h>
#include <wx/variant.h>
#include <wx/xrc/xmlres.h>
#include <wx/string.h>
#include <wx/stattext.h>
+2
View File
@@ -1,4 +1,6 @@
#include "AuiPaneLayout.hpp"
#include <string>
#include <cstddef>
namespace Slic3r { namespace GUI {
+36
View File
@@ -4,17 +4,53 @@
#include "libslic3r/Model.hpp"
#include "libslic3r/Format/bbs_3mf.hpp"
#include <vector>
#include <string>
#include <memory>
#include <boost/filesystem/path.hpp>
#include "slic3r/GUI/Project.hpp"
#include "slic3r/GUI/Widgets/StateColor.hpp"
#include "slic3r/GUI/Field.hpp"
#include "slic3r/GUI/Widgets/TextInput.hpp"
#include "libslic3r/Preset.hpp"
#include <cstddef>
#include <cstring>
#include "slic3r/GUI/GUI.hpp"
#include <boost/filesystem/operations.hpp>
#include "slic3r/GUI/GUI_Utils.hpp"
#include <utility>
#include "slic3r/GUI/Widgets/AMSItem.hpp"
#include <iterator>
#include "slic3r/GUI/Widgets/Button.hpp"
#include <wx/anybutton.h>
#include "slic3r/GUI/Tabbook.hpp"
#include <ctime>
#include <map>
#include "slic3r/GUI/Printer/PrinterFileSystem.h"
#include "slic3r/GUI/Widgets/ComboBox.hpp"
#include <wx/app.h>
#include <wx/bookctrl.h>
#include <wx/button.h>
#include <wx/event.h>
#include <wx/gdicmn.h>
#include <wx/panel.h>
#include <wx/image.h>
#include <wx/dcclient.h>
#include <wx/notebook.h>
#include <wx/chartype.h>
#include <wx/scrolwin.h>
#include <wx/sizer.h>
#include <wx/bmpcbox.h>
#include <wx/bmpbuttn.h>
#include <wx/string.h>
#include <wx/stattext.h>
#include <wx/textctrl.h>
#include <wx/treectrl.h>
#include <wx/imaglist.h>
#include <wx/settings.h>
#include <wx/filedlg.h>
#include <wx/wrapsizer.h>
#include <wx/wupdlock.h>
#include <wx/dataview.h>
#include <wx/tokenzr.h>
+11
View File
@@ -2,6 +2,16 @@
#define slic3r_Auxiliary_hpp_
#include "Tabbook.hpp"
#include <array>
#include "slic3r/GUI/Widgets/TextInput.hpp"
#include <boost/filesystem/path.hpp>
#include <wx/bookctrl.h>
#include <wx/event.h>
#include <wx/dynarray.h>
#include "slic3r/GUI/Widgets/Button.hpp"
#include "slic3r/GUI/Widgets/ComboBox.hpp"
#include <string>
#include "slic3r/GUI/Printer/PrinterFileSystem.h"
#include <wx/notebook.h>
#include <wx/scrolwin.h>
#include <wx/sizer.h>
@@ -10,6 +20,7 @@
#include <wx/treectrl.h>
#include <wx/imaglist.h>
#include <wx/artprov.h>
#include <wx/wrapsizer.h>
#include <wx/xrc/xmlres.h>
#include <wx/string.h>
#include <wx/stattext.h>
+13
View File
@@ -4,9 +4,22 @@
#include "libslic3r/Format/bbs_3mf.hpp"
#include <array>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/directory.hpp>
#include <boost/log/trivial.hpp>
#include <wx/filefn.h>
#include <wx/dataview.h>
#include <map>
#include <wx/debug.h>
#include <cstddef>
#include <wx/arrstr.h>
#include <wx/log.h>
#include <wx/string.h>
#include <wx/variant.h>
#include <wx/types.h>
const static std::array<wxString, 4> s_default_folders = {
_L("Model Pictures"),
@@ -9,6 +9,12 @@
#include "I18N.hpp"
#include <boost/filesystem.hpp>
#include <wx/dynarray.h>
#include <boost/filesystem/path.hpp>
#include <cstddef>
#include <wx/string.h>
#include <wx/arrstr.h>
#include <wx/variant.h>
class AuxiliaryModelNode;
WX_DEFINE_ARRAY_PTR(AuxiliaryModelNode*, AuxiliaryModelNodePtrArray);
+5
View File
@@ -5,6 +5,11 @@
#include "libslic3r/Utils.hpp"
#include <boost/property_tree/ptree.hpp>
#include "slic3r/GUI/GUI_Utils.hpp"
#include <wx/wx.h>
#include <wx/gdicmn.h>
#include <wx/dialog.h>
#include <wx/toplevel.h>
namespace pt = boost::property_tree;
typedef pt::ptree JSON;
+6
View File
@@ -1,5 +1,11 @@
#include "BBLStatusBar.hpp"
#include <wx/panel.h>
#include <wx/event.h>
#include <wx/gdicmn.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <string>
#include <wx/timer.h>
#include <wx/gauge.h>
#include <wx/button.h>
+5
View File
@@ -1,5 +1,10 @@
#include "BBLStatusBarBind.hpp"
#include <wx/panel.h>
#include <wx/event.h>
#include <wx/sizer.h>
#include "slic3r/GUI/Widgets/Label.hpp"
#include <string>
#include <wx/timer.h>
#include <wx/gauge.h>
#include <wx/button.h>
+1
View File
@@ -2,6 +2,7 @@
#define BBLStatusBarBind_HPP
#include <wx/panel.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/simplebook.h>
+10
View File
@@ -1,5 +1,15 @@
#include "BBLStatusBarPrint.hpp"
#include <wx/event.h>
#include <wx/panel.h>
#include <wx/sizer.h>
#include <wx/string.h>
#include "slic3r/GUI/Widgets/Label.hpp"
#include "slic3r/GUI/Widgets/StateColor.hpp"
#include <utility>
#include "slic3r/GUI/Widgets/Button.hpp"
#include "slic3r/GUI/wxExtensions.hpp"
#include <cstddef>
#include <wx/timer.h>
#include <wx/gauge.h>
#include <wx/button.h>
+2
View File
@@ -1,7 +1,9 @@
#ifndef BBLStatusBarPrint_HPP
#define BBLStatusBarPrint_HPP
#include <wx/event.h>
#include <wx/panel.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <memory>
+8
View File
@@ -1,5 +1,13 @@
#include "BBLStatusBarSend.hpp"
#include <wx/event.h>
#include <wx/panel.h>
#include <wx/sizer.h>
#include <wx/string.h>
#include "slic3r/GUI/Widgets/Label.hpp"
#include "slic3r/GUI/Widgets/Button.hpp"
#include "slic3r/GUI/wxExtensions.hpp"
#include <cstddef>
#include <wx/timer.h>
#include <wx/gauge.h>
#include <wx/button.h>
+2
View File
@@ -1,7 +1,9 @@
#ifndef BBLSTATUSBARSEND_HPP
#define BBLSTATUSBARSEND_HPP
#include <wx/event.h>
#include <wx/panel.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <memory>
+12
View File
@@ -2,7 +2,19 @@
#include "wx/artprov.h"
#include "wx/aui/framemanager.h"
#include "wx/display.h"
#include <wx/gdicmn.h>
#include <wx/event.h>
#include <wx/dcbuffer.h>
#include <wx/dc.h>
#include <wx/aui/auibar.h>
#include "slic3r/GUI/Widgets/StateColor.hpp"
#include <wx/settings.h>
#include "slic3r/GUI/Widgets/Label.hpp"
#include <wx/image.h>
#include <wx/string.h>
#include <cstddef>
#include <wx/utils.h>
#include <wx/window.h>
#include "I18N.hpp"
#include "GUI_App.hpp"
#include "GUI.hpp"
+3
View File
@@ -7,6 +7,9 @@
#include "DeviceManager.hpp"
#include <wx/control.h>
#include <wx/string.h>
#include <wx/gdicmn.h>
#include <wx/event.h>
using namespace Slic3r::GUI;
@@ -4,8 +4,26 @@
#include "MainFrame.hpp"
#include "format.hpp"
#include <cstddef>
#include <exception>
#include "libslic3r/Config.hpp"
#include <cstdint>
#include <functional>
#include <libslic3r/Exception.hpp>
#include <utility>
#include <string>
#include <vector>
#include <new>
#include "libslic3r/GCode/ThumbnailData.hpp"
#include "libslic3r/PrintConfig.hpp"
#include "libslic3r/Zipper.hpp"
#include <mutex>
#include "libslic3r/PrintBase.hpp"
#include <ostream>
#include <memory>
#include "libslic3r/Polygon.hpp"
#include <wx/app.h>
#include <wx/event.h>
#include <wx/panel.h>
#include <wx/stdpaths.h>
@@ -36,6 +54,7 @@
#include "I18N.hpp"
// #include "RemovableDriveManager.hpp"
#include "libslic3r_version.h"
#include "slic3r/GUI/Plater.hpp"
namespace Slic3r {
@@ -1,12 +1,21 @@
#ifndef slic3r_GUI_BackgroundSlicingProcess_hpp_
#define slic3r_GUI_BackgroundSlicingProcess_hpp_
#include <exception>
#include <cassert>
#include <cstddef>
#include "libslic3r/Config.hpp"
#include "libslic3r/Polygon.hpp"
#include <memory>
#include <functional>
#include <string>
#include <condition_variable>
#include <mutex>
#include <boost/thread.hpp>
#include <utility>
#include <vector>
#include <wx/event.h>
#include "libslic3r/PrintBase.hpp"
@@ -1,7 +1,14 @@
#include "BaseTransparentDPIFrame.hpp"
#include "slic3r/GUI/GUI_Utils.hpp"
#include "slic3r/GUI/Widgets/StateColor.hpp"
#include "slic3r/GUI/wxExtensions.hpp"
#include "slic3r/GUI/Widgets/Label.hpp"
#include "slic3r/GUI/Event.hpp"
#include <thread>
#include <wx/dcclient.h>
#include <wx/event.h>
#include <wx/gdicmn.h>
#include <wx/sizer.h>
#include <wx/slider.h>
#include <wx/dcmemory.h>
@@ -14,6 +21,9 @@
#include "Widgets/TextInput.hpp"
#include "Notebook.hpp"
#include <chrono>
#include <wx/string.h>
#include <wx/toplevel.h>
#include <wx/timer.h>
#include "Widgets/Button.hpp"
#include "Widgets/CheckBox.hpp"
#include "CapsuleButton.hpp"
@@ -2,9 +2,13 @@
#define _BaseTransparentDPIFrame_H_
#include <future>
#include "slic3r/GUI/Event.hpp"
#include <thread>
#include "GUI_App.hpp"
#include "GUI_Utils.hpp"
#include <wx/gdicmn.h>
#include <wx/string.h>
#include <wx/sizer.h>
#include <wx/timer.h>
class Button;
+24
View File
@@ -2,6 +2,30 @@
#include "GUI_App.hpp"
#include "OptionsGroup.hpp"
#include "libslic3r/Point.hpp"
#include <string>
#include <cassert>
#include "libslic3r/Config.hpp"
#include <utility>
#include <wx/string.h>
#include "libslic3r/BuildVolume.hpp"
#include "slic3r/GUI/Field.hpp"
#include <wx/event.h>
#include <wx/gdicmn.h>
#include "slic3r/GUI/Widgets/Button.hpp"
#include <wx/panel.h>
#include <wx/bookctrl.h>
#include "slic3r/GUI/2DBed.hpp"
#include <memory>
#include <boost/filesystem/operations.hpp>
#include <boost/any.hpp>
#include <exception>
#include "libslic3r/libslic3r.h"
#include <vector>
#include <cmath>
#include <wx/filedlg.h>
#include "slic3r/GUI/GUI.hpp"
#include <wx/busycursor.h>
#include <wx/wx.h>
#include <wx/numformatter.h>
#include <wx/sizer.h>
+9
View File
@@ -11,8 +11,17 @@
#include "Widgets/ComboBox.hpp"
#include <memory>
#include "libslic3r/Point.hpp"
#include <string>
#include <vector>
#include "libslic3r/Config.hpp"
#include <wx/dialog.h>
#include <wx/panel.h>
#include <wx/event.h>
#include <wx/gdicmn.h>
#include <wx/simplebook.h> // ORCA
#include <wx/string.h>
namespace Slic3r {
namespace GUI {
+34
View File
@@ -1,10 +1,44 @@
#include "BindDialog.hpp"
#include "GUI_App.hpp"
#include "slic3r/GUI/GUI_Utils.hpp"
#include <wx/intl.h>
#include <wx/gdicmn.h>
#include <wx/toplevel.h>
#include <wx/panel.h>
#include <wx/simplebook.h>
#include "slic3r/GUI/Widgets/Label.hpp"
#include "slic3r/GUI/Widgets/HyperLink.hpp"
#include "slic3r/GUI/Widgets/TextInput.hpp"
#include <wx/string.h>
#include <wx/textctrl.h>
#include <wx/event.h>
#include "slic3r/GUI/Widgets/Button.hpp"
#include <cstddef>
#include <wx/utils.h>
#include "slic3r/GUI/MsgDialog.hpp"
#include "slic3r/GUI/Widgets/StaticBox.hpp"
#include "slic3r/GUI/wxExtensions.hpp"
#include <wx/wrapsizer.h>
#include "slic3r/GUI/Widgets/CheckBox.hpp"
#include "slic3r/GUI/ReleaseNote.hpp"
#include <wx/tglbtn.h>
#include <memory>
#include "slic3r/GUI/BBLStatusBarBind.hpp"
#include "slic3r/GUI/Jobs/BindJob.hpp"
#include "slic3r/GUI/Printer/PrinterFileSystem.h"
#include "slic3r/GUI/DeviceCore/DevDefs.h"
#include "slic3r/GUI/Jobs/Worker.hpp"
#include <utility>
#include "slic3r/GUI/GUI.hpp"
#include <wx/image.h>
#include <wx/stattext.h>
#include <wx/wx.h>
#include <wx/mstream.h>
#include <wx/sizer.h>
#include <wx/statbox.h>
#include "bambu_networking.hpp"
#include "Http.hpp"
#include "wx/evtloop.h"
#include <wx/tokenzr.h>
#include <wx/richmsgdlg.h>
+7
View File
@@ -3,9 +3,16 @@
#include "I18N.hpp"
#include <cstddef>
#include "slic3r/GUI/Widgets/Label.hpp"
#include <memory>
#include <wx/event.h>
#include "slic3r/GUI/Widgets/StaticBox.hpp"
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/panel.h>
#include <wx/settings.h>
#include <wx/simplebook.h>
#include <wx/string.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
+16
View File
@@ -5,8 +5,24 @@
#include "GUI.hpp"
#include "GUI_Utils.hpp"
#include <algorithm>
#include <boost/algorithm/string/replace.hpp>
#include <boost/nowide/cstdio.hpp>
#include <boost/filesystem.hpp>
#include <utility>
#include <string>
#include <wx/image.h>
#include <cstddef>
#include <wx/dcmemory.h>
#include <wx/gdicmn.h>
#include <map>
#include <cstdio>
#include <cstdlib>
#include "libslic3r/LocalesUtils.hpp"
#include <cstring>
#include <vector>
#include <cstdint>
#include <imgui.h>
#ifdef __WXGTK2__
// Broken alpha workaround
+3
View File
@@ -1,9 +1,12 @@
#ifndef SLIC3R_GUI_BITMAP_CACHE_HPP
#define SLIC3R_GUI_BITMAP_CACHE_HPP
#include <cstddef>
#include <map>
#include <string>
#include <vector>
#include <wx/colour.h>
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
+2
View File
@@ -5,6 +5,8 @@
#include <string>
#include <boost/algorithm/string.hpp>
#include <wx/bmpcbox.h>
#include <wx/gdicmn.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/textctrl.h>
+2
View File
@@ -1,8 +1,10 @@
#ifndef slic3r_BitmapComboBox_hpp_
#define slic3r_BitmapComboBox_hpp_
#include <cstddef>
#include <wx/bmpcbox.h>
#include <wx/gdicmn.h>
#include <wx/string.h>
#include "GUI_Utils.hpp"
+12
View File
@@ -2,15 +2,27 @@
#include "BonjourDialog.hpp"
#include "libslic3r/Config.hpp"
#include <memory>
#include <boost/asio/ip/address.hpp>
#include <cstddef>
#include <set>
#include <mutex>
#include <boost/nowide/convert.hpp>
#include <wx/event.h>
#include <utility>
#include <wx/gdicmn.h>
#include <wx/dialog.h>
#include "slic3r/GUI/Widgets/Label.hpp"
#include <wx/listbase.h>
#include <vector>
#include <wx/sizer.h>
#include <wx/listctrl.h>
#include <wx/stattext.h>
#include <wx/timer.h>
#include <wx/toplevel.h>
#include <wx/wupdlock.h>
#include "slic3r/GUI/GUI.hpp"
+3
View File
@@ -2,11 +2,14 @@
#define slic3r_BonjourDialog_hpp_
#include <cstddef>
#include "libslic3r/Config.hpp"
#include <memory>
#include <boost/asio/ip/address.hpp>
#include <vector>
#include <wx/dialog.h>
#include <wx/event.h>
#include <wx/string.h>
#include "libslic3r/PrintConfig.hpp"
+18
View File
@@ -15,14 +15,32 @@
#include "libslic3r/Config.hpp"
#include <boost/algorithm/string/predicate.hpp>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <wx/event.h>
#include <wx/gdicmn.h>
#include "libslic3r/CAD/SketchEngine.hpp"
#include <vector>
#include <memory>
#include <string>
#include <functional>
#include "libslic3r/Color.hpp"
#include "slic3r/GUI/CAD/DesignSketchTool.hpp"
#include "libslic3r/Point.hpp"
#include <utility>
#include "libslic3r/CAD/CadDocument.hpp"
#include "libslic3r/BoundingBox.hpp"
#include <wx/glcanvas.h>
#include <wx/panel.h>
#include <wx/stopwatch.h> // wxGetLocalTimeMillis: the right-click vs right-hold budget
#include <wx/sizer.h>
#include <wx/frame.h>
#include <wx/stattext.h>
#include <wx/string.h>
#include <wx/time.h>
#include <wx/toplevel.h>
#include <wx/window.h>
namespace Slic3r {
namespace GUI {
+8
View File
@@ -1,12 +1,20 @@
#ifndef slic3r_DesignCanvas_hpp_
#define slic3r_DesignCanvas_hpp_
#include <vector>
#include "libslic3r/Point.hpp"
#include "libslic3r/CAD/CadDocument.hpp"
#include "libslic3r/Color.hpp"
#include <utility>
#include <wx/colour.h>
#include <wx/event.h>
#include <wx/panel.h>
#include <wx/popupwin.h>
#include <functional>
#include <memory>
#include <string>
#include <wx/string.h>
#include "slic3r/GUI/3DBed.hpp"
#include "slic3r/GUI/Camera.hpp"
+38
View File
@@ -1,4 +1,5 @@
#include "slic3r/GUI/CAD/DesignPanel.hpp"
#include "libslic3r_version.h"
#include "slic3r/GUI/CAD/DesignCanvas.hpp"
#include "slic3r/GUI/CAD/DesignSketchTool.hpp"
#include "slic3r/GUI/CAD/DesignOffer.hpp" // generated offer table — see scripts/CAD/tool_atlas.json
@@ -7,6 +8,11 @@
#include "libslic3r/Format/OBJ.hpp"
#include "libslic3r/Format/bbs_3mf.hpp" // put_other_changes: mark the project dirty outside the undo stack
#include <TopoDS_Face.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Shape.hxx>
#include <Eigen/Geometry>
#include <TopAbs_Orientation.hxx>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/log/trivial.hpp> // the offer/atlas join check reports on the log
@@ -14,15 +20,45 @@
#include <cassert>
#include <cstdarg> // offer_trace: diagnostic row dump for the offer ladder
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include "libslic3r/CAD/SketchEngine.hpp"
#include "libslic3r/CAD/CadDocument.hpp"
#include "libslic3r/Point.hpp"
#include <cstdlib>
#include <exception>
#include "libslic3r/BoundingBox.hpp"
#include "libslic3r/Color.hpp"
#include "libslic3r/CAD/SketchSolver.hpp"
#include <map>
#include <math.h>
#include <set>
#include <wx/event.h>
#include <wx/gdicmn.h>
#include <wx/chartype.h>
#include <vector>
#include <wx/scrolwin.h>
#include <wx/anybutton.h>
#include "slic3r/GUI/Widgets/StateColor.hpp"
#include <utility>
#include <wx/listbase.h>
#include <wx/busycursor.h>
#include <wx/colourdata.h>
#include "slic3r/GUI/CAD/DesignInteraction.hpp"
#include <wx/sizer.h>
#include <wx/button.h>
#include <wx/spinbutt.h>
#include <wx/stattext.h>
#include <wx/checkbox.h>
#include <wx/checklst.h>
#include <wx/spinctrl.h>
#include <wx/listctrl.h>
#include <wx/string.h>
#include <wx/treebase.h>
#include <wx/tglbtn.h>
#include <wx/textctrl.h>
#include <wx/translation.h>
#include <wx/treectrl.h>
#include <wx/imaglist.h>
#include <wx/statline.h>
@@ -35,6 +71,7 @@
#include <wx/colordlg.h>
#include <wx/menu.h>
#include <wx/progdlg.h>
#include <wx/unichar.h>
#include <wx/utils.h> // wxWindowDisabler, wxMilliSleep
#include <wx/msgdlg.h> // wxMessageBox
@@ -45,6 +82,7 @@
#include <algorithm>
#include <thread>
#include <atomic>
#include <wx/window.h>
#include "slic3r/GUI/wxExtensions.hpp" // ScalableButton, create_scaled_bitmap
#include "slic3r/GUI/Widgets/Label.hpp" // HarmonyOS Sans fonts (Head_*/Body_*) shared with the rest of Orca
+9
View File
@@ -1,8 +1,17 @@
#ifndef slic3r_DesignPanel_hpp_
#define slic3r_DesignPanel_hpp_
#include <string>
#include "libslic3r/Point.hpp"
#include "libslic3r/CAD/SketchEngine.hpp"
#include "libslic3r/TriangleMesh.hpp"
#include <wx/accel.h>
#include <wx/event.h>
#include <wx/gdicmn.h>
#include <wx/colour.h>
#include <wx/panel.h>
#include <wx/scrolwin.h>
#include <wx/string.h>
#include <wx/treebase.h> // wxTreeItemId
#include <vector>
+18
View File
@@ -5,6 +5,11 @@
#include "slic3r/GUI/CAD/SketchInlineEditor.hpp"
#include "slic3r/GUI/Plater.hpp"
#include <Eigen/Core>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Edge.hxx>
#include <Eigen/Geometry>
#include <imgui/imgui.h>
#include <imgui/imgui_internal.h>
#include "libslic3r/BuildVolume.hpp"
@@ -15,6 +20,19 @@
#include "libslic3r/TriangleMesh.hpp"
#include <GL/glew.h>
#include "libslic3r/CAD/SketchEngine.hpp"
#include "libslic3r/Point.hpp"
#include <vector>
#include <math.h>
#include "libslic3r/CAD/SketchSolver.hpp"
#include "libslic3r/Line.hpp"
#include <string>
#include "libslic3r/CAD/SketchInference.hpp"
#include <utility>
#include "libslic3r/CAD/CadDocument.hpp"
#include "slic3r/GUI/GLModel.hpp"
#include "libslic3r/BoundingBox.hpp"
#include <initializer_list>
#include <wx/gdicmn.h>
#include <algorithm>
#include <climits>
+3
View File
@@ -8,7 +8,10 @@
#include "libslic3r/CAD/SketchSolver.hpp"
#include "slic3r/GUI/GLModel.hpp"
#include "slic3r/GUI/GLSelectionRectangle.hpp" // left-drag rubber band over the committed bodies
#include <Eigen/Core>
#include <functional>
#include "libslic3r/Color.hpp"
#include <math.h>
#include <vector>
#include <string>
#include <utility>
+7
View File
@@ -1,4 +1,11 @@
#include "slic3r/GUI/CAD/McpControl.hpp"
#include "libslic3r/Point.hpp"
#include <stdexcept>
#include <math.h>
#include <TopAbs_ShapeEnum.hxx>
#include <Standard_TypeDef.hxx>
#include <exception>
#include <cstdint>
#ifndef _WIN32 // POSIX Unix-domain-socket transport only (slice 1)
@@ -5,6 +5,7 @@
#include "slic3r/GUI/I18N.hpp"
#include "libslic3r/Color.hpp"
#include <functional>
#include <imgui/imgui.h>
#include <imgui/imgui_internal.h> // BringWindowToDisplayFront / GetCurrentWindow
@@ -12,6 +13,8 @@
#include <cstdlib>
#include <cstring>
#include <string>
#include <wx/gdicmn.h>
#include <utility>
namespace Slic3r {
namespace GUI {
+31
View File
@@ -8,7 +8,38 @@
#include "MsgDialog.hpp"
#include "slic3r/Utils/CalibUtils.hpp"
#include "Widgets/DialogButtons.hpp"
#include "libslic3r/Config.hpp"
#include <boost/log/trivial.hpp>
#include <string>
#include <vector>
#include "libslic3r/calib.hpp"
#include "slic3r/GUI/GUI_Utils.hpp"
#include <wx/event.h>
#include <wx/dialog.h>
#include "slic3r/GUI/Widgets/Button.hpp"
#include "slic3r/GUI/Widgets/SwitchButton.hpp"
#include "slic3r/GUI/Widgets/Label.hpp"
#include <array>
#include <cstdlib>
#include <cassert>
#include "slic3r/GUI/DeviceCore/DevDefs.h"
#include "slic3r/GUI/Widgets/TextInput.hpp"
#include "libslic3r/PrintConfig.hpp"
#include <algorithm>
#include <wx/arrstr.h>
#include <set>
#include <sstream>
#include <ios>
#include <iomanip>
#include <cstddef>
#include <cstdint>
#include <wx/gbsizer.h>
#include <wx/gdicmn.h>
#include <wx/tglbtn.h>
#include <wx/panel.h>
#include <wx/timer.h>
#include <wx/sizer.h>
#include <wx/string.h>
#include "Plater.hpp"
#include "DeviceCore/DevExtruderSystem.h"
+10
View File
@@ -6,6 +6,16 @@
#include "Widgets/ComboBox.hpp"
#include "Widgets/SwitchButton.hpp"
#include "DeviceManager.hpp"
#include <vector>
#include "libslic3r/calib.hpp"
#include <wx/event.h>
#include <wx/timer.h>
#include <wx/panel.h>
#include "slic3r/GUI/DeviceErrorDialog.hpp"
#include <string>
#include "slic3r/GUI/Widgets/TextInput.hpp"
#include <wx/arrstr.h>
#include <map>
namespace Slic3r {
namespace GUI {
+17
View File
@@ -12,6 +12,23 @@
#include "Widgets/StaticBox.hpp"
#include "DeviceCore/DevConfig.h"
#include <wx/colour.h>
#include "slic3r/GUI/GUI_Utils.hpp"
#include <wx/wx.h>
#include <wx/gdicmn.h>
#include <wx/toplevel.h>
#include <wx/panel.h>
#include "slic3r/GUI/Widgets/Label.hpp"
#include "slic3r/GUI/Widgets/AMSItem.hpp"
#include "slic3r/GUI/Widgets/StaticLine.hpp"
#include "slic3r/GUI/Widgets/StepCtrl.hpp"
#include <utility>
#include "slic3r/GUI/Widgets/Button.hpp"
#include <wx/event.h>
#include <wx/string.h>
#include <wx/stattext.h>
#include "slic3r/GUI/DeviceManager.hpp"
#include <boost/log/trivial.hpp>
static wxColour FG_COLOR = wxColour(0x32, 0x3A, 0x3D);
static wxColour BG_COLOR = wxColour(0xF8, 0xF8, 0xF8);
+4
View File
@@ -1,6 +1,10 @@
#ifndef slic3r_GUI_Calibration_hpp_
#define slic3r_GUI_Calibration_hpp_
#include <map>
#include <string>
#include <vector>
#include <wx/event.h>
#include <wx/wx.h>
#include <wx/intl.h>
#include <wx/collpane.h>
+29
View File
@@ -1,4 +1,33 @@
#include "libslic3r/calib.hpp"
#include "slic3r/GUI/Widgets/StateColor.hpp"
#include <wx/dcclient.h>
#include <wx/dc.h>
#include "slic3r/GUI/Widgets/Label.hpp"
#include "slic3r/GUI/Widgets/PopupWindow.hpp"
#include <boost/log/trivial.hpp>
#include "libslic3r/Thread.hpp"
#include <memory>
#include <vector>
#include <utility>
#include <algorithm>
#include "slic3r/GUI/Widgets/SideTools.hpp"
#include <cstddef>
#include "slic3r/GUI/Tabbook.hpp"
#include <wx/colour.h>
#include "slic3r/GUI/CalibrationWizard.hpp"
#include "slic3r/GUI/CalibrationWizardPage.hpp"
#include "slic3r/GUI/CalibrationWizardPresetPage.hpp"
#include "slic3r/GUI/CalibrationWizardSavePage.hpp"
#include <wx/dcgraph.h>
#include <wx/event.h>
#include <wx/string.h>
#include <wx/gdicmn.h>
#include <wx/panel.h>
#include <wx/popupwin.h>
#include <wx/sizer.h>
#include <wx/scrolwin.h>
#include <wx/timer.h>
#include <wx/notebook.h>
#include "GUI.hpp"
#include "GUI_App.hpp"
#include "MainFrame.hpp"
+2 -1
View File
@@ -4,7 +4,8 @@
#include "CalibrationWizard.hpp"
#include "Tabbook.hpp"
#include "Lazy.hpp"
//#include "Widgets/SideTools.hpp"
#include "SelectMachinePop.hpp"
#include "Widgets/SideTools.hpp"
namespace Slic3r { namespace GUI {
+29
View File
@@ -1,4 +1,5 @@
#include "CalibrationWizard.hpp"
#include "CalibUtils.hpp"
#include "I18N.hpp"
#include "GUI_App.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
@@ -7,6 +8,34 @@
#include "../../libslic3r/calib.hpp"
#include "Tabbook.hpp"
#include "CaliHistoryDialog.hpp"
#include <wx/event.h>
#include <wx/string.h>
#include <map>
#include "libslic3r/Preset.hpp"
#include <utility>
#include "libslic3r/PrintConfig.hpp"
#include "libslic3r/libslic3r.h"
#include <wx/gdicmn.h>
#include <wx/panel.h>
#include <wx/colour.h>
#include <wx/scrolwin.h>
#include <functional>
#include <boost/log/trivial.hpp>
#include <string>
#include "libslic3r/Config.hpp"
#include "slic3r/GUI/CalibrationWizardPresetPage.hpp"
#include <vector>
#include "slic3r/GUI/ReleaseNote.hpp"
#include <cassert>
#include "slic3r/GUI/CalibrationWizardStartPage.hpp"
#include "slic3r/GUI/CalibrationWizardCaliPage.hpp"
#include "slic3r/GUI/CalibrationWizardSavePage.hpp"
#include "slic3r/GUI/DeviceCore/DevCalib.h"
#include "slic3r/GUI/DeviceCore/DevDefs.h"
#include <wx/arrstr.h>
#include <algorithm>
#include "slic3r/GUI/GUI.hpp"
#include "libslic3r/ParameterUtils.hpp"
namespace Slic3r { namespace GUI {
+14
View File
@@ -10,6 +10,20 @@
#include "CalibrationWizardCaliPage.hpp"
#include "CalibrationWizardSavePage.hpp"
#include "StagedBuild.hpp"
#include <wx/panel.h>
#include "libslic3r/calib.hpp"
#include <wx/string.h>
#include <wx/gdicmn.h>
#include <wx/event.h>
#include <string>
#include <map>
#include "libslic3r/Config.hpp"
#include "libslic3r/PrintConfig.hpp"
#include <functional>
#include <wx/scrolwin.h>
#include <wx/sizer.h>
#include <vector>
#include "slic3r/GUI/ReleaseNote.hpp"
namespace Slic3r { namespace GUI {
@@ -1,9 +1,27 @@
#include "CalibrationWizardCaliPage.hpp"
#include "CalibUtils.hpp"
#include "MainFrame.hpp"
#include "I18N.hpp"
#include "Widgets/Label.hpp"
#include "DeviceCore/DevManager.h"
#include <wx/string.h>
#include "libslic3r/calib.hpp"
#include "slic3r/GUI/CalibrationWizardPage.hpp"
#include <wx/event.h>
#include <wx/gdicmn.h>
#include <wx/sizer.h>
#include <cstddef>
#include <wx/arrstr.h>
#include "slic3r/GUI/StatusPanel.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/ReleaseNote.hpp"
#include <boost/log/trivial.hpp>
#include <cassert>
#include <string>
#include "slic3r/GUI/GUI.hpp"
#include "libslic3r/Utils.hpp"
#include <wx/panel.h>
namespace Slic3r { namespace GUI {
@@ -3,6 +3,12 @@
#include "CalibrationWizardPage.hpp"
#include "StatusPanel.hpp"
#include "libslic3r/calib.hpp"
#include <wx/event.h>
#include <wx/gdicmn.h>
#include "slic3r/GUI/DeviceManager.hpp"
#include <wx/sizer.h>
#include "slic3r/GUI/ReleaseNote.hpp"
namespace Slic3r { namespace GUI {
+26
View File
@@ -1,9 +1,35 @@
#include "CalibrationWizardPage.hpp"
#include "CalibUtils.hpp"
#include "I18N.hpp"
#include "Widgets/Label.hpp"
#include "MsgDialog.hpp"
#include "DeviceCore/DevFilaSystem.h"
#include <wx/event.h>
#include "slic3r/GUI/DeviceCore/DevDefs.h"
#include <wx/string.h>
#include "libslic3r/calib.hpp"
#include <string>
#include "slic3r/GUI/GUI_App.hpp"
#include <boost/algorithm/string/predicate.hpp>
#include "slic3r/GUI/Widgets/Button.hpp"
#include "slic3r/GUI/Widgets/StateColor.hpp"
#include <utility>
#include <wx/colour.h>
#include <wx/gdicmn.h>
#include <wx/panel.h>
#include "slic3r/GUI/PresetComboBoxes.hpp"
#include "libslic3r/PrintConfig.hpp"
#include "slic3r/GUI/wxExtensions.hpp"
#include <wx/anybutton.h>
#include "slic3r/GUI/Widgets/HyperLink.hpp"
#include <wx/utils.h>
#include <wx/arrstr.h>
#include "slic3r/GUI/Widgets/PopupWindow.hpp"
#include <wx/dcclient.h>
#include "slic3r/GUI/BBLStatusBarSend.hpp"
#include <memory>
#include <wx/scrolwin.h>
namespace Slic3r { namespace GUI {
+14
View File
@@ -13,6 +13,20 @@
#include "slic3r/Utils/CalibUtils.hpp"
#include "../../libslic3r/calib.hpp"
#include "slic3r/GUI/DeviceManager.hpp"
#include <wx/panel.h>
#include <wx/gdicmn.h>
#include "libslic3r/PrintConfig.hpp"
#include <string>
#include "slic3r/GUI/Widgets/CheckBox.hpp"
#include <vector>
#include <wx/arrstr.h>
#include "slic3r/GUI/Widgets/Label.hpp"
#include "slic3r/GUI/Widgets/PopupWindow.hpp"
#include <wx/string.h>
#include <memory>
#include "slic3r/GUI/BBLStatusBarSend.hpp"
#include <wx/scrolwin.h>
namespace Slic3r { namespace GUI {
@@ -1,5 +1,43 @@
#include "libslic3r/calib.hpp"
#include <functional>
#include <cstddef>
#include <boost/log/trivial.hpp>
#include "libslic3r/PrintConfig.hpp"
#include "libslic3r/CommonDefs.hpp"
#include <cstdint>
#include "libslic3r/Config.hpp"
#include "libslic3r/Preset.hpp"
#include <algorithm>
#include <map>
#include <cassert>
#include "libslic3r/PresetBundle.hpp"
#include <cstdlib>
#include <regex>
#include <wx/event.h>
#include <wx/gdicmn.h>
#include <wx/panel.h>
#include <wx/string.h>
#include <wx/valtext.h>
#include <wx/textctrl.h>
#include <wx/arrstr.h>
#include "slic3r/GUI/Widgets/ComboBox.hpp"
#include <string>
#include <wx/sizer.h>
#include "slic3r/GUI/CalibrationWizardPage.hpp"
#include "slic3r/GUI/Widgets/AMSItem.hpp"
#include "slic3r/GUI/Widgets/Button.hpp"
#include "slic3r/GUI/Widgets/StateColor.hpp"
#include <utility>
#include <wx/anybutton.h>
#include "slic3r/GUI/Widgets/CheckBox.hpp"
#include <wx/tglbtn.h>
#include <vector>
#include "slic3r/GUI/BBLStatusBarSend.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/DeviceCore/DevDefs.h"
#include <wx/chartype.h>
#include "CalibrationWizardPresetPage.hpp"
#include "CalibUtils.hpp"
#include "GUI.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "I18N.hpp"
@@ -2,6 +2,30 @@
#define slic3r_GUI_CalibrationWizardPresetPage_hpp_
#include "CalibrationWizardPage.hpp"
#include <wx/panel.h>
#include <wx/event.h>
#include <wx/gdicmn.h>
#include "libslic3r/calib.hpp"
#include <wx/sizer.h>
#include "slic3r/GUI/Widgets/TextInput.hpp"
#include <wx/string.h>
#include <wx/arrstr.h>
#include <functional>
#include "slic3r/GUI/Widgets/ComboBox.hpp"
#include "slic3r/GUI/Widgets/Label.hpp"
#include <vector>
#include <string>
#include "slic3r/GUI/DeviceManager.hpp"
#include <map>
#include "libslic3r/Preset.hpp"
#include "libslic3r/PrintConfig.hpp"
#include <memory>
#include "slic3r/GUI/Jobs/ProgressIndicator.hpp"
#include "slic3r/GUI/Widgets/AMSItem.hpp"
#include <cstddef>
#include "slic3r/GUI/Widgets/Button.hpp"
#include <unordered_map>
#include "slic3r/GUI/wxExtensions.hpp"
namespace Slic3r { namespace GUI {
@@ -1,4 +1,5 @@
#include "CalibrationWizardSavePage.hpp"
#include "CalibUtils.hpp"
#include "GUI.hpp"
#include "I18N.hpp"
#include "Widgets/Label.hpp"
@@ -6,6 +7,34 @@
#include "DeviceCore/DevConfigUtil.h"
#include "DeviceCore/DevNozzleSystem.h"
#include "DeviceCore/DevNozzleRack.h"
#include <wx/string.h>
#include "libslic3r/calib.hpp"
#include "libslic3r/PresetBundle.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include <wx/event.h>
#include <wx/gdicmn.h>
#include "slic3r/GUI/CalibrationWizardPage.hpp"
#include "slic3r/GUI/Widgets/TextInput.hpp"
#include "slic3r/GUI/Widgets/ComboBox.hpp"
#include <wx/panel.h>
#include <vector>
#include <utility>
#include <unordered_set>
#include <string>
#include <algorithm>
#include <wx/valtext.h>
#include <wx/arrstr.h>
#include <map>
#include <wx/sizer.h>
#include "libslic3r/PrintConfig.hpp"
#include <wx/anybutton.h>
#include "slic3r/GUI/wxExtensions.hpp"
#include <boost/log/trivial.hpp>
#include "slic3r/GUI/DeviceCore/DevCalib.h"
#include <cassert>
#include "slic3r/GUI/DeviceCore/DevDefs.h"
#include "slic3r/GUI/Widgets/CheckBox.hpp"
#include <wx/tglbtn.h>
namespace Slic3r { namespace GUI {
@@ -3,6 +3,24 @@
#include "CalibrationWizardPage.hpp"
#include "Widgets/TextInput.hpp"
#include <wx/event.h>
#include <wx/gdicmn.h>
#include <wx/sizer.h>
#include <wx/panel.h>
#include <wx/string.h>
#include "slic3r/GUI/Widgets/ComboBox.hpp"
#include "slic3r/GUI/Widgets/Label.hpp"
#include <string>
#include "slic3r/GUI/DeviceManager.hpp"
#include <vector>
#include <utility>
#include "libslic3r/calib.hpp"
#include "slic3r/GUI/DeviceCore/DevCalib.h"
#include "slic3r/GUI/DeviceCore/DevDefs.h"
#include <map>
#include <memory>
#include "slic3r/GUI/Jobs/ProgressIndicator.hpp"
#include "slic3r/GUI/Widgets/CheckBox.hpp"
namespace Slic3r { namespace GUI {
@@ -1,6 +1,17 @@
#include "CalibrationWizardStartPage.hpp"
#include "I18N.hpp"
#include "Widgets/Label.hpp"
#include <wx/event.h>
#include <wx/gdicmn.h>
#include "slic3r/GUI/CalibrationWizardPage.hpp"
#include <wx/sizer.h>
#include <wx/string.h>
#include <string>
#include "slic3r/GUI/wxExtensions.hpp"
#include "libslic3r/calib.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/DeviceManager.hpp"
#include "slic3r/GUI/DeviceCore/DevDefs.h"
namespace Slic3r { namespace GUI {
@@ -2,6 +2,14 @@
#define slic3r_GUI_CalibrationWizardStartPage_hpp_
#include "CalibrationWizardPage.hpp"
#include <wx/event.h>
#include <wx/gdicmn.h>
#include "libslic3r/calib.hpp"
#include <wx/sizer.h>
#include "slic3r/GUI/Widgets/Label.hpp"
#include <wx/string.h>
#include <string>
#include "slic3r/GUI/DeviceManager.hpp"
namespace Slic3r { namespace GUI {
+15
View File
@@ -3,6 +3,21 @@
#include "Camera.hpp"
#include "GUI_App.hpp"
#include "libslic3r/Technologies.hpp"
#include <string>
#include "libslic3r/Point.hpp"
#include <algorithm>
#include "libslic3r/Geometry.hpp"
#include <cmath>
#include "libslic3r/BoundingBox.hpp"
#include <cassert>
#include "slic3r/GUI/3DScene.hpp"
#include <cstdlib>
#include <utility>
#include <vector>
#include <cfloat>
#include "libslic3r/TriangleMesh.hpp"
#include <math.h>
#if ENABLE_CAMERA_STATISTICS
#include "Mouse3DController.hpp"
#include "Plater.hpp"
+9
View File
@@ -3,7 +3,16 @@
#include "libslic3r/BoundingBox.hpp"
#include "3DScene.hpp"
#include <Eigen/Geometry>
#include <algorithm>
#include <array>
#include "libslic3r/Point.hpp"
#include <utility>
#include <string>
#include <cassert>
#include "libslic3r/Technologies.hpp"
#include <cstdlib>
#include "libslic3r/libslic3r.h"
namespace Slic3r {
namespace GUI {
+19
View File
@@ -4,9 +4,28 @@
#include "Widgets/Label.hpp"
#include "libslic3r/Utils.hpp"
#include "BitmapCache.hpp"
#include <wx/object.h>
#include "slic3r/GUI/Widgets/PopupWindow.hpp"
#include <wx/event.h>
#include <wx/colour.h>
#include <wx/popupwin.h>
#include "slic3r/GUI/Widgets/SwitchButton.hpp"
#include <wx/panel.h>
#include <wx/gdicmn.h>
#include <cstddef>
#include "slic3r/GUI/Widgets/RadioBox.hpp"
#include <string>
#include <vector>
#include <algorithm>
#include <wx/dcclient.h>
#include <wx/dc.h>
#include <wx/progdlg.h>
#include <wx/clipbrd.h>
#include <wx/dcgraph.h>
#include <wx/string.h>
#include <wx/scrolwin.h>
#include <wx/sizer.h>
#include <wx/timer.h>
#include <wx/utils.h>
#include "GUI_App.hpp"
#include <slic3r/GUI/StatusPanel.hpp>
+9
View File
@@ -4,9 +4,18 @@
#include "slic3r/GUI/MonitorBasePanel.h"
#include "DeviceManager.hpp"
#include "GUI.hpp"
#include <wx/event.h>
#include <cstddef>
#include <string>
#include <vector>
#include "slic3r/GUI/DeviceErrorDialog.hpp"
#include "slic3r/GUI/wxExtensions.hpp"
#include <wx/panel.h>
#include <wx/bitmap.h>
#include <wx/image.h>
#include <wx/string.h>
#include <wx/scrolwin.h>
#include <wx/rtti.h>
#include <wx/timer.h>
#include <wx/sizer.h>
#include <wx/gbsizer.h>
+10
View File
@@ -1,6 +1,16 @@
#include "CameraUtils.hpp"
#include <Eigen/Core>
#include <cstddef>
#include <cassert>
#include <cmath>
#include <igl/project.h> // projecting points
#include <igl/unproject.h>
#include "libslic3r/Point.hpp"
#include "slic3r/GUI/Camera.hpp"
#include <vector>
#include "libslic3r/Polygon.hpp"
#include "libslic3r/TriangleMesh.hpp"
#include <limits>
#include "slic3r/GUI/3DScene.hpp" // GLVolume
#include "libslic3r/Geometry/ConvexHull.hpp"
+2
View File
@@ -3,6 +3,8 @@
#include "Camera.hpp"
#include "libslic3r/Point.hpp"
#include <vector>
#include "libslic3r/Polygon.hpp"
namespace Slic3r {
class GLVolume;
}
+8
View File
@@ -1,7 +1,15 @@
#include "GUI_App.hpp"
#include "CapsuleButton.hpp"
#include "Widgets/StateColor.hpp"
#include <wx/colour.h>
#include "slic3r/GUI/wxExtensions.hpp"
#include <wx/dcbuffer.h>
#include <wx/string.h>
#include <wx/panel.h>
#include <wx/sizer.h>
#include <wx/gdicmn.h>
#include <wx/event.h>
#include <wx/window.h>
#include "wx/graphics.h"
#include "Widgets/Label.hpp"
+4
View File
@@ -3,6 +3,10 @@
#include "wxExtensions.hpp"
#include "Widgets/Label.hpp"
#include <wx/panel.h>
#include <wx/checklst.h>
#include <wx/string.h>
#include <wx/event.h>
namespace Slic3r { namespace GUI {
class CapsuleButton : public wxPanel
+18
View File
@@ -2,6 +2,24 @@
#include "GUI_App.hpp"
#include "MainFrame.hpp"
#include "slic3r/GUI/GUI_Utils.hpp"
#include <wx/event.h>
#include "slic3r/GUI/Gizmos/GLGizmoBase.hpp"
#include <wx/gdicmn.h>
#include <wx/toplevel.h>
#include "slic3r/GUI/Widgets/Label.hpp"
#include <wx/sizer.h>
#include "slic3r/GUI/Widgets/SpinInput.hpp"
#include <wx/string.h>
#include "slic3r/GUI/Widgets/CheckBox.hpp"
#include "slic3r/GUI/Widgets/ProgressBar.hpp"
#include "slic3r/GUI/Widgets/StateColor.hpp"
#include <wx/colour.h>
#include "slic3r/GUI/Widgets/DialogButtons.hpp"
#include "slic3r/GUI/Widgets/Button.hpp"
#include "slic3r/GUI/Selection.hpp"
#include <wx/utils.h>
#include "slic3r/GUI/Jobs/Job.hpp"
namespace Slic3r { namespace GUI {

Some files were not shown because too many files have changed in this diff Show More