2018-06-19 15:43:59 +00:00
|
|
|
#ifndef APPCONTROLLER_HPP
|
|
|
|
#define APPCONTROLLER_HPP
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
#include <memory>
|
2018-06-25 15:13:36 +00:00
|
|
|
#include <atomic>
|
2018-06-25 10:40:01 +00:00
|
|
|
#include <iostream>
|
2018-06-25 15:13:36 +00:00
|
|
|
|
2018-09-12 11:17:47 +00:00
|
|
|
#include "GUI/ProgressIndicator.hpp"
|
|
|
|
|
|
|
|
#include <PrintConfig.hpp>
|
2018-06-19 15:43:59 +00:00
|
|
|
|
|
|
|
namespace Slic3r {
|
|
|
|
|
|
|
|
class Model;
|
|
|
|
class Print;
|
|
|
|
class PrintObject;
|
2018-06-29 15:46:21 +00:00
|
|
|
class PrintConfig;
|
2018-08-30 09:40:06 +00:00
|
|
|
class ProgressStatusBar;
|
2018-09-17 13:12:13 +00:00
|
|
|
class DynamicPrintConfig;
|
2018-06-19 15:43:59 +00:00
|
|
|
|
2018-09-19 16:02:04 +00:00
|
|
|
/// A Progress indicator object smart pointer
|
|
|
|
using ProgresIndicatorPtr = std::shared_ptr<ProgressIndicator>;
|
|
|
|
|
|
|
|
using FilePath = std::string;
|
|
|
|
using FilePathList = std::vector<FilePath>;
|
|
|
|
|
|
|
|
/// Common runtime issue types
|
|
|
|
enum class IssueType {
|
|
|
|
INFO,
|
|
|
|
WARN,
|
|
|
|
WARN_Q, // Warning with a question to continue
|
|
|
|
ERR,
|
|
|
|
FATAL
|
|
|
|
};
|
|
|
|
|
2018-06-26 15:02:46 +00:00
|
|
|
/**
|
|
|
|
* @brief A boilerplate class for creating application logic. It should provide
|
2018-06-27 08:28:44 +00:00
|
|
|
* features as issue reporting and progress indication, etc...
|
2018-06-26 15:02:46 +00:00
|
|
|
*
|
2018-06-27 08:28:44 +00:00
|
|
|
* The lower lever UI independent classes can be manipulated with a subclass
|
2018-06-26 15:02:46 +00:00
|
|
|
* of this controller class. We can also catch any exceptions that lower level
|
|
|
|
* methods could throw and display appropriate errors and warnings.
|
|
|
|
*
|
2018-06-27 08:28:44 +00:00
|
|
|
* Note that the outer and the inner interface of this class is free from any
|
|
|
|
* UI toolkit dependencies. We can implement it with any UI framework or make it
|
|
|
|
* a cli client.
|
2018-06-26 15:02:46 +00:00
|
|
|
*/
|
2018-09-19 16:02:04 +00:00
|
|
|
class AppControllerBase {
|
2018-06-19 15:43:59 +00:00
|
|
|
public:
|
|
|
|
|
2018-09-19 16:02:04 +00:00
|
|
|
using Ptr = std::shared_ptr<AppControllerBase>;
|
2018-06-25 15:13:36 +00:00
|
|
|
|
2018-09-19 16:02:04 +00:00
|
|
|
inline virtual ~AppControllerBase() {}
|
2018-06-19 15:43:59 +00:00
|
|
|
|
2018-06-26 15:02:46 +00:00
|
|
|
/**
|
|
|
|
* @brief Query some paths from the user.
|
|
|
|
*
|
|
|
|
* It should display a file chooser dialog in case of a UI application.
|
|
|
|
* @param title Title of a possible query dialog.
|
|
|
|
* @param extensions Recognized file extensions.
|
2018-09-19 12:54:37 +00:00
|
|
|
* @return Returns a list of paths chosen by the user.
|
2018-06-26 15:02:46 +00:00
|
|
|
*/
|
2018-09-19 16:02:04 +00:00
|
|
|
virtual FilePathList query_destination_paths(
|
2018-09-17 13:12:13 +00:00
|
|
|
const std::string& title,
|
2018-09-19 16:02:04 +00:00
|
|
|
const std::string& extensions,
|
|
|
|
const std::string& functionid = "",
|
|
|
|
const std::string& hint = "") const = 0;
|
2018-06-19 15:43:59 +00:00
|
|
|
|
2018-06-26 15:02:46 +00:00
|
|
|
/**
|
|
|
|
* @brief Same as query_destination_paths but works for directories only.
|
|
|
|
*/
|
2018-09-19 16:02:04 +00:00
|
|
|
virtual FilePathList query_destination_dirs(
|
|
|
|
const std::string& title,
|
|
|
|
const std::string& functionid = "",
|
|
|
|
const std::string& hint = "") const = 0;
|
2018-06-19 15:43:59 +00:00
|
|
|
|
2018-06-26 15:02:46 +00:00
|
|
|
/**
|
2018-06-27 08:28:44 +00:00
|
|
|
* @brief Same as query_destination_paths but returns only one path.
|
2018-06-26 15:02:46 +00:00
|
|
|
*/
|
2018-09-19 16:02:04 +00:00
|
|
|
virtual FilePath query_destination_path(
|
2018-09-17 13:12:13 +00:00
|
|
|
const std::string& title,
|
2018-06-25 11:24:37 +00:00
|
|
|
const std::string& extensions,
|
2018-09-19 16:02:04 +00:00
|
|
|
const std::string& functionid = "",
|
|
|
|
const std::string& hint = "") const = 0;
|
2018-06-19 15:43:59 +00:00
|
|
|
|
2018-06-26 15:02:46 +00:00
|
|
|
/**
|
|
|
|
* @brief Report an issue to the user be it fatal or recoverable.
|
|
|
|
*
|
|
|
|
* In a UI app this should display some message dialog.
|
|
|
|
*
|
|
|
|
* @param issuetype The type of the runtime issue.
|
|
|
|
* @param description A somewhat longer description of the issue.
|
|
|
|
* @param brief A very brief description. Can be used for message dialog
|
|
|
|
* title.
|
|
|
|
*/
|
2018-09-19 16:02:04 +00:00
|
|
|
virtual bool report_issue(IssueType issuetype,
|
|
|
|
const std::string& description,
|
|
|
|
const std::string& brief) = 0;
|
2018-06-19 15:43:59 +00:00
|
|
|
|
2018-06-26 15:02:46 +00:00
|
|
|
/**
|
2018-07-03 10:43:17 +00:00
|
|
|
* @brief Return the global progress indicator for the current controller.
|
|
|
|
* Can be empty as well.
|
|
|
|
*
|
|
|
|
* Only one thread should use the global indicator at a time.
|
2018-06-26 15:02:46 +00:00
|
|
|
*/
|
2018-09-19 16:02:04 +00:00
|
|
|
virtual ProgresIndicatorPtr global_progress_indicator() = 0;
|
2018-06-19 15:43:59 +00:00
|
|
|
|
2018-09-19 16:02:04 +00:00
|
|
|
virtual void global_progress_indicator(ProgresIndicatorPtr gpri) = 0;
|
2018-06-19 15:43:59 +00:00
|
|
|
|
2018-06-26 15:02:46 +00:00
|
|
|
/**
|
|
|
|
* @brief A predicate telling the caller whether it is the thread that
|
|
|
|
* created the AppConroller object itself. This probably means that the
|
|
|
|
* execution is in the UI thread. Otherwise it returns false meaning that
|
|
|
|
* some worker thread called this function.
|
2018-06-27 08:28:44 +00:00
|
|
|
* @return Return true for the same caller thread that created this
|
2018-06-26 15:02:46 +00:00
|
|
|
* object and false for every other.
|
|
|
|
*/
|
2018-09-19 16:02:04 +00:00
|
|
|
virtual bool is_main_thread() const = 0;
|
2018-06-26 13:51:47 +00:00
|
|
|
|
2018-06-27 16:23:53 +00:00
|
|
|
/**
|
|
|
|
* @brief The frontend supports asynch execution.
|
|
|
|
*
|
|
|
|
* A Graphic UI will support this, a CLI may not. This can be used in
|
|
|
|
* subclass methods to decide whether to start threads for block free UI.
|
|
|
|
*
|
|
|
|
* Note that even a progress indicator's update called regularly can solve
|
|
|
|
* the blocking UI problem in some cases even when an event loop is present.
|
|
|
|
* This is how wxWidgets gauge work but creating a separate thread will make
|
|
|
|
* the UI even more fluent.
|
|
|
|
*
|
|
|
|
* @return true if a job or method can be executed asynchronously, false
|
|
|
|
* otherwise.
|
|
|
|
*/
|
2018-09-19 16:02:04 +00:00
|
|
|
virtual bool supports_asynch() const = 0;
|
2018-06-27 16:23:53 +00:00
|
|
|
|
2018-09-19 16:02:04 +00:00
|
|
|
virtual void process_events() = 0;
|
2018-06-20 12:50:18 +00:00
|
|
|
|
2018-06-26 15:02:46 +00:00
|
|
|
/**
|
2018-06-27 08:28:44 +00:00
|
|
|
* @brief Create a new progress indicator and return a smart pointer to it.
|
2018-06-26 15:02:46 +00:00
|
|
|
* @param statenum The number of states for the given procedure.
|
|
|
|
* @param title The title of the procedure.
|
|
|
|
* @param firstmsg The message for the first subtask to be displayed.
|
|
|
|
* @return Smart pointer to the created object.
|
|
|
|
*/
|
2018-09-19 16:02:04 +00:00
|
|
|
virtual ProgresIndicatorPtr create_progress_indicator(
|
2018-06-20 12:50:18 +00:00
|
|
|
unsigned statenum,
|
2018-09-17 13:12:13 +00:00
|
|
|
const std::string& title,
|
2018-09-19 16:02:04 +00:00
|
|
|
const std::string& firstmsg = "") const = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Implementation of AppControllerBase for the GUI app
|
|
|
|
*/
|
|
|
|
class AppControllerGui: public AppControllerBase {
|
|
|
|
private:
|
|
|
|
class PriData; // Some structure to store progress indication data
|
|
|
|
|
|
|
|
// Pimpl data for thread safe progress indication features
|
|
|
|
std::unique_ptr<PriData> m_pri_data;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
AppControllerGui();
|
|
|
|
|
|
|
|
virtual ~AppControllerGui();
|
|
|
|
|
|
|
|
virtual FilePathList query_destination_paths(
|
|
|
|
const std::string& title,
|
|
|
|
const std::string& extensions,
|
|
|
|
const std::string& functionid,
|
|
|
|
const std::string& hint) const override;
|
|
|
|
|
|
|
|
virtual FilePathList query_destination_dirs(
|
|
|
|
const std::string& /*title*/,
|
|
|
|
const std::string& /*functionid*/,
|
|
|
|
const std::string& /*hint*/) const override { return {}; }
|
|
|
|
|
|
|
|
virtual FilePath query_destination_path(
|
|
|
|
const std::string& title,
|
|
|
|
const std::string& extensions,
|
|
|
|
const std::string& functionid,
|
|
|
|
const std::string& hint) const override;
|
|
|
|
|
|
|
|
virtual bool report_issue(IssueType issuetype,
|
|
|
|
const std::string& description,
|
|
|
|
const std::string& brief = std::string()) override;
|
|
|
|
|
|
|
|
virtual ProgresIndicatorPtr global_progress_indicator() override;
|
|
|
|
|
|
|
|
virtual void global_progress_indicator(ProgresIndicatorPtr gpri) override;
|
2018-07-02 14:15:21 +00:00
|
|
|
|
2018-09-19 16:02:04 +00:00
|
|
|
virtual bool is_main_thread() const override;
|
|
|
|
|
|
|
|
virtual bool supports_asynch() const override;
|
|
|
|
|
|
|
|
virtual void process_events() override;
|
|
|
|
|
|
|
|
virtual ProgresIndicatorPtr create_progress_indicator(
|
2018-07-02 14:15:21 +00:00
|
|
|
unsigned statenum,
|
2018-09-19 16:02:04 +00:00
|
|
|
const std::string& title,
|
|
|
|
const std::string& firstmsg) const override;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
// This is a global progress indicator placeholder. In the Slic3r UI it can
|
|
|
|
// contain the progress indicator on the statusbar.
|
|
|
|
ProgresIndicatorPtr m_global_progressind;
|
|
|
|
};
|
|
|
|
|
|
|
|
class AppControllerCli: public AppControllerBase {
|
|
|
|
|
|
|
|
class CliProgress : public ProgressIndicator {
|
|
|
|
std::string m_msg, m_title;
|
|
|
|
public:
|
|
|
|
virtual void message(const std::string& msg) override {
|
|
|
|
m_msg = msg;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void title(const std::string& title) override {
|
|
|
|
m_title = title;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
AppControllerCli() {
|
|
|
|
std::cout << "Cli AppController ready..." << std::endl;
|
|
|
|
m_global_progressind = std::make_shared<CliProgress>();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~AppControllerCli() {}
|
|
|
|
|
|
|
|
virtual FilePathList query_destination_paths(
|
|
|
|
const std::string& /*title*/,
|
|
|
|
const std::string& /*extensions*/,
|
|
|
|
const std::string& /*functionid*/,
|
|
|
|
const std::string& /*hint*/) const override { return {}; }
|
|
|
|
|
|
|
|
virtual FilePathList query_destination_dirs(
|
|
|
|
const std::string& /*title*/,
|
|
|
|
const std::string& /*functionid*/,
|
|
|
|
const std::string& /*hint*/) const override { return {}; }
|
|
|
|
|
|
|
|
virtual FilePath query_destination_path(
|
|
|
|
const std::string& /*title*/,
|
|
|
|
const std::string& /*extensions*/,
|
|
|
|
const std::string& /*functionid*/,
|
|
|
|
const std::string& /*hint*/) const override { return "out.zip"; }
|
|
|
|
|
|
|
|
virtual bool report_issue(IssueType /*issuetype*/,
|
|
|
|
const std::string& description,
|
|
|
|
const std::string& brief) override {
|
|
|
|
std::cerr << brief << ": " << description << std::endl;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ProgresIndicatorPtr global_progress_indicator() override {
|
|
|
|
return m_global_progressind;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void global_progress_indicator(ProgresIndicatorPtr) override {}
|
|
|
|
|
|
|
|
virtual bool is_main_thread() const override { return true; }
|
|
|
|
|
|
|
|
virtual bool supports_asynch() const override { return false; }
|
|
|
|
|
|
|
|
virtual void process_events() override {}
|
|
|
|
|
|
|
|
virtual ProgresIndicatorPtr create_progress_indicator(
|
|
|
|
unsigned /*statenum*/,
|
|
|
|
const std::string& /*title*/,
|
|
|
|
const std::string& /*firstmsg*/) const override {
|
|
|
|
return std::make_shared<CliProgress>();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
2018-06-20 12:50:18 +00:00
|
|
|
|
2018-06-27 08:28:44 +00:00
|
|
|
// This is a global progress indicator placeholder. In the Slic3r UI it can
|
|
|
|
// contain the progress indicator on the statusbar.
|
2018-09-19 12:54:37 +00:00
|
|
|
ProgresIndicatorPtr m_global_progressind;
|
2018-06-19 15:43:59 +00:00
|
|
|
};
|
|
|
|
|
2018-09-19 11:43:15 +00:00
|
|
|
class Zipper {
|
|
|
|
struct Impl;
|
|
|
|
std::unique_ptr<Impl> m_impl;
|
|
|
|
public:
|
|
|
|
|
|
|
|
Zipper(const std::string& zipfilepath);
|
|
|
|
~Zipper();
|
|
|
|
|
|
|
|
void next_entry(const std::string& fname);
|
|
|
|
|
|
|
|
std::string get_name() const;
|
|
|
|
|
|
|
|
std::ostream& stream();
|
|
|
|
|
|
|
|
void close();
|
|
|
|
};
|
|
|
|
|
2018-06-26 15:02:46 +00:00
|
|
|
/**
|
|
|
|
* @brief Implementation of the printing logic.
|
|
|
|
*/
|
2018-09-19 16:02:04 +00:00
|
|
|
class PrintController {
|
2018-09-19 12:54:37 +00:00
|
|
|
Print *m_print = nullptr;
|
|
|
|
std::function<void()> m_rempools;
|
2018-09-19 09:08:10 +00:00
|
|
|
protected:
|
|
|
|
|
|
|
|
// Data structure with the png export input data
|
|
|
|
struct PngExportData {
|
|
|
|
std::string zippath; // output zip file
|
|
|
|
unsigned long width_px = 1440; // resolution - rows
|
|
|
|
unsigned long height_px = 2560; // resolution columns
|
|
|
|
double width_mm = 68.0, height_mm = 120.0; // dimensions in mm
|
|
|
|
double exp_time_first_s = 35.0; // first exposure time
|
|
|
|
double exp_time_s = 8.0; // global exposure time
|
|
|
|
double corr_x = 1.0; // offsetting in x
|
|
|
|
double corr_y = 1.0; // offsetting in y
|
|
|
|
double corr_z = 1.0; // offsetting in y
|
|
|
|
};
|
|
|
|
|
|
|
|
// Should display a dialog with the input fields for printing to png
|
|
|
|
PngExportData query_png_export_data(const DynamicPrintConfig&);
|
|
|
|
|
|
|
|
// The previous export data, to pre-populate the dialog
|
2018-09-19 12:54:37 +00:00
|
|
|
PngExportData m_prev_expdata;
|
2018-09-19 09:08:10 +00:00
|
|
|
|
|
|
|
void slice(ProgresIndicatorPtr pri);
|
|
|
|
|
2018-06-19 15:43:59 +00:00
|
|
|
public:
|
|
|
|
|
2018-06-26 15:02:46 +00:00
|
|
|
// Must be public for perl to use it
|
2018-09-19 12:54:37 +00:00
|
|
|
explicit inline PrintController(Print *print): m_print(print) {}
|
2018-06-20 12:50:18 +00:00
|
|
|
|
2018-06-26 15:02:46 +00:00
|
|
|
PrintController(const PrintController&) = delete;
|
|
|
|
PrintController(PrintController&&) = delete;
|
|
|
|
|
|
|
|
using Ptr = std::unique_ptr<PrintController>;
|
|
|
|
|
2018-06-20 12:50:18 +00:00
|
|
|
inline static Ptr create(Print *print) {
|
2018-06-26 14:08:58 +00:00
|
|
|
return PrintController::Ptr( new PrintController(print) );
|
2018-06-20 12:50:18 +00:00
|
|
|
}
|
2018-06-19 15:43:59 +00:00
|
|
|
|
2018-09-19 09:08:10 +00:00
|
|
|
/**
|
|
|
|
* @brief Slice the loaded print scene.
|
|
|
|
*/
|
|
|
|
void slice();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Slice the print into zipped png files.
|
|
|
|
*/
|
|
|
|
void slice_to_png();
|
2018-06-27 15:43:54 +00:00
|
|
|
|
2018-06-29 15:46:21 +00:00
|
|
|
const PrintConfig& config() const;
|
2018-06-20 12:50:18 +00:00
|
|
|
};
|
|
|
|
|
2018-06-26 15:02:46 +00:00
|
|
|
/**
|
|
|
|
* @brief Top level controller.
|
|
|
|
*/
|
2018-09-19 16:02:04 +00:00
|
|
|
class AppController {
|
2018-09-19 12:54:37 +00:00
|
|
|
Model *m_model = nullptr;
|
2018-06-20 12:50:18 +00:00
|
|
|
PrintController::Ptr printctl;
|
2018-09-19 12:54:37 +00:00
|
|
|
std::atomic<bool> m_arranging;
|
2018-06-20 12:50:18 +00:00
|
|
|
public:
|
|
|
|
|
2018-06-26 15:02:46 +00:00
|
|
|
/**
|
|
|
|
* @brief Get the print controller object.
|
|
|
|
*
|
|
|
|
* @return Return a raw pointer instead of a smart one for perl to be able
|
|
|
|
* to use this function and access the print controller.
|
|
|
|
*/
|
2018-06-20 12:50:18 +00:00
|
|
|
PrintController * print_ctl() { return printctl.get(); }
|
|
|
|
|
2018-06-26 15:02:46 +00:00
|
|
|
/**
|
|
|
|
* @brief Set a model object.
|
|
|
|
*
|
|
|
|
* @param model A raw pointer to the model object. This can be used from
|
|
|
|
* perl.
|
|
|
|
*/
|
2018-09-19 12:54:37 +00:00
|
|
|
void set_model(Model *model) { m_model = model; }
|
2018-06-19 15:43:59 +00:00
|
|
|
|
2018-06-26 15:02:46 +00:00
|
|
|
/**
|
|
|
|
* @brief Set the print object from perl.
|
|
|
|
*
|
|
|
|
* This will create a print controller that will then be accessible from
|
|
|
|
* perl.
|
|
|
|
* @param print A print object which can be a perl-ish extension as well.
|
|
|
|
*/
|
2018-06-20 12:50:18 +00:00
|
|
|
void set_print(Print *print) {
|
|
|
|
printctl = PrintController::create(print);
|
|
|
|
}
|
2018-06-19 15:43:59 +00:00
|
|
|
|
2018-06-26 15:02:46 +00:00
|
|
|
/**
|
|
|
|
* @brief Set up a global progress indicator.
|
|
|
|
*
|
|
|
|
* In perl we have a progress indicating status bar on the bottom of the
|
|
|
|
* window which is defined and created in perl. We can pass the ID-s of the
|
|
|
|
* gauge and the statusbar id and make a wrapper implementation of the
|
2018-09-17 13:12:13 +00:00
|
|
|
* ProgressIndicator interface so we can use this GUI widget from C++.
|
2018-06-26 15:02:46 +00:00
|
|
|
*
|
|
|
|
* This function should be called from perl.
|
|
|
|
*
|
|
|
|
* @param gauge_id The ID of the gague widget of the status bar.
|
|
|
|
* @param statusbar_id The ID of the status bar.
|
|
|
|
*/
|
2018-08-30 09:40:06 +00:00
|
|
|
void set_global_progress_indicator(ProgressStatusBar *prs);
|
2018-06-28 16:47:18 +00:00
|
|
|
|
|
|
|
void arrange_model();
|
2018-06-19 15:43:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // APPCONTROLLER_HPP
|