e273813615b865f617e6af2a8d56f00f1514f9ce
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / preferencesthread.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2011 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "aboutprefs.h"
23 #include "appearanceprefs.h"
24 #include "asset.h"
25 #include "audiodevice.inc"
26 #include "bcsignals.h"
27 #include "bctrace.h"
28 #include "cache.h"
29 #include "cplayback.h"
30 #include "cwindow.h"
31 #include "cwindowgui.h"
32 #include "bchash.h"
33 #include "edl.h"
34 #include "edlsession.h"
35 #include "file.h"
36 #include "filesystem.h"
37 #include "fonts.h"
38 #include "interfaceprefs.h"
39 #include "keys.h"
40 #include "language.h"
41 #include "levelwindow.h"
42 #include "levelwindowgui.h"
43 #include "mainclock.h"
44 #include "mainerror.h"
45 #include "mbuttons.h"
46 #include "meterpanel.h"
47 #include "mutex.h"
48 #include "mwindow.h"
49 #include "mwindowgui.h"
50 #include "patchbay.h"
51 #include "performanceprefs.h"
52 #include "playbackengine.h"
53 #include "playbackprefs.h"
54 #include "preferences.h"
55 #include "record.h"
56 #include "recordprefs.h"
57 #include "render.h"
58 #include "shbtnprefs.h"
59 #include "theme.h"
60 #include "trackcanvas.h"
61 #include "transportque.h"
62 #include "vwindow.h"
63 #include "vwindowgui.h"
64
65 #include <string.h>
66
67
68
69 #define WIDTH xS(860)
70 #define HEIGHT yS(700)
71
72
73 PreferencesMenuitem::PreferencesMenuitem(MWindow *mwindow)
74  : BC_MenuItem(_("Preferences..."), _("Shift-P"), 'P')
75 {
76         this->mwindow = mwindow;
77
78         set_shift(1);
79         thread = new PreferencesThread(mwindow);
80 }
81
82 PreferencesMenuitem::~PreferencesMenuitem()
83 {
84         delete thread;
85 }
86
87
88 int PreferencesMenuitem::handle_event()
89 {
90         mwindow->gui->unlock_window();
91         thread->start();
92         mwindow->gui->lock_window("PreferencesMenuitem::handle_event");
93         return 1;
94 }
95
96
97
98
99 PreferencesThread::PreferencesThread(MWindow *mwindow)
100  : BC_DialogThread()
101 {
102         this->mwindow = mwindow;
103         window = 0;
104         thread_running = 0;
105         confirm_dialog = 0;
106 }
107
108 PreferencesThread::~PreferencesThread()
109 {
110         delete confirm_dialog;
111         close_window();
112 }
113
114 BC_Window* PreferencesThread::new_gui()
115 {
116
117         preferences = new Preferences;
118         edl = new EDL;
119         edl->create_objects();
120         current_dialog = mwindow->defaults->get("DEFAULTPREF", 0);
121         preferences->copy_from(mwindow->preferences);
122         edl->copy_session(mwindow->edl);
123         redraw_indexes = 0;
124         redraw_meters = 0;
125         redraw_times = 0;
126         redraw_overlays = 0;
127         close_assets = 0;
128         reload_plugins = 0;
129         //int need_new_indexes = 0;
130         rerender = 0;
131
132         mwindow->gui->lock_window("NewThread::new_gui");
133         int scr_x = mwindow->gui->get_screen_x(0, -1);
134         int scr_w = mwindow->gui->get_screen_w(0, -1);
135         int scr_h = mwindow->gui->get_screen_h(0, -1);
136
137         int w = WIDTH, h = HEIGHT;
138         int min_w = mwindow->theme->preferencescategory_x;
139         for(int i = 0; i < CATEGORIES; i++) {
140                 min_w += PreferencesButton::calculate_w(mwindow->gui, category_to_text(i)) -
141                         mwindow->theme->preferences_category_overlap;
142         }
143         if( w < min_w ) w = min_w;
144         int x = scr_x + scr_w / 2 - w / 2;
145         int y = scr_h / 2 - h / 2;
146
147         window = new PreferencesWindow(mwindow, this, x, y, w, h);
148         window->create_objects();
149         mwindow->gui->unlock_window();
150
151         thread_running = 1;
152         return window;
153 }
154
155 void PreferencesThread::handle_close_event(int result)
156 {
157         thread_running = 0;
158         if(!result)
159         {
160                 apply_settings();
161                 mwindow->save_defaults();
162         }
163
164         window = 0;
165         delete preferences;
166         edl->Garbage::remove_user();
167         preferences = 0;
168         edl = 0;
169
170         mwindow->defaults->update("DEFAULTPREF", current_dialog);
171         if( mwindow->restart() )
172                 mwindow->gui->set_done(0);
173 }
174
175
176
177 int PreferencesThread::update_framerate()
178 {
179         if(thread_running)
180         {
181                 lock_dialog("PreferencesThread::update_framerate");
182                 PreferencesWindow *window = (PreferencesWindow*)get_gui();
183                 if(window) window->update_framerate();
184                 unlock_dialog();
185         }
186         return 0;
187 }
188
189
190 void PreferencesThread::update_rates()
191 {
192         if(thread_running)
193         {
194                 lock_dialog("PreferencesThread::update_framerate");
195                 PreferencesWindow *window = (PreferencesWindow*)get_gui();
196                 if(window) window->update_rates();
197                 unlock_dialog();
198         }
199 }
200
201 int PreferencesThread::apply_settings()
202 {
203 // Compare sessions
204
205         PlaybackConfig *this_playback_config = edl->session->playback_config;
206         AudioOutConfig *this_aconfig = this_playback_config->aconfig;
207         VideoOutConfig *this_vconfig = this_playback_config->vconfig;
208         PlaybackConfig *playback_config = mwindow->edl->session->playback_config;
209         AudioOutConfig *aconfig = playback_config->aconfig;
210         VideoOutConfig *vconfig = playback_config->vconfig;
211
212         rerender =
213                 edl->session->need_rerender(mwindow->edl->session) ||
214                 (preferences->force_uniprocessor != mwindow->preferences->force_uniprocessor) ||
215                 this_playback_config->active_config != playback_config->active_config ||
216                 (*this_aconfig != *aconfig) || (*this_vconfig != *vconfig) ||
217                 !preferences->brender_asset->equivalent(*mwindow->preferences->brender_asset, 0, 1, edl);
218
219         if( preferences->autocolor_assets != mwindow->preferences->autocolor_assets )
220                 redraw_indexes = 1;
221
222         if( preferences->yuv_color_space != mwindow->preferences->yuv_color_space ||
223             preferences->yuv_color_range != mwindow->preferences->yuv_color_range ) {
224                 YUV::yuv.yuv_set_colors(
225                         preferences->yuv_color_space,
226                         preferences->yuv_color_range);
227                 rerender = 1;
228         }
229
230         if( preferences->highlight_inverse != mwindow->preferences->highlight_inverse ) {
231                 mwindow->gui->lock_window("PreferencesThread::apply_settings 0");
232                 mwindow->gui->hide_cursor(0);
233                 mwindow->gui->unlock_window();
234                 redraw_overlays = 1;
235         }
236         PreferencesWindow *window = (PreferencesWindow*)get_gui();
237         if( window ) window->unlock_window();
238         mwindow->stop_brender();
239         if( window ) window->lock_window("PreferencesThread::apply_settings 5");
240
241         if( strcmp(preferences->theme, mwindow->preferences->theme) ||
242             strcmp(preferences->plugin_icons, mwindow->preferences->plugin_icons) ||
243             preferences->awindow_picon_h != mwindow->preferences->awindow_picon_h ||
244             preferences->layout_scale != mwindow->preferences->layout_scale ||
245             preferences->vicon_size != mwindow->preferences->vicon_size ||
246             preferences->vicon_color_mode != mwindow->preferences->vicon_color_mode )
247                 mwindow->restart_status = -1;  // reconstruct/restart program
248         if( strcmp(preferences->lv2_path, mwindow->preferences->lv2_path) != 0 )
249                 reload_plugins = 1;
250         if( reload_plugins ) {
251                 MWindow::remove_plugin_index();
252                 File::setenv_path("LV2_PATH", preferences->lv2_path, 1);
253                 mwindow->restart_status = -1;
254         }
255
256         mwindow->edl->copy_session(edl, 1);
257         mwindow->preferences->copy_from(preferences);
258
259         BC_Signals::set_catch_segv(mwindow->preferences->trap_sigsegv);
260         BC_Signals::set_catch_intr(mwindow->preferences->trap_sigintr);
261         BC_WindowBase::get_resources()->popupmenu_btnup = mwindow->preferences->popupmenu_btnup;
262         BC_WindowBase::get_resources()->grab_input_focus = mwindow->preferences->grab_input_focus;
263         BC_WindowBase::get_resources()->textbox_focus_policy = mwindow->preferences->textbox_focus_policy;
264         if( mwindow->preferences->trap_sigsegv || mwindow->preferences->trap_sigintr ) {
265                 BC_Trace::enable_locks();
266         }
267         else {
268                 BC_Trace::disable_locks();
269         }
270
271         mwindow->reset_android_remote();
272         int ffmpeg_early_probe = mwindow->preferences->get_file_probe_armed("FFMPEG_Early");
273         mwindow->gui->ffmpeg_toggle->update(ffmpeg_early_probe);
274         mwindow->gui->ffmpeg_toggle->set_tooltip(ffmpeg_early_probe ?
275                 FFMPEG_EARLY_TIP : FFMPEG_LATE_TIP);
276         mwindow->gui->mainshbtns->load(mwindow->preferences);
277         mwindow->init_brender();
278
279 //edl->session->recording_format->dump();
280 //mwindow->edl->session->recording_format->dump();
281 #ifdef GLx4
282         if(((mwindow->edl->session->output_w % 4) ||
283                 (mwindow->edl->session->output_h % 4)) &&
284                 mwindow->edl->session->playback_config->vconfig->driver == PLAYBACK_X11_GL)
285         {
286                 MainError::show_error(
287                         _("This project's dimensions are not multiples of 4 so\n"
288                         "it can't be rendered by OpenGL."));
289         }
290 #endif
291
292         if(redraw_meters)
293         {
294                 mwindow->cwindow->gui->lock_window("PreferencesThread::apply_settings");
295                 mwindow->cwindow->gui->meters->change_format(edl->session->meter_format,
296                         edl->session->min_meter_db,
297                         edl->session->max_meter_db);
298                 mwindow->cwindow->gui->unlock_window();
299
300
301
302                 for(int i = 0; i < mwindow->vwindows.size(); i++) {
303                         VWindow *vwindow = mwindow->vwindows.get(i);
304                         if( !vwindow->is_running() ) continue;
305                         vwindow->gui->lock_window("PreferencesThread::apply_settings");
306                         vwindow->gui->meters->change_format(edl->session->meter_format,
307                                 edl->session->min_meter_db,
308                                 edl->session->max_meter_db);
309                         vwindow->gui->unlock_window();
310
311                 }
312
313
314                 mwindow->gui->lock_window("PreferencesThread::apply_settings 1");
315                 mwindow->gui->set_meter_format(edl->session->meter_format,
316                         edl->session->min_meter_db,
317                         edl->session->max_meter_db);
318                 mwindow->gui->unlock_window();
319
320
321
322                 mwindow->lwindow->gui->lock_window("PreferencesThread::apply_settings");
323                 mwindow->lwindow->gui->panel->change_format(edl->session->meter_format,
324                         edl->session->min_meter_db,
325                         edl->session->max_meter_db);
326                 mwindow->lwindow->gui->unlock_window();
327         }
328
329         if(redraw_overlays)
330         {
331                 mwindow->gui->lock_window("PreferencesThread::apply_settings 2");
332                 mwindow->gui->show_cursor(0);
333                 mwindow->gui->draw_overlays(1);
334                 mwindow->gui->unlock_window();
335         }
336
337         if(redraw_times)
338         {
339                 mwindow->gui->lock_window("PreferencesThread::apply_settings 3");
340                 mwindow->gui->update(0, NO_DRAW, 1, 0, 0, 1, 0);
341                 mwindow->gui->redraw_time_dependancies();
342                 mwindow->gui->unlock_window();
343         }
344
345         if(rerender)
346         {
347 //printf("PreferencesThread::apply_settings 1\n");
348 // This doesn't stop and restart, only reloads the assets before
349 // the next play command.
350                 mwindow->cwindow->refresh_frame(CHANGE_ALL, mwindow->edl);
351 //printf("PreferencesThread::apply_settings 10\n");
352         }
353
354         if(redraw_indexes)
355         {
356                 mwindow->gui->lock_window("PreferencesThread::apply_settings 4");
357                 mwindow->gui->draw_trackmovement();
358                 mwindow->gui->unlock_window();
359         }
360
361         if(redraw_times || redraw_overlays || redraw_indexes)
362         {
363                 mwindow->gui->lock_window("PreferencesThread::apply_settings 5");
364                 mwindow->gui->flush();
365                 mwindow->gui->unlock_window();
366         }
367
368         return 0;
369 }
370
371 const char *PreferencesThread::busy()
372 {
373         if( mwindow->render->thread->running() )
374                 return _("render");
375         Record *record = mwindow->gui->record;
376         if( record->capturing || record->recording || record->writing_file )
377                 return _("record");
378         return 0;
379 }
380
381 void PreferencesThread::confirm_update(const char *reason, int close)
382 {
383         delete confirm_dialog;
384         confirm_dialog = new PreferencesConfirmDialog(this, reason, close);
385         confirm_dialog->start();
386 }
387
388 const char* PreferencesThread::category_to_text(int category)
389 {
390         PlaybackConfig *playback_config = edl->session->playback_config;
391         switch(category)
392         {
393                 case PLAYBACK_A:
394                         return playback_config->active_config==0 ?
395                                  _("*Playback A") : _("Playback A");
396                 case PLAYBACK_B:
397                         return playback_config->active_config==1 ?
398                                  _("*Playback B") : _("Playback B");
399                 case RECORD:
400                         return _("Recording");
401                 case PERFORMANCE:
402                         return _("Performance");
403                 case INTERFACE:
404                         return _("Interface");
405                 case APPEARANCE:
406                         return _("Appearance");
407                 case ABOUT:
408                         return _("About");
409         }
410         return "";
411 }
412
413 int PreferencesThread::text_to_category(const char *category)
414 {
415 SET_TRACE
416         int min_result = -1, result, result_num = 0;
417         for(int i = 0; i < CATEGORIES; i++)
418         {
419                 result = labs(strcmp(category_to_text(i), category));
420                 if(result < min_result || min_result < 0)
421                 {
422                         min_result = result;
423                         result_num = i;
424                 }
425         }
426 SET_TRACE
427         return result_num;
428 }
429
430
431 PreferencesWindow::PreferencesWindow(MWindow *mwindow,
432         PreferencesThread *thread, int x, int y, int w, int h)
433  : BC_Window(_(PROGRAM_NAME ": Preferences"), x,y, w,h,w,h, 1)
434 {
435         this->mwindow = mwindow;
436         this->thread = thread;
437         dialog = 0;
438         category = 0;
439 }
440
441 PreferencesWindow::~PreferencesWindow()
442 {
443         lock_window("PreferencesWindow::~PreferencesWindow");
444         delete category;
445
446
447         if(dialog) delete dialog;
448
449
450         for(int i = 0; i < categories.total; i++)
451                 delete categories.values[i];
452         unlock_window();
453 }
454
455 void PreferencesWindow::create_objects()
456 {
457         BC_Button *button;
458
459         lock_window("PreferencesWindow::create_objects");
460         set_icon(mwindow->theme->get_image("mwindow_icon"));
461         mwindow->theme->draw_preferences_bg(this);
462         flash();
463
464         int x = mwindow->theme->preferencescategory_x;
465         int y = mwindow->theme->preferencescategory_y;
466         for(int i = 0; i < CATEGORIES; i++)
467         {
468                 add_subwindow(category_button[i] = new PreferencesButton(mwindow,
469                         thread, x, y, i, thread->category_to_text(i),
470                         (i == thread->current_dialog) ?
471                                 mwindow->theme->get_image_set("category_button_checked") :
472                                 mwindow->theme->get_image_set("category_button")));
473                 x += category_button[i]->get_w() -
474                         mwindow->theme->preferences_category_overlap;
475         }
476
477
478 //      for(int i = 0; i < CATEGORIES; i++)
479 //              categories.append(new BC_ListBoxItem(thread->category_to_text(i)));
480 //      category = new PreferencesCategory(mwindow,
481 //              thread,
482 //              mwindow->theme->preferencescategory_x,
483 //              mwindow->theme->preferencescategory_y);
484 //      category->create_objects();
485
486
487         add_subwindow(button = new PreferencesOK(mwindow, thread));
488         add_subwindow(new PreferencesApply(mwindow, thread));
489         add_subwindow(new PreferencesCancel(mwindow, thread));
490
491         set_current_dialog(thread->current_dialog);
492
493         show_window();
494         unlock_window();
495 }
496
497 int PreferencesWindow::update_framerate()
498 {
499         lock_window("PreferencesWindow::update_framerate");
500         if(thread->current_dialog < PreferencesThread::RECORD)
501         {
502                 dialog->draw_framerate(1);
503 //              flash();
504         }
505         unlock_window();
506         return 0;
507 }
508
509
510 void PreferencesWindow::update_rates()
511 {
512         lock_window("PreferencesWindow::update_rates");
513         if(thread->current_dialog == PreferencesThread::PERFORMANCE)
514         {
515                 dialog->update_rates();
516         }
517         unlock_window();
518 }
519
520
521 int PreferencesWindow::set_current_dialog(int number)
522 {
523         if(dialog) delete dialog;
524         dialog = 0;
525         thread->current_dialog = number;
526
527 //PRINT_TRACE
528         PreferencesDialog *dialog2 = dialog;
529         dialog = 0;
530 //PRINT_TRACE
531
532 // Redraw category buttons
533         for(int i = 0; i < CATEGORIES; i++)
534         {
535                 if(i == number)
536                 {
537                         category_button[i]->set_images(
538                                 mwindow->theme->get_image_set("category_button_checked"));
539                 }
540                 else
541                 {
542                         category_button[i]->set_images(
543                                 mwindow->theme->get_image_set("category_button"));
544                 }
545                 category_button[i]->draw_face(0);
546
547 // Copy face to background for next button's overlap.
548 // Still can't do state changes right.
549         }
550
551
552 //PRINT_TRACE
553         PlaybackConfig *playback_config = thread->edl->session->playback_config;
554         switch(number)
555         {
556                 case PreferencesThread::PLAYBACK_A:
557                 case PreferencesThread::PLAYBACK_B:
558                         playback_config->load_defaults(mwindow->defaults,
559                                 number == PreferencesThread::PLAYBACK_A ? 0 : 1);
560                         add_subwindow(dialog = new PlaybackPrefs(mwindow, this, number));
561                         break;
562
563                 case PreferencesThread::RECORD:
564                         add_subwindow(dialog = new RecordPrefs(mwindow, this));
565                         break;
566
567                 case PreferencesThread::PERFORMANCE:
568                         add_subwindow(dialog = new PerformancePrefs(mwindow, this));
569                         break;
570
571                 case PreferencesThread::INTERFACE:
572                         add_subwindow(dialog = new InterfacePrefs(mwindow, this));
573                         break;
574
575                 case PreferencesThread::APPEARANCE:
576                         add_subwindow(dialog = new AppearancePrefs(mwindow, this));
577                         break;
578
579                 case PreferencesThread::ABOUT:
580                         add_subwindow(dialog = new AboutPrefs(mwindow, this));
581                         break;
582         }
583
584 //PRINT_TRACE
585         if(dialog)
586         {
587                 dialog->draw_top_background(this, 0, 0, dialog->get_w(), dialog->get_h());
588 //printf("PreferencesWindow::set_current_dialog %d\n", __LINE__);
589                 dialog->create_objects();
590 //printf("PreferencesWindow::set_current_dialog %d\n", __LINE__);
591                 dialog->lower_window();
592                 dialog->show_window(0);
593         }
594
595         if(dialog2)
596         {
597                 dialog2->hide_window(0);
598                 delete dialog2;
599         }
600
601         return 0;
602 }
603
604
605 PreferencesButton::PreferencesButton(MWindow *mwindow,
606         PreferencesThread *thread,
607         int x,
608         int y,
609         int category,
610         const char *text,
611         VFrame **images)
612  : BC_GenericButton(x, y, text, images)
613 {
614         this->mwindow = mwindow;
615         this->thread = thread;
616         this->category = category;
617 }
618
619 int PreferencesButton::handle_event()
620 {
621         thread->window->set_current_dialog(category);
622         return 1;
623 }
624
625
626 PreferencesDialog::PreferencesDialog(MWindow *mwindow,
627         PreferencesWindow *pwindow)
628  : BC_SubWindow(xS(10), yS(40),
629         pwindow->get_w() - xS(20),
630         pwindow->get_h() - BC_GenericButton::calculate_h() - yS(10 + 40))
631 {
632         this->pwindow = pwindow;
633         this->mwindow = mwindow;
634         preferences = pwindow->thread->preferences;
635 }
636
637 PreferencesDialog::~PreferencesDialog()
638 {
639 }
640
641
642 // ============================== category window
643
644 PreferencesApply::PreferencesApply(MWindow *mwindow, PreferencesThread *thread)
645  : BC_GenericButton(thread->window->get_w() / 2 - BC_GenericButton::calculate_w(thread->window, _("Apply")) / 2,
646         thread->window->get_h() - BC_GenericButton::calculate_h() - yS(10),
647         _("Apply"))
648 {
649         this->mwindow = mwindow;
650         this->thread = thread;
651 }
652 int PreferencesApply::handle_event()
653 {
654         const char *reason = thread->busy();
655         if( reason )
656                 thread->confirm_update(reason, 0);
657         else {
658                 thread->apply_settings();
659                 mwindow->save_defaults();
660         }
661         return 1;
662 }
663 int PreferencesApply::resize_event(int w, int h)
664 {
665         reposition_window(w/2 - get_w()/2, h-get_h()-yS(10));
666         return 1;
667 }
668
669
670 PreferencesOK::PreferencesOK(MWindow *mwindow, PreferencesThread *thread)
671  : BC_GenericButton(xS(10),
672         thread->window->get_h() - BC_GenericButton::calculate_h() - yS(10),
673         _("OK"))
674 {
675         this->mwindow = mwindow;
676         this->thread = thread;
677 }
678 PreferencesOK::~PreferencesOK()
679 {
680 }
681
682 int PreferencesOK::keypress_event()
683 {
684         if( get_keypress() == RETURN )
685                 return handle_event();
686         return 0;
687 }
688
689 int PreferencesOK::handle_event()
690 {
691         const char *reason = mwindow->restart() ? _("restart") : thread->busy();
692         if( reason )
693                 thread->confirm_update(reason, 1);
694         else
695                 thread->window->set_done(0);
696         return 1;
697 }
698 int PreferencesOK::resize_event(int w, int h)
699 {
700         reposition_window(xS(10), h-get_h()-yS(10));
701         return 1;
702 }
703
704
705 PreferencesConfirmDialog::PreferencesConfirmDialog(PreferencesThread *thread,
706                 const char *reason, int close)
707 {
708         this->thread = thread;
709         this->close = close;
710         sprintf(query, _("Busy: %s in progress. Are you sure?"), reason);
711 }
712 PreferencesConfirmDialog::~PreferencesConfirmDialog()
713 {
714 }
715 BC_Window *PreferencesConfirmDialog::new_gui()
716 {
717         qwindow = new PreferencesConfirmWindow(this);
718         qwindow->create_objects(query, 0);
719         return qwindow;
720 }
721 void PreferencesConfirmDialog::handle_done_event(int result)
722 {
723         if( !result ) return; // no
724         if( !close ) {
725                 thread->window->lock_window("PreferencesConfirmDialog::handle_done_event");
726                 thread->apply_settings();
727                 thread->mwindow->save_defaults();
728                 thread->window->unlock_window();
729         }
730         else
731                 thread->window->set_done(0);
732 }
733
734 PreferencesConfirmWindow::PreferencesConfirmWindow(PreferencesConfirmDialog *dialog)
735  : QuestionWindow(dialog->thread->mwindow)
736 {
737         this->dialog = dialog;
738 }
739 PreferencesConfirmWindow::~PreferencesConfirmWindow()
740 {
741 }
742
743
744 PreferencesCancel::PreferencesCancel(MWindow *mwindow, PreferencesThread *thread)
745  : BC_GenericButton(thread->window->get_w() - BC_GenericButton::calculate_w(thread->window, _("Cancel")) - xS(10),
746         thread->window->get_h() - BC_GenericButton::calculate_h() - yS(10),
747         _("Cancel"))
748 {
749         this->mwindow = mwindow;
750         this->thread = thread;
751 }
752 int PreferencesCancel::keypress_event()
753 {
754         if(get_keypress() == ESC)
755         {
756                 thread->window->set_done(1);
757                 return 1;
758         }
759         return 0;
760 }
761 int PreferencesCancel::handle_event()
762 {
763         thread->window->set_done(1);
764         return 1;
765 }
766 int PreferencesCancel::resize_event(int w, int h)
767 {
768         reposition_window(w-get_w()-xS(10), h-get_h()-yS(10));
769         return 1;
770 }
771
772
773 PreferencesCategory::PreferencesCategory(MWindow *mwindow, PreferencesThread *thread, int x, int y)
774  : BC_PopupTextBox(thread->window,
775                 &thread->window->categories,
776                 thread->category_to_text(thread->current_dialog),
777                 x, y, xS(200), yS(150))
778 {
779         this->mwindow = mwindow;
780         this->thread = thread;
781 }
782
783 PreferencesCategory::~PreferencesCategory()
784 {
785 }
786
787 int PreferencesCategory::handle_event()
788 {
789 SET_TRACE
790         thread->window->set_current_dialog(thread->text_to_category(get_text()));
791 SET_TRACE
792         return 1;
793 }