Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_gcode_viewer
This commit is contained in:
commit
dea641183c
6
resources/icons/tick_mark.svg
Normal file
6
resources/icons/tick_mark.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(0 -292.77)">
|
||||
<path d="m2.2728 301.7 3.2932 4.8789 8.3542-11.435" fill="none" stroke="#00af00" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.9994"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 319 B |
@ -44,6 +44,7 @@
|
||||
#include "libslic3r/Format/OBJ.hpp"
|
||||
#include "libslic3r/Format/SL1.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
|
||||
#include "PrusaSlicer.hpp"
|
||||
|
||||
@ -52,7 +53,6 @@
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
#include "slic3r/GUI/InstanceCheck.hpp"
|
||||
#include "slic3r/GUI/AppConfig.hpp"
|
||||
#include "slic3r/GUI/MainFrame.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#endif /* SLIC3R_GUI */
|
||||
|
@ -1,661 +1,165 @@
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
@ -15,8 +15,8 @@
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/format/format_fwd.hpp>
|
||||
|
||||
#include <wx/string.h>
|
||||
#include "I18N.hpp"
|
||||
//#include <wx/string.h>
|
||||
//#include "I18N.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@ -110,7 +110,7 @@ void AppConfig::set_defaults()
|
||||
erase("", "object_settings_size");
|
||||
}
|
||||
|
||||
void AppConfig::load()
|
||||
std::string AppConfig::load()
|
||||
{
|
||||
// 1) Read the complete config file into a boost::property_tree.
|
||||
namespace pt = boost::property_tree;
|
||||
@ -120,10 +120,15 @@ void AppConfig::load()
|
||||
pt::read_ini(ifs, tree);
|
||||
} catch (pt::ptree_error& ex) {
|
||||
// Error while parsing config file. We'll customize the error message and rethrow to be displayed.
|
||||
// ! But to avoid the use of _utf8 (related to use of wxWidgets)
|
||||
// we will rethrow this exception from the place of load() call, if returned value wouldn't be empty
|
||||
/*
|
||||
throw std::runtime_error(
|
||||
_utf8(L("Error parsing PrusaSlicer config file, it is probably corrupted. "
|
||||
"Try to manually delete the file to recover from the error. Your user profiles will not be affected.")) +
|
||||
"\n\n" + AppConfig::config_path() + "\n\n" + ex.what());
|
||||
*/
|
||||
return ex.what();
|
||||
}
|
||||
|
||||
// 2) Parse the property_tree, extract the sections and key / value pairs.
|
||||
@ -169,6 +174,7 @@ void AppConfig::load()
|
||||
// Override missing or keys with their defaults.
|
||||
this->set_defaults();
|
||||
m_dirty = false;
|
||||
return "";
|
||||
}
|
||||
|
||||
void AppConfig::save()
|
@ -29,7 +29,8 @@ public:
|
||||
void set_defaults();
|
||||
|
||||
// Load the slic3r.ini from a user profile directory (or a datadir, if configured).
|
||||
void load();
|
||||
// return error string or empty strinf
|
||||
std::string load();
|
||||
// Store the slic3r.ini into a user profile directory (or a datadir, if configured).
|
||||
void save();
|
||||
|
@ -149,6 +149,12 @@ add_library(libslic3r STATIC
|
||||
PolygonTrimmer.hpp
|
||||
Polyline.cpp
|
||||
Polyline.hpp
|
||||
Preset.cpp
|
||||
Preset.hpp
|
||||
PresetBundle.cpp
|
||||
PresetBundle.hpp
|
||||
AppConfig.cpp
|
||||
AppConfig.hpp
|
||||
Print.cpp
|
||||
Print.hpp
|
||||
PrintBase.cpp
|
||||
|
@ -1878,10 +1878,11 @@ namespace Slic3r {
|
||||
volume->calculate_convex_hull();
|
||||
|
||||
// recreate custom supports from previously loaded attribute
|
||||
assert(geometry.custom_supports.size() == triangles_count);
|
||||
for (unsigned i=0; i<triangles_count; ++i) {
|
||||
if (! geometry.custom_supports[i].empty())
|
||||
volume->m_supported_facets.set_triangle_from_string(i, geometry.custom_supports[i]);
|
||||
size_t index = src_start_id/3 + i;
|
||||
assert(index < geometry.custom_supports.size());
|
||||
if (! geometry.custom_supports[index].empty())
|
||||
volume->m_supported_facets.set_triangle_from_string(i, geometry.custom_supports[index]);
|
||||
}
|
||||
|
||||
// apply the remaining volume's metadata
|
||||
|
@ -2,9 +2,6 @@
|
||||
|
||||
#include "Preset.hpp"
|
||||
#include "AppConfig.hpp"
|
||||
#include "BitmapCache.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
@ -12,6 +9,16 @@
|
||||
#include <Windows.h>
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
// instead of #include "slic3r/GUI/I18N.hpp" :
|
||||
#ifndef L
|
||||
// !!! If you needed to translate some string,
|
||||
// !!! please use _L(string)
|
||||
// !!! _() - is a standard wxWidgets macro to translate
|
||||
// !!! L() is used only for marking localizable string
|
||||
// !!! It will be used in "xgettext" to create a Locating Message Catalog.
|
||||
#define L(s) s
|
||||
#endif /* L */
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
@ -19,6 +26,7 @@
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
#include <boost/nowide/cenv.hpp>
|
||||
@ -30,15 +38,9 @@
|
||||
#include <boost/locale.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include <wx/image.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/bmpcbox.h>
|
||||
#include <wx/wupdlock.h>
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/PlaceholderParser.hpp"
|
||||
#include "Plater.hpp"
|
||||
#include "libslic3r.h"
|
||||
#include "Utils.hpp"
|
||||
#include "PlaceholderParser.hpp"
|
||||
|
||||
using boost::property_tree::ptree;
|
||||
|
||||
@ -245,9 +247,9 @@ const std::string& Preset::suffix_modified()
|
||||
return g_suffix_modified;
|
||||
}
|
||||
|
||||
void Preset::update_suffix_modified()
|
||||
void Preset::update_suffix_modified(const std::string& new_suffix_modified)
|
||||
{
|
||||
g_suffix_modified = (" (" + _(L("modified")) + ")").ToUTF8().data();
|
||||
g_suffix_modified = new_suffix_modified;
|
||||
}
|
||||
// Remove an optional "(modified)" suffix from a name.
|
||||
// This converts a UI name to a unique preset identifier.
|
||||
@ -591,10 +593,7 @@ const std::vector<std::string>& Preset::sla_printer_options()
|
||||
PresetCollection::PresetCollection(Preset::Type type, const std::vector<std::string> &keys, const Slic3r::StaticPrintConfig &defaults, const std::string &default_name) :
|
||||
m_type(type),
|
||||
m_edited_preset(type, "", false),
|
||||
m_idx_selected(0),
|
||||
m_bitmap_main_frame(new wxBitmap),
|
||||
m_bitmap_add(new wxBitmap),
|
||||
m_bitmap_cache(new GUI::BitmapCache)
|
||||
m_idx_selected(0)
|
||||
{
|
||||
// Insert just the default preset.
|
||||
this->add_default_preset(keys, defaults, default_name);
|
||||
@ -603,12 +602,6 @@ PresetCollection::PresetCollection(Preset::Type type, const std::vector<std::str
|
||||
|
||||
PresetCollection::~PresetCollection()
|
||||
{
|
||||
delete m_bitmap_main_frame;
|
||||
m_bitmap_main_frame = nullptr;
|
||||
delete m_bitmap_add;
|
||||
m_bitmap_add = nullptr;
|
||||
delete m_bitmap_cache;
|
||||
m_bitmap_cache = nullptr;
|
||||
}
|
||||
|
||||
void PresetCollection::reset(bool delete_files)
|
||||
@ -952,16 +945,6 @@ bool PresetCollection::delete_preset(const std::string& name)
|
||||
return true;
|
||||
}
|
||||
|
||||
void PresetCollection::load_bitmap_default(const std::string &file_name)
|
||||
{
|
||||
*m_bitmap_main_frame = create_scaled_bitmap(file_name);
|
||||
}
|
||||
|
||||
void PresetCollection::load_bitmap_add(const std::string &file_name)
|
||||
{
|
||||
*m_bitmap_add = create_scaled_bitmap(file_name);
|
||||
}
|
||||
|
||||
const Preset* PresetCollection::get_selected_preset_parent() const
|
||||
{
|
||||
if (this->get_selected_idx() == size_t(-1))
|
||||
@ -1120,279 +1103,15 @@ size_t PresetCollection::update_compatible_internal(const PresetWithVendorProfil
|
||||
// Delete the current preset, activate the first visible preset.
|
||||
//void PresetCollection::delete_current_preset();
|
||||
|
||||
// Update the wxChoice UI component from this list of presets.
|
||||
// Hide the
|
||||
void PresetCollection::update_plater_ui(GUI::PresetComboBox *ui)
|
||||
{
|
||||
if (ui == nullptr)
|
||||
return;
|
||||
|
||||
// Otherwise fill in the list from scratch.
|
||||
ui->Freeze();
|
||||
ui->Clear();
|
||||
size_t selected_preset_item = INT_MAX; // some value meaning that no one item is selected
|
||||
|
||||
const Preset &selected_preset = this->get_selected_preset();
|
||||
// Show wide icons if the currently selected preset is not compatible with the current printer,
|
||||
// and draw a red flag in front of the selected preset.
|
||||
bool wide_icons = ! selected_preset.is_compatible && m_bitmap_incompatible != nullptr;
|
||||
|
||||
/* It's supposed that standard size of an icon is 16px*16px for 100% scaled display.
|
||||
* So set sizes for solid_colored icons used for filament preset
|
||||
* and scale them in respect to em_unit value
|
||||
*/
|
||||
const float scale_f = ui->em_unit() * 0.1f;
|
||||
const int icon_height = 16 * scale_f + 0.5f;
|
||||
const int icon_width = 16 * scale_f + 0.5f;
|
||||
const int thin_space_icon_width = 4 * scale_f + 0.5f;
|
||||
const int wide_space_icon_width = 6 * scale_f + 0.5f;
|
||||
|
||||
std::map<wxString, wxBitmap*> nonsys_presets;
|
||||
wxString selected = "";
|
||||
wxString tooltip = "";
|
||||
if (!this->m_presets.front().is_visible)
|
||||
ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap));
|
||||
for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++ i) {
|
||||
const Preset &preset = this->m_presets[i];
|
||||
if (! preset.is_visible || (! preset.is_compatible && i != m_idx_selected))
|
||||
continue;
|
||||
|
||||
std::string bitmap_key = "";
|
||||
// !!! Temporary solution, till refactoring: create and use "sla_printer" icon instead of m_bitmap_main_frame
|
||||
wxBitmap main_bmp = m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap;
|
||||
if (m_type == Preset::TYPE_PRINTER && preset.printer_technology()==ptSLA ) {
|
||||
bitmap_key = "sla_printer";
|
||||
main_bmp = create_scaled_bitmap("sla_printer");
|
||||
}
|
||||
|
||||
// If the filament preset is not compatible and there is a "red flag" icon loaded, show it left
|
||||
// to the filament color image.
|
||||
if (wide_icons)
|
||||
bitmap_key += preset.is_compatible ? ",cmpt" : ",ncmpt";
|
||||
bitmap_key += (preset.is_system || preset.is_default) ? ",syst" : ",nsyst";
|
||||
wxBitmap *bmp = m_bitmap_cache->find(bitmap_key);
|
||||
if (bmp == nullptr) {
|
||||
// Create the bitmap with color bars.
|
||||
std::vector<wxBitmap> bmps;
|
||||
if (wide_icons)
|
||||
// Paint a red flag for incompatible presets.
|
||||
bmps.emplace_back(preset.is_compatible ? m_bitmap_cache->mkclear(icon_width, icon_height) : *m_bitmap_incompatible);
|
||||
// Paint the color bars.
|
||||
bmps.emplace_back(m_bitmap_cache->mkclear(thin_space_icon_width, icon_height));
|
||||
bmps.emplace_back(main_bmp);
|
||||
// Paint a lock at the system presets.
|
||||
bmps.emplace_back(m_bitmap_cache->mkclear(wide_space_icon_width, icon_height));
|
||||
bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmap_lock : m_bitmap_cache->mkclear(icon_width, icon_height));
|
||||
bmp = m_bitmap_cache->insert(bitmap_key, bmps);
|
||||
}
|
||||
|
||||
const std::string name = preset.alias.empty() ? preset.name : preset.alias;
|
||||
if (preset.is_default || preset.is_system) {
|
||||
ui->Append(wxString::FromUTF8((/*preset.*/name + (preset.is_dirty ? g_suffix_modified : "")).c_str()),
|
||||
(bmp == 0) ? main_bmp : *bmp);
|
||||
if (i == m_idx_selected ||
|
||||
// just in case: mark selected_preset_item as a first added element
|
||||
selected_preset_item == INT_MAX) {
|
||||
selected_preset_item = ui->GetCount() - 1;
|
||||
tooltip = wxString::FromUTF8(preset.name.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nonsys_presets.emplace(wxString::FromUTF8((/*preset.*/name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), bmp/*preset.is_compatible*/);
|
||||
if (i == m_idx_selected) {
|
||||
selected = wxString::FromUTF8((/*preset.*/name + (preset.is_dirty ? g_suffix_modified : "")).c_str());
|
||||
tooltip = wxString::FromUTF8(preset.name.c_str());
|
||||
}
|
||||
}
|
||||
if (i + 1 == m_num_default_presets)
|
||||
ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap));
|
||||
}
|
||||
if (!nonsys_presets.empty())
|
||||
{
|
||||
ui->set_label_marker(ui->Append(PresetCollection::separator(L("User presets")), wxNullBitmap));
|
||||
for (std::map<wxString, wxBitmap*>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
|
||||
ui->Append(it->first, *it->second);
|
||||
if (it->first == selected ||
|
||||
// just in case: mark selected_preset_item as a first added element
|
||||
selected_preset_item == INT_MAX)
|
||||
selected_preset_item = ui->GetCount() - 1;
|
||||
}
|
||||
}
|
||||
if (m_type == Preset::TYPE_PRINTER || m_type == Preset::TYPE_SLA_MATERIAL) {
|
||||
std::string bitmap_key = "";
|
||||
// If the filament preset is not compatible and there is a "red flag" icon loaded, show it left
|
||||
// to the filament color image.
|
||||
if (wide_icons)
|
||||
bitmap_key += "wide,";
|
||||
bitmap_key += "edit_preset_list";
|
||||
wxBitmap *bmp = m_bitmap_cache->find(bitmap_key);
|
||||
if (bmp == nullptr) {
|
||||
// Create the bitmap with color bars.
|
||||
std::vector<wxBitmap> bmps;
|
||||
if (wide_icons)
|
||||
// Paint a red flag for incompatible presets.
|
||||
bmps.emplace_back(m_bitmap_cache->mkclear(icon_width, icon_height));
|
||||
// Paint the color bars.
|
||||
bmps.emplace_back(m_bitmap_cache->mkclear(thin_space_icon_width, icon_height));
|
||||
bmps.emplace_back(*m_bitmap_main_frame);
|
||||
// Paint a lock at the system presets.
|
||||
bmps.emplace_back(m_bitmap_cache->mkclear(wide_space_icon_width, icon_height));
|
||||
// bmps.emplace_back(m_bitmap_add ? *m_bitmap_add : wxNullBitmap);
|
||||
bmps.emplace_back(create_scaled_bitmap("edit_uni"));
|
||||
bmp = m_bitmap_cache->insert(bitmap_key, bmps);
|
||||
}
|
||||
if (m_type == Preset::TYPE_SLA_MATERIAL)
|
||||
ui->set_label_marker(ui->Append(PresetCollection::separator(L("Add/Remove materials")), *bmp), GUI::PresetComboBox::LABEL_ITEM_WIZARD_MATERIALS);
|
||||
else
|
||||
ui->set_label_marker(ui->Append(PresetCollection::separator(L("Add/Remove printers")), *bmp), GUI::PresetComboBox::LABEL_ITEM_WIZARD_PRINTERS);
|
||||
}
|
||||
|
||||
/* But, if selected_preset_item is still equal to INT_MAX, it means that
|
||||
* there is no presets added to the list.
|
||||
* So, select last combobox item ("Add/Remove preset")
|
||||
*/
|
||||
if (selected_preset_item == INT_MAX)
|
||||
selected_preset_item = ui->GetCount() - 1;
|
||||
|
||||
ui->SetSelection(selected_preset_item);
|
||||
ui->SetToolTip(tooltip.IsEmpty() ? ui->GetString(selected_preset_item) : tooltip);
|
||||
ui->check_selection(selected_preset_item);
|
||||
ui->Thaw();
|
||||
|
||||
// Update control min size after rescale (changed Display DPI under MSW)
|
||||
if (ui->GetMinWidth() != 20 * ui->em_unit())
|
||||
ui->SetMinSize(wxSize(20 * ui->em_unit(), ui->GetSize().GetHeight()));
|
||||
}
|
||||
|
||||
size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible, const int em/* = 10*/)
|
||||
{
|
||||
if (ui == nullptr)
|
||||
return 0;
|
||||
ui->Freeze();
|
||||
ui->Clear();
|
||||
size_t selected_preset_item = INT_MAX; // some value meaning that no one item is selected
|
||||
|
||||
/* It's supposed that standard size of an icon is 16px*16px for 100% scaled display.
|
||||
* So set sizes for solid_colored(empty) icons used for preset
|
||||
* and scale them in respect to em_unit value
|
||||
*/
|
||||
const float scale_f = em * 0.1f;
|
||||
const int icon_height = 16 * scale_f + 0.5f;
|
||||
const int icon_width = 16 * scale_f + 0.5f;
|
||||
|
||||
std::map<wxString, wxBitmap*> nonsys_presets;
|
||||
wxString selected = "";
|
||||
if (!this->m_presets.front().is_visible)
|
||||
ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap);
|
||||
for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++i) {
|
||||
const Preset &preset = this->m_presets[i];
|
||||
if (! preset.is_visible || (! show_incompatible && ! preset.is_compatible && i != m_idx_selected))
|
||||
continue;
|
||||
std::string bitmap_key = "tab";
|
||||
|
||||
// !!! Temporary solution, till refactoring: create and use "sla_printer" icon instead of m_bitmap_main_frame
|
||||
wxBitmap main_bmp = m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap;
|
||||
if (m_type == Preset::TYPE_PRINTER && preset.printer_technology() == ptSLA) {
|
||||
bitmap_key = "sla_printer";
|
||||
main_bmp = create_scaled_bitmap("sla_printer");
|
||||
}
|
||||
|
||||
bitmap_key += preset.is_compatible ? ",cmpt" : ",ncmpt";
|
||||
bitmap_key += (preset.is_system || preset.is_default) ? ",syst" : ",nsyst";
|
||||
wxBitmap *bmp = m_bitmap_cache->find(bitmap_key);
|
||||
if (bmp == nullptr) {
|
||||
// Create the bitmap with color bars.
|
||||
std::vector<wxBitmap> bmps;
|
||||
const wxBitmap* tmp_bmp = preset.is_compatible ? m_bitmap_compatible : m_bitmap_incompatible;
|
||||
bmps.emplace_back((tmp_bmp == 0) ? main_bmp : *tmp_bmp);
|
||||
// Paint a lock at the system presets.
|
||||
bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmap_lock : m_bitmap_cache->mkclear(icon_width, icon_height));
|
||||
bmp = m_bitmap_cache->insert(bitmap_key, bmps);
|
||||
}
|
||||
|
||||
if (preset.is_default || preset.is_system) {
|
||||
ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()),
|
||||
(bmp == 0) ? main_bmp : *bmp);
|
||||
if (i == m_idx_selected ||
|
||||
// just in case: mark selected_preset_item as a first added element
|
||||
selected_preset_item == INT_MAX)
|
||||
selected_preset_item = ui->GetCount() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), bmp/*preset.is_compatible*/);
|
||||
if (i == m_idx_selected)
|
||||
selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str());
|
||||
}
|
||||
if (i + 1 == m_num_default_presets)
|
||||
ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap);
|
||||
}
|
||||
if (!nonsys_presets.empty())
|
||||
{
|
||||
ui->Append(PresetCollection::separator(L("User presets")), wxNullBitmap);
|
||||
for (std::map<wxString, wxBitmap*>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
|
||||
ui->Append(it->first, *it->second);
|
||||
if (it->first == selected ||
|
||||
// just in case: mark selected_preset_item as a first added element
|
||||
selected_preset_item == INT_MAX)
|
||||
selected_preset_item = ui->GetCount() - 1;
|
||||
}
|
||||
}
|
||||
if (m_type == Preset::TYPE_PRINTER) {
|
||||
wxBitmap *bmp = m_bitmap_cache->find("edit_printer_list");
|
||||
if (bmp == nullptr) {
|
||||
// Create the bitmap with color bars.
|
||||
std::vector<wxBitmap> bmps;
|
||||
bmps.emplace_back(*m_bitmap_main_frame);
|
||||
// bmps.emplace_back(m_bitmap_add ? *m_bitmap_add : wxNullBitmap);
|
||||
bmps.emplace_back(create_scaled_bitmap("edit_uni"));
|
||||
bmp = m_bitmap_cache->insert("add_printer_tab", bmps);
|
||||
}
|
||||
ui->Append(PresetCollection::separator("Add a new printer"), *bmp);
|
||||
}
|
||||
|
||||
/* But, if selected_preset_item is still equal to INT_MAX, it means that
|
||||
* there is no presets added to the list.
|
||||
* So, select last combobox item ("Add/Remove preset")
|
||||
*/
|
||||
if (selected_preset_item == INT_MAX)
|
||||
selected_preset_item = ui->GetCount() - 1;
|
||||
|
||||
ui->SetSelection(selected_preset_item);
|
||||
ui->SetToolTip(ui->GetString(selected_preset_item));
|
||||
ui->Thaw();
|
||||
return selected_preset_item;
|
||||
}
|
||||
|
||||
// Update a dirty floag of the current preset, update the labels of the UI component accordingly.
|
||||
// Update a dirty flag of the current preset
|
||||
// Return true if the dirty flag changed.
|
||||
bool PresetCollection::update_dirty_ui(wxBitmapComboBox *ui)
|
||||
bool PresetCollection::update_dirty()
|
||||
{
|
||||
wxWindowUpdateLocker noUpdates(ui);
|
||||
// 1) Update the dirty flag of the current preset.
|
||||
bool was_dirty = this->get_selected_preset().is_dirty;
|
||||
bool is_dirty = current_is_dirty();
|
||||
this->get_selected_preset().is_dirty = is_dirty;
|
||||
this->get_edited_preset().is_dirty = is_dirty;
|
||||
// 2) Update the labels.
|
||||
for (unsigned int ui_id = 0; ui_id < ui->GetCount(); ++ ui_id) {
|
||||
std::string old_label = ui->GetString(ui_id).utf8_str().data();
|
||||
std::string preset_name = Preset::remove_suffix_modified(old_label);
|
||||
const Preset *preset = this->find_preset(preset_name, false);
|
||||
// The old_label could be the "----- system presets ------" or the "------- user presets --------" separator.
|
||||
// assert(preset != nullptr);
|
||||
if (preset != nullptr) {
|
||||
std::string new_label = preset->is_dirty ? preset->name + g_suffix_modified : preset->name;
|
||||
if (old_label != new_label)
|
||||
ui->SetString(ui_id, wxString::FromUTF8(new_label.c_str()));
|
||||
}
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
// wxWidgets on OSX do not upload the text of the combo box line automatically.
|
||||
// Force it to update by re-selecting.
|
||||
ui->SetSelection(ui->GetSelection());
|
||||
#endif /* __APPLE __ */
|
||||
|
||||
return was_dirty != is_dirty;
|
||||
}
|
||||
|
||||
@ -1606,16 +1325,6 @@ std::string PresetCollection::path_from_name(const std::string &new_name) const
|
||||
return (boost::filesystem::path(m_dir_path) / file_name).make_preferred().string();
|
||||
}
|
||||
|
||||
void PresetCollection::clear_bitmap_cache()
|
||||
{
|
||||
m_bitmap_cache->clear();
|
||||
}
|
||||
|
||||
wxString PresetCollection::separator(const std::string &label)
|
||||
{
|
||||
return wxString::FromUTF8(PresetCollection::separator_head()) + _(label) + wxString::FromUTF8(PresetCollection::separator_tail());
|
||||
}
|
||||
|
||||
const Preset& PrinterPresetCollection::default_preset_for(const DynamicPrintConfig &config) const
|
||||
{
|
||||
const ConfigOptionEnumGeneric *opt_printer_technology = config.opt<ConfigOptionEnumGeneric>("printer_technology");
|
||||
@ -1633,6 +1342,462 @@ const Preset* PrinterPresetCollection::find_by_model_id(const std::string &model
|
||||
return it != cend() ? &*it : nullptr;
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// *** PhysicalPrinter ***
|
||||
// -------------------------
|
||||
|
||||
std::string PhysicalPrinter::separator()
|
||||
{
|
||||
return " * ";
|
||||
}
|
||||
|
||||
const std::vector<std::string>& PhysicalPrinter::printer_options()
|
||||
{
|
||||
static std::vector<std::string> s_opts;
|
||||
if (s_opts.empty()) {
|
||||
s_opts = {
|
||||
"preset_name",
|
||||
"printer_technology",
|
||||
"printer_model",
|
||||
"host_type",
|
||||
"print_host",
|
||||
"printhost_apikey",
|
||||
"printhost_cafile",
|
||||
"authorization_type",
|
||||
"login",
|
||||
"password"
|
||||
};
|
||||
}
|
||||
return s_opts;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& PhysicalPrinter::print_host_options()
|
||||
{
|
||||
static std::vector<std::string> s_opts;
|
||||
if (s_opts.empty()) {
|
||||
s_opts = {
|
||||
"print_host",
|
||||
"printhost_apikey",
|
||||
"printhost_cafile"
|
||||
};
|
||||
}
|
||||
return s_opts;
|
||||
}
|
||||
|
||||
std::vector<std::string> PhysicalPrinter::presets_with_print_host_information(const PrinterPresetCollection& printer_presets)
|
||||
{
|
||||
std::vector<std::string> presets;
|
||||
for (const Preset& preset : printer_presets)
|
||||
if (has_print_host_information(preset.config))
|
||||
presets.emplace_back(preset.name);
|
||||
|
||||
return presets;
|
||||
}
|
||||
|
||||
bool PhysicalPrinter::has_print_host_information(const DynamicPrintConfig& config)
|
||||
{
|
||||
for (const std::string& opt : print_host_options())
|
||||
if (!config.opt_string(opt).empty())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::set<std::string>& PhysicalPrinter::get_preset_names() const
|
||||
{
|
||||
return preset_names;
|
||||
}
|
||||
|
||||
bool PhysicalPrinter::has_empty_config() const
|
||||
{
|
||||
return config.opt_string("print_host" ).empty() &&
|
||||
config.opt_string("printhost_apikey").empty() &&
|
||||
config.opt_string("printhost_cafile").empty() &&
|
||||
config.opt_string("login" ).empty() &&
|
||||
config.opt_string("password" ).empty();
|
||||
}
|
||||
|
||||
void PhysicalPrinter::update_preset_names_in_config()
|
||||
{
|
||||
if (!preset_names.empty()) {
|
||||
std::string name;
|
||||
for (auto el : preset_names)
|
||||
name += el + ";";
|
||||
name.pop_back();
|
||||
config.set_key_value("preset_name", new ConfigOptionString(name));
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicalPrinter::save(const std::string& file_name_from, const std::string& file_name_to)
|
||||
{
|
||||
// rename the file
|
||||
boost::nowide::rename(file_name_from.data(), file_name_to.data());
|
||||
this->file = file_name_to;
|
||||
// save configuration
|
||||
this->config.save(this->file);
|
||||
}
|
||||
|
||||
void PhysicalPrinter::update_from_preset(const Preset& preset)
|
||||
{
|
||||
config.apply_only(preset.config, printer_options(), false);
|
||||
// add preset names to the options list
|
||||
auto ret = preset_names.emplace(preset.name);
|
||||
update_preset_names_in_config();
|
||||
}
|
||||
|
||||
void PhysicalPrinter::update_from_config(const DynamicPrintConfig& new_config)
|
||||
{
|
||||
config.apply_only(new_config, printer_options(), false);
|
||||
|
||||
std::string str = config.opt_string("preset_name");
|
||||
std::set<std::string> values{};
|
||||
if (!str.empty()) {
|
||||
boost::split(values, str, boost::is_any_of(";"));
|
||||
for (const std::string& val : values)
|
||||
preset_names.emplace(val);
|
||||
}
|
||||
preset_names = values;
|
||||
}
|
||||
|
||||
void PhysicalPrinter::reset_presets()
|
||||
{
|
||||
return preset_names.clear();
|
||||
}
|
||||
|
||||
bool PhysicalPrinter::add_preset(const std::string& preset_name)
|
||||
{
|
||||
return preset_names.emplace(preset_name).second;
|
||||
}
|
||||
|
||||
bool PhysicalPrinter::delete_preset(const std::string& preset_name)
|
||||
{
|
||||
return preset_names.erase(preset_name) > 0;
|
||||
}
|
||||
|
||||
PhysicalPrinter::PhysicalPrinter(const std::string& name, const Preset& preset) :
|
||||
name(name)
|
||||
{
|
||||
update_from_preset(preset);
|
||||
}
|
||||
|
||||
void PhysicalPrinter::set_name(const std::string& name)
|
||||
{
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
std::string PhysicalPrinter::get_full_name(std::string preset_name) const
|
||||
{
|
||||
return name + separator() + preset_name;
|
||||
}
|
||||
|
||||
std::string PhysicalPrinter::get_short_name(std::string full_name)
|
||||
{
|
||||
int pos = full_name.find(separator());
|
||||
if (pos > 0)
|
||||
boost::erase_tail(full_name, full_name.length() - pos);
|
||||
return full_name;
|
||||
}
|
||||
|
||||
std::string PhysicalPrinter::get_preset_name(std::string name)
|
||||
{
|
||||
int pos = name.find(separator());
|
||||
boost::erase_head(name, pos + 3);
|
||||
return Preset::remove_suffix_modified(name);
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------
|
||||
// *** PhysicalPrinterCollection ***
|
||||
// -----------------------------------
|
||||
|
||||
PhysicalPrinterCollection::PhysicalPrinterCollection( const std::vector<std::string>& keys)
|
||||
{
|
||||
}
|
||||
|
||||
// Load all printers found in dir_path.
|
||||
// Throws an exception on error.
|
||||
void PhysicalPrinterCollection::load_printers(const std::string& dir_path, const std::string& subdir)
|
||||
{
|
||||
boost::filesystem::path dir = boost::filesystem::canonical(boost::filesystem::path(dir_path) / subdir).make_preferred();
|
||||
m_dir_path = dir.string();
|
||||
std::string errors_cummulative;
|
||||
// Store the loaded printers into a new vector, otherwise the binary search for already existing presets would be broken.
|
||||
std::deque<PhysicalPrinter> printers_loaded;
|
||||
for (auto& dir_entry : boost::filesystem::directory_iterator(dir))
|
||||
if (Slic3r::is_ini_file(dir_entry)) {
|
||||
std::string name = dir_entry.path().filename().string();
|
||||
// Remove the .ini suffix.
|
||||
name.erase(name.size() - 4);
|
||||
if (this->find_printer(name, false)) {
|
||||
// This happens when there's is a preset (most likely legacy one) with the same name as a system preset
|
||||
// that's already been loaded from a bundle.
|
||||
BOOST_LOG_TRIVIAL(warning) << "Printer already present, not loading: " << name;
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
PhysicalPrinter printer(name);
|
||||
printer.file = dir_entry.path().string();
|
||||
// Load the preset file, apply preset values on top of defaults.
|
||||
try {
|
||||
DynamicPrintConfig config;
|
||||
config.load_from_ini(printer.file);
|
||||
printer.update_from_config(config);
|
||||
printer.loaded = true;
|
||||
}
|
||||
catch (const std::ifstream::failure& err) {
|
||||
throw std::runtime_error(std::string("The selected preset cannot be loaded: ") + printer.file + "\n\tReason: " + err.what());
|
||||
}
|
||||
catch (const std::runtime_error& err) {
|
||||
throw std::runtime_error(std::string("Failed loading the preset file: ") + printer.file + "\n\tReason: " + err.what());
|
||||
}
|
||||
printers_loaded.emplace_back(printer);
|
||||
}
|
||||
catch (const std::runtime_error& err) {
|
||||
errors_cummulative += err.what();
|
||||
errors_cummulative += "\n";
|
||||
}
|
||||
}
|
||||
m_printers.insert(m_printers.end(), std::make_move_iterator(printers_loaded.begin()), std::make_move_iterator(printers_loaded.end()));
|
||||
std::sort(m_printers.begin(), m_printers.end());
|
||||
if (!errors_cummulative.empty())
|
||||
throw std::runtime_error(errors_cummulative);
|
||||
}
|
||||
|
||||
// if there is saved user presets, contains information about "Print Host upload",
|
||||
// Create default printers with this presets
|
||||
// Note! "Print Host upload" options will be cleared after physical printer creations
|
||||
void PhysicalPrinterCollection::load_printers_from_presets(PrinterPresetCollection& printer_presets)
|
||||
{
|
||||
int cnt=0;
|
||||
for (Preset& preset: printer_presets) {
|
||||
DynamicPrintConfig& config = preset.config;
|
||||
const std::vector<std::string>& options = PhysicalPrinter::print_host_options();
|
||||
|
||||
for(const std::string& option : options) {
|
||||
if (!config.opt_string(option).empty()) {
|
||||
// check if printer with those "Print Host upload" options already exist
|
||||
PhysicalPrinter* existed_printer = find_printer_with_same_config(config);
|
||||
if (existed_printer)
|
||||
// just add preset for this printer
|
||||
existed_printer->add_preset(preset.name);
|
||||
else {
|
||||
std::string new_printer_name = (boost::format("Printer %1%") % ++cnt ).str();
|
||||
while (find_printer(new_printer_name))
|
||||
new_printer_name = (boost::format("Printer %1%") % ++cnt).str();
|
||||
|
||||
// create new printer from this preset
|
||||
PhysicalPrinter printer(new_printer_name, preset);
|
||||
printer.loaded = true;
|
||||
save_printer(printer);
|
||||
}
|
||||
|
||||
// erase "Print Host upload" information from the preset
|
||||
for (const std::string& opt : options)
|
||||
config.opt_string(opt).clear();
|
||||
// save changes for preset
|
||||
preset.save();
|
||||
|
||||
// update those changes for edited preset if it's equal to the preset
|
||||
Preset& edited = printer_presets.get_edited_preset();
|
||||
if (preset.name == edited.name) {
|
||||
for (const std::string& opt : options)
|
||||
edited.config.opt_string(opt).clear();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PhysicalPrinter* PhysicalPrinterCollection::find_printer( const std::string& name, bool first_visible_if_not_found)
|
||||
{
|
||||
auto it = this->find_printer_internal(name);
|
||||
// Ensure that a temporary copy is returned if the preset found is currently selected.
|
||||
return (it != m_printers.end() && it->name == name) ? &this->printer(it - m_printers.begin()) :
|
||||
first_visible_if_not_found ? &this->printer(0) : nullptr;
|
||||
}
|
||||
|
||||
PhysicalPrinter* PhysicalPrinterCollection::find_printer_with_same_config(const DynamicPrintConfig& config)
|
||||
{
|
||||
for (const PhysicalPrinter& printer :*this) {
|
||||
bool is_equal = true;
|
||||
for (const std::string& opt : PhysicalPrinter::print_host_options())
|
||||
if (is_equal && printer.config.opt_string(opt) != config.opt_string(opt))
|
||||
is_equal = false;
|
||||
|
||||
if (is_equal)
|
||||
return find_printer(printer.name);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Generate a file path from a profile name. Add the ".ini" suffix if it is missing.
|
||||
std::string PhysicalPrinterCollection::path_from_name(const std::string& new_name) const
|
||||
{
|
||||
std::string file_name = boost::iends_with(new_name, ".ini") ? new_name : (new_name + ".ini");
|
||||
return (boost::filesystem::path(m_dir_path) / file_name).make_preferred().string();
|
||||
}
|
||||
|
||||
void PhysicalPrinterCollection::save_printer(PhysicalPrinter& edited_printer, const std::string& renamed_from/* = ""*/)
|
||||
{
|
||||
// controll and update preset_names in edited_printer config
|
||||
edited_printer.update_preset_names_in_config();
|
||||
|
||||
std::string name = renamed_from.empty() ? edited_printer.name : renamed_from;
|
||||
// 1) Find the printer with a new_name or create a new one,
|
||||
// initialize it with the edited config.
|
||||
auto it = this->find_printer_internal(name);
|
||||
if (it != m_printers.end() && it->name == name) {
|
||||
// Printer with the same name found.
|
||||
// Overwriting an existing preset.
|
||||
it->config = std::move(edited_printer.config);
|
||||
it->name = edited_printer.name;
|
||||
it->preset_names = edited_printer.preset_names;
|
||||
}
|
||||
else {
|
||||
// Creating a new printer.
|
||||
it = m_printers.insert(it, edited_printer);
|
||||
}
|
||||
assert(it != m_printers.end());
|
||||
|
||||
// 2) Save printer
|
||||
PhysicalPrinter& printer = *it;
|
||||
if (printer.file.empty())
|
||||
printer.file = this->path_from_name(printer.name);
|
||||
|
||||
if (printer.file == this->path_from_name(printer.name))
|
||||
printer.save();
|
||||
else
|
||||
// if printer was renamed, we should rename a file and than save the config
|
||||
printer.save(printer.file, this->path_from_name(printer.name));
|
||||
|
||||
// update idx_selected
|
||||
m_idx_selected = it - m_printers.begin();
|
||||
}
|
||||
|
||||
bool PhysicalPrinterCollection::delete_printer(const std::string& name)
|
||||
{
|
||||
auto it = this->find_printer_internal(name);
|
||||
if (it == m_printers.end())
|
||||
return false;
|
||||
|
||||
const PhysicalPrinter& printer = *it;
|
||||
// Erase the preset file.
|
||||
boost::nowide::remove(printer.file.c_str());
|
||||
m_printers.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PhysicalPrinterCollection::delete_selected_printer()
|
||||
{
|
||||
if (!has_selection())
|
||||
return false;
|
||||
const PhysicalPrinter& printer = this->get_selected_printer();
|
||||
|
||||
// Erase the preset file.
|
||||
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
|
||||
unselect_printer();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PhysicalPrinterCollection::delete_preset_from_printers( const std::string& preset_name)
|
||||
{
|
||||
std::vector<std::string> printers_for_delete;
|
||||
for (PhysicalPrinter& printer : m_printers) {
|
||||
if (printer.preset_names.size() == 1 && *printer.preset_names.begin() == preset_name)
|
||||
printers_for_delete.emplace_back(printer.name);
|
||||
else if (printer.delete_preset(preset_name))
|
||||
save_printer(printer);
|
||||
}
|
||||
|
||||
if (!printers_for_delete.empty())
|
||||
for (const std::string& printer_name : printers_for_delete)
|
||||
delete_printer(printer_name);
|
||||
|
||||
unselect_printer();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get list of printers which have more than one preset and "preset_name" preset is one of them
|
||||
std::vector<std::string> PhysicalPrinterCollection::get_printers_with_preset(const std::string& preset_name)
|
||||
{
|
||||
std::vector<std::string> printers;
|
||||
|
||||
for (auto printer : m_printers) {
|
||||
if (printer.preset_names.size() == 1)
|
||||
continue;
|
||||
if (printer.preset_names.find(preset_name) != printer.preset_names.end())
|
||||
printers.emplace_back(printer.name);
|
||||
}
|
||||
|
||||
return printers;
|
||||
}
|
||||
|
||||
// Get list of printers which has only "preset_name" preset
|
||||
std::vector<std::string> PhysicalPrinterCollection::get_printers_with_only_preset(const std::string& preset_name)
|
||||
{
|
||||
std::vector<std::string> printers;
|
||||
|
||||
for (auto printer : m_printers)
|
||||
if (printer.preset_names.size() == 1 && *printer.preset_names.begin() == preset_name)
|
||||
printers.emplace_back(printer.name);
|
||||
|
||||
return printers;
|
||||
}
|
||||
|
||||
std::string PhysicalPrinterCollection::get_selected_full_printer_name() const
|
||||
{
|
||||
return (m_idx_selected == size_t(-1)) ? std::string() : this->get_selected_printer().get_full_name(m_selected_preset);
|
||||
}
|
||||
|
||||
void PhysicalPrinterCollection::select_printer(const std::string& full_name)
|
||||
{
|
||||
std::string printer_name = PhysicalPrinter::get_short_name(full_name);
|
||||
auto it = this->find_printer_internal(printer_name);
|
||||
if (it == m_printers.end()) {
|
||||
unselect_printer();
|
||||
return;
|
||||
}
|
||||
|
||||
// update idx_selected
|
||||
m_idx_selected = it - m_printers.begin();
|
||||
|
||||
// update name of the currently selected preset
|
||||
if (printer_name == full_name)
|
||||
// use first preset in the list
|
||||
m_selected_preset = *it->preset_names.begin();
|
||||
else
|
||||
m_selected_preset = it->get_preset_name(full_name);
|
||||
}
|
||||
|
||||
void PhysicalPrinterCollection::select_printer(const PhysicalPrinter& printer)
|
||||
{
|
||||
return select_printer(printer.name);
|
||||
}
|
||||
|
||||
bool PhysicalPrinterCollection::has_selection() const
|
||||
{
|
||||
return m_idx_selected != size_t(-1);
|
||||
}
|
||||
|
||||
void PhysicalPrinterCollection::unselect_printer()
|
||||
{
|
||||
m_idx_selected = size_t(-1);
|
||||
m_selected_preset.clear();
|
||||
}
|
||||
|
||||
bool PhysicalPrinterCollection::is_selected(PhysicalPrinterCollection::ConstIterator it, const std::string& preset_name) const
|
||||
{
|
||||
return m_idx_selected == it - m_printers.begin() &&
|
||||
m_selected_preset == preset_name;
|
||||
}
|
||||
|
||||
|
||||
namespace PresetUtils {
|
||||
const VendorProfile::PrinterModel* system_printer_model(const Preset &preset)
|
||||
{
|
@ -8,27 +8,14 @@
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/property_tree/ptree_fwd.hpp>
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "libslic3r/Semver.hpp"
|
||||
|
||||
class wxBitmap;
|
||||
class wxBitmapComboBox;
|
||||
class wxChoice;
|
||||
class wxItemContainer;
|
||||
class wxString;
|
||||
class wxWindow;
|
||||
#include "PrintConfig.hpp"
|
||||
#include "Semver.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class AppConfig;
|
||||
class PresetBundle;
|
||||
|
||||
namespace GUI {
|
||||
class BitmapCache;
|
||||
class PresetComboBox;
|
||||
}
|
||||
|
||||
enum ConfigFileType
|
||||
{
|
||||
CONFIG_FILE_TYPE_UNKNOWN,
|
||||
@ -236,7 +223,7 @@ public:
|
||||
static const std::vector<std::string>& sla_material_options();
|
||||
static const std::vector<std::string>& sla_print_options();
|
||||
|
||||
static void update_suffix_modified();
|
||||
static void update_suffix_modified(const std::string& new_suffix_modified);
|
||||
static const std::string& suffix_modified();
|
||||
static std::string remove_suffix_modified(const std::string& name);
|
||||
static void normalize(DynamicPrintConfig &config);
|
||||
@ -322,18 +309,6 @@ public:
|
||||
// returns true if the preset was deleted successfully.
|
||||
bool delete_preset(const std::string& name);
|
||||
|
||||
// Load default bitmap to be placed at the wxBitmapComboBox of a MainFrame.
|
||||
void load_bitmap_default(const std::string &file_name);
|
||||
|
||||
// Load "add new printer" bitmap to be placed at the wxBitmapComboBox of a MainFrame.
|
||||
void load_bitmap_add(const std::string &file_name);
|
||||
|
||||
// Compatible & incompatible marks, to be placed at the wxBitmapComboBox items.
|
||||
void set_bitmap_compatible (const wxBitmap *bmp) { m_bitmap_compatible = bmp; }
|
||||
void set_bitmap_incompatible(const wxBitmap *bmp) { m_bitmap_incompatible = bmp; }
|
||||
void set_bitmap_lock (const wxBitmap *bmp) { m_bitmap_lock = bmp; }
|
||||
void set_bitmap_lock_open (const wxBitmap *bmp) { m_bitmap_lock_open = bmp; }
|
||||
|
||||
// Enable / disable the "- default -" preset.
|
||||
void set_default_suppressed(bool default_suppressed);
|
||||
bool is_default_suppressed() const { return m_default_suppressed; }
|
||||
@ -446,18 +421,9 @@ public:
|
||||
// Return a sorted list of system preset names.
|
||||
std::vector<std::string> system_preset_names() const;
|
||||
|
||||
// Update the choice UI from the list of presets.
|
||||
// If show_incompatible, all presets are shown, otherwise only the compatible presets are shown.
|
||||
// If an incompatible preset is selected, it is shown as well.
|
||||
size_t update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible, const int em = 10);
|
||||
// Update the choice UI from the list of presets.
|
||||
// Only the compatible presets are shown.
|
||||
// If an incompatible preset is selected, it is shown as well.
|
||||
void update_plater_ui(GUI::PresetComboBox *ui);
|
||||
|
||||
// Update a dirty floag of the current preset, update the labels of the UI component accordingly.
|
||||
// Update a dirty flag of the current preset
|
||||
// Return true if the dirty flag changed.
|
||||
bool update_dirty_ui(wxBitmapComboBox *ui);
|
||||
bool update_dirty();
|
||||
|
||||
// Select a profile by its name. Return true if the selection changed.
|
||||
// Without force, the selection is only updated if the index changes.
|
||||
@ -467,16 +433,7 @@ public:
|
||||
// Generate a file path from a profile name. Add the ".ini" suffix if it is missing.
|
||||
std::string path_from_name(const std::string &new_name) const;
|
||||
|
||||
void clear_bitmap_cache();
|
||||
|
||||
#ifdef __linux__
|
||||
static const char* separator_head() { return "------- "; }
|
||||
static const char* separator_tail() { return " -------"; }
|
||||
#else /* __linux__ */
|
||||
static const char* separator_head() { return "————— "; }
|
||||
static const char* separator_tail() { return " —————"; }
|
||||
#endif /* __linux__ */
|
||||
static wxString separator(const std::string &label);
|
||||
size_t num_default_presets() { return m_num_default_presets; }
|
||||
|
||||
protected:
|
||||
// Select a preset, if it exists. If it does not exist, select an invalid (-1) index.
|
||||
@ -547,23 +504,10 @@ private:
|
||||
// Is the "- default -" preset suppressed?
|
||||
bool m_default_suppressed = true;
|
||||
size_t m_num_default_presets = 0;
|
||||
// Compatible & incompatible marks, to be placed at the wxBitmapComboBox items of a Plater.
|
||||
// These bitmaps are not owned by PresetCollection, but by a PresetBundle.
|
||||
const wxBitmap *m_bitmap_compatible = nullptr;
|
||||
const wxBitmap *m_bitmap_incompatible = nullptr;
|
||||
const wxBitmap *m_bitmap_lock = nullptr;
|
||||
const wxBitmap *m_bitmap_lock_open = nullptr;
|
||||
// Marks placed at the wxBitmapComboBox of a MainFrame.
|
||||
// These bitmaps are owned by PresetCollection.
|
||||
wxBitmap *m_bitmap_main_frame;
|
||||
// "Add printer profile" icon, owned by PresetCollection.
|
||||
wxBitmap *m_bitmap_add;
|
||||
|
||||
// Path to the directory to store the config files into.
|
||||
std::string m_dir_path;
|
||||
|
||||
// Caching color bitmaps for the filament combo box.
|
||||
GUI::BitmapCache *m_bitmap_cache = nullptr;
|
||||
|
||||
// to access select_preset_by_name_strict()
|
||||
friend class PresetBundle;
|
||||
};
|
||||
@ -585,6 +529,206 @@ namespace PresetUtils {
|
||||
const VendorProfile::PrinterModel* system_printer_model(const Preset &preset);
|
||||
} // namespace PresetUtils
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
class PhysicalPrinter
|
||||
{
|
||||
public:
|
||||
PhysicalPrinter() {}
|
||||
PhysicalPrinter(const std::string& name) : name(name){}
|
||||
PhysicalPrinter(const std::string& name, const Preset& preset);
|
||||
void set_name(const std::string &name);
|
||||
|
||||
// Name of the Physical Printer, usually derived form the file name.
|
||||
std::string name;
|
||||
// File name of the Physical Printer.
|
||||
std::string file;
|
||||
// Configuration data, loaded from a file, or set from the defaults.
|
||||
DynamicPrintConfig config;
|
||||
// set of presets used with this physical printer
|
||||
std::set<std::string> preset_names;
|
||||
|
||||
// Has this profile been loaded?
|
||||
bool loaded = false;
|
||||
|
||||
static std::string separator();
|
||||
static const std::vector<std::string>& printer_options();
|
||||
static const std::vector<std::string>& print_host_options();
|
||||
static std::vector<std::string> presets_with_print_host_information(const PrinterPresetCollection& printer_presets);
|
||||
static bool has_print_host_information(const DynamicPrintConfig& config);
|
||||
|
||||
const std::set<std::string>& get_preset_names() const;
|
||||
|
||||
bool has_empty_config() const;
|
||||
void update_preset_names_in_config();
|
||||
|
||||
void save() { this->config.save(this->file); }
|
||||
void save(const std::string& file_name_from, const std::string& file_name_to);
|
||||
|
||||
void update_from_preset(const Preset& preset);
|
||||
void update_from_config(const DynamicPrintConfig &new_config);
|
||||
|
||||
// add preset to the preset_names
|
||||
// return false, if preset with this name is already exist in the set
|
||||
bool add_preset(const std::string& preset_name);
|
||||
bool delete_preset(const std::string& preset_name);
|
||||
void reset_presets();
|
||||
|
||||
// Return a printer technology, return ptFFF if the printer technology is not set.
|
||||
static PrinterTechnology printer_technology(const DynamicPrintConfig& cfg) {
|
||||
auto* opt = cfg.option<ConfigOptionEnum<PrinterTechnology>>("printer_technology");
|
||||
// The following assert may trigger when importing some legacy profile,
|
||||
// but it is safer to keep it here to capture the cases where the "printer_technology" key is queried, where it should not.
|
||||
return (opt == nullptr) ? ptFFF : opt->value;
|
||||
}
|
||||
PrinterTechnology printer_technology() const { return printer_technology(this->config); }
|
||||
|
||||
// Sort lexicographically by a preset name. The preset name shall be unique across a single PresetCollection.
|
||||
bool operator<(const PhysicalPrinter& other) const { return this->name < other.name; }
|
||||
|
||||
// get full printer name included a name of the preset
|
||||
std::string get_full_name(std::string preset_name) const;
|
||||
|
||||
// get printer name from the full name uncluded preset name
|
||||
static std::string get_short_name(std::string full_name);
|
||||
|
||||
// get preset name from the full name uncluded printer name
|
||||
static std::string get_preset_name(std::string full_name);
|
||||
|
||||
protected:
|
||||
friend class PhysicalPrinterCollection;
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------
|
||||
// *** PhysicalPrinterCollection ***
|
||||
// ---------------------------------
|
||||
|
||||
// Collections of physical printers
|
||||
class PhysicalPrinterCollection
|
||||
{
|
||||
public:
|
||||
PhysicalPrinterCollection(const std::vector<std::string>& keys);
|
||||
~PhysicalPrinterCollection() {}
|
||||
|
||||
typedef std::deque<PhysicalPrinter>::iterator Iterator;
|
||||
typedef std::deque<PhysicalPrinter>::const_iterator ConstIterator;
|
||||
Iterator begin() { return m_printers.begin(); }
|
||||
ConstIterator begin() const { return m_printers.cbegin(); }
|
||||
ConstIterator cbegin() const { return m_printers.cbegin(); }
|
||||
Iterator end() { return m_printers.end(); }
|
||||
ConstIterator end() const { return m_printers.cend(); }
|
||||
ConstIterator cend() const { return m_printers.cend(); }
|
||||
|
||||
bool empty() const {return m_printers.empty(); }
|
||||
|
||||
void reset(bool delete_files) {};
|
||||
|
||||
const std::deque<PhysicalPrinter>& operator()() const { return m_printers; }
|
||||
|
||||
// Load ini files of the particular type from the provided directory path.
|
||||
void load_printers(const std::string& dir_path, const std::string& subdir);
|
||||
void load_printers_from_presets(PrinterPresetCollection &printer_presets);
|
||||
|
||||
// Save the printer under a new name. If the name is different from the old one,
|
||||
// a new printer is stored into the list of printers.
|
||||
// New printer is activated.
|
||||
void save_printer(PhysicalPrinter& printer, const std::string& renamed_from = "");
|
||||
|
||||
// Delete the current preset, activate the first visible preset.
|
||||
// returns true if the preset was deleted successfully.
|
||||
bool delete_printer(const std::string& name);
|
||||
// Delete the selected preset
|
||||
// returns true if the preset was deleted successfully.
|
||||
bool delete_selected_printer();
|
||||
// Delete preset_name preset from all printers:
|
||||
// If there is last preset for the printer and first_check== false, then delete this printer
|
||||
// returns true if all presets were deleted successfully.
|
||||
bool delete_preset_from_printers(const std::string& preset_name);
|
||||
|
||||
// Get list of printers which have more than one preset and "preset_name" preset is one of them
|
||||
std::vector<std::string> get_printers_with_preset( const std::string &preset_name);
|
||||
// Get list of printers which has only "preset_name" preset
|
||||
std::vector<std::string> get_printers_with_only_preset( const std::string &preset_name);
|
||||
|
||||
// Return the selected preset, without the user modifications applied.
|
||||
PhysicalPrinter& get_selected_printer() { return m_printers[m_idx_selected]; }
|
||||
const PhysicalPrinter& get_selected_printer() const { return m_printers[m_idx_selected]; }
|
||||
|
||||
size_t get_selected_idx() const { return m_idx_selected; }
|
||||
// Returns the name of the selected preset, or an empty string if no preset is selected.
|
||||
std::string get_selected_printer_name() const { return (m_idx_selected == size_t(-1)) ? std::string() : this->get_selected_printer().name; }
|
||||
// Returns the config of the selected printer, or nullptr if no printer is selected.
|
||||
DynamicPrintConfig* get_selected_printer_config() { return (m_idx_selected == size_t(-1)) ? nullptr : &(this->get_selected_printer().config); }
|
||||
// Returns the config of the selected printer, or nullptr if no printer is selected.
|
||||
PrinterTechnology get_selected_printer_technology() { return (m_idx_selected == size_t(-1)) ? PrinterTechnology::ptAny : this->get_selected_printer().printer_technology(); }
|
||||
|
||||
// Each physical printer can have a several related preset,
|
||||
// so, use the next functions to get an exact names of selections in the list:
|
||||
// Returns the full name of the selected printer, or an empty string if no preset is selected.
|
||||
std::string get_selected_full_printer_name() const;
|
||||
// Returns the printer model of the selected preset, or an empty string if no preset is selected.
|
||||
std::string get_selected_printer_preset_name() const { return (m_idx_selected == size_t(-1)) ? std::string() : m_selected_preset; }
|
||||
|
||||
// Select printer by the full printer name, which contains name of printer, separator and name of selected preset
|
||||
// If full_name doesn't contain name of selected preset, then select first preset in the list for this printer
|
||||
void select_printer(const std::string& full_name);
|
||||
void select_printer(const PhysicalPrinter& printer);
|
||||
bool has_selection() const;
|
||||
void unselect_printer() ;
|
||||
bool is_selected(ConstIterator it, const std::string &preset_name) const;
|
||||
|
||||
// Return a printer by an index. If the printer is active, a temporary copy is returned.
|
||||
PhysicalPrinter& printer(size_t idx) { return m_printers[idx]; }
|
||||
const PhysicalPrinter& printer(size_t idx) const { return const_cast<PhysicalPrinterCollection*>(this)->printer(idx); }
|
||||
|
||||
// Return a preset by its name. If the preset is active, a temporary copy is returned.
|
||||
// If a preset is not found by its name, null is returned.
|
||||
PhysicalPrinter* find_printer(const std::string& name, bool first_visible_if_not_found = false);
|
||||
const PhysicalPrinter* find_printer(const std::string& name, bool first_visible_if_not_found = false) const
|
||||
{
|
||||
return const_cast<PhysicalPrinterCollection*>(this)->find_printer(name, first_visible_if_not_found);
|
||||
}
|
||||
|
||||
// Generate a file path from a profile name. Add the ".ini" suffix if it is missing.
|
||||
std::string path_from_name(const std::string& new_name) const;
|
||||
|
||||
private:
|
||||
PhysicalPrinterCollection& operator=(const PhysicalPrinterCollection& other);
|
||||
|
||||
// Find a preset position in the sorted list of presets.
|
||||
// The "-- default -- " preset is always the first, so it needs
|
||||
// to be handled differently.
|
||||
// If a preset does not exist, an iterator is returned indicating where to insert a preset with the same name.
|
||||
std::deque<PhysicalPrinter>::iterator find_printer_internal(const std::string& name)
|
||||
{
|
||||
PhysicalPrinter printer(name);
|
||||
auto it = std::lower_bound(m_printers.begin(), m_printers.end(), printer);
|
||||
return it;
|
||||
}
|
||||
std::deque<PhysicalPrinter>::const_iterator find_printer_internal(const std::string& name) const
|
||||
{
|
||||
return const_cast<PhysicalPrinterCollection*>(this)->find_printer_internal(name);
|
||||
}
|
||||
|
||||
PhysicalPrinter* find_printer_with_same_config( const DynamicPrintConfig &config);
|
||||
|
||||
// List of printers
|
||||
// Use deque to force the container to allocate an object per each entry,
|
||||
// so that the addresses of the presets don't change during resizing of the container.
|
||||
std::deque<PhysicalPrinter> m_printers;
|
||||
|
||||
// Selected printer.
|
||||
size_t m_idx_selected = size_t(-1);
|
||||
// The name of the preset which is currently select for this printer
|
||||
std::string m_selected_preset;
|
||||
|
||||
// Path to the directory to store the config files into.
|
||||
std::string m_dir_path;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif /* slic3r_Preset_hpp_ */
|
@ -1,12 +1,12 @@
|
||||
#include <cassert>
|
||||
|
||||
#include "PresetBundle.hpp"
|
||||
#include "BitmapCache.hpp"
|
||||
#include "Plater.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "libslic3r.h"
|
||||
#include "Utils.hpp"
|
||||
#include "Model.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <fstream>
|
||||
#include <unordered_set>
|
||||
#include <boost/filesystem.hpp>
|
||||
@ -21,17 +21,6 @@
|
||||
#include <boost/locale.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include <wx/dcmemory.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/bmpcbox.h>
|
||||
#include <wx/wupdlock.h>
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
|
||||
|
||||
// Store the print/filament/printer presets into a "presets" subdirectory of the Slic3rPE config dir.
|
||||
// This breaks compatibility with the upstream Slic3r if the --datadir is used to switch between the two versions.
|
||||
@ -53,15 +42,8 @@ PresetBundle::PresetBundle() :
|
||||
sla_materials(Preset::TYPE_SLA_MATERIAL, Preset::sla_material_options(), static_cast<const SLAMaterialConfig&>(SLAFullPrintConfig::defaults())),
|
||||
sla_prints(Preset::TYPE_SLA_PRINT, Preset::sla_print_options(), static_cast<const SLAPrintObjectConfig&>(SLAFullPrintConfig::defaults())),
|
||||
printers(Preset::TYPE_PRINTER, Preset::printer_options(), static_cast<const HostConfig&>(FullPrintConfig::defaults()), "- default FFF -"),
|
||||
m_bitmapCompatible(new wxBitmap),
|
||||
m_bitmapIncompatible(new wxBitmap),
|
||||
m_bitmapLock(new wxBitmap),
|
||||
m_bitmapLockOpen(new wxBitmap),
|
||||
m_bitmapCache(new GUI::BitmapCache)
|
||||
physical_printers(PhysicalPrinter::printer_options())
|
||||
{
|
||||
if (wxImage::FindHandler(wxBITMAP_TYPE_PNG) == nullptr)
|
||||
wxImage::AddHandler(new wxPNGHandler);
|
||||
|
||||
// The following keys are handled by the UI, they do not have a counterpart in any StaticPrintConfig derived classes,
|
||||
// therefore they need to be handled differently. As they have no counterpart in StaticPrintConfig, they are not being
|
||||
// initialized based on PrintConfigDef(), but to empty values (zeros, empty vectors, empty strings).
|
||||
@ -112,16 +94,6 @@ PresetBundle::PresetBundle() :
|
||||
preset.inherits();
|
||||
}
|
||||
|
||||
// Load the default preset bitmaps.
|
||||
// #ys_FIXME_to_delete we'll load them later, using em_unit()
|
||||
// this->prints .load_bitmap_default("cog");
|
||||
// this->sla_prints .load_bitmap_default("package_green.png");
|
||||
// this->filaments .load_bitmap_default("spool.png");
|
||||
// this->sla_materials.load_bitmap_default("package_green.png");
|
||||
// this->printers .load_bitmap_default("printer_empty.png");
|
||||
// this->printers .load_bitmap_add("add.png");
|
||||
// this->load_compatible_bitmaps();
|
||||
|
||||
// Re-activate the default presets, so their "edited" preset copies will be updated with the additional configuration values above.
|
||||
this->prints .select_preset(0);
|
||||
this->sla_prints .select_preset(0);
|
||||
@ -134,20 +106,6 @@ PresetBundle::PresetBundle() :
|
||||
|
||||
PresetBundle::~PresetBundle()
|
||||
{
|
||||
assert(m_bitmapCompatible != nullptr);
|
||||
assert(m_bitmapIncompatible != nullptr);
|
||||
assert(m_bitmapLock != nullptr);
|
||||
assert(m_bitmapLockOpen != nullptr);
|
||||
delete m_bitmapCompatible;
|
||||
m_bitmapCompatible = nullptr;
|
||||
delete m_bitmapIncompatible;
|
||||
m_bitmapIncompatible = nullptr;
|
||||
delete m_bitmapLock;
|
||||
m_bitmapLock = nullptr;
|
||||
delete m_bitmapLockOpen;
|
||||
m_bitmapLockOpen = nullptr;
|
||||
delete m_bitmapCache;
|
||||
m_bitmapCache = nullptr;
|
||||
}
|
||||
|
||||
void PresetBundle::reset(bool delete_files)
|
||||
@ -182,14 +140,16 @@ void PresetBundle::setup_directories()
|
||||
data_dir / "presets" / "filament",
|
||||
data_dir / "presets" / "sla_print",
|
||||
data_dir / "presets" / "sla_material",
|
||||
data_dir / "presets" / "printer"
|
||||
data_dir / "presets" / "printer",
|
||||
data_dir / "presets" / "physical_printer"
|
||||
#else
|
||||
// Store the print/filament/printer presets at the same location as the upstream Slic3r.
|
||||
data_dir / "print",
|
||||
data_dir / "filament",
|
||||
data_dir / "sla_print",
|
||||
data_dir / "sla_material",
|
||||
data_dir / "printer"
|
||||
data_dir / "printer",
|
||||
data_dir / "physical_printer"
|
||||
#endif
|
||||
};
|
||||
for (const boost::filesystem::path &path : paths) {
|
||||
@ -239,6 +199,11 @@ void PresetBundle::load_presets(AppConfig &config, const std::string &preferred_
|
||||
} catch (const std::runtime_error &err) {
|
||||
errors_cummulative += err.what();
|
||||
}
|
||||
try {
|
||||
this->physical_printers.load_printers(dir_user_presets, "physical_printer");
|
||||
} catch (const std::runtime_error &err) {
|
||||
errors_cummulative += err.what();
|
||||
}
|
||||
this->update_multi_material_filament_presets();
|
||||
this->update_compatible(PresetSelectCompatibleType::Never);
|
||||
if (! errors_cummulative.empty())
|
||||
@ -465,6 +430,13 @@ void PresetBundle::load_selections(AppConfig &config, const std::string &preferr
|
||||
// exist.
|
||||
this->update_compatible(PresetSelectCompatibleType::Always);
|
||||
this->update_multi_material_filament_presets();
|
||||
|
||||
// Parse the initial physical printer name.
|
||||
std::string initial_physical_printer_name = remove_ini_suffix(config.get("extras", "physical_printer"));
|
||||
|
||||
// Activate physical printer from the config
|
||||
if (!initial_physical_printer_name.empty())
|
||||
physical_printers.select_printer(initial_physical_printer_name);
|
||||
}
|
||||
|
||||
// Export selections (current print, current filaments, current printer) into config.ini
|
||||
@ -484,36 +456,8 @@ void PresetBundle::export_selections(AppConfig &config)
|
||||
config.set("presets", "sla_print", sla_prints.get_selected_preset_name());
|
||||
config.set("presets", "sla_material", sla_materials.get_selected_preset_name());
|
||||
config.set("presets", "printer", printers.get_selected_preset_name());
|
||||
}
|
||||
|
||||
void PresetBundle::load_compatible_bitmaps()
|
||||
{
|
||||
*m_bitmapCompatible = create_scaled_bitmap("flag_green");
|
||||
*m_bitmapIncompatible = create_scaled_bitmap("flag_red");
|
||||
*m_bitmapLock = create_scaled_bitmap("lock_closed");
|
||||
*m_bitmapLockOpen = create_scaled_bitmap("lock_open");
|
||||
|
||||
prints .set_bitmap_compatible(m_bitmapCompatible);
|
||||
filaments .set_bitmap_compatible(m_bitmapCompatible);
|
||||
sla_prints .set_bitmap_compatible(m_bitmapCompatible);
|
||||
sla_materials.set_bitmap_compatible(m_bitmapCompatible);
|
||||
|
||||
prints .set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
filaments .set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
sla_prints .set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
sla_materials.set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
|
||||
prints .set_bitmap_lock(m_bitmapLock);
|
||||
filaments .set_bitmap_lock(m_bitmapLock);
|
||||
sla_prints .set_bitmap_lock(m_bitmapLock);
|
||||
sla_materials.set_bitmap_lock(m_bitmapLock);
|
||||
printers .set_bitmap_lock(m_bitmapLock);
|
||||
|
||||
prints .set_bitmap_lock_open(m_bitmapLock);
|
||||
filaments .set_bitmap_lock_open(m_bitmapLock);
|
||||
sla_prints .set_bitmap_lock_open(m_bitmapLock);
|
||||
sla_materials.set_bitmap_lock_open(m_bitmapLock);
|
||||
printers .set_bitmap_lock_open(m_bitmapLock);
|
||||
config.set("extras", "physical_printer", physical_printers.get_selected_full_printer_name());
|
||||
}
|
||||
|
||||
DynamicPrintConfig PresetBundle::full_config() const
|
||||
@ -886,8 +830,6 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
||||
// 4) Load the project config values (the per extruder wipe matrix etc).
|
||||
this->project_config.apply_only(config, s_project_options);
|
||||
|
||||
update_custom_gcode_per_print_z_from_config(GUI::wxGetApp().plater()->model().custom_gcode_per_print_z, &this->project_config);
|
||||
|
||||
break;
|
||||
}
|
||||
case ptSLA:
|
||||
@ -1544,207 +1486,11 @@ void PresetBundle::export_configbundle(const std::string &path, bool export_syst
|
||||
// an optional "(modified)" suffix will be removed from the filament name.
|
||||
void PresetBundle::set_filament_preset(size_t idx, const std::string &name)
|
||||
{
|
||||
if (name.find_first_of(PresetCollection::separator_head()) == 0)
|
||||
return;
|
||||
|
||||
if (idx >= filament_presets.size())
|
||||
if (idx >= filament_presets.size())
|
||||
filament_presets.resize(idx + 1, filaments.default_preset().name);
|
||||
filament_presets[idx] = Preset::remove_suffix_modified(name);
|
||||
}
|
||||
|
||||
void PresetBundle::load_default_preset_bitmaps()
|
||||
{
|
||||
// Clear bitmap cache, before load new scaled default preset bitmaps
|
||||
m_bitmapCache->clear();
|
||||
this->prints.clear_bitmap_cache();
|
||||
this->sla_prints.clear_bitmap_cache();
|
||||
this->filaments.clear_bitmap_cache();
|
||||
this->sla_materials.clear_bitmap_cache();
|
||||
this->printers.clear_bitmap_cache();
|
||||
|
||||
this->prints.load_bitmap_default("cog");
|
||||
this->sla_prints.load_bitmap_default("cog");
|
||||
this->filaments.load_bitmap_default("spool.png");
|
||||
this->sla_materials.load_bitmap_default("resin");
|
||||
this->printers.load_bitmap_default("printer");
|
||||
this->printers.load_bitmap_add("add.png");
|
||||
this->load_compatible_bitmaps();
|
||||
}
|
||||
|
||||
void PresetBundle::update_plater_filament_ui(unsigned int idx_extruder, GUI::PresetComboBox *ui)
|
||||
{
|
||||
if (ui == nullptr || this->printers.get_edited_preset().printer_technology() == ptSLA ||
|
||||
this->filament_presets.size() <= idx_extruder )
|
||||
return;
|
||||
|
||||
unsigned char rgb[3];
|
||||
std::string extruder_color = this->printers.get_edited_preset().config.opt_string("extruder_colour", idx_extruder);
|
||||
if (!m_bitmapCache->parse_color(extruder_color, rgb))
|
||||
// Extruder color is not defined.
|
||||
extruder_color.clear();
|
||||
|
||||
// Fill in the list from scratch.
|
||||
ui->Freeze();
|
||||
ui->Clear();
|
||||
size_t selected_preset_item = INT_MAX; // some value meaning that no one item is selected
|
||||
|
||||
const Preset *selected_preset = this->filaments.find_preset(this->filament_presets[idx_extruder]);
|
||||
// Show wide icons if the currently selected preset is not compatible with the current printer,
|
||||
// and draw a red flag in front of the selected preset.
|
||||
bool wide_icons = selected_preset != nullptr && ! selected_preset->is_compatible && m_bitmapIncompatible != nullptr;
|
||||
assert(selected_preset != nullptr);
|
||||
std::map<wxString, wxBitmap*> nonsys_presets;
|
||||
wxString selected_str = "";
|
||||
if (!this->filaments().front().is_visible)
|
||||
ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap));
|
||||
|
||||
/* It's supposed that standard size of an icon is 16px*16px for 100% scaled display.
|
||||
* So set sizes for solid_colored icons used for filament preset
|
||||
* and scale them in respect to em_unit value
|
||||
*/
|
||||
const float scale_f = ui->em_unit() * 0.1f;
|
||||
|
||||
// To avoid the errors of number rounding for different combination of monitor configuration,
|
||||
// let use scaled 8px, as a smallest icon unit
|
||||
const int icon_unit = 8 * scale_f + 0.5f;
|
||||
const int normal_icon_width = 2 * icon_unit; //16 * scale_f + 0.5f;
|
||||
const int thin_icon_width = icon_unit; //8 * scale_f + 0.5f;
|
||||
const int wide_icon_width = 3 * icon_unit; //24 * scale_f + 0.5f;
|
||||
|
||||
const int space_icon_width = 2 * scale_f + 0.5f;
|
||||
|
||||
// To avoid asserts, each added bitmap to wxBitmapCombobox should be the same size, so
|
||||
// set a bitmap height to m_bitmapLock->GetHeight()
|
||||
//
|
||||
// To avoid asserts, each added bitmap to wxBitmapCombobox should be the same size.
|
||||
// But for some display scaling (for example 125% or 175%) normal_icon_width differs from icon width.
|
||||
// So:
|
||||
// for nonsystem presets set a width of empty bitmap to m_bitmapLock->GetWidth()
|
||||
// for compatible presets set a width of empty bitmap to m_bitmapIncompatible->GetWidth()
|
||||
//
|
||||
// Note, under OSX we should use a Scaled Height/Width because of Retina scale
|
||||
#ifdef __APPLE__
|
||||
const int icon_height = m_bitmapLock->GetScaledHeight();
|
||||
const int lock_icon_width = m_bitmapLock->GetScaledWidth();
|
||||
const int flag_icon_width = m_bitmapIncompatible->GetScaledWidth();
|
||||
#else
|
||||
const int icon_height = m_bitmapLock->GetHeight();
|
||||
const int lock_icon_width = m_bitmapLock->GetWidth();
|
||||
const int flag_icon_width = m_bitmapIncompatible->GetWidth();
|
||||
#endif
|
||||
|
||||
wxString tooltip = "";
|
||||
|
||||
for (int i = this->filaments().front().is_visible ? 0 : 1; i < int(this->filaments().size()); ++i) {
|
||||
const Preset &preset = this->filaments.preset(i);
|
||||
bool selected = this->filament_presets[idx_extruder] == preset.name;
|
||||
if (! preset.is_visible || (! preset.is_compatible && ! selected))
|
||||
continue;
|
||||
// Assign an extruder color to the selected item if the extruder color is defined.
|
||||
std::string filament_rgb = preset.config.opt_string("filament_colour", 0);
|
||||
std::string extruder_rgb = (selected && !extruder_color.empty()) ? extruder_color : filament_rgb;
|
||||
bool single_bar = filament_rgb == extruder_rgb;
|
||||
std::string bitmap_key = single_bar ? filament_rgb : filament_rgb + extruder_rgb;
|
||||
// If the filament preset is not compatible and there is a "red flag" icon loaded, show it left
|
||||
// to the filament color image.
|
||||
if (wide_icons)
|
||||
bitmap_key += preset.is_compatible ? ",cmpt" : ",ncmpt";
|
||||
bitmap_key += (preset.is_system || preset.is_default) ? ",syst" : ",nsyst";
|
||||
if (preset.is_dirty)
|
||||
bitmap_key += ",drty";
|
||||
wxBitmap *bitmap = m_bitmapCache->find(bitmap_key);
|
||||
if (bitmap == nullptr) {
|
||||
// Create the bitmap with color bars.
|
||||
std::vector<wxBitmap> bmps;
|
||||
if (wide_icons)
|
||||
// Paint a red flag for incompatible presets.
|
||||
bmps.emplace_back(preset.is_compatible ? m_bitmapCache->mkclear(flag_icon_width, icon_height) : *m_bitmapIncompatible);
|
||||
// Paint the color bars.
|
||||
m_bitmapCache->parse_color(filament_rgb, rgb);
|
||||
bmps.emplace_back(m_bitmapCache->mksolid(single_bar ? wide_icon_width : normal_icon_width, icon_height, rgb));
|
||||
if (! single_bar) {
|
||||
m_bitmapCache->parse_color(extruder_rgb, rgb);
|
||||
bmps.emplace_back(m_bitmapCache->mksolid(thin_icon_width, icon_height, rgb));
|
||||
}
|
||||
// Paint a lock at the system presets.
|
||||
bmps.emplace_back(m_bitmapCache->mkclear(space_icon_width, icon_height));
|
||||
bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmapLock : m_bitmapCache->mkclear(lock_icon_width, icon_height));
|
||||
// (preset.is_dirty ? *m_bitmapLockOpen : *m_bitmapLock) : m_bitmapCache->mkclear(16, 16));
|
||||
bitmap = m_bitmapCache->insert(bitmap_key, bmps);
|
||||
}
|
||||
|
||||
const std::string name = preset.alias.empty() ? preset.name : preset.alias;
|
||||
if (preset.is_default || preset.is_system) {
|
||||
ui->Append(wxString::FromUTF8((/*preset.*/name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()),
|
||||
(bitmap == 0) ? wxNullBitmap : *bitmap);
|
||||
if (selected ||
|
||||
// just in case: mark selected_preset_item as a first added element
|
||||
selected_preset_item == INT_MAX ) {
|
||||
selected_preset_item = ui->GetCount() - 1;
|
||||
tooltip = wxString::FromUTF8(preset.name.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nonsys_presets.emplace(wxString::FromUTF8((/*preset.*/name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()),
|
||||
(bitmap == 0) ? &wxNullBitmap : bitmap);
|
||||
if (selected) {
|
||||
selected_str = wxString::FromUTF8((/*preset.*/name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str());
|
||||
tooltip = wxString::FromUTF8(preset.name.c_str());
|
||||
}
|
||||
}
|
||||
if (preset.is_default)
|
||||
ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap));
|
||||
}
|
||||
|
||||
if (!nonsys_presets.empty())
|
||||
{
|
||||
ui->set_label_marker(ui->Append(PresetCollection::separator(L("User presets")), wxNullBitmap));
|
||||
for (std::map<wxString, wxBitmap*>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
|
||||
ui->Append(it->first, *it->second);
|
||||
if (it->first == selected_str ||
|
||||
// just in case: mark selected_preset_item as a first added element
|
||||
selected_preset_item == INT_MAX) {
|
||||
selected_preset_item = ui->GetCount() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitmap_key = "";
|
||||
if (wide_icons)
|
||||
bitmap_key += "wide,";
|
||||
bitmap_key += "edit_preset_list";
|
||||
wxBitmap* bmp = m_bitmapCache->find(bitmap_key);
|
||||
if (bmp == nullptr) {
|
||||
// Create the bitmap with color bars.
|
||||
std::vector<wxBitmap> bmps;
|
||||
if (wide_icons)
|
||||
// Paint a red flag for incompatible presets.
|
||||
bmps.emplace_back(m_bitmapCache->mkclear(flag_icon_width, icon_height));
|
||||
// Paint the color bars + a lock at the system presets.
|
||||
bmps.emplace_back(m_bitmapCache->mkclear(wide_icon_width+space_icon_width, icon_height));
|
||||
bmps.emplace_back(create_scaled_bitmap("edit_uni"));
|
||||
bmp = m_bitmapCache->insert(bitmap_key, bmps);
|
||||
}
|
||||
ui->set_label_marker(ui->Append(PresetCollection::separator(L("Add/Remove filaments")), *bmp), GUI::PresetComboBox::LABEL_ITEM_WIZARD_FILAMENTS);
|
||||
|
||||
/* But, if selected_preset_item is still equal to INT_MAX, it means that
|
||||
* there is no presets added to the list.
|
||||
* So, select last combobox item ("Add/Remove filaments")
|
||||
*/
|
||||
if (selected_preset_item == INT_MAX)
|
||||
selected_preset_item = ui->GetCount() - 1;
|
||||
|
||||
ui->SetSelection(selected_preset_item);
|
||||
ui->SetToolTip(tooltip.IsEmpty() ? ui->GetString(selected_preset_item) : tooltip);
|
||||
ui->check_selection(selected_preset_item);
|
||||
ui->Thaw();
|
||||
|
||||
// Update control min size after rescale (changed Display DPI under MSW)
|
||||
if (ui->GetMinWidth() != 20 * ui->em_unit())
|
||||
ui->SetMinSize(wxSize(20 * ui->em_unit(), ui->GetSize().GetHeight()));
|
||||
}
|
||||
|
||||
void PresetBundle::set_default_suppressed(bool default_suppressed)
|
||||
{
|
||||
prints.set_default_suppressed(default_suppressed);
|
@ -1,22 +1,15 @@
|
||||
#ifndef slic3r_PresetBundle_hpp_
|
||||
#define slic3r_PresetBundle_hpp_
|
||||
|
||||
#include "AppConfig.hpp"
|
||||
#include "Preset.hpp"
|
||||
#include "AppConfig.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
class wxWindow;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace GUI {
|
||||
class BitmapCache;
|
||||
};
|
||||
|
||||
// Bundle of Print + Filament + Printer presets.
|
||||
class PresetBundle
|
||||
{
|
||||
@ -45,6 +38,7 @@ public:
|
||||
PresetCollection& materials(PrinterTechnology pt) { return pt == ptFFF ? this->filaments : this->sla_materials; }
|
||||
const PresetCollection& materials(PrinterTechnology pt) const { return pt == ptFFF ? this->filaments : this->sla_materials; }
|
||||
PrinterPresetCollection printers;
|
||||
PhysicalPrinterCollection physical_printers;
|
||||
// Filament preset names for a multi-extruder or multi-material print.
|
||||
// extruders.size() should be the same as printers.get_edited_preset().config.nozzle_diameter.size()
|
||||
std::vector<std::string> filament_presets;
|
||||
@ -110,9 +104,6 @@ public:
|
||||
// Export a config bundle file containing all the presets and the names of the active presets.
|
||||
void export_configbundle(const std::string &path, bool export_system_settings = false);
|
||||
|
||||
// Update a filament selection combo box on the plater for an idx_extruder.
|
||||
void update_plater_filament_ui(unsigned int idx_extruder, GUI::PresetComboBox *ui);
|
||||
|
||||
// Enable / disable the "- default -" preset.
|
||||
void set_default_suppressed(bool default_suppressed);
|
||||
|
||||
@ -132,8 +123,6 @@ public:
|
||||
void update_compatible(PresetSelectCompatibleType select_other_print_if_incompatible, PresetSelectCompatibleType select_other_filament_if_incompatible);
|
||||
void update_compatible(PresetSelectCompatibleType select_other_if_incompatible) { this->update_compatible(select_other_if_incompatible, select_other_if_incompatible); }
|
||||
|
||||
void load_default_preset_bitmaps();
|
||||
|
||||
// Set the is_visible flag for printer vendors, printer models and printer variants
|
||||
// based on the user configuration.
|
||||
// If the "vendor" section is missing, enable all models and variants of the particular vendor.
|
||||
@ -163,21 +152,9 @@ private:
|
||||
// If it is not an external config, then the config will be stored into the user profile directory.
|
||||
void load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config);
|
||||
void load_config_file_config_bundle(const std::string &path, const boost::property_tree::ptree &tree);
|
||||
void load_compatible_bitmaps();
|
||||
|
||||
DynamicPrintConfig full_fff_config() const;
|
||||
DynamicPrintConfig full_sla_config() const;
|
||||
|
||||
// Indicator, that the preset is compatible with the selected printer.
|
||||
wxBitmap *m_bitmapCompatible;
|
||||
// Indicator, that the preset is NOT compatible with the selected printer.
|
||||
wxBitmap *m_bitmapIncompatible;
|
||||
// Indicator, that the preset is system and not modified.
|
||||
wxBitmap *m_bitmapLock;
|
||||
// Indicator, that the preset is system and user modified.
|
||||
wxBitmap *m_bitmapLockOpen;
|
||||
// Caching color bitmaps for the filament combo box.
|
||||
GUI::BitmapCache *m_bitmapCache;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
@ -130,6 +130,37 @@ void PrintConfigDef::init_common_params()
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0.2));
|
||||
|
||||
// Options used by physical printers
|
||||
|
||||
def = this->add("login", coString);
|
||||
def->label = L("Login");
|
||||
// def->tooltip = L("");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
|
||||
def = this->add("password", coString);
|
||||
def->label = L("Password");
|
||||
// def->tooltip = L("");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
|
||||
def = this->add("preset_name", coString);
|
||||
def->label = L("Printer preset name");
|
||||
def->tooltip = L("Related printer preset name");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
|
||||
def = this->add("authorization_type", coEnum);
|
||||
def->label = L("Authorization Type");
|
||||
// def->tooltip = L("");
|
||||
def->enum_keys_map = &ConfigOptionEnum<AuthorizationType>::get_enum_values();
|
||||
def->enum_values.push_back("key");
|
||||
def->enum_values.push_back("user");
|
||||
def->enum_labels.push_back("KeyPassword");
|
||||
def->enum_labels.push_back("UserPassword");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionEnum<AuthorizationType>(atKeyPassword));
|
||||
}
|
||||
|
||||
void PrintConfigDef::init_fff_params()
|
||||
|
@ -33,6 +33,10 @@ enum PrintHostType {
|
||||
htOctoPrint, htDuet, htFlashAir, htAstroBox
|
||||
};
|
||||
|
||||
enum AuthorizationType {
|
||||
atKeyPassword, atUserPassword
|
||||
};
|
||||
|
||||
enum InfillPattern : int {
|
||||
ipRectilinear, ipMonotonous, ipGrid, ipTriangles, ipStars, ipCubic, ipLine, ipConcentric, ipHoneycomb, ip3DHoneycomb,
|
||||
ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipCount,
|
||||
@ -109,6 +113,15 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<PrintHostType>::g
|
||||
return keys_map;
|
||||
}
|
||||
|
||||
template<> inline const t_config_enum_values& ConfigOptionEnum<AuthorizationType>::get_enum_values() {
|
||||
static t_config_enum_values keys_map;
|
||||
if (keys_map.empty()) {
|
||||
keys_map["key"] = atKeyPassword;
|
||||
keys_map["user"] = atUserPassword;
|
||||
}
|
||||
return keys_map;
|
||||
}
|
||||
|
||||
template<> inline const t_config_enum_values& ConfigOptionEnum<InfillPattern>::get_enum_values() {
|
||||
static t_config_enum_values keys_map;
|
||||
if (keys_map.empty()) {
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
// this needs to be included early for MSVC (listing it in Build.PL is not enough)
|
||||
#include <memory>
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <ostream>
|
||||
#include <iostream>
|
||||
|
@ -12,8 +12,6 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/SysInfoDialog.hpp
|
||||
GUI/KBShortcutsDialog.cpp
|
||||
GUI/KBShortcutsDialog.hpp
|
||||
GUI/AppConfig.cpp
|
||||
GUI/AppConfig.hpp
|
||||
GUI/BackgroundSlicingProcess.cpp
|
||||
GUI/BackgroundSlicingProcess.hpp
|
||||
GUI/BitmapCache.cpp
|
||||
@ -67,10 +65,6 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/GCodeViewer.cpp
|
||||
GUI/Preferences.cpp
|
||||
GUI/Preferences.hpp
|
||||
GUI/Preset.cpp
|
||||
GUI/Preset.hpp
|
||||
GUI/PresetBundle.cpp
|
||||
GUI/PresetBundle.hpp
|
||||
GUI/PresetHints.cpp
|
||||
GUI/PresetHints.hpp
|
||||
GUI/GUI.cpp
|
||||
@ -87,6 +81,10 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/MainFrame.hpp
|
||||
GUI/Plater.cpp
|
||||
GUI/Plater.hpp
|
||||
GUI/PresetComboBoxes.hpp
|
||||
GUI/PresetComboBoxes.cpp
|
||||
GUI/PhysicalPrinterDialog.hpp
|
||||
GUI/PhysicalPrinterDialog.cpp
|
||||
GUI/GUI_ObjectList.cpp
|
||||
GUI/GUI_ObjectList.hpp
|
||||
GUI/GUI_ObjectManipulation.cpp
|
||||
|
@ -1,6 +1,4 @@
|
||||
#include "Snapshot.hpp"
|
||||
#include "../GUI/AppConfig.hpp"
|
||||
#include "../GUI/PresetBundle.hpp"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
@ -11,7 +9,7 @@
|
||||
#include <boost/property_tree/ptree_fwd.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
|
||||
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/Time.hpp"
|
||||
#include "libslic3r/Config.hpp"
|
||||
|
@ -10,7 +10,7 @@
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
#include "GUI_App.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "GLCanvas3D.hpp"
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
#include "3DScene.hpp"
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "GUI_App.hpp"
|
||||
#if ENABLE_ENVIRONMENT_MAP
|
||||
#include "Plater.hpp"
|
||||
#include "AppConfig.hpp"
|
||||
#endif // ENABLE_ENVIRONMENT_MAP
|
||||
|
||||
#include "libslic3r/ExtrusionEntity.hpp"
|
||||
@ -29,6 +28,7 @@
|
||||
#include "slic3r/GUI/BitmapCache.hpp"
|
||||
#include "libslic3r/Format/STL.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
|
||||
#include "Camera.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "AppConfig.hpp"
|
||||
#if ENABLE_CAMERA_STATISTICS
|
||||
#include "Mouse3DController.hpp"
|
||||
#include "Plater.hpp"
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "ConfigManipulation.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
|
||||
#include <wx/msgdlg.h>
|
||||
|
||||
|
@ -20,9 +20,8 @@
|
||||
#include <wx/radiobut.h>
|
||||
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "slic3r/Utils/PresetUpdater.hpp"
|
||||
#include "AppConfig.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "BedShapeDialog.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
|
@ -295,6 +295,7 @@ void Field::msw_rescale(bool rescale_sidetext)
|
||||
{
|
||||
m_Undo_to_sys_btn->msw_rescale();
|
||||
m_Undo_btn->msw_rescale();
|
||||
m_blinking_bmp->msw_rescale();
|
||||
|
||||
// update em_unit value
|
||||
m_em_unit = em_unit(m_parent);
|
||||
@ -1079,6 +1080,8 @@ boost::any& Choice::get_value()
|
||||
m_value = static_cast<SLADisplayOrientation>(ret_enum);
|
||||
else if (m_opt_id.compare("support_pillar_connection_mode") == 0)
|
||||
m_value = static_cast<SLAPillarConnectionMode>(ret_enum);
|
||||
else if (m_opt_id == "authorization_type")
|
||||
m_value = static_cast<AuthorizationType>(ret_enum);
|
||||
}
|
||||
else if (m_opt.gui_type == "f_enum_open") {
|
||||
const int ret_enum = field->GetSelection();
|
||||
|
@ -151,6 +151,8 @@ public:
|
||||
virtual wxSizer* getSizer() { return nullptr; }
|
||||
virtual wxWindow* getWindow() { return nullptr; }
|
||||
|
||||
wxStaticText* getLabel() { return m_Label; }
|
||||
|
||||
bool is_matched(const std::string& string, const std::string& pattern);
|
||||
void get_value_by_opt_type(wxString& str, const bool check_value = true);
|
||||
|
||||
|
@ -15,11 +15,11 @@
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/Technologies.hpp"
|
||||
#include "libslic3r/Tesselate.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
#include "slic3r/GUI/BackgroundSlicingProcess.hpp"
|
||||
#include "slic3r/GUI/GLShader.hpp"
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
#include "slic3r/GUI/PresetBundle.hpp"
|
||||
#include "slic3r/GUI/Tab.hpp"
|
||||
#include "slic3r/GUI/GUI_Preview.hpp"
|
||||
#include "slic3r/GUI/OpenGLManager.hpp"
|
||||
|
@ -194,6 +194,8 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
|
||||
config.set_key_value(opt_key, new ConfigOptionEnum<SLADisplayOrientation>(boost::any_cast<SLADisplayOrientation>(value)));
|
||||
else if(opt_key.compare("support_pillar_connection_mode") == 0)
|
||||
config.set_key_value(opt_key, new ConfigOptionEnum<SLAPillarConnectionMode>(boost::any_cast<SLAPillarConnectionMode>(value)));
|
||||
else if(opt_key == "authorization_type")
|
||||
config.set_key_value(opt_key, new ConfigOptionEnum<AuthorizationType>(boost::any_cast<AuthorizationType>(value)));
|
||||
}
|
||||
break;
|
||||
case coPoints:{
|
||||
|
@ -28,14 +28,16 @@
|
||||
#include <wx/log.h>
|
||||
#include <wx/intl.h>
|
||||
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/textctrl.h>
|
||||
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/I18N.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "AppConfig.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "3DScene.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "Plater.hpp"
|
||||
@ -323,7 +325,13 @@ void GUI_App::init_app_config()
|
||||
// load settings
|
||||
app_conf_exists = app_config->exists();
|
||||
if (app_conf_exists) {
|
||||
app_config->load();
|
||||
std::string error = app_config->load();
|
||||
if (!error.empty())
|
||||
// Error while parsing config file. We'll customize the error message and rethrow to be displayed.
|
||||
throw std::runtime_error(
|
||||
_u8L("Error parsing PrusaSlicer config file, it is probably corrupted. "
|
||||
"Try to manually delete the file to recover from the error. Your user profiles will not be affected.") +
|
||||
"\n\n" + AppConfig::config_path() + "\n\n" + error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -635,6 +643,27 @@ void GUI_App::set_auto_toolbar_icon_scale(float scale) const
|
||||
app_config->set("auto_toolbar_size", val);
|
||||
}
|
||||
|
||||
// check user printer_presets for the containing information about "Print Host upload"
|
||||
void GUI_App::check_printer_presets()
|
||||
{
|
||||
std::vector<std::string> preset_names = PhysicalPrinter::presets_with_print_host_information(preset_bundle->printers);
|
||||
if (preset_names.empty())
|
||||
return;
|
||||
|
||||
wxString msg_text = _L("You have next presets with saved options for \"Print Host upload\"") + ":";
|
||||
for (const std::string& preset_name : preset_names)
|
||||
msg_text += "\n \"" + from_u8(preset_name) + "\",";
|
||||
msg_text.RemoveLast();
|
||||
msg_text += "\n\n" + _L("But from this version of PrusaSlicer we don't show/use this information in Printer Settings.\n"
|
||||
"Now, this information will be exposed in physical printers settings.") + "\n\n" +
|
||||
_L("By default new Printer devices will be named as \"Printer N\" during its creation.\n"
|
||||
"Note: This name can be changed later from the physical printers settings");
|
||||
|
||||
wxMessageDialog(nullptr, msg_text, _L("Information"), wxOK | wxICON_INFORMATION).ShowModal();
|
||||
|
||||
preset_bundle->physical_printers.load_printers_from_presets(preset_bundle->printers);
|
||||
}
|
||||
|
||||
void GUI_App::recreate_GUI(const wxString& msg_name)
|
||||
{
|
||||
mainframe->shutdown();
|
||||
@ -957,7 +986,7 @@ bool GUI_App::load_language(wxString language, bool initial)
|
||||
m_imgui->set_language(into_u8(language_info->CanonicalName));
|
||||
//FIXME This is a temporary workaround, the correct solution is to switch to "C" locale during file import / export only.
|
||||
wxSetlocale(LC_NUMERIC, "C");
|
||||
Preset::update_suffix_modified();
|
||||
Preset::update_suffix_modified((" (" + _L("modified") + ")").ToUTF8().data());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1178,6 +1207,10 @@ bool GUI_App::checked_tab(Tab* tab)
|
||||
// Update UI / Tabs to reflect changes in the currently loaded presets
|
||||
void GUI_App::load_current_presets()
|
||||
{
|
||||
// check printer_presets for the containing information about "Print Host upload"
|
||||
// and create physical printer from it, if any exists
|
||||
check_printer_presets();
|
||||
|
||||
PrinterTechnology printer_technology = preset_bundle->printers.get_edited_preset().printer_technology();
|
||||
this->plater()->set_printer_technology(printer_technology);
|
||||
for (Tab *tab : tabs_list)
|
||||
|
@ -3,10 +3,10 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include "Preset.hpp"
|
||||
#include "ImGuiWrapper.hpp"
|
||||
#include "ConfigWizard.hpp"
|
||||
#include "OpenGLManager.hpp"
|
||||
#include "libslic3r/Preset.hpp"
|
||||
|
||||
#include <wx/app.h>
|
||||
#include <wx/colour.h>
|
||||
@ -150,6 +150,7 @@ public:
|
||||
wxSize get_min_size() const;
|
||||
float toolbar_icon_scale(const bool is_limited = false) const;
|
||||
void set_auto_toolbar_icon_scale(float scale) const;
|
||||
void check_printer_presets();
|
||||
|
||||
void recreate_GUI(const wxString& message);
|
||||
void system_info();
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "OptionsGroup.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "GLCanvas3D.hpp"
|
||||
#include "Plater.hpp"
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
#include "GUI_ObjectManipulation.hpp"
|
||||
#include "GUI_ObjectLayers.hpp"
|
||||
@ -7,7 +8,6 @@
|
||||
#include "Plater.hpp"
|
||||
|
||||
#include "OptionsGroup.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "Tab.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
@ -88,9 +88,6 @@ ObjectList::ObjectList(wxWindow* parent) :
|
||||
{
|
||||
// Fill CATEGORY_ICON
|
||||
{
|
||||
// Note: `this` isn't passed to create_scaled_bitmap() here because of bugs in the widget,
|
||||
// see note in PresetBundle::load_compatible_bitmaps()
|
||||
|
||||
// ptFFF
|
||||
CATEGORY_ICON[L("Layers and Perimeters")] = create_scaled_bitmap("layers");
|
||||
CATEGORY_ICON[L("Infill")] = create_scaled_bitmap("infill");
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "OptionsGroup.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/Geometry.hpp"
|
||||
#include "Selection.hpp"
|
||||
|
@ -4,8 +4,8 @@
|
||||
#include "OptionsGroup.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "Plater.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "BackgroundSlicingProcess.hpp"
|
||||
#include "OpenGLManager.hpp"
|
||||
#include "GLCanvas3D.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "DoubleSlider.hpp"
|
||||
#include "Plater.hpp"
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
|
@ -6,9 +6,9 @@
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/PresetBundle.hpp"
|
||||
#include "slic3r/GUI/Camera.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "slic3r/GUI/GUI_ObjectSettings.hpp"
|
||||
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "slic3r/GUI/PresetBundle.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "slic3r/GUI/GUI_ObjectSettings.hpp"
|
||||
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "slic3r/GUI/PresetBundle.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include "slic3r/GUI/Camera.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
|
||||
#include "slic3r/GUI/PresetBundle.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include "slic3r/GUI/Camera.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/GUI_ObjectManipulation.hpp"
|
||||
#include "slic3r/GUI/PresetBundle.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "slic3r/Utils/UndoRedo.hpp"
|
||||
|
||||
@ -19,6 +18,7 @@
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoHollow.hpp"
|
||||
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
|
||||
#include <wx/glcanvas.h>
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
#ifndef L
|
||||
// !!! If you needed to translate some wxString,
|
||||
// !!! please use _(L(string))
|
||||
// !!! please use _L(string)
|
||||
// !!! _() - is a standard wxWidgets macro to translate
|
||||
// !!! L() is used only for marking localizable string
|
||||
// !!! It will be used in "xgettext" to create a Locating Message Catalog.
|
||||
|
@ -2,13 +2,12 @@
|
||||
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/AppConfig.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "slic3r/GUI/PresetBundle.hpp"
|
||||
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
||||
#include "slic3r/Utils/SLAImport.hpp"
|
||||
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/stattext.h>
|
||||
|
@ -15,12 +15,11 @@
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "libslic3r/Polygon.hpp"
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
|
||||
#include "Tab.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "ProgressStatusBar.hpp"
|
||||
#include "3DScene.hpp"
|
||||
#include "AppConfig.hpp"
|
||||
#include "PrintHostDialogs.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
@ -104,11 +103,6 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
|
||||
SLIC3R_VERSION +
|
||||
_(L(" - Remember to check for updates at https://github.com/prusa3d/PrusaSlicer/releases")));
|
||||
|
||||
/* Load default preset bitmaps before a tabpanel initialization,
|
||||
* but after filling of an em_unit value
|
||||
*/
|
||||
wxGetApp().preset_bundle->load_default_preset_bitmaps();
|
||||
|
||||
// initialize tabpanel and menubar
|
||||
init_tabpanel();
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
@ -717,11 +711,6 @@ void MainFrame::on_dpi_changed(const wxRect& suggested_rect)
|
||||
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT
|
||||
this->SetFont(this->normal_font());
|
||||
|
||||
/* Load default preset bitmaps before a tabpanel initialization,
|
||||
* but after filling of an em_unit value
|
||||
*/
|
||||
wxGetApp().preset_bundle->load_default_preset_bitmaps();
|
||||
|
||||
// update Plater
|
||||
wxGetApp().plater()->msw_rescale();
|
||||
|
||||
@ -766,8 +755,6 @@ void MainFrame::on_sys_color_changed()
|
||||
// update label colors in respect to the system mode
|
||||
wxGetApp().init_label_colours();
|
||||
|
||||
wxGetApp().preset_bundle->load_default_preset_bitmaps();
|
||||
|
||||
// update Plater
|
||||
wxGetApp().plater()->sys_color_changed();
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "Mouse3DController.hpp"
|
||||
|
||||
#include "Camera.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "AppConfig.hpp"
|
||||
#include "GLCanvas3D.hpp"
|
||||
#include "Plater.hpp"
|
||||
#include "NotificationManager.hpp"
|
||||
|
@ -729,31 +729,34 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
|
||||
opt_key == "fill_pattern" ) {
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<InfillPattern>>(opt_key)->value);
|
||||
}
|
||||
else if (opt_key.compare("ironing_type") == 0 ) {
|
||||
else if (opt_key == "ironing_type") {
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<IroningType>>(opt_key)->value);
|
||||
}
|
||||
else if (opt_key.compare("gcode_flavor") == 0 ) {
|
||||
else if (opt_key == "gcode_flavor") {
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<GCodeFlavor>>(opt_key)->value);
|
||||
}
|
||||
else if (opt_key.compare("support_material_pattern") == 0) {
|
||||
else if (opt_key == "support_material_pattern") {
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<SupportMaterialPattern>>(opt_key)->value);
|
||||
}
|
||||
else if (opt_key.compare("seam_position") == 0) {
|
||||
else if (opt_key == "seam_position") {
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<SeamPosition>>(opt_key)->value);
|
||||
}
|
||||
else if (opt_key.compare("host_type") == 0) {
|
||||
else if (opt_key == "host_type") {
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<PrintHostType>>(opt_key)->value);
|
||||
}
|
||||
else if (opt_key.compare("display_orientation") == 0) {
|
||||
else if (opt_key == "display_orientation") {
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<SLADisplayOrientation>>(opt_key)->value);
|
||||
}
|
||||
else if (opt_key.compare("support_pillar_connection_mode") == 0) {
|
||||
else if (opt_key == "support_pillar_connection_mode") {
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<SLAPillarConnectionMode>>(opt_key)->value);
|
||||
}
|
||||
else if (opt_key == "authorization_type") {
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<AuthorizationType>>(opt_key)->value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case coPoints:
|
||||
if (opt_key.compare("bed_shape") == 0)
|
||||
if (opt_key == "bed_shape")
|
||||
ret = config.option<ConfigOptionPoints>(opt_key)->values;
|
||||
else
|
||||
ret = config.option<ConfigOptionPoints>(opt_key)->get_at(idx);
|
||||
|
@ -149,6 +149,13 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void show_field(const t_config_option_key& opt_key, bool show = true) {
|
||||
Field* field = get_field(opt_key);
|
||||
field->getWindow()->Show(show);
|
||||
field->getLabel()->Show(show);
|
||||
}
|
||||
void hide_field(const t_config_option_key& opt_key) { show_field(opt_key, false); }
|
||||
|
||||
void set_name(const wxString& new_name) {
|
||||
stb->SetLabel(new_name);
|
||||
}
|
||||
|
564
src/slic3r/GUI/PhysicalPrinterDialog.cpp
Normal file
564
src/slic3r/GUI/PhysicalPrinterDialog.cpp
Normal file
@ -0,0 +1,564 @@
|
||||
#include "PhysicalPrinterDialog.hpp"
|
||||
#include "PresetComboBoxes.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/statbox.h>
|
||||
#include <wx/wupdlock.h>
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "format.hpp"
|
||||
#include "Tab.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "PrintHostDialogs.hpp"
|
||||
#include "../Utils/ASCIIFolding.hpp"
|
||||
#include "../Utils/PrintHost.hpp"
|
||||
#include "../Utils/FixModelByWin10.hpp"
|
||||
#include "../Utils/UndoRedo.hpp"
|
||||
#include "RemovableDriveManager.hpp"
|
||||
#include "BitmapCache.hpp"
|
||||
#include "BonjourDialog.hpp"
|
||||
|
||||
using Slic3r::GUI::format_wxstr;
|
||||
|
||||
//static const std::pair<unsigned int, unsigned int> THUMBNAIL_SIZE_3MF = { 256, 256 };
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
#define BORDER_W 10
|
||||
|
||||
//------------------------------------------
|
||||
// PresetForPrinter
|
||||
//------------------------------------------
|
||||
|
||||
PresetForPrinter::PresetForPrinter(PhysicalPrinterDialog* parent, const std::string& preset_name) :
|
||||
m_parent(parent)
|
||||
{
|
||||
m_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_delete_preset_btn = new ScalableButton(parent, wxID_ANY, "cross", "", wxDefaultSize, wxDefaultPosition, /*wxBU_LEFT | */wxBU_EXACTFIT);
|
||||
m_delete_preset_btn->SetFont(wxGetApp().normal_font());
|
||||
m_delete_preset_btn->SetToolTip(_L("Delete this preset from this printer device"));
|
||||
m_delete_preset_btn->Bind(wxEVT_BUTTON, &PresetForPrinter::DeletePreset, this);
|
||||
|
||||
m_presets_list = new PresetComboBox(parent, Preset::TYPE_PRINTER);
|
||||
m_presets_list->set_printer_technology(parent->get_printer_technology());
|
||||
|
||||
m_presets_list->set_selection_changed_function([this](int selection) {
|
||||
std::string selected_string = Preset::remove_suffix_modified(m_presets_list->GetString(selection).ToUTF8().data());
|
||||
Preset* preset = wxGetApp().preset_bundle->printers.find_preset(selected_string);
|
||||
assert(preset);
|
||||
Preset& edited_preset = wxGetApp().preset_bundle->printers.get_edited_preset();
|
||||
if (preset->name == edited_preset.name)
|
||||
preset = &edited_preset;
|
||||
|
||||
// if created physical printer doesn't have any settings, use the settings from the selected preset
|
||||
if (m_parent->get_printer()->has_empty_config()) {
|
||||
// update Print Host upload from the selected preset
|
||||
m_parent->get_printer()->update_from_preset(*preset);
|
||||
// update values in parent (PhysicalPrinterDialog)
|
||||
m_parent->update();
|
||||
}
|
||||
|
||||
// update PrinterTechnology if it was changed
|
||||
if (m_presets_list->set_printer_technology(preset->printer_technology()))
|
||||
m_parent->set_printer_technology(preset->printer_technology());
|
||||
|
||||
update_full_printer_name();
|
||||
});
|
||||
m_presets_list->update(preset_name);
|
||||
|
||||
m_info_line = new wxStaticText(parent, wxID_ANY, _L("This printer will be shown in the presets list as") + ":");
|
||||
|
||||
m_full_printer_name = new wxStaticText(parent, wxID_ANY, "");
|
||||
m_full_printer_name->SetFont(wxGetApp().bold_font());
|
||||
|
||||
wxBoxSizer* preset_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
preset_sizer->Add(m_presets_list , 1, wxEXPAND);
|
||||
preset_sizer->Add(m_delete_preset_btn , 0, wxEXPAND | wxLEFT, BORDER_W);
|
||||
|
||||
wxBoxSizer* name_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
name_sizer->Add(m_info_line, 0, wxEXPAND);
|
||||
name_sizer->Add(m_full_printer_name, 0, wxEXPAND | wxLEFT, BORDER_W);
|
||||
|
||||
m_sizer->Add(preset_sizer , 0, wxEXPAND);
|
||||
m_sizer->Add(name_sizer, 0, wxEXPAND);
|
||||
}
|
||||
|
||||
PresetForPrinter::~PresetForPrinter()
|
||||
{
|
||||
m_presets_list->Destroy();
|
||||
m_delete_preset_btn->Destroy();
|
||||
m_info_line->Destroy();
|
||||
m_full_printer_name->Destroy();
|
||||
}
|
||||
|
||||
void PresetForPrinter::DeletePreset(wxEvent& event)
|
||||
{
|
||||
m_parent->DeletePreset(this);
|
||||
}
|
||||
|
||||
void PresetForPrinter::update_full_printer_name()
|
||||
{
|
||||
wxString printer_name = m_parent->get_printer_name();
|
||||
wxString preset_name = m_presets_list->GetString(m_presets_list->GetSelection());
|
||||
|
||||
m_full_printer_name->SetLabelText(printer_name + " * " + preset_name);
|
||||
}
|
||||
|
||||
std::string PresetForPrinter::get_preset_name()
|
||||
{
|
||||
return into_u8(m_presets_list->GetString(m_presets_list->GetSelection()));
|
||||
}
|
||||
|
||||
void PresetForPrinter::SuppressDelete()
|
||||
{
|
||||
m_delete_preset_btn->Enable(false);
|
||||
|
||||
// this case means that now we have only one related preset for the printer
|
||||
// So, allow any selection
|
||||
m_presets_list->set_printer_technology(ptAny);
|
||||
m_presets_list->update();
|
||||
}
|
||||
|
||||
void PresetForPrinter::AllowDelete()
|
||||
{
|
||||
if (!m_delete_preset_btn->IsEnabled())
|
||||
m_delete_preset_btn->Enable();
|
||||
|
||||
m_presets_list->set_printer_technology(m_parent->get_printer_technology());
|
||||
m_presets_list->update();
|
||||
}
|
||||
|
||||
void PresetForPrinter::msw_rescale()
|
||||
{
|
||||
m_presets_list->msw_rescale();
|
||||
m_delete_preset_btn->msw_rescale();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------
|
||||
// PhysicalPrinterDialog
|
||||
//------------------------------------------
|
||||
|
||||
PhysicalPrinterDialog::PhysicalPrinterDialog(wxString printer_name)
|
||||
: DPIDialog(NULL, wxID_ANY, _L("Physical Printer"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), -1), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
{
|
||||
SetFont(wxGetApp().normal_font());
|
||||
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
|
||||
m_default_name = _L("Type here the name of your printer device");
|
||||
bool new_printer = true;
|
||||
|
||||
if (printer_name.IsEmpty())
|
||||
printer_name = m_default_name;
|
||||
else {
|
||||
std::string full_name = into_u8(printer_name);
|
||||
printer_name = from_u8(PhysicalPrinter::get_short_name(full_name));
|
||||
new_printer = false;
|
||||
}
|
||||
|
||||
wxStaticText* label_top = new wxStaticText(this, wxID_ANY, _L("Descriptive name for the printer device") + ":");
|
||||
|
||||
m_add_preset_btn = new ScalableButton(this, wxID_ANY, "add_copies", "", wxDefaultSize, wxDefaultPosition, /*wxBU_LEFT | */wxBU_EXACTFIT);
|
||||
m_add_preset_btn->SetFont(wxGetApp().normal_font());
|
||||
m_add_preset_btn->SetToolTip(_L("Add preset for this printer device"));
|
||||
m_add_preset_btn->Bind(wxEVT_BUTTON, &PhysicalPrinterDialog::AddPreset, this);
|
||||
|
||||
m_printer_name = new wxTextCtrl(this, wxID_ANY, printer_name, wxDefaultPosition, wxDefaultSize);
|
||||
m_printer_name->Bind(wxEVT_TEXT, [this](wxEvent&) { this->update_full_printer_names(); });
|
||||
|
||||
PhysicalPrinterCollection& printers = wxGetApp().preset_bundle->physical_printers;
|
||||
PhysicalPrinter* printer = printers.find_printer(into_u8(printer_name));
|
||||
if (!printer) {
|
||||
const Preset& preset = wxGetApp().preset_bundle->printers.get_edited_preset();
|
||||
printer = new PhysicalPrinter(into_u8(printer_name), preset);
|
||||
// if printer_name is empty it means that new printer is created, so enable all items in the preset list
|
||||
m_presets.emplace_back(new PresetForPrinter(this, preset.name));
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::set<std::string>& preset_names = printer->get_preset_names();
|
||||
for (const std::string& preset_name : preset_names)
|
||||
m_presets.emplace_back(new PresetForPrinter(this, preset_name));
|
||||
}
|
||||
assert(printer);
|
||||
m_printer = *printer;
|
||||
|
||||
if (m_presets.size() == 1)
|
||||
m_presets.front()->SuppressDelete();
|
||||
|
||||
update_full_printer_names();
|
||||
|
||||
m_config = &m_printer.config;
|
||||
|
||||
m_optgroup = new ConfigOptionsGroup(this, _L("Print Host upload"), m_config);
|
||||
build_printhost_settings(m_optgroup);
|
||||
|
||||
wxStdDialogButtonSizer* btns = this->CreateStdDialogButtonSizer(wxOK | wxCANCEL);
|
||||
wxButton* btnOK = static_cast<wxButton*>(this->FindWindowById(wxID_OK, this));
|
||||
btnOK->Bind(wxEVT_BUTTON, &PhysicalPrinterDialog::OnOK, this);
|
||||
|
||||
wxBoxSizer* nameSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
nameSizer->Add(m_printer_name, 1, wxEXPAND);
|
||||
nameSizer->Add(m_add_preset_btn, 0, wxEXPAND | wxLEFT, BORDER_W);
|
||||
|
||||
m_presets_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
for (PresetForPrinter* preset : m_presets)
|
||||
m_presets_sizer->Add(preset->sizer(), 1, wxEXPAND | wxTOP, BORDER_W);
|
||||
|
||||
wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
topSizer->Add(label_top , 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, BORDER_W);
|
||||
topSizer->Add(nameSizer , 0, wxEXPAND | wxLEFT | wxRIGHT, BORDER_W);
|
||||
topSizer->Add(m_presets_sizer , 0, wxEXPAND | wxLEFT | wxRIGHT, BORDER_W);
|
||||
topSizer->Add(m_optgroup->sizer , 1, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, BORDER_W);
|
||||
topSizer->Add(btns , 0, wxEXPAND | wxALL, BORDER_W);
|
||||
|
||||
SetSizer(topSizer);
|
||||
topSizer->SetSizeHints(this);
|
||||
|
||||
if (new_printer) {
|
||||
m_printer_name->SetFocus();
|
||||
m_printer_name->SelectAll();
|
||||
}
|
||||
}
|
||||
|
||||
PhysicalPrinterDialog::~PhysicalPrinterDialog()
|
||||
{
|
||||
for (PresetForPrinter* preset : m_presets) {
|
||||
delete preset;
|
||||
preset = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgroup)
|
||||
{
|
||||
m_optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
|
||||
if (opt_key == "authorization_type")
|
||||
this->update();
|
||||
};
|
||||
|
||||
m_optgroup->append_single_option_line("host_type");
|
||||
|
||||
auto create_sizer_with_btn = [this](wxWindow* parent, ScalableButton** btn, const std::string& icon_name, const wxString& label) {
|
||||
*btn = new ScalableButton(parent, wxID_ANY, icon_name, label, wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT);
|
||||
(*btn)->SetFont(wxGetApp().normal_font());
|
||||
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(*btn);
|
||||
return sizer;
|
||||
};
|
||||
|
||||
auto printhost_browse = [=](wxWindow* parent)
|
||||
{
|
||||
auto sizer = create_sizer_with_btn(parent, &m_printhost_browse_btn, "browse", _L("Browse") + " " + dots);
|
||||
m_printhost_browse_btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent& e) {
|
||||
BonjourDialog dialog(this, Preset::printer_technology(m_printer.config));
|
||||
if (dialog.show_and_lookup()) {
|
||||
m_optgroup->set_value("print_host", std::move(dialog.get_selected()), true);
|
||||
m_optgroup->get_field("print_host")->field_changed();
|
||||
}
|
||||
});
|
||||
|
||||
return sizer;
|
||||
};
|
||||
|
||||
auto print_host_test = [=](wxWindow* parent) {
|
||||
auto sizer = create_sizer_with_btn(parent, &m_printhost_test_btn, "test", _L("Test"));
|
||||
|
||||
m_printhost_test_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) {
|
||||
std::unique_ptr<PrintHost> host(PrintHost::get_print_host(m_config));
|
||||
if (!host) {
|
||||
const wxString text = _L("Could not get a valid Printer Host reference");
|
||||
show_error(this, text);
|
||||
return;
|
||||
}
|
||||
wxString msg;
|
||||
if (host->test(msg)) {
|
||||
show_info(this, host->get_test_ok_msg(), _L("Success!"));
|
||||
}
|
||||
else {
|
||||
show_error(this, host->get_test_failed_msg(msg));
|
||||
}
|
||||
});
|
||||
|
||||
return sizer;
|
||||
};
|
||||
|
||||
// Set a wider width for a better alignment
|
||||
Option option = m_optgroup->get_option("print_host");
|
||||
option.opt.width = Field::def_width_wider();
|
||||
Line host_line = m_optgroup->create_single_option_line(option);
|
||||
host_line.append_widget(printhost_browse);
|
||||
host_line.append_widget(print_host_test);
|
||||
m_optgroup->append_line(host_line);
|
||||
|
||||
m_optgroup->append_single_option_line("authorization_type");
|
||||
|
||||
option = m_optgroup->get_option("printhost_apikey");
|
||||
option.opt.width = Field::def_width_wider();
|
||||
m_optgroup->append_single_option_line(option);
|
||||
|
||||
const auto ca_file_hint = _u8L("HTTPS CA file is optional. It is only needed if you use HTTPS with a self-signed certificate.");
|
||||
|
||||
if (Http::ca_file_supported()) {
|
||||
option = m_optgroup->get_option("printhost_cafile");
|
||||
option.opt.width = Field::def_width_wider();
|
||||
Line cafile_line = m_optgroup->create_single_option_line(option);
|
||||
|
||||
auto printhost_cafile_browse = [=](wxWindow* parent) {
|
||||
auto sizer = create_sizer_with_btn(parent, &m_printhost_cafile_browse_btn, "browse", _L("Browse") + " " + dots);
|
||||
m_printhost_cafile_browse_btn->Bind(wxEVT_BUTTON, [this, m_optgroup](wxCommandEvent e) {
|
||||
static const auto filemasks = _L("Certificate files (*.crt, *.pem)|*.crt;*.pem|All files|*.*");
|
||||
wxFileDialog openFileDialog(this, _L("Open CA certificate file"), "", "", filemasks, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
if (openFileDialog.ShowModal() != wxID_CANCEL) {
|
||||
m_optgroup->set_value("printhost_cafile", std::move(openFileDialog.GetPath()), true);
|
||||
m_optgroup->get_field("printhost_cafile")->field_changed();
|
||||
}
|
||||
});
|
||||
|
||||
return sizer;
|
||||
};
|
||||
|
||||
cafile_line.append_widget(printhost_cafile_browse);
|
||||
m_optgroup->append_line(cafile_line);
|
||||
|
||||
Line cafile_hint{ "", "" };
|
||||
cafile_hint.full_width = 1;
|
||||
cafile_hint.widget = [this, ca_file_hint](wxWindow* parent) {
|
||||
auto txt = new wxStaticText(parent, wxID_ANY, ca_file_hint);
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(txt);
|
||||
return sizer;
|
||||
};
|
||||
m_optgroup->append_line(cafile_hint);
|
||||
}
|
||||
else {
|
||||
Line line{ "", "" };
|
||||
line.full_width = 1;
|
||||
|
||||
line.widget = [ca_file_hint](wxWindow* parent) {
|
||||
std::string info = _u8L("HTTPS CA File") + ":\n\t" +
|
||||
(boost::format(_u8L("On this system, %s uses HTTPS certificates from the system Certificate Store or Keychain.")) % SLIC3R_APP_NAME).str() +
|
||||
"\n\t" + _u8L("To use a custom CA file, please import your CA file into Certificate Store / Keychain.");
|
||||
|
||||
//auto txt = new wxStaticText(parent, wxID_ANY, from_u8((boost::format("%1%\n\n\t%2%") % info % ca_file_hint).str()));
|
||||
auto txt = new wxStaticText(parent, wxID_ANY, from_u8((boost::format("%1%\n\t%2%") % info % ca_file_hint).str()));
|
||||
txt->SetFont(wxGetApp().normal_font());
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(txt, 1, wxEXPAND);
|
||||
return sizer;
|
||||
};
|
||||
|
||||
m_optgroup->append_line(line);
|
||||
}
|
||||
|
||||
for (const std::string& opt_key : std::vector<std::string>{ "login", "password" }) {
|
||||
option = m_optgroup->get_option(opt_key);
|
||||
option.opt.width = Field::def_width_wider();
|
||||
m_optgroup->append_single_option_line(option);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::update()
|
||||
{
|
||||
m_optgroup->reload_config();
|
||||
|
||||
const PrinterTechnology tech = Preset::printer_technology(*m_config);
|
||||
// Only offer the host type selection for FFF, for SLA it's always the SL1 printer (at the moment)
|
||||
if (tech == ptFFF) {
|
||||
m_optgroup->show_field("host_type");
|
||||
m_optgroup->hide_field("authorization_type");
|
||||
for (const std::string& opt_key : std::vector<std::string>{ "login", "password" })
|
||||
m_optgroup->hide_field(opt_key);
|
||||
}
|
||||
else {
|
||||
m_optgroup->set_value("host_type", int(PrintHostType::htOctoPrint), false);
|
||||
m_optgroup->hide_field("host_type");
|
||||
|
||||
m_optgroup->show_field("authorization_type");
|
||||
|
||||
AuthorizationType auth_type = m_config->option<ConfigOptionEnum<AuthorizationType>>("authorization_type")->value;
|
||||
m_optgroup->show_field("printhost_apikey", auth_type == AuthorizationType::atKeyPassword);
|
||||
|
||||
for (const std::string& opt_key : std::vector<std::string>{ "login", "password" })
|
||||
m_optgroup->show_field(opt_key, auth_type == AuthorizationType::atUserPassword);
|
||||
}
|
||||
|
||||
this->Layout();
|
||||
}
|
||||
|
||||
|
||||
wxString PhysicalPrinterDialog::get_printer_name()
|
||||
{
|
||||
return m_printer_name->GetValue();
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::update_full_printer_names()
|
||||
{
|
||||
for (PresetForPrinter* preset : m_presets)
|
||||
preset->update_full_printer_name();
|
||||
|
||||
this->Layout();
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::set_printer_technology(PrinterTechnology pt)
|
||||
{
|
||||
m_config->set_key_value("printer_technology", new ConfigOptionEnum<PrinterTechnology>(pt));
|
||||
update();
|
||||
}
|
||||
|
||||
PrinterTechnology PhysicalPrinterDialog::get_printer_technology()
|
||||
{
|
||||
return m_printer.printer_technology();
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||
{
|
||||
const int& em = em_unit();
|
||||
|
||||
m_printhost_browse_btn->msw_rescale();
|
||||
m_printhost_test_btn->msw_rescale();
|
||||
if (m_printhost_cafile_browse_btn)
|
||||
m_printhost_cafile_browse_btn->msw_rescale();
|
||||
|
||||
m_optgroup->msw_rescale();
|
||||
|
||||
msw_buttons_rescale(this, em, { wxID_OK, wxID_CANCEL });
|
||||
|
||||
for (PresetForPrinter* preset : m_presets)
|
||||
preset->msw_rescale();
|
||||
|
||||
const wxSize& size = wxSize(45 * em, 35 * em);
|
||||
SetMinSize(size);
|
||||
|
||||
Fit();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::OnOK(wxEvent& event)
|
||||
{
|
||||
wxString printer_name = m_printer_name->GetValue();
|
||||
if (printer_name.IsEmpty()) {
|
||||
warning_catcher(this, _L("The supplied name is empty. It can't be saved."));
|
||||
return;
|
||||
}
|
||||
if (printer_name == m_default_name) {
|
||||
warning_catcher(this, _L("You should to change a name of your printer device. It can't be saved."));
|
||||
return;
|
||||
}
|
||||
|
||||
PhysicalPrinterCollection& printers = wxGetApp().preset_bundle->physical_printers;
|
||||
const PhysicalPrinter* existing = printers.find_printer(into_u8(printer_name));
|
||||
if (existing && into_u8(printer_name) != printers.get_selected_printer_name())
|
||||
{
|
||||
wxString msg_text = from_u8((boost::format(_u8L("Printer with name \"%1%\" already exists.")) % printer_name).str());
|
||||
msg_text += "\n" + _L("Replace?");
|
||||
wxMessageDialog dialog(nullptr, msg_text, _L("Warning"), wxICON_WARNING | wxYES | wxNO);
|
||||
|
||||
if (dialog.ShowModal() == wxID_NO)
|
||||
return;
|
||||
}
|
||||
|
||||
std::set<std::string> repeat_presets;
|
||||
m_printer.reset_presets();
|
||||
for (PresetForPrinter* preset : m_presets) {
|
||||
if (!m_printer.add_preset(preset->get_preset_name()))
|
||||
repeat_presets.emplace(preset->get_preset_name());
|
||||
}
|
||||
|
||||
if (!repeat_presets.empty())
|
||||
{
|
||||
wxString repeatable_presets = "\n";
|
||||
for (const std::string& preset_name : repeat_presets)
|
||||
repeatable_presets += " " + from_u8(preset_name) + "\n";
|
||||
repeatable_presets += "\n";
|
||||
|
||||
wxString msg_text = from_u8((boost::format(_u8L("Next printer preset(s) is(are) duplicated:%1%"
|
||||
"Should I add it(they) just once for the printer \"%2%\" and close the Editing Dialog?")) % repeatable_presets % printer_name).str());
|
||||
wxMessageDialog dialog(nullptr, msg_text, _L("Warning"), wxICON_WARNING | wxYES | wxNO);
|
||||
if (dialog.ShowModal() == wxID_NO)
|
||||
return;
|
||||
}
|
||||
|
||||
std::string renamed_from;
|
||||
// temporary save previous printer name if it was edited
|
||||
if (m_printer.name != into_u8(m_default_name) &&
|
||||
m_printer.name != into_u8(printer_name))
|
||||
renamed_from = m_printer.name;
|
||||
|
||||
//update printer name, if it was changed
|
||||
m_printer.set_name(into_u8(printer_name));
|
||||
|
||||
// save new physical printer
|
||||
printers.save_printer(m_printer, renamed_from);
|
||||
|
||||
if (m_printer.preset_names.find(printers.get_selected_printer_preset_name()) == m_printer.preset_names.end()) {
|
||||
// select first preset for this printer
|
||||
printers.select_printer(m_printer);
|
||||
// refresh preset list on Printer Settings Tab
|
||||
wxGetApp().get_tab(Preset::TYPE_PRINTER)->select_preset(printers.get_selected_printer_preset_name());
|
||||
}
|
||||
else
|
||||
wxGetApp().get_tab(Preset::TYPE_PRINTER)->update_preset_choice();
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::AddPreset(wxEvent& event)
|
||||
{
|
||||
m_presets.emplace_back(new PresetForPrinter(this));
|
||||
// enable DELETE button for the first preset, if was disabled
|
||||
m_presets.front()->AllowDelete();
|
||||
|
||||
m_presets_sizer->Add(m_presets.back()->sizer(), 1, wxEXPAND | wxTOP, BORDER_W);
|
||||
update_full_printer_names();
|
||||
|
||||
this->Fit();
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::DeletePreset(PresetForPrinter* preset_for_printer)
|
||||
{
|
||||
if (m_presets.size() == 1) {
|
||||
wxString msg_text = _L("It's not possible to delete last related preset for the printer.");
|
||||
wxMessageDialog dialog(nullptr, msg_text, _L("Infornation"), wxICON_INFORMATION | wxOK);
|
||||
dialog.ShowModal();
|
||||
return;
|
||||
}
|
||||
|
||||
assert(preset_for_printer);
|
||||
auto it = std::find(m_presets.begin(), m_presets.end(), preset_for_printer);
|
||||
if (it == m_presets.end())
|
||||
return;
|
||||
|
||||
const int remove_id = it - m_presets.begin();
|
||||
m_presets_sizer->Remove(remove_id);
|
||||
delete preset_for_printer;
|
||||
m_presets.erase(it);
|
||||
|
||||
if (m_presets.size() == 1)
|
||||
m_presets.front()->SuppressDelete();
|
||||
|
||||
this->Layout();
|
||||
this->Fit();
|
||||
}
|
||||
|
||||
|
||||
}} // namespace Slic3r::GUI
|
105
src/slic3r/GUI/PhysicalPrinterDialog.hpp
Normal file
105
src/slic3r/GUI/PhysicalPrinterDialog.hpp
Normal file
@ -0,0 +1,105 @@
|
||||
#ifndef slic3r_PhysicalPrinterDialog_hpp_
|
||||
#define slic3r_PhysicalPrinterDialog_hpp_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <wx/gdicmn.h>
|
||||
|
||||
#include "libslic3r/Preset.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
|
||||
class wxString;
|
||||
class wxTextCtrl;
|
||||
class wxStaticText;
|
||||
class ScalableButton;
|
||||
class wxBoxSizer;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace GUI {
|
||||
|
||||
class PresetComboBox;
|
||||
|
||||
//------------------------------------------
|
||||
// PresetForPrinter
|
||||
//------------------------------------------
|
||||
//static std::string g_info_string = " (modified)";
|
||||
class PhysicalPrinterDialog;
|
||||
class PresetForPrinter
|
||||
{
|
||||
PhysicalPrinterDialog* m_parent { nullptr };
|
||||
|
||||
PresetComboBox* m_presets_list { nullptr };
|
||||
ScalableButton* m_delete_preset_btn { nullptr };
|
||||
wxStaticText* m_info_line { nullptr };
|
||||
wxStaticText* m_full_printer_name { nullptr };
|
||||
|
||||
wxBoxSizer* m_sizer { nullptr };
|
||||
|
||||
void DeletePreset(wxEvent& event);
|
||||
|
||||
public:
|
||||
PresetForPrinter(PhysicalPrinterDialog* parent, const std::string& preset_name = "");
|
||||
~PresetForPrinter();
|
||||
|
||||
wxBoxSizer* sizer() { return m_sizer; }
|
||||
void update_full_printer_name();
|
||||
std::string get_preset_name();
|
||||
void SuppressDelete();
|
||||
void AllowDelete();
|
||||
|
||||
void msw_rescale();
|
||||
void on_sys_color_changed() {};
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------
|
||||
// PhysicalPrinterDialog
|
||||
//------------------------------------------
|
||||
|
||||
class ConfigOptionsGroup;
|
||||
class PhysicalPrinterDialog : public DPIDialog
|
||||
{
|
||||
PhysicalPrinter m_printer;
|
||||
wxString m_default_name;
|
||||
DynamicPrintConfig* m_config { nullptr };
|
||||
|
||||
wxTextCtrl* m_printer_name { nullptr };
|
||||
std::vector<PresetForPrinter*> m_presets;
|
||||
|
||||
ConfigOptionsGroup* m_optgroup { nullptr };
|
||||
|
||||
ScalableButton* m_add_preset_btn {nullptr};
|
||||
ScalableButton* m_printhost_browse_btn {nullptr};
|
||||
ScalableButton* m_printhost_test_btn {nullptr};
|
||||
ScalableButton* m_printhost_cafile_browse_btn {nullptr};
|
||||
|
||||
wxBoxSizer* m_presets_sizer {nullptr};
|
||||
|
||||
void build_printhost_settings(ConfigOptionsGroup* optgroup);
|
||||
void OnOK(wxEvent& event);
|
||||
void AddPreset(wxEvent& event);
|
||||
|
||||
public:
|
||||
PhysicalPrinterDialog(wxString printer_name);
|
||||
~PhysicalPrinterDialog();
|
||||
|
||||
void update();
|
||||
wxString get_printer_name();
|
||||
void update_full_printer_names();
|
||||
PhysicalPrinter* get_printer() {return &m_printer; }
|
||||
void set_printer_technology(PrinterTechnology pt);
|
||||
PrinterTechnology get_printer_technology();
|
||||
|
||||
void DeletePreset(PresetForPrinter* preset_for_printer);
|
||||
|
||||
protected:
|
||||
void on_dpi_changed(const wxRect& suggested_rect) override;
|
||||
void on_sys_color_changed() override {};
|
||||
};
|
||||
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
@ -24,7 +24,6 @@
|
||||
#include <wx/dnd.h>
|
||||
#include <wx/progdlg.h>
|
||||
#include <wx/wupdlock.h>
|
||||
#include <wx/colordlg.h>
|
||||
#include <wx/numdlg.h>
|
||||
#include <wx/debug.h>
|
||||
#include <wx/busyinfo.h>
|
||||
@ -48,6 +47,7 @@
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
@ -70,7 +70,6 @@
|
||||
#include "Jobs/ArrangeJob.hpp"
|
||||
#include "Jobs/RotoptimizeJob.hpp"
|
||||
#include "Jobs/SLAImportJob.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "BackgroundSlicingProcess.hpp"
|
||||
#include "ProgressStatusBar.hpp"
|
||||
#include "PrintHostDialogs.hpp"
|
||||
@ -83,6 +82,7 @@
|
||||
#include "RemovableDriveManager.hpp"
|
||||
#include "InstanceCheck.hpp"
|
||||
#include "NotificationManager.hpp"
|
||||
#include "PresetComboBoxes.hpp"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "Gizmos/GLGizmosManager.hpp"
|
||||
@ -260,153 +260,6 @@ void SlicedInfo::SetTextAndShow(SlicedInfoIdx idx, const wxString& text, const w
|
||||
info_vec[idx].second->Show(show);
|
||||
}
|
||||
|
||||
PresetComboBox::PresetComboBox(wxWindow *parent, Preset::Type preset_type) :
|
||||
PresetBitmapComboBox(parent, wxSize(15 * wxGetApp().em_unit(), -1)),
|
||||
preset_type(preset_type),
|
||||
last_selected(wxNOT_FOUND),
|
||||
m_em_unit(wxGetApp().em_unit())
|
||||
{
|
||||
SetFont(wxGetApp().normal_font());
|
||||
#ifdef _WIN32
|
||||
// Workaround for ignoring CBN_EDITCHANGE events, which are processed after the content of the combo box changes, so that
|
||||
// the index of the item inside CBN_EDITCHANGE may no more be valid.
|
||||
EnableTextChangedEvents(false);
|
||||
#endif /* _WIN32 */
|
||||
Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &evt) {
|
||||
auto selected_item = evt.GetSelection();
|
||||
|
||||
auto marker = reinterpret_cast<Marker>(this->GetClientData(selected_item));
|
||||
if (marker >= LABEL_ITEM_MARKER && marker < LABEL_ITEM_MAX) {
|
||||
this->SetSelection(this->last_selected);
|
||||
evt.StopPropagation();
|
||||
if (marker >= LABEL_ITEM_WIZARD_PRINTERS) {
|
||||
ConfigWizard::StartPage sp = ConfigWizard::SP_WELCOME;
|
||||
switch (marker) {
|
||||
case LABEL_ITEM_WIZARD_PRINTERS: sp = ConfigWizard::SP_PRINTERS; break;
|
||||
case LABEL_ITEM_WIZARD_FILAMENTS: sp = ConfigWizard::SP_FILAMENTS; break;
|
||||
case LABEL_ITEM_WIZARD_MATERIALS: sp = ConfigWizard::SP_MATERIALS; break;
|
||||
}
|
||||
wxTheApp->CallAfter([sp]() { wxGetApp().run_wizard(ConfigWizard::RR_USER, sp); });
|
||||
}
|
||||
} else if ( this->last_selected != selected_item ||
|
||||
wxGetApp().get_tab(this->preset_type)->get_presets()->current_is_dirty() ) {
|
||||
this->last_selected = selected_item;
|
||||
evt.SetInt(this->preset_type);
|
||||
evt.Skip();
|
||||
} else {
|
||||
evt.StopPropagation();
|
||||
}
|
||||
});
|
||||
|
||||
if (preset_type == Slic3r::Preset::TYPE_FILAMENT)
|
||||
{
|
||||
Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &event) {
|
||||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||
const Preset* selected_preset = preset_bundle->filaments.find_preset(preset_bundle->filament_presets[extruder_idx]);
|
||||
// Wide icons are shown if the currently selected preset is not compatible with the current printer,
|
||||
// and red flag is drown in front of the selected preset.
|
||||
bool wide_icons = selected_preset != nullptr && !selected_preset->is_compatible;
|
||||
float scale = m_em_unit*0.1f;
|
||||
|
||||
int shifl_Left = wide_icons ? int(scale * 16 + 0.5) : 0;
|
||||
#if defined(wxBITMAPCOMBOBOX_OWNERDRAWN_BASED)
|
||||
shifl_Left += int(scale * 4 + 0.5f); // IMAGE_SPACING_RIGHT = 4 for wxBitmapComboBox -> Space left of image
|
||||
#endif
|
||||
int icon_right_pos = shifl_Left + int(scale * (24+4) + 0.5);
|
||||
int mouse_pos = event.GetLogicalPosition(wxClientDC(this)).x;
|
||||
if (mouse_pos < shifl_Left || mouse_pos > icon_right_pos ) {
|
||||
// Let the combo box process the mouse click.
|
||||
event.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
// Swallow the mouse click and open the color picker.
|
||||
|
||||
// get current color
|
||||
DynamicPrintConfig* cfg = wxGetApp().get_tab(Preset::TYPE_PRINTER)->get_config();
|
||||
auto colors = static_cast<ConfigOptionStrings*>(cfg->option("extruder_colour")->clone());
|
||||
wxColour clr(colors->values[extruder_idx]);
|
||||
if (!clr.IsOk())
|
||||
clr = wxColour(0,0,0); // Don't set alfa to transparence
|
||||
|
||||
auto data = new wxColourData();
|
||||
data->SetChooseFull(1);
|
||||
data->SetColour(clr);
|
||||
|
||||
wxColourDialog dialog(this, data);
|
||||
dialog.CenterOnParent();
|
||||
if (dialog.ShowModal() == wxID_OK)
|
||||
{
|
||||
colors->values[extruder_idx] = dialog.GetColourData().GetColour().GetAsString(wxC2S_HTML_SYNTAX).ToStdString();
|
||||
|
||||
DynamicPrintConfig cfg_new = *cfg;
|
||||
cfg_new.set_key_value("extruder_colour", colors);
|
||||
|
||||
wxGetApp().get_tab(Preset::TYPE_PRINTER)->load_config(cfg_new);
|
||||
preset_bundle->update_plater_filament_ui(extruder_idx, this);
|
||||
wxGetApp().plater()->on_config_change(cfg_new);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
edit_btn = new ScalableButton(parent, wxID_ANY, "cog");
|
||||
edit_btn->SetToolTip(_L("Click to edit preset"));
|
||||
|
||||
edit_btn->Bind(wxEVT_BUTTON, ([preset_type, this](wxCommandEvent)
|
||||
{
|
||||
Tab* tab = wxGetApp().get_tab(preset_type);
|
||||
if (!tab)
|
||||
return;
|
||||
|
||||
int page_id = wxGetApp().tab_panel()->FindPage(tab);
|
||||
if (page_id == wxNOT_FOUND)
|
||||
return;
|
||||
|
||||
wxGetApp().tab_panel()->SetSelection(page_id);
|
||||
|
||||
// Switch to Settings NotePad
|
||||
wxGetApp().mainframe->select_tab();
|
||||
|
||||
/* In a case of a multi-material printing, for editing another Filament Preset
|
||||
* it's needed to select this preset for the "Filament settings" Tab
|
||||
*/
|
||||
if (preset_type == Preset::TYPE_FILAMENT && wxGetApp().extruders_edited_cnt() > 1)
|
||||
{
|
||||
const std::string& selected_preset = GetString(GetSelection()).ToUTF8().data();
|
||||
|
||||
// Call select_preset() only if there is new preset and not just modified
|
||||
if ( !boost::algorithm::ends_with(selected_preset, Preset::suffix_modified()) )
|
||||
{
|
||||
const std::string& preset_name = wxGetApp().preset_bundle->filaments.get_preset_name_by_alias(selected_preset);
|
||||
tab->select_preset(/*selected_preset*/preset_name);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
PresetComboBox::~PresetComboBox()
|
||||
{
|
||||
if (edit_btn)
|
||||
edit_btn->Destroy();
|
||||
}
|
||||
|
||||
|
||||
void PresetComboBox::set_label_marker(int item, LabelItemType label_item_type)
|
||||
{
|
||||
this->SetClientData(item, (void*)label_item_type);
|
||||
}
|
||||
|
||||
void PresetComboBox::check_selection(int selection)
|
||||
{
|
||||
this->last_selected = selection;
|
||||
}
|
||||
|
||||
void PresetComboBox::msw_rescale()
|
||||
{
|
||||
m_em_unit = wxGetApp().em_unit();
|
||||
edit_btn->msw_rescale();
|
||||
}
|
||||
|
||||
// Frequently changed parameters
|
||||
|
||||
class FreqChangedParams : public OG_Settings
|
||||
@ -704,12 +557,12 @@ struct Sidebar::priv
|
||||
|
||||
ModeSizer *mode_sizer;
|
||||
wxFlexGridSizer *sizer_presets;
|
||||
PresetComboBox *combo_print;
|
||||
std::vector<PresetComboBox*> combos_filament;
|
||||
PlaterPresetComboBox *combo_print;
|
||||
std::vector<PlaterPresetComboBox*> combos_filament;
|
||||
wxBoxSizer *sizer_filaments;
|
||||
PresetComboBox *combo_sla_print;
|
||||
PresetComboBox *combo_sla_material;
|
||||
PresetComboBox *combo_printer;
|
||||
PlaterPresetComboBox *combo_sla_print;
|
||||
PlaterPresetComboBox *combo_sla_material;
|
||||
PlaterPresetComboBox *combo_printer;
|
||||
|
||||
wxBoxSizer *sizer_params;
|
||||
FreqChangedParams *frequently_changed_parameters{ nullptr };
|
||||
@ -808,10 +661,10 @@ Sidebar::Sidebar(Plater *parent)
|
||||
|
||||
p->sizer_filaments = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
auto init_combo = [this](PresetComboBox **combo, wxString label, Preset::Type preset_type, bool filament) {
|
||||
auto init_combo = [this](PlaterPresetComboBox **combo, wxString label, Preset::Type preset_type, bool filament) {
|
||||
auto *text = new wxStaticText(p->presets_panel, wxID_ANY, label + " :");
|
||||
text->SetFont(wxGetApp().small_font());
|
||||
*combo = new PresetComboBox(p->presets_panel, preset_type);
|
||||
*combo = new PlaterPresetComboBox(p->presets_panel, preset_type);
|
||||
|
||||
auto combo_and_btn_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
combo_and_btn_sizer->Add(*combo, 1, wxEXPAND);
|
||||
@ -948,8 +801,8 @@ Sidebar::Sidebar(Plater *parent)
|
||||
|
||||
Sidebar::~Sidebar() {}
|
||||
|
||||
void Sidebar::init_filament_combo(PresetComboBox **combo, const int extr_idx) {
|
||||
*combo = new PresetComboBox(p->presets_panel, Slic3r::Preset::TYPE_FILAMENT);
|
||||
void Sidebar::init_filament_combo(PlaterPresetComboBox **combo, const int extr_idx) {
|
||||
*combo = new PlaterPresetComboBox(p->presets_panel, Slic3r::Preset::TYPE_FILAMENT);
|
||||
// # copy icons from first choice
|
||||
// $choice->SetItemBitmap($_, $choices->[0]->GetItemBitmap($_)) for 0..$#presets;
|
||||
|
||||
@ -984,18 +837,18 @@ void Sidebar::update_all_preset_comboboxes()
|
||||
|
||||
// Update the print choosers to only contain the compatible presets, update the dirty flags.
|
||||
if (print_tech == ptFFF)
|
||||
preset_bundle.prints.update_plater_ui(p->combo_print);
|
||||
p->combo_print->update();
|
||||
else {
|
||||
preset_bundle.sla_prints.update_plater_ui(p->combo_sla_print);
|
||||
preset_bundle.sla_materials.update_plater_ui(p->combo_sla_material);
|
||||
p->combo_sla_print->update();
|
||||
p->combo_sla_material->update();
|
||||
}
|
||||
// Update the printer choosers, update the dirty flags.
|
||||
preset_bundle.printers.update_plater_ui(p->combo_printer);
|
||||
p->combo_printer->update();
|
||||
// Update the filament choosers to only contain the compatible presets, update the color preview,
|
||||
// update the dirty flags.
|
||||
if (print_tech == ptFFF) {
|
||||
for (size_t i = 0; i < p->combos_filament.size(); ++i)
|
||||
preset_bundle.update_plater_filament_ui(i, p->combos_filament[i]);
|
||||
for (PlaterPresetComboBox* cb : p->combos_filament)
|
||||
cb->update();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1017,23 +870,22 @@ void Sidebar::update_presets(Preset::Type preset_type)
|
||||
preset_bundle.set_filament_preset(0, name);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < filament_cnt; i++) {
|
||||
preset_bundle.update_plater_filament_ui(i, p->combos_filament[i]);
|
||||
}
|
||||
for (size_t i = 0; i < filament_cnt; i++)
|
||||
p->combos_filament[i]->update();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Preset::TYPE_PRINT:
|
||||
preset_bundle.prints.update_plater_ui(p->combo_print);
|
||||
p->combo_print->update();
|
||||
break;
|
||||
|
||||
case Preset::TYPE_SLA_PRINT:
|
||||
preset_bundle.sla_prints.update_plater_ui(p->combo_sla_print);
|
||||
p->combo_sla_print->update();
|
||||
break;
|
||||
|
||||
case Preset::TYPE_SLA_MATERIAL:
|
||||
preset_bundle.sla_materials.update_plater_ui(p->combo_sla_material);
|
||||
p->combo_sla_material->update();
|
||||
break;
|
||||
|
||||
case Preset::TYPE_PRINTER:
|
||||
@ -1069,18 +921,14 @@ void Sidebar::msw_rescale()
|
||||
|
||||
p->mode_sizer->msw_rescale();
|
||||
|
||||
// Rescale preset comboboxes in respect to the current em_unit ...
|
||||
for (PresetComboBox* combo : std::vector<PresetComboBox*> { p->combo_print,
|
||||
for (PlaterPresetComboBox* combo : std::vector<PlaterPresetComboBox*> { p->combo_print,
|
||||
p->combo_sla_print,
|
||||
p->combo_sla_material,
|
||||
p->combo_printer } )
|
||||
combo->msw_rescale();
|
||||
for (PresetComboBox* combo : p->combos_filament)
|
||||
for (PlaterPresetComboBox* combo : p->combos_filament)
|
||||
combo->msw_rescale();
|
||||
|
||||
// ... then refill them and set min size to correct layout of the sidebar
|
||||
update_all_preset_comboboxes();
|
||||
|
||||
p->frequently_changed_parameters->msw_rescale();
|
||||
p->object_list->msw_rescale();
|
||||
p->object_manipulation->msw_rescale();
|
||||
@ -1101,22 +949,16 @@ void Sidebar::msw_rescale()
|
||||
|
||||
void Sidebar::sys_color_changed()
|
||||
{
|
||||
// Update preset comboboxes in respect to the system color ...
|
||||
// combo->msw_rescale() updates icon on button, so use it
|
||||
for (PresetComboBox* combo : std::vector<PresetComboBox*>{ p->combo_print,
|
||||
for (PlaterPresetComboBox* combo : std::vector<PlaterPresetComboBox*>{ p->combo_print,
|
||||
p->combo_sla_print,
|
||||
p->combo_sla_material,
|
||||
p->combo_printer })
|
||||
combo->msw_rescale();
|
||||
for (PresetComboBox* combo : p->combos_filament)
|
||||
for (PlaterPresetComboBox* combo : p->combos_filament)
|
||||
combo->msw_rescale();
|
||||
|
||||
// ... then refill them and set min size to correct layout of the sidebar
|
||||
update_all_preset_comboboxes();
|
||||
|
||||
p->object_list->sys_color_changed();
|
||||
p->object_manipulation->sys_color_changed();
|
||||
// p->object_settings->msw_rescale();
|
||||
p->object_layers->sys_color_changed();
|
||||
|
||||
// btn...->msw_rescale() updates icon on button, so use it
|
||||
@ -1479,7 +1321,7 @@ void Sidebar::update_ui_from_settings()
|
||||
update_sliced_info_sizer();
|
||||
}
|
||||
|
||||
std::vector<PresetComboBox*>& Sidebar::combos_filament()
|
||||
std::vector<PlaterPresetComboBox*>& Sidebar::combos_filament()
|
||||
{
|
||||
return p->combos_filament;
|
||||
}
|
||||
@ -2339,6 +2181,8 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
if (!config.empty()) {
|
||||
Preset::normalize(config);
|
||||
wxGetApp().preset_bundle->load_config_model(filename.string(), std::move(config));
|
||||
if (printer_technology == ptFFF)
|
||||
CustomGCode::update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, &wxGetApp().preset_bundle->project_config);
|
||||
wxGetApp().load_current_presets();
|
||||
is_project_file = true;
|
||||
}
|
||||
@ -3428,7 +3272,7 @@ void Plater::priv::set_current_panel(wxPanel* panel)
|
||||
void Plater::priv::on_select_preset(wxCommandEvent &evt)
|
||||
{
|
||||
auto preset_type = static_cast<Preset::Type>(evt.GetInt());
|
||||
auto *combo = static_cast<PresetComboBox*>(evt.GetEventObject());
|
||||
auto *combo = static_cast<PlaterPresetComboBox*>(evt.GetEventObject());
|
||||
|
||||
// see https://github.com/prusa3d/PrusaSlicer/issues/3889
|
||||
// Under OSX: in case of use of a same names written in different case (like "ENDER" and "Ender"),
|
||||
@ -3447,19 +3291,27 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt)
|
||||
//! instead of
|
||||
//! combo->GetStringSelection().ToUTF8().data());
|
||||
|
||||
const std::string preset_name = wxGetApp().preset_bundle->get_preset_name_by_alias(preset_type,
|
||||
std::string preset_name = wxGetApp().preset_bundle->get_preset_name_by_alias(preset_type,
|
||||
Preset::remove_suffix_modified(combo->GetString(selection).ToUTF8().data()));
|
||||
|
||||
if (preset_type == Preset::TYPE_FILAMENT) {
|
||||
wxGetApp().preset_bundle->set_filament_preset(idx, preset_name);
|
||||
}
|
||||
|
||||
bool select_preset = !combo->selection_is_changed_according_to_physical_printers();
|
||||
// TODO: ?
|
||||
if (preset_type == Preset::TYPE_FILAMENT && sidebar->is_multifilament()) {
|
||||
// Only update the plater UI for the 2nd and other filaments.
|
||||
wxGetApp().preset_bundle->update_plater_filament_ui(idx, combo);
|
||||
combo->update();
|
||||
}
|
||||
else {
|
||||
else if (select_preset) {
|
||||
if (preset_type == Preset::TYPE_PRINTER) {
|
||||
PhysicalPrinterCollection& physical_printers = wxGetApp().preset_bundle->physical_printers;
|
||||
if(combo->is_selected_physical_printer())
|
||||
preset_name = physical_printers.get_selected_printer_preset_name();
|
||||
else
|
||||
physical_printers.unselect_printer();
|
||||
}
|
||||
wxWindowUpdateLocker noUpdates(sidebar->presets_panel());
|
||||
wxGetApp().get_tab(preset_type)->select_preset(preset_name);
|
||||
}
|
||||
@ -4321,7 +4173,12 @@ void Plater::priv::show_action_buttons(const bool ready_to_slice) const
|
||||
this->ready_to_slice = ready_to_slice;
|
||||
|
||||
wxWindowUpdateLocker noUpdater(sidebar);
|
||||
const auto prin_host_opt = config->option<ConfigOptionString>("print_host");
|
||||
|
||||
DynamicPrintConfig* selected_printer_config = wxGetApp().preset_bundle->physical_printers.get_selected_printer_config();
|
||||
if (!selected_printer_config)
|
||||
selected_printer_config = config;
|
||||
|
||||
const auto prin_host_opt = selected_printer_config->option<ConfigOptionString>("print_host");
|
||||
const bool send_gcode_shown = prin_host_opt != nullptr && !prin_host_opt->value.empty();
|
||||
|
||||
// when a background processing is ON, export_btn and/or send_btn are showing
|
||||
@ -5301,7 +5158,9 @@ void Plater::send_gcode()
|
||||
{
|
||||
if (p->model.objects.empty()) { return; }
|
||||
|
||||
PrintHostJob upload_job(p->config);
|
||||
// if physical_printer is selected, send gcode for this printer
|
||||
DynamicPrintConfig* physical_printer_config = wxGetApp().preset_bundle->physical_printers.get_selected_printer_config();
|
||||
PrintHostJob upload_job(physical_printer_config ? physical_printer_config : p->config);
|
||||
if (upload_job.empty()) { return; }
|
||||
|
||||
// Obtain default output path
|
||||
@ -5412,12 +5271,12 @@ void Plater::on_extruders_change(size_t num_extruders)
|
||||
size_t i = choices.size();
|
||||
while ( i < num_extruders )
|
||||
{
|
||||
PresetComboBox* choice/*{ nullptr }*/;
|
||||
PlaterPresetComboBox* choice/*{ nullptr }*/;
|
||||
sidebar().init_filament_combo(&choice, i);
|
||||
choices.push_back(choice);
|
||||
|
||||
// initialize selection
|
||||
wxGetApp().preset_bundle->update_plater_filament_ui(i, choice);
|
||||
choice->update();
|
||||
++i;
|
||||
}
|
||||
|
||||
|
@ -6,14 +6,12 @@
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#include <wx/panel.h>
|
||||
#include <wx/bmpcbox.h>
|
||||
|
||||
#include "Preset.hpp"
|
||||
#include "Selection.hpp"
|
||||
|
||||
#include "libslic3r/Preset.hpp"
|
||||
#include "libslic3r/BoundingBox.hpp"
|
||||
#include "Jobs/Job.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "Search.hpp"
|
||||
|
||||
class wxButton;
|
||||
@ -51,46 +49,13 @@ class NotificationManager;
|
||||
struct Camera;
|
||||
class Bed3D;
|
||||
class GLToolbar;
|
||||
class PlaterPresetComboBox;
|
||||
|
||||
using t_optgroups = std::vector <std::shared_ptr<ConfigOptionsGroup>>;
|
||||
|
||||
class Plater;
|
||||
enum class ActionButtonType : int;
|
||||
|
||||
class PresetComboBox : public PresetBitmapComboBox
|
||||
{
|
||||
public:
|
||||
PresetComboBox(wxWindow *parent, Preset::Type preset_type);
|
||||
~PresetComboBox();
|
||||
|
||||
ScalableButton* edit_btn { nullptr };
|
||||
|
||||
enum LabelItemType {
|
||||
LABEL_ITEM_MARKER = 0xffffff01,
|
||||
LABEL_ITEM_WIZARD_PRINTERS,
|
||||
LABEL_ITEM_WIZARD_FILAMENTS,
|
||||
LABEL_ITEM_WIZARD_MATERIALS,
|
||||
|
||||
LABEL_ITEM_MAX,
|
||||
};
|
||||
|
||||
void set_label_marker(int item, LabelItemType label_item_type = LABEL_ITEM_MARKER);
|
||||
void set_extruder_idx(const int extr_idx) { extruder_idx = extr_idx; }
|
||||
int get_extruder_idx() const { return extruder_idx; }
|
||||
int em_unit() const { return m_em_unit; }
|
||||
void check_selection(int selection);
|
||||
|
||||
void msw_rescale();
|
||||
|
||||
private:
|
||||
typedef std::size_t Marker;
|
||||
|
||||
Preset::Type preset_type;
|
||||
int last_selected;
|
||||
int extruder_idx = -1;
|
||||
int m_em_unit;
|
||||
};
|
||||
|
||||
class Sidebar : public wxPanel
|
||||
{
|
||||
ConfigOptionMode m_mode;
|
||||
@ -102,7 +67,7 @@ public:
|
||||
Sidebar &operator=(const Sidebar &) = delete;
|
||||
~Sidebar();
|
||||
|
||||
void init_filament_combo(PresetComboBox **combo, const int extr_idx);
|
||||
void init_filament_combo(PlaterPresetComboBox **combo, const int extr_idx);
|
||||
void remove_unused_filament_combos(const size_t current_extruder_count);
|
||||
void update_all_preset_comboboxes();
|
||||
void update_presets(Slic3r::Preset::Type preset_type);
|
||||
@ -141,7 +106,7 @@ public:
|
||||
void update_searcher();
|
||||
void update_ui_from_settings();
|
||||
|
||||
std::vector<PresetComboBox*>& combos_filament();
|
||||
std::vector<PlaterPresetComboBox*>& combos_filament();
|
||||
Search::OptionsSearcher& get_searcher();
|
||||
std::string& get_search_line();
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include "Preferences.hpp"
|
||||
#include "AppConfig.hpp"
|
||||
#include "OptionsGroup.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
1331
src/slic3r/GUI/PresetComboBoxes.cpp
Normal file
1331
src/slic3r/GUI/PresetComboBoxes.cpp
Normal file
File diff suppressed because it is too large
Load Diff
276
src/slic3r/GUI/PresetComboBoxes.hpp
Normal file
276
src/slic3r/GUI/PresetComboBoxes.hpp
Normal file
@ -0,0 +1,276 @@
|
||||
#ifndef slic3r_PresetComboBoxes_hpp_
|
||||
#define slic3r_PresetComboBoxes_hpp_
|
||||
|
||||
#include <wx/bmpcbox.h>
|
||||
#include <wx/gdicmn.h>
|
||||
|
||||
#include "libslic3r/Preset.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
|
||||
class wxString;
|
||||
class wxTextCtrl;
|
||||
class wxStaticText;
|
||||
class ScalableButton;
|
||||
class wxBoxSizer;
|
||||
class wxComboBox;
|
||||
class wxStaticBitmap;
|
||||
class wxRadioBox;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace GUI {
|
||||
|
||||
class BitmapCache;
|
||||
|
||||
// ---------------------------------
|
||||
// *** PresetComboBox ***
|
||||
// ---------------------------------
|
||||
|
||||
// BitmapComboBox used to presets list on Sidebar and Tabs
|
||||
class PresetComboBox : public wxBitmapComboBox
|
||||
{
|
||||
public:
|
||||
PresetComboBox(wxWindow* parent, Preset::Type preset_type, const wxSize& size = wxDefaultSize);
|
||||
~PresetComboBox();
|
||||
|
||||
enum LabelItemType {
|
||||
LABEL_ITEM_PHYSICAL_PRINTER = 0xffffff01,
|
||||
LABEL_ITEM_DISABLED,
|
||||
LABEL_ITEM_MARKER,
|
||||
LABEL_ITEM_PHYSICAL_PRINTERS,
|
||||
LABEL_ITEM_WIZARD_PRINTERS,
|
||||
LABEL_ITEM_WIZARD_FILAMENTS,
|
||||
LABEL_ITEM_WIZARD_MATERIALS,
|
||||
|
||||
LABEL_ITEM_MAX,
|
||||
};
|
||||
|
||||
void set_label_marker(int item, LabelItemType label_item_type = LABEL_ITEM_MARKER);
|
||||
bool set_printer_technology(PrinterTechnology pt);
|
||||
|
||||
void set_selection_changed_function(std::function<void(int)> sel_changed) { on_selection_changed = sel_changed; }
|
||||
|
||||
bool is_selected_physical_printer();
|
||||
|
||||
// Return true, if physical printer was selected
|
||||
// and next internal selection was accomplished
|
||||
bool selection_is_changed_according_to_physical_printers();
|
||||
|
||||
void update(std::string select_preset);
|
||||
|
||||
virtual void update();
|
||||
virtual void msw_rescale();
|
||||
|
||||
protected:
|
||||
typedef std::size_t Marker;
|
||||
std::function<void(int)> on_selection_changed { nullptr };
|
||||
|
||||
Preset::Type m_type;
|
||||
std::string m_main_bitmap_name;
|
||||
|
||||
PresetBundle* m_preset_bundle {nullptr};
|
||||
PresetCollection* m_collection {nullptr};
|
||||
|
||||
// Caching bitmaps for the all bitmaps, used in preset comboboxes
|
||||
static BitmapCache& bitmap_cache();
|
||||
|
||||
// Indicator, that the preset is compatible with the selected printer.
|
||||
ScalableBitmap m_bitmapCompatible;
|
||||
// Indicator, that the preset is NOT compatible with the selected printer.
|
||||
ScalableBitmap m_bitmapIncompatible;
|
||||
|
||||
int m_last_selected;
|
||||
int m_em_unit;
|
||||
|
||||
// parameters for an icon's drawing
|
||||
int icon_height;
|
||||
int norm_icon_width;
|
||||
int thin_icon_width;
|
||||
int wide_icon_width;
|
||||
int space_icon_width;
|
||||
int thin_space_icon_width;
|
||||
int wide_space_icon_width;
|
||||
|
||||
PrinterTechnology printer_technology {ptAny};
|
||||
|
||||
void invalidate_selection();
|
||||
void validate_selection(bool predicate = false);
|
||||
void update_selection();
|
||||
|
||||
#ifdef __linux__
|
||||
static const char* separator_head() { return "------- "; }
|
||||
static const char* separator_tail() { return " -------"; }
|
||||
#else // __linux__
|
||||
static const char* separator_head() { return "————— "; }
|
||||
static const char* separator_tail() { return " —————"; }
|
||||
#endif // __linux__
|
||||
static wxString separator(const std::string& label);
|
||||
|
||||
wxBitmap* get_bmp( std::string bitmap_key, bool wide_icons, const std::string& main_icon_name,
|
||||
bool is_compatible = true, bool is_system = false, bool is_single_bar = false,
|
||||
std::string filament_rgb = "", std::string extruder_rgb = "");
|
||||
|
||||
wxBitmap* get_bmp( std::string bitmap_key, const std::string& main_icon_name, const std::string& next_icon_name,
|
||||
bool is_enabled = true, bool is_compatible = true, bool is_system = false);
|
||||
|
||||
#ifdef __APPLE__
|
||||
/* For PresetComboBox we use bitmaps that are created from images that are already scaled appropriately for Retina
|
||||
* (Contrary to the intuition, the `scale` argument for Bitmap's constructor doesn't mean
|
||||
* "please scale this to such and such" but rather
|
||||
* "the wxImage is already sized for backing scale such and such". )
|
||||
* Unfortunately, the constructor changes the size of wxBitmap too.
|
||||
* Thus We need to use unscaled size value for bitmaps that we use
|
||||
* to avoid scaled size of control items.
|
||||
* For this purpose control drawing methods and
|
||||
* control size calculation methods (virtual) are overridden.
|
||||
**/
|
||||
virtual bool OnAddBitmap(const wxBitmap& bitmap) override;
|
||||
virtual void OnDrawItem(wxDC& dc, const wxRect& rect, int item, int flags) const override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
void fill_width_height();
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------
|
||||
// *** PlaterPresetComboBox ***
|
||||
// ---------------------------------
|
||||
|
||||
class PlaterPresetComboBox : public PresetComboBox
|
||||
{
|
||||
public:
|
||||
PlaterPresetComboBox(wxWindow *parent, Preset::Type preset_type);
|
||||
~PlaterPresetComboBox();
|
||||
|
||||
ScalableButton* edit_btn { nullptr };
|
||||
|
||||
void set_extruder_idx(const int extr_idx) { m_extruder_idx = extr_idx; }
|
||||
int get_extruder_idx() const { return m_extruder_idx; }
|
||||
|
||||
bool switch_to_tab();
|
||||
void show_add_menu();
|
||||
void show_edit_menu();
|
||||
|
||||
void update() override;
|
||||
void msw_rescale() override;
|
||||
|
||||
private:
|
||||
int m_extruder_idx = -1;
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------
|
||||
// *** TabPresetComboBox ***
|
||||
// ---------------------------------
|
||||
|
||||
class TabPresetComboBox : public PresetComboBox
|
||||
{
|
||||
bool show_incompatible {false};
|
||||
bool m_enable_all {false};
|
||||
|
||||
public:
|
||||
TabPresetComboBox(wxWindow *parent, Preset::Type preset_type);
|
||||
~TabPresetComboBox() {}
|
||||
void set_show_incompatible_presets(bool show_incompatible_presets) {
|
||||
show_incompatible = show_incompatible_presets;
|
||||
}
|
||||
|
||||
void update() override;
|
||||
void update_dirty();
|
||||
void msw_rescale() override;
|
||||
|
||||
void set_enable_all(bool enable=true) { m_enable_all = enable; }
|
||||
|
||||
PresetCollection* presets() const { return m_collection; }
|
||||
Preset::Type type() const { return m_type; }
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------
|
||||
// SavePresetDialog
|
||||
//------------------------------------------------
|
||||
|
||||
class SavePresetDialog : public DPIDialog
|
||||
{
|
||||
enum ActionType
|
||||
{
|
||||
ChangePreset,
|
||||
AddPreset,
|
||||
Switch,
|
||||
UndefAction
|
||||
};
|
||||
|
||||
struct Item
|
||||
{
|
||||
enum ValidationType
|
||||
{
|
||||
Valid,
|
||||
NoValid,
|
||||
Warning
|
||||
};
|
||||
|
||||
Item(Preset::Type type, const std::string& suffix, wxBoxSizer* sizer, SavePresetDialog* parent);
|
||||
|
||||
void update_valid_bmp();
|
||||
void accept();
|
||||
|
||||
bool is_valid() const { return m_valid_type != NoValid; }
|
||||
Preset::Type type() const { return m_type; }
|
||||
std::string preset_name() const { return m_preset_name; }
|
||||
|
||||
private:
|
||||
Preset::Type m_type;
|
||||
ValidationType m_valid_type;
|
||||
std::string m_preset_name;
|
||||
|
||||
SavePresetDialog* m_parent {nullptr};
|
||||
wxStaticBitmap* m_valid_bmp {nullptr};
|
||||
wxComboBox* m_combo {nullptr};
|
||||
wxStaticText* m_valid_label {nullptr};
|
||||
|
||||
PresetCollection* m_presets {nullptr};
|
||||
|
||||
void update();
|
||||
};
|
||||
|
||||
std::vector<Item> m_items;
|
||||
|
||||
wxBoxSizer* m_presets_sizer {nullptr};
|
||||
wxStaticText* m_label {nullptr};
|
||||
wxRadioBox* m_action_radio_box {nullptr};
|
||||
wxBoxSizer* m_radio_sizer {nullptr};
|
||||
ActionType m_action {UndefAction};
|
||||
|
||||
std::string m_ph_printer_name;
|
||||
std::string m_old_preset_name;
|
||||
|
||||
public:
|
||||
|
||||
SavePresetDialog(Preset::Type type, const std::string& suffix);
|
||||
~SavePresetDialog() {}
|
||||
|
||||
void AddItem(Preset::Type type, const std::string& suffix);
|
||||
|
||||
std::string get_name();
|
||||
std::string get_name(Preset::Type type);
|
||||
|
||||
bool enable_ok_btn() const;
|
||||
void add_info_for_edit_ph_printer(wxBoxSizer *sizer);
|
||||
void update_info_for_edit_ph_printer(const std::string &preset_name);
|
||||
void layout();
|
||||
|
||||
protected:
|
||||
void on_dpi_changed(const wxRect& suggested_rect) override;
|
||||
void on_sys_color_changed() override {}
|
||||
|
||||
private:
|
||||
void update_physical_printers(const std::string& preset_name);
|
||||
void accept();
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
@ -4,7 +4,6 @@
|
||||
#include "libslic3r/Slicing.hpp"
|
||||
#include "libslic3r/libslic3r.h"
|
||||
|
||||
#include "PresetBundle.hpp"
|
||||
#include "PresetHints.hpp"
|
||||
|
||||
#include <wx/intl.h>
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "PresetBundle.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
@ -15,11 +15,11 @@
|
||||
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "AppConfig.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "../Utils/PrintHost.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
|
@ -9,10 +9,10 @@
|
||||
#include "wx/dataview.h"
|
||||
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "Plater.hpp"
|
||||
#include "Tab.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
|
||||
#define FTS_FUZZY_MATCH_IMPLEMENTATION
|
||||
#include "fts_fuzzy_match.h"
|
||||
|
@ -14,8 +14,8 @@
|
||||
#include <wx/dialog.h>
|
||||
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "Preset.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "libslic3r/Preset.hpp"
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
@ -1,8 +1,8 @@
|
||||
// #include "libslic3r/GCodeSender.hpp"
|
||||
#include "slic3r/Utils/Serial.hpp"
|
||||
#include "Tab.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "PresetHints.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
||||
@ -27,14 +27,15 @@
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include "wxExtensions.hpp"
|
||||
#include "PresetComboBoxes.hpp"
|
||||
#include <wx/wupdlock.h>
|
||||
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
#include "ConfigWizard.hpp"
|
||||
#include "Plater.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "format.hpp"
|
||||
#include "PhysicalPrinterDialog.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
@ -160,10 +161,17 @@ void Tab::create_preset_tab()
|
||||
#endif //__WXOSX__
|
||||
|
||||
// preset chooser
|
||||
m_presets_choice = new PresetBitmapComboBox(panel, wxSize(35 * m_em_unit, -1));
|
||||
m_presets_choice = new TabPresetComboBox(panel, m_type);
|
||||
m_presets_choice->set_selection_changed_function([this](int selection) {
|
||||
if (!m_presets_choice->selection_is_changed_according_to_physical_printers())
|
||||
{
|
||||
if (m_type == Preset::TYPE_PRINTER && !m_presets_choice->is_selected_physical_printer())
|
||||
m_preset_bundle->physical_printers.unselect_printer();
|
||||
|
||||
// search combox
|
||||
// m_search = new Search::SearchCtrl(panel);
|
||||
// select preset
|
||||
select_preset(m_presets_choice->GetString(selection).ToUTF8().data());
|
||||
}
|
||||
});
|
||||
|
||||
auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||||
|
||||
@ -173,6 +181,8 @@ void Tab::create_preset_tab()
|
||||
|
||||
add_scaled_button(panel, &m_btn_save_preset, "save");
|
||||
add_scaled_button(panel, &m_btn_delete_preset, "cross");
|
||||
if (m_type == Preset::Type::TYPE_PRINTER)
|
||||
add_scaled_button(panel, &m_btn_edit_ph_printer, "cog");
|
||||
|
||||
m_show_incompatible_presets = false;
|
||||
add_scaled_bitmap(this, m_bmp_show_incompatible_presets, "flag_red");
|
||||
@ -184,6 +194,8 @@ void Tab::create_preset_tab()
|
||||
m_btn_save_preset->SetToolTip(from_u8((boost::format(_utf8(L("Save current %s"))) % m_title).str()));
|
||||
m_btn_delete_preset->SetToolTip(_(L("Delete this preset")));
|
||||
m_btn_delete_preset->Disable();
|
||||
if (m_btn_edit_ph_printer)
|
||||
m_btn_edit_ph_printer->Disable();
|
||||
|
||||
add_scaled_button(panel, &m_question_btn, "question");
|
||||
m_question_btn->SetToolTip(_(L("Hover the cursor over buttons to find more information \n"
|
||||
@ -238,6 +250,10 @@ void Tab::create_preset_tab()
|
||||
m_hsizer->Add(m_btn_save_preset, 0, wxALIGN_CENTER_VERTICAL);
|
||||
m_hsizer->AddSpacer(int(4 * scale_factor));
|
||||
m_hsizer->Add(m_btn_delete_preset, 0, wxALIGN_CENTER_VERTICAL);
|
||||
if (m_btn_edit_ph_printer) {
|
||||
m_hsizer->AddSpacer(int(4 * scale_factor));
|
||||
m_hsizer->Add(m_btn_edit_ph_printer, 0, wxALIGN_CENTER_VERTICAL);
|
||||
}
|
||||
m_hsizer->AddSpacer(int(/*16*/8 * scale_factor));
|
||||
m_hsizer->Add(m_btn_hide_incompatible_presets, 0, wxALIGN_CENTER_VERTICAL);
|
||||
m_hsizer->AddSpacer(int(8 * scale_factor));
|
||||
@ -278,41 +294,19 @@ void Tab::create_preset_tab()
|
||||
m_treectrl->Bind(wxEVT_TREE_SEL_CHANGED, &Tab::OnTreeSelChange, this);
|
||||
m_treectrl->Bind(wxEVT_KEY_DOWN, &Tab::OnKeyDown, this);
|
||||
|
||||
m_presets_choice->Bind(wxEVT_COMBOBOX, ([this](wxCommandEvent e) {
|
||||
//! Because of The MSW and GTK version of wxBitmapComboBox derived from wxComboBox,
|
||||
//! but the OSX version derived from wxOwnerDrawnCombo, instead of:
|
||||
//! select_preset(m_presets_choice->GetStringSelection().ToUTF8().data());
|
||||
//! we doing next:
|
||||
// int selected_item = m_presets_choice->GetSelection();
|
||||
|
||||
// see https://github.com/prusa3d/PrusaSlicer/issues/3889
|
||||
// Under OSX: in case of use of a same names written in different case (like "ENDER" and "Ender")
|
||||
// m_presets_choice->GetSelection() will return first item, because search in PopupListCtrl is case-insensitive.
|
||||
// So, use GetSelection() from event parameter
|
||||
int selected_item = e.GetSelection();
|
||||
if (m_selected_preset_item == size_t(selected_item) && !m_presets->current_is_dirty())
|
||||
return;
|
||||
if (selected_item >= 0) {
|
||||
std::string selected_string = m_presets_choice->GetString(selected_item).ToUTF8().data();
|
||||
if (selected_string.find(PresetCollection::separator_head()) == 0
|
||||
/*selected_string == "------- System presets -------" ||
|
||||
selected_string == "------- User presets -------"*/) {
|
||||
m_presets_choice->SetSelection(m_selected_preset_item);
|
||||
if (wxString::FromUTF8(selected_string.c_str()) == PresetCollection::separator(L("Add a new printer")))
|
||||
wxTheApp->CallAfter([]() { wxGetApp().run_wizard(ConfigWizard::RR_USER); });
|
||||
return;
|
||||
}
|
||||
m_selected_preset_item = selected_item;
|
||||
select_preset(selected_string);
|
||||
}
|
||||
}));
|
||||
|
||||
m_btn_save_preset->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { save_preset(); }));
|
||||
m_btn_delete_preset->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { delete_preset(); }));
|
||||
m_btn_hide_incompatible_presets->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) {
|
||||
toggle_show_hide_incompatible();
|
||||
}));
|
||||
|
||||
if (m_btn_edit_ph_printer)
|
||||
m_btn_edit_ph_printer->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) {
|
||||
PhysicalPrinterDialog dlg(m_presets_choice->GetString(m_presets_choice->GetSelection()));
|
||||
if (dlg.ShowModal() == wxID_OK)
|
||||
update_tab_ui();
|
||||
}));
|
||||
|
||||
// Fill cache for mode bitmaps
|
||||
m_mode_bitmap_cache.reserve(3);
|
||||
m_mode_bitmap_cache.push_back(ScalableBitmap(this, "mode_simple" , mode_icon_px_size()));
|
||||
@ -778,14 +772,14 @@ void Tab::on_roll_back_value(const bool to_sys /*= true*/)
|
||||
// comparing the selected preset config with $self->{config}.
|
||||
void Tab::update_dirty()
|
||||
{
|
||||
m_presets->update_dirty_ui(m_presets_choice);
|
||||
m_presets_choice->update_dirty();
|
||||
on_presets_changed();
|
||||
update_changed_ui();
|
||||
}
|
||||
|
||||
void Tab::update_tab_ui()
|
||||
{
|
||||
m_selected_preset_item = m_presets->update_tab_ui(m_presets_choice, m_show_incompatible_presets, m_em_unit);
|
||||
m_presets_choice->update();
|
||||
}
|
||||
|
||||
// Load a provied DynamicConfig into the tab, modifying the active preset.
|
||||
@ -847,20 +841,20 @@ void Tab::update_visibility()
|
||||
|
||||
void Tab::msw_rescale()
|
||||
{
|
||||
m_em_unit = wxGetApp().em_unit();
|
||||
m_em_unit = em_unit(m_parent);
|
||||
|
||||
m_mode_sizer->msw_rescale();
|
||||
m_presets_choice->msw_rescale();
|
||||
|
||||
m_presets_choice->SetSize(35 * m_em_unit, -1);
|
||||
m_treectrl->SetMinSize(wxSize(20 * m_em_unit, -1));
|
||||
|
||||
update_tab_ui();
|
||||
|
||||
// rescale buttons and cached bitmaps
|
||||
for (const auto btn : m_scaled_buttons)
|
||||
btn->msw_rescale();
|
||||
for (const auto bmp : m_scaled_bitmaps)
|
||||
bmp->msw_rescale();
|
||||
for (const auto ikon : m_blinking_ikons)
|
||||
ikon.second->msw_rescale();
|
||||
for (ScalableBitmap& bmp : m_mode_bitmap_cache)
|
||||
bmp.msw_rescale();
|
||||
|
||||
@ -963,7 +957,7 @@ void Tab::load_key_value(const std::string& opt_key, const boost::any& value, bo
|
||||
// Don't select another profile if this profile happens to become incompatible.
|
||||
m_preset_bundle->update_compatible(PresetSelectCompatibleType::Never);
|
||||
}
|
||||
m_presets->update_dirty_ui(m_presets_choice);
|
||||
m_presets_choice->update_dirty();
|
||||
on_presets_changed();
|
||||
update();
|
||||
}
|
||||
@ -2148,11 +2142,10 @@ void TabPrinter::build_fff()
|
||||
line.append_widget(serial_test);
|
||||
optgroup->append_line(line);
|
||||
}
|
||||
#endif
|
||||
|
||||
optgroup = page->new_optgroup(L("Print Host upload"));
|
||||
build_printhost(optgroup.get());
|
||||
|
||||
#endif
|
||||
optgroup = page->new_optgroup(L("Firmware"));
|
||||
optgroup->append_single_option_line("gcode_flavor");
|
||||
optgroup->append_single_option_line("silent_mode");
|
||||
@ -2310,8 +2303,10 @@ void TabPrinter::build_sla()
|
||||
optgroup->append_single_option_line("min_initial_exposure_time");
|
||||
optgroup->append_single_option_line("max_initial_exposure_time");
|
||||
|
||||
/*
|
||||
optgroup = page->new_optgroup(L("Print Host upload"));
|
||||
build_printhost(optgroup.get());
|
||||
*/
|
||||
|
||||
const int notes_field_height = 25; // 250
|
||||
|
||||
@ -2699,11 +2694,13 @@ void TabPrinter::update_fff()
|
||||
m_serial_test_btn->Disable();
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
std::unique_ptr<PrintHost> host(PrintHost::get_print_host(m_config));
|
||||
m_print_host_test_btn->Enable(!m_config->opt_string("print_host").empty() && host->can_test());
|
||||
m_printhost_browse_btn->Enable(host->has_auto_discovery());
|
||||
}
|
||||
*/
|
||||
|
||||
bool have_multiple_extruders = m_extruders_count > 1;
|
||||
get_field("toolchange_gcode")->toggle(have_multiple_extruders);
|
||||
@ -2805,7 +2802,7 @@ void Tab::load_current_preset()
|
||||
{
|
||||
const Preset& preset = m_presets->get_edited_preset();
|
||||
|
||||
(preset.is_default || preset.is_system) ? m_btn_delete_preset->Disable() : m_btn_delete_preset->Enable(true);
|
||||
update_btns_enabling();
|
||||
|
||||
update();
|
||||
if (m_type == Slic3r::Preset::TYPE_PRINTER) {
|
||||
@ -2942,10 +2939,31 @@ void Tab::update_page_tree_visibility()
|
||||
|
||||
}
|
||||
|
||||
void Tab::update_btns_enabling()
|
||||
{
|
||||
// we can't delete last preset from the physical printer
|
||||
if (m_type == Preset::TYPE_PRINTER && m_preset_bundle->physical_printers.has_selection())
|
||||
m_btn_delete_preset->Enable(m_preset_bundle->physical_printers.get_selected_printer().preset_names.size() > 1);
|
||||
else {
|
||||
const Preset& preset = m_presets->get_edited_preset();
|
||||
m_btn_delete_preset->Enable(!preset.is_default && !preset.is_system);
|
||||
}
|
||||
|
||||
// we can edit physical printer only if it's selected in the list
|
||||
if (m_btn_edit_ph_printer)
|
||||
m_btn_edit_ph_printer->Enable(m_preset_bundle->physical_printers.has_selection());
|
||||
}
|
||||
|
||||
void Tab::update_preset_choice()
|
||||
{
|
||||
m_presets_choice->update();
|
||||
update_btns_enabling();
|
||||
}
|
||||
|
||||
// Called by the UI combo box when the user switches profiles, and also to delete the current profile.
|
||||
// Select a preset by a name.If !defined(name), then the default preset is selected.
|
||||
// If the current profile is modified, user is asked to save the changes.
|
||||
void Tab::select_preset(std::string preset_name, bool delete_current)
|
||||
void Tab::select_preset(std::string preset_name, bool delete_current /*=false*/, const std::string& last_selected_ph_printer_name/* =""*/)
|
||||
{
|
||||
if (preset_name.empty()) {
|
||||
if (delete_current) {
|
||||
@ -3053,7 +3071,16 @@ void Tab::select_preset(std::string preset_name, bool delete_current)
|
||||
}
|
||||
|
||||
if (canceled) {
|
||||
if (m_type == Preset::TYPE_PRINTER) {
|
||||
if (!last_selected_ph_printer_name.empty() &&
|
||||
m_presets->get_edited_preset().name == PhysicalPrinter::get_preset_name(last_selected_ph_printer_name)) {
|
||||
// If preset selection was canceled and previously was selected physical printer, we should select it back
|
||||
m_preset_bundle->physical_printers.select_printer(last_selected_ph_printer_name);
|
||||
}
|
||||
}
|
||||
|
||||
update_tab_ui();
|
||||
|
||||
// Trigger the on_presets_changed event so that we also restore the previous value in the plater selector,
|
||||
// if this action was initiated from the plater.
|
||||
on_presets_changed();
|
||||
@ -3095,6 +3122,7 @@ void Tab::select_preset(std::string preset_name, bool delete_current)
|
||||
else if (printer_technology == ptSLA && m_dependent_tabs.front() != Preset::Type::TYPE_SLA_PRINT)
|
||||
m_dependent_tabs = { Preset::Type::TYPE_SLA_PRINT, Preset::Type::TYPE_SLA_MATERIAL };
|
||||
}
|
||||
|
||||
load_current_preset();
|
||||
}
|
||||
}
|
||||
@ -3234,56 +3262,10 @@ void Tab::save_preset(std::string name /*= ""*/, bool detach)
|
||||
std::string suffix = detach ? _utf8(L("Detached")) : _CTX_utf8(L_CONTEXT("Copy", "PresetName"), "PresetName");
|
||||
|
||||
if (name.empty()) {
|
||||
const Preset &preset = m_presets->get_selected_preset();
|
||||
auto default_name = preset.is_default ? "Untitled" :
|
||||
// preset.is_system ? (boost::format(_CTX_utf8(L_CONTEXT("%1% - Copy", "PresetName"), "PresetName")) % preset.name).str() :
|
||||
preset.is_system ? (boost::format(("%1% - %2%")) % preset.name % suffix).str() :
|
||||
preset.name;
|
||||
|
||||
bool have_extention = boost::iends_with(default_name, ".ini");
|
||||
if (have_extention) {
|
||||
size_t len = default_name.length()-4;
|
||||
default_name.resize(len);
|
||||
}
|
||||
//[map $_->name, grep !$_->default && !$_->external, @{$self->{presets}}],
|
||||
std::vector<std::string> values;
|
||||
for (size_t i = 0; i < m_presets->size(); ++i) {
|
||||
const Preset &preset = m_presets->preset(i);
|
||||
if (preset.is_default || preset.is_system || preset.is_external)
|
||||
continue;
|
||||
values.push_back(preset.name);
|
||||
}
|
||||
|
||||
SavePresetWindow dlg(parent());
|
||||
dlg.build(title(), default_name, values);
|
||||
SavePresetDialog dlg(m_type, suffix);
|
||||
if (dlg.ShowModal() != wxID_OK)
|
||||
return;
|
||||
name = dlg.get_name();
|
||||
if (name == "") {
|
||||
show_error(this, _(L("The supplied name is empty. It can't be saved.")));
|
||||
return;
|
||||
}
|
||||
const Preset *existing = m_presets->find_preset(name, false);
|
||||
if (existing && (existing->is_default || existing->is_system)) {
|
||||
show_error(this, _(L("Cannot overwrite a system profile.")));
|
||||
return;
|
||||
}
|
||||
if (existing && (existing->is_external)) {
|
||||
show_error(this, _(L("Cannot overwrite an external profile.")));
|
||||
return;
|
||||
}
|
||||
if (existing && name != preset.name)
|
||||
{
|
||||
wxString msg_text = GUI::from_u8((boost::format(_utf8(L("Preset with name \"%1%\" already exists."))) % name).str());
|
||||
msg_text += "\n" + _(L("Replace?"));
|
||||
wxMessageDialog dialog(nullptr, msg_text, _(L("Warning")), wxICON_WARNING | wxYES | wxNO);
|
||||
|
||||
if (dialog.ShowModal() == wxID_NO)
|
||||
return;
|
||||
|
||||
// Remove the preset from the list.
|
||||
m_presets->delete_preset(name);
|
||||
}
|
||||
}
|
||||
|
||||
// Save the preset into Slic3r::data_dir / presets / section_name / preset_name.ini
|
||||
@ -3345,13 +3327,70 @@ void Tab::delete_preset()
|
||||
// Don't let the user delete the ' - default - ' configuration.
|
||||
std::string action = current_preset.is_external ? _utf8(L("remove")) : _utf8(L("delete"));
|
||||
// TRN remove/delete
|
||||
const wxString msg = from_u8((boost::format(_utf8(L("Are you sure you want to %1% the selected preset?"))) % action).str());
|
||||
|
||||
PhysicalPrinterCollection& physical_printers = m_preset_bundle->physical_printers;
|
||||
wxString msg;
|
||||
if (m_presets_choice->is_selected_physical_printer())
|
||||
msg = from_u8((boost::format(_u8L("Are you sure you want to delete \"%1%\" preset from the physical printer \"%2%\"?"))
|
||||
% current_preset.name % physical_printers.get_selected_printer_name()).str());
|
||||
else
|
||||
{
|
||||
if (m_type == Preset::TYPE_PRINTER && !physical_printers.empty())
|
||||
{
|
||||
// Check preset for delete in physical printers
|
||||
// Ask a customer about next action, if there is a printer with just one preset and this preset is equal to delete
|
||||
std::vector<std::string> ph_printers = physical_printers.get_printers_with_preset(current_preset.name);
|
||||
std::vector<std::string> ph_printers_only = physical_printers.get_printers_with_only_preset(current_preset.name);
|
||||
|
||||
if (!ph_printers.empty()) {
|
||||
msg += _L("Next physical printer(s) has/have selected preset") + ":";
|
||||
for (const std::string& printer : ph_printers)
|
||||
msg += "\n \"" + from_u8(printer) + "\",";
|
||||
msg.RemoveLast();
|
||||
msg += "\n" + _L("Note, that selected preset will be deleted from this/those printer(s) too.")+ "\n\n";
|
||||
}
|
||||
|
||||
if (!ph_printers_only.empty()) {
|
||||
msg += _L("Next physical printer(s) has/have one and only selected preset") + ":";
|
||||
for (const std::string& printer : ph_printers_only)
|
||||
msg += "\n \"" + from_u8(printer) + "\",";
|
||||
msg.RemoveLast();
|
||||
msg += "\n" + _L("Note, that this/those printer(s) will be deleted after deleting of the selected preset.") + "\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
msg += from_u8((boost::format(_u8L("Are you sure you want to %1% the selected preset?")) % action).str());
|
||||
}
|
||||
|
||||
action = current_preset.is_external ? _utf8(L("Remove")) : _utf8(L("Delete"));
|
||||
// TRN Remove/Delete
|
||||
wxString title = from_u8((boost::format(_utf8(L("%1% Preset"))) % action).str()); //action + _(L(" Preset"));
|
||||
if (current_preset.is_default ||
|
||||
wxID_YES != wxMessageDialog(parent(), msg, title, wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION).ShowModal())
|
||||
return;
|
||||
|
||||
// if we just delete preset from the physical printer
|
||||
if (m_presets_choice->is_selected_physical_printer()) {
|
||||
PhysicalPrinter& printer = physical_printers.get_selected_printer();
|
||||
|
||||
if (printer.preset_names.size() == 1) {
|
||||
wxMessageDialog dialog(nullptr, _L("It's a last for this physical printer. We can't delete it"), _L("Information"), wxICON_INFORMATION | wxOK);
|
||||
dialog.ShowModal();
|
||||
return;
|
||||
}
|
||||
// just delete this preset from the current physical printer
|
||||
printer.delete_preset(m_presets->get_edited_preset().name);
|
||||
// select first from the possible presets for this printer
|
||||
physical_printers.select_printer(printer);
|
||||
|
||||
this->select_preset(physical_printers.get_selected_printer_preset_name());
|
||||
return;
|
||||
}
|
||||
|
||||
// delete selected preset from printers and printer, if it's needed
|
||||
if (m_type == Preset::TYPE_PRINTER && !physical_printers.empty())
|
||||
physical_printers.delete_preset_from_printers(current_preset.name);
|
||||
|
||||
// Select will handle of the preset dependencies, of saving & closing the depending profiles, and
|
||||
// finally of deleting the preset.
|
||||
this->select_preset("", true);
|
||||
@ -3360,6 +3399,7 @@ void Tab::delete_preset()
|
||||
void Tab::toggle_show_hide_incompatible()
|
||||
{
|
||||
m_show_incompatible_presets = !m_show_incompatible_presets;
|
||||
m_presets_choice->set_show_incompatible_presets(m_show_incompatible_presets);
|
||||
update_show_hide_incompatible_button();
|
||||
update_tab_ui();
|
||||
}
|
||||
|
@ -33,12 +33,14 @@
|
||||
#include "Event.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "ConfigManipulation.hpp"
|
||||
#include "Preset.hpp"
|
||||
#include "OptionsGroup.hpp"
|
||||
#include "libslic3r/Preset.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
class TabPresetComboBox;
|
||||
|
||||
// Single Tab page containing a{ vsizer } of{ optgroups }
|
||||
// package Slic3r::GUI::Tab::Page;
|
||||
using ConfigOptionsGroupShp = std::shared_ptr<ConfigOptionsGroup>;
|
||||
@ -113,10 +115,11 @@ protected:
|
||||
Preset::Type m_type;
|
||||
std::string m_name;
|
||||
const wxString m_title;
|
||||
PresetBitmapComboBox* m_presets_choice;
|
||||
TabPresetComboBox* m_presets_choice;
|
||||
ScalableButton* m_search_btn;
|
||||
ScalableButton* m_btn_save_preset;
|
||||
ScalableButton* m_btn_delete_preset;
|
||||
ScalableButton* m_btn_edit_ph_printer {nullptr};
|
||||
ScalableButton* m_btn_hide_incompatible_presets;
|
||||
wxBoxSizer* m_hsizer;
|
||||
wxBoxSizer* m_left_sizer;
|
||||
@ -206,8 +209,6 @@ protected:
|
||||
bool m_is_nonsys_values{ true };
|
||||
bool m_postpone_update_ui {false};
|
||||
|
||||
size_t m_selected_preset_item{ 0 };
|
||||
|
||||
void set_type();
|
||||
|
||||
int m_em_unit;
|
||||
@ -275,8 +276,10 @@ public:
|
||||
void load_current_preset();
|
||||
void rebuild_page_tree();
|
||||
void update_page_tree_visibility();
|
||||
// Select a new preset, possibly delete the current one.
|
||||
void select_preset(std::string preset_name = "", bool delete_current = false);
|
||||
void update_btns_enabling();
|
||||
void update_preset_choice();
|
||||
// Select a new preset, possibly delete the current one.
|
||||
void select_preset(std::string preset_name = "", bool delete_current = false, const std::string& last_selected_ph_printer_name = "");
|
||||
bool may_discard_current_dirty_preset(PresetCollection* presets = nullptr, const std::string& new_printer_name = "");
|
||||
bool may_switch_to_SLA_preset();
|
||||
|
||||
@ -320,7 +323,6 @@ public:
|
||||
|
||||
DynamicPrintConfig* get_config() { return m_config; }
|
||||
PresetCollection* get_presets() { return m_presets; }
|
||||
size_t get_selected_preset_item() { return m_selected_preset_item; }
|
||||
|
||||
void on_value_change(const std::string& opt_key, const boost::any& value);
|
||||
|
||||
|
@ -304,94 +304,6 @@ void wxCheckListBoxComboPopup::OnListBoxSelection(wxCommandEvent& evt)
|
||||
}
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
// *** PresetBitmapComboBox ***
|
||||
|
||||
/* For PresetBitmapComboBox we use bitmaps that are created from images that are already scaled appropriately for Retina
|
||||
* (Contrary to the intuition, the `scale` argument for Bitmap's constructor doesn't mean
|
||||
* "please scale this to such and such" but rather
|
||||
* "the wxImage is already sized for backing scale such and such". )
|
||||
* Unfortunately, the constructor changes the size of wxBitmap too.
|
||||
* Thus We need to use unscaled size value for bitmaps that we use
|
||||
* to avoid scaled size of control items.
|
||||
* For this purpose control drawing methods and
|
||||
* control size calculation methods (virtual) are overridden.
|
||||
**/
|
||||
|
||||
PresetBitmapComboBox::PresetBitmapComboBox(wxWindow* parent, const wxSize& size) :
|
||||
wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, size, 0, nullptr, wxCB_READONLY)
|
||||
{}
|
||||
|
||||
#ifdef __APPLE__
|
||||
bool PresetBitmapComboBox::OnAddBitmap(const wxBitmap& bitmap)
|
||||
{
|
||||
if (bitmap.IsOk())
|
||||
{
|
||||
// we should use scaled! size values of bitmap
|
||||
int width = (int)bitmap.GetScaledWidth();
|
||||
int height = (int)bitmap.GetScaledHeight();
|
||||
|
||||
if (m_usedImgSize.x < 0)
|
||||
{
|
||||
// If size not yet determined, get it from this image.
|
||||
m_usedImgSize.x = width;
|
||||
m_usedImgSize.y = height;
|
||||
|
||||
// Adjust control size to vertically fit the bitmap
|
||||
wxWindow* ctrl = GetControl();
|
||||
ctrl->InvalidateBestSize();
|
||||
wxSize newSz = ctrl->GetBestSize();
|
||||
wxSize sz = ctrl->GetSize();
|
||||
if (newSz.y > sz.y)
|
||||
ctrl->SetSize(sz.x, newSz.y);
|
||||
else
|
||||
DetermineIndent();
|
||||
}
|
||||
|
||||
wxCHECK_MSG(width == m_usedImgSize.x && height == m_usedImgSize.y,
|
||||
false,
|
||||
"you can only add images of same size");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void PresetBitmapComboBox::OnDrawItem(wxDC& dc,
|
||||
const wxRect& rect,
|
||||
int item,
|
||||
int flags) const
|
||||
{
|
||||
const wxBitmap& bmp = *(wxBitmap*)m_bitmaps[item];
|
||||
if (bmp.IsOk())
|
||||
{
|
||||
// we should use scaled! size values of bitmap
|
||||
wxCoord w = bmp.GetScaledWidth();
|
||||
wxCoord h = bmp.GetScaledHeight();
|
||||
|
||||
const int imgSpacingLeft = 4;
|
||||
|
||||
// Draw the image centered
|
||||
dc.DrawBitmap(bmp,
|
||||
rect.x + (m_usedImgSize.x - w) / 2 + imgSpacingLeft,
|
||||
rect.y + (rect.height - h) / 2,
|
||||
true);
|
||||
}
|
||||
|
||||
wxString text = GetString(item);
|
||||
if (!text.empty())
|
||||
dc.DrawText(text,
|
||||
rect.x + m_imgAreaWidth + 1,
|
||||
rect.y + (rect.height - dc.GetCharHeight()) / 2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// *** wxDataViewTreeCtrlComboPopup ***
|
||||
|
||||
const unsigned int wxDataViewTreeCtrlComboPopup::DefaultWidth = 270;
|
||||
@ -823,11 +735,12 @@ void MenuWithSeparators::SetSecondSeparator()
|
||||
// ----------------------------------------------------------------------------
|
||||
ScalableBitmap::ScalableBitmap( wxWindow *parent,
|
||||
const std::string& icon_name/* = ""*/,
|
||||
const int px_cnt/* = 16*/):
|
||||
const int px_cnt/* = 16*/,
|
||||
const bool grayscale/* = false*/):
|
||||
m_parent(parent), m_icon_name(icon_name),
|
||||
m_px_cnt(px_cnt)
|
||||
{
|
||||
m_bmp = create_scaled_bitmap(icon_name, parent, px_cnt);
|
||||
m_bmp = create_scaled_bitmap(icon_name, parent, px_cnt, grayscale);
|
||||
}
|
||||
|
||||
wxSize ScalableBitmap::GetBmpSize() const
|
||||
@ -860,7 +773,7 @@ int ScalableBitmap::GetBmpHeight() const
|
||||
|
||||
void ScalableBitmap::msw_rescale()
|
||||
{
|
||||
m_bmp = create_scaled_bitmap(m_icon_name, m_parent, m_px_cnt);
|
||||
m_bmp = create_scaled_bitmap(m_icon_name, m_parent, m_px_cnt, m_grayscale);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -94,37 +94,6 @@ public:
|
||||
void OnListBoxSelection(wxCommandEvent& evt);
|
||||
};
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
// *** PresetBitmapComboBox ***
|
||||
|
||||
// BitmapComboBox used to presets list on Sidebar and Tabs
|
||||
class PresetBitmapComboBox: public wxBitmapComboBox
|
||||
{
|
||||
public:
|
||||
PresetBitmapComboBox(wxWindow* parent, const wxSize& size = wxDefaultSize);
|
||||
~PresetBitmapComboBox() {}
|
||||
|
||||
#ifdef __APPLE__
|
||||
protected:
|
||||
/* For PresetBitmapComboBox we use bitmaps that are created from images that are already scaled appropriately for Retina
|
||||
* (Contrary to the intuition, the `scale` argument for Bitmap's constructor doesn't mean
|
||||
* "please scale this to such and such" but rather
|
||||
* "the wxImage is already sized for backing scale such and such". )
|
||||
* Unfortunately, the constructor changes the size of wxBitmap too.
|
||||
* Thus We need to use unscaled size value for bitmaps that we use
|
||||
* to avoid scaled size of control items.
|
||||
* For this purpose control drawing methods and
|
||||
* control size calculation methods (virtual) are overridden.
|
||||
**/
|
||||
virtual bool OnAddBitmap(const wxBitmap& bitmap) override;
|
||||
virtual void OnDrawItem(wxDC& dc, const wxRect& rect, int item, int flags) const override;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// *** wxDataViewTreeCtrlComboBox ***
|
||||
|
||||
@ -160,7 +129,8 @@ public:
|
||||
ScalableBitmap() {};
|
||||
ScalableBitmap( wxWindow *parent,
|
||||
const std::string& icon_name = "",
|
||||
const int px_cnt = 16);
|
||||
const int px_cnt = 16,
|
||||
const bool grayscale = false);
|
||||
|
||||
~ScalableBitmap() {}
|
||||
|
||||
@ -181,6 +151,7 @@ private:
|
||||
wxBitmap m_bmp = wxBitmap();
|
||||
std::string m_icon_name = "";
|
||||
int m_px_cnt {16};
|
||||
bool m_grayscale {false};
|
||||
};
|
||||
|
||||
|
||||
|
@ -30,10 +30,10 @@
|
||||
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/Format/3mf.hpp"
|
||||
#include "../GUI/GUI.hpp"
|
||||
#include "../GUI/I18N.hpp"
|
||||
#include "../GUI/PresetBundle.hpp"
|
||||
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/progdlg.h>
|
||||
|
@ -19,9 +19,9 @@
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/format.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
#include "slic3r/GUI/PresetBundle.hpp"
|
||||
#include "slic3r/GUI/UpdateDialogs.hpp"
|
||||
#include "slic3r/GUI/ConfigWizard.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include "libslic3r/Format/OBJ.hpp"
|
||||
#include "libslic3r/Format/PRUS.hpp"
|
||||
#include "libslic3r/Format/STL.hpp"
|
||||
#include "slic3r/GUI/PresetBundle.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
%}
|
||||
|
||||
%name{Slic3r::Model} class Model {
|
||||
|
Loading…
Reference in New Issue
Block a user