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