47
Gtk::TreeModelColumn<bool> selState;
48
Gtk::TreeModelColumn<RefPtr<Gdk::Pixbuf> > thumbnail;
49
Gtk::TreeModelColumn<std::string> name;
50
Gtk::TreeModelColumn<std::string> desc;
52
VobFields(Gtk::TreeModelColumnRecord& rec)
43
61
static VobFields& VF()
45
return VobFields::Instance();
63
return GetColumnFields<VobFields>();
48
66
ImportData::ImportData(): srcChooser(Gtk::FILE_CHOOSER_ACTION_OPEN),
62
80
case ipCHOOSE_SOURCE:
63
title = "Choose Source DVD-Video";
81
title = _("Choose Source DVD-Video");
65
83
case ipSELECT_VOBS:
66
title = "Select Videos to Import";
84
title = _("Select Videos to Import");
68
86
case ipCHOOSE_DEST:
69
title = "Select Folder to Save Videos";
87
title = _("Select Folder to Save Videos");
71
89
case ipIMPORT_PROC:
72
title = "Importing...";
90
title = _("Importing...");
75
title = "Import is completed.";
93
title = _("Import is completed.");
185
203
std::string desc = (str::stream(Mpeg::SecToHMS(vob.tmLen, true)) << ", "
186
204
<< vob.sz.x << "x" << vob.sz.y << ", "
187
205
<< (vob.aspect == af4_3 ? "4:3" : "16:9") << ", "
188
<< std::fixed << std::setprecision(2) << vob.Count()/512. << " Mb").str();
206
<< std::fixed << std::setprecision(2) << vob.Count()/512. << " " << _("MB")).str();
189
207
row[VF().desc] = desc;
191
209
CompleteSelection(id, false);
194
212
id.numToThumb = 0;
197
// бывают случаи вызова prepare на одной странице дважды
198
// - set_current_page() + "map"
199
if( id.curPage != ipSELECT_VOBS ) // дважды
200
id.thumbIdler.ConnectIdle(bl::bind(&OnSelectIdle, boost::ref(id)));
215
ASSERT( id.curPage != ipSELECT_VOBS );
216
id.thumbIdler.ConnectIdle(bl::bind(&OnSelectIdle, boost::ref(id)));
203
219
id.CloseIdlers();
236
static void OnSelectSource(ImportData& id)
252
static ReaderPtr OpenDVD(const std::string& dvd_path, ImportData& id)
238
Gtk::FileChooserWidget& fcw = id.srcChooser;
239
std::string dvd_path = fcw.get_filename().raw();
242
255
ReaderPtr rd = OpenDVD(dvd_path, is_pal);
243
256
if( rd && id.addToProject && (is_pal != Project::AData().PalTvSystem()) )
252
265
SetCurPageComplete(id.ast, id.reader);
270
static void OnSelectSource(ImportData& id)
272
if( id.ast.get_current_page() != ipCHOOSE_SOURCE )
275
// :TODO: порой тупит и выдает "" (файл не выделен якобы)
276
// Из-за этого errLbl может скрываться когда не надо
277
Gtk::FileChooserWidget& fcw = id.srcChooser;
278
std::string dvd_path = fcw.get_filename().raw();
280
OpenDVD(dvd_path, id);
255
283
bool SetVobSel(Gtk::TreeIter& itr, bool select_all)
356
384
static void PackSelectionButton(Gtk::HBox& hbox, RefPtr<Gtk::SizeGroup> sg, bool select_all,
359
const char* text = select_all ? "Select All" : "Unselect All" ;
387
const char* text = select_all ? _("Select All") : _("Unselect All") ;
360
388
Gtk::Button& btn = PackStart(hbox, NewManaged<Gtk::Button>(text));
361
389
sg->add_widget(btn);
379
407
// мы не можем пустить исключение здесь, потому что оно пойдет
380
408
// и через C-шный код (Gtk) - отложим
381
if( MessageBox("Are you sure to stop importing?",
409
if( MessageBox(_("Are you sure to stop importing?"),
382
410
Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO) == Gtk::RESPONSE_YES )
383
411
id.isBreak = true;
401
429
static void OnApply(ImportData& id)
431
// смотри коммит ae37d209 в git://git.gnome.org/gtk+
432
#if GTK_CHECK_VERSION(2,17,7)
433
id.ast.set_current_page(ipIMPORT_PROC);
403
436
std::string& dir_path = id.destPath;
404
437
VobArr& arr = id.dvdVobs;
405
438
ASSERT( fs::is_directory(dir_path) );
407
440
bool res = Project::HaveFullAccess(dir_path);
409
MessageBox("Cant write to folder " + dir_path + " (check permissions).",
442
MessageBox(BF_("Cant write to folder %1% (check permissions).") % dir_path % bf::stop,
410
443
Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);
434
467
std::string name = itr->get_value(VF().name);
435
468
std::string fname = AppendPath(dir_path, name);
436
469
if( fs::exists(fname) )
437
if( MessageBox("The file already " + name + " already exists. Overwrite it?",
470
if( MessageBox(BF_("A file named \"%1%\" already exists. Do you want to replace it?") % name % bf::stop,
438
471
Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO) != Gtk::RESPONSE_YES )
463
496
std::string err_str;
464
497
Gtk::TreePath pth;
465
498
if( !Project::TryAddMedia(fname.c_str(), pth, err_str) )
466
500
LOG_ERR << "Import error: " << err_str << io::endl;
470
505
catch(const std::exception& err)
473
const char* what = err.what();
474
if( what && (strcmp(what, USERT_BREAK_STR) != 0) )
475
MessageBox("Import error!", Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, what);
508
const char* what = err.what();
509
if( what && (strcmp(what, USERT_BREAK_STR) != 0) )
510
MessageBox(_("Import error!"), Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, what);
479
const char* final = res ? "Videos successfully imported."
480
: "Import has been interrupted." ;
514
const char* final = res ? _("Videos successfully imported.")
515
: _("Import has been interrupted.") ;
481
516
FillLabelForImport(id.finalMsg, final);
518
// смотри коммит ae37d209 в git://git.gnome.org/gtk+
519
#if !GTK_CHECK_VERSION(2,17,7)
482
520
id.ast.set_current_page(ipEND);
485
524
static Gtk::VBox& AppendVBoxAsPage(Gtk::Assistant& ast, Gtk::Container*& page)
507
546
void ConstructImporter(ImportData& id)
509
548
Gtk::Assistant& ast = id.ast;
510
ast.set_title("DVD-Video Import");
549
ast.set_title(_("DVD-Video Import"));
511
550
ast.set_default_size(600, 500);
513
552
ast.signal_cancel().connect(&Gtk::Main::quit);
530
569
typ = Gtk::ASSISTANT_PAGE_INTRO;
532
571
Gtk::FileChooserWidget& fcw = id.srcChooser;
533
PackFCWPage(vbox, fcw, "Choose DVD disc, DVD folder or iso image file.");
572
PackFCWPage(vbox, fcw, _("Choose DVD disc, DVD folder or iso image file."));
534
573
fcw.signal_selection_changed().connect(bl::bind(&OnSelectSource, ref_id));
547
586
//fcw.set_filter(ff);
549
588
Gtk::Label& err_lbl = id.errLbl;
550
err_lbl.set_markup("<span foreground=\"red\">NTSC/PAL mismatch. Try another disc"
551
" or import to project of corresponding type.</span>");
589
err_lbl.set_markup(boost::format("<span foreground=\"red\">%1%</span>")
590
% _("NTSC/PAL mismatch. Try another disc or import to project of corresponding type.")
552
592
ast.add_action_widget(err_lbl); // по умолчанию не видна
553
593
SetExpandFill(err_lbl);
554
594
SetAlign(err_lbl);
563
603
RefPtr<Gtk::ListStore>& vob_list = id.vobList;
564
vob_list = Gtk::ListStore::create(VF());
604
vob_list = Gtk::ListStore::create(GetColumnRecord<VobFields>());
566
606
Gtk::TreeView& view = NewManaged<Gtk::TreeView>(vob_list);
567
607
view.signal_row_activated().connect(bl::bind(&OnVobActivate, bl::_1, ref_id));
571
611
sel_rndr.signal_toggled().connect(bl::bind(&OnSelVob, ref_id));
574
Gtk::TreeView::Column& name_cln = NewManaged<Gtk::TreeView::Column>("Name");
614
Gtk::TreeView::Column& name_cln = NewManaged<Gtk::TreeView::Column>(_("Name"));
575
615
name_cln.set_resizable(true);
576
616
name_cln.set_expand(true);
584
624
name_cln.pack_start(rndr);
585
625
name_cln.set_renderer(rndr, VF().name);
586
626
view.append_column(name_cln);
587
view.append_column("Details", VF().desc);
627
view.append_column(_("Details"), VF().desc);
589
629
Gtk::ScrolledWindow& scr_win = PackStart(hbox, NewManaged<Gtk::ScrolledWindow>(),
590
630
Gtk::PACK_EXPAND_WIDGET);
630
670
typ = Gtk::ASSISTANT_PAGE_CONFIRM;
632
672
Gtk::FileChooserWidget& fcw = NewManaged<Gtk::FileChooserWidget>(Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER);
633
PackFCWPage(vbox, fcw, "It is desirable the destination folder to be empty.");
673
PackFCWPage(vbox, fcw, _("It is desirable the destination folder to be empty."));
635
675
fcw.signal_selection_changed().connect(
636
676
bl::bind(&OnSelectDest, boost::ref(fcw), ref_id));
681
721
id.addToProject = true;
683
723
ConstructImporter(id);
725
// По опыту с помощником (GtkAssistant) стало ясно:
726
// - до момента show_all() вообще нельзя менять текущую страницу,
727
// типы страниц и т.д.; иначе легко получить "UB", выражающееся в сегфолтах
729
// - вывод: хочется изменения в помощнике - создавай его по-другому с самого
730
// начала (ConstructImporter())
685
734
if( !dvd_path.empty() )
687
// реализовать переход сразу на 2ю страницу оказалось
689
// - после явного открытия reader'а самое главное -
690
// не дать srcChooser переустановить его вызовом
691
// OnSelectSource() =>
692
// - перепробовав все, что можно (и скрытие, и удаление
693
// первой страницы, ...), стало ясно, что нельзя вызывать
694
// show_all() окна, если на первой странице =>
695
// - простой переход на 2ю страницу дает сегфолт, если
696
// ранее не проходил show_all() (см. интересную функцию
697
// compute_last_button_state()) - пат
698
// - и только смена типа с GTK_ASSISTANT_PAGE_CONTENT на любой
699
// другой дала нужный результат!
702
ReaderPtr rd = OpenDVD(dvd_path, is_pal);
703
if( rd && (is_pal == Project::AData().PalTvSystem()) )
705
// чтоб не смутить OnPreparePage()
706
id.curPage = ipCHOOSE_SOURCE;
709
ast.set_page_type(*ast.get_nth_page(ipSELECT_VOBS), Gtk::ASSISTANT_PAGE_INTRO);
736
// перейдем в директорию
737
id.srcChooser.set_filename(dvd_path);
739
if( OpenDVD(dvd_path, id) )
710
740
ast.set_current_page(ipSELECT_VOBS);
713
// не получилось - тогда хотя бы перейдем в директорию
714
id.srcChooser.select_filename(dvd_path);
719
746
} // namespace DVD