1 #include "step_export_window.hpp"
2 #include "export_step/export_step.hpp"
3 #include "board/step_export_settings.hpp"
4 #include "util/util.hpp"
5 #include "util/gtk_util.hpp"
6 #include "document/idocument_board.hpp"
7 #include <thread>
8 
9 namespace horizon {
10 
prepare_chooser(Glib::RefPtr<Gtk::FileChooser> chooser)11 void StepExportWindow::MyExportFileChooser::prepare_chooser(Glib::RefPtr<Gtk::FileChooser> chooser)
12 {
13     auto filter = Gtk::FileFilter::create();
14     filter->set_name("STEP models");
15     filter->add_pattern("*.step");
16     filter->add_pattern("*.stp");
17     chooser->add_filter(filter);
18 }
19 
prepare_filename(std::string & filename)20 void StepExportWindow::MyExportFileChooser::prepare_filename(std::string &filename)
21 {
22     if (!endswith(filename, ".step") && !endswith(filename, ".stp")) {
23         filename += ".step";
24     }
25 }
26 
create(Gtk::Window * p,IDocumentBoard & c,const std::string & project_dir)27 StepExportWindow *StepExportWindow::create(Gtk::Window *p, IDocumentBoard &c, const std::string &project_dir)
28 {
29     StepExportWindow *w;
30     Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create();
31     x->add_from_resource("/org/horizon-eda/horizon/imp/step_export.ui");
32     x->get_widget_derived("window", w, c, project_dir);
33     w->set_transient_for(*p);
34     return w;
35 }
36 
StepExportWindow(BaseObjectType * cobject,const Glib::RefPtr<Gtk::Builder> & x,IDocumentBoard & c,const std::string & project_dir)37 StepExportWindow::StepExportWindow(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &x, IDocumentBoard &c,
38                                    const std::string &project_dir)
39     : Gtk::Window(cobject), core(c), settings(core.get_step_export_settings())
40 {
41     set_modal(true);
42     GET_WIDGET(header);
43     GET_WIDGET(spinner);
44     GET_WIDGET(export_button);
45     GET_WIDGET(filename_button);
46     GET_WIDGET(filename_entry);
47     GET_WIDGET(prefix_entry);
48     GET_WIDGET(log_textview);
49     GET_WIDGET(include_3d_models_switch);
50 
51     export_button->signal_clicked().connect(sigc::mem_fun(*this, &StepExportWindow::generate));
52 
53     export_filechooser.attach(filename_entry, filename_button, this);
54     export_filechooser.set_project_dir(project_dir);
55     export_filechooser.bind_filename(settings.filename);
56     export_filechooser.signal_changed().connect([this] {
57         s_signal_changed.emit();
58         update_export_button();
59     });
60 
61     bind_widget(include_3d_models_switch, settings.include_3d_models);
62     bind_widget(prefix_entry, settings.prefix);
63 
64     include_3d_models_switch->property_active().signal_changed().connect([this] { s_signal_changed.emit(); });
65     prefix_entry->signal_changed().connect([this] { s_signal_changed.emit(); });
66 
67     tag = log_textview->get_buffer()->create_tag();
68     tag->property_font_features() = "tnum 1";
69     tag->property_font_features_set() = true;
70 
71 
72     export_dispatcher.connect([this] {
73         std::lock_guard<std::mutex> guard(msg_queue_mutex);
74         auto buffer = log_textview->get_buffer();
75         while (msg_queue.size()) {
76             const std::string &msg = msg_queue.front();
77             buffer->insert(buffer->end(), msg + "\n");
78             auto adj = log_textview->get_vadjustment();
79             adj->set_value(adj->get_upper());
80             msg_queue.pop_front();
81         }
82         {
83             Gtk::TextIter ibegin, iend;
84             buffer->get_bounds(ibegin, iend);
85             buffer->remove_all_tags(ibegin, iend);
86             buffer->apply_tag(tag, ibegin, iend);
87         }
88         if (export_running == false)
89             set_is_busy(false);
90     });
91     update_export_button();
92 }
93 
generate()94 void StepExportWindow::generate()
95 {
96     if (export_running)
97         return;
98     if (settings.filename.size() == 0)
99         return;
100     set_is_busy(true);
101     log_textview->get_buffer()->set_text("");
102     msg_queue.clear();
103     export_running = true;
104     STEPExportSettings my_settings = settings;
105     my_settings.filename = export_filechooser.get_filename_abs();
106     std::thread thr(&StepExportWindow::export_thread, this, my_settings);
107     thr.detach();
108 }
109 
export_thread(STEPExportSettings my_settings)110 void StepExportWindow::export_thread(STEPExportSettings my_settings)
111 {
112     try {
113         export_step(
114                 my_settings.filename, *core.get_board(), core.get_pool(), my_settings.include_3d_models,
115                 [this](const std::string &msg) {
116                     {
117                         std::lock_guard<std::mutex> guard(msg_queue_mutex);
118                         msg_queue.push_back(msg);
119                     }
120                     export_dispatcher.emit();
121                 },
122                 &core.get_colors(), my_settings.prefix);
123     }
124     catch (const std::exception &e) {
125         {
126             std::lock_guard<std::mutex> guard(msg_queue_mutex);
127             msg_queue.push_back(std::string("Error: ") + e.what());
128         }
129         export_dispatcher.emit();
130     }
131     catch (...) {
132         {
133             std::lock_guard<std::mutex> guard(msg_queue_mutex);
134             msg_queue.push_back("Error: unknown error");
135         }
136         export_dispatcher.emit();
137     }
138 
139     export_running = false;
140     export_dispatcher.emit();
141 }
142 
set_can_export(bool v)143 void StepExportWindow::set_can_export(bool v)
144 {
145     can_export = v;
146     update_export_button();
147 }
148 
update_export_button()149 void StepExportWindow::update_export_button()
150 {
151     std::string txt;
152     if (!export_running) {
153         if (settings.filename.size() == 0) {
154             txt = "output filename not set";
155         }
156     }
157     else {
158         txt = "busy";
159     }
160     widget_set_insensitive_tooltip(*export_button, txt);
161 }
162 
set_is_busy(bool v)163 void StepExportWindow::set_is_busy(bool v)
164 {
165     update_export_button();
166     spinner->property_active() = v;
167     header->set_show_close_button(!v);
168 }
169 
170 } // namespace horizon
171