From 7e49cf91469c6bf3aa9e2b9a1a30285e37155656 Mon Sep 17 00:00:00 2001 From: Sergio Costas Date: Sat, 19 Jul 2014 01:50:07 +0200 Subject: [PATCH] Added dvd menu window Added support for modification callbacks in the interface_manager class Added support for ColorButton widgets in the interface_manager class --- data/interface/wmain.ui | 8 +- data/interface/wmenu.ui | 1048 ++++++++++++++++++++++++++++++ src/devede/configuration_data.py | 11 + src/devede/dvd_menu.py | 85 +++ src/devede/file_movie.py | 1 - src/devede/interface_manager.py | 130 ++-- src/devede/project.py | 31 +- 7 files changed, 1271 insertions(+), 43 deletions(-) create mode 100644 data/interface/wmenu.ui create mode 100644 src/devede/dvd_menu.py diff --git a/data/interface/wmain.ui b/data/interface/wmain.ui index 7c829bd..495623b 100644 --- a/data/interface/wmain.ui +++ b/data/interface/wmain.ui @@ -602,7 +602,7 @@ - + True False 0 @@ -624,6 +624,7 @@ False 0 True + 0 @@ -633,11 +634,12 @@ - + Menu options True True True + 0 @@ -647,7 +649,7 @@ - + Preview menu True True diff --git a/data/interface/wmenu.ui b/data/interface/wmenu.ui new file mode 100644 index 0000000..0cbfaa5 --- /dev/null +++ b/data/interface/wmenu.ui @@ -0,0 +1,1048 @@ + + + + + + 100 + 1 + 10 + + + 100 + 1 + 10 + + + 100 + 1 + 10 + + + 100 + 1 + 10 + + + False + False + True + False + False + + + True + False + vertical + + + True + False + + + True + False + vertical + + + True + False + 0 + none + + + True + False + 12 + + + True + False + 4 + + + True + False + 1 + Text: + + + 0 + 0 + 1 + 1 + + + + + True + False + 1 + Font: + + + 0 + 1 + 1 + 1 + + + + + True + False + 1 + Text color: + + + 2 + 0 + 1 + 1 + + + + + True + False + 1 + Shadow color: + + + 2 + 1 + 1 + 1 + + + + + True + True + + + 1 + 0 + 1 + 1 + + + + + True + True + True + Sans 12 + + + + 1 + 1 + 1 + 1 + + + + + True + True + True + True + + + 3 + 0 + 1 + 1 + + + + + True + True + True + True + + + 3 + 1 + 1 + 1 + + + + + + + + + True + False + <b>Menu title</b> + True + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + + + True + False + + + True + True + 0 + + + + + Set default background + True + True + True + + + + False + True + 1 + + + + + + + + + True + False + <b>Menu background</b> + True + + + + + False + True + 1 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + + + True + False + + + True + True + 0 + + + + + Set menus without sound + True + True + True + + + + False + True + 1 + + + + + + + + + True + False + <b>Menu music</b> + True + + + + + False + True + 2 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + + + True + False + <b>Vertical</b> + True + + + 0 + 0 + 1 + 1 + + + + + True + False + <b>Horizontal</b> + True + + + 1 + 0 + 1 + 1 + + + + + True + False + + + 2 + 0 + 1 + 1 + + + + + True + False + <b>Margins (%)</b> + True + + + 3 + 0 + 1 + 1 + + + + + True + False + + + 4 + 0 + 1 + 1 + + + + + True + False + + + 2 + 1 + 1 + 1 + + + + + True + False + + + 4 + 1 + 1 + 1 + + + + + True + False + + + 3 + 2 + 1 + 1 + + + + + True + False + + + 4 + 3 + 1 + 1 + + + + + True + False + + + 2 + 3 + 1 + 1 + + + + + Top + True + True + False + 0 + True + True + + + 0 + 1 + 1 + 1 + + + + + Middle + True + True + False + 0 + True + True + top + + + 0 + 2 + 1 + 1 + + + + + Bottom + True + True + False + 0 + True + True + top + + + 0 + 3 + 1 + 1 + + + + + Left + True + True + False + 0 + True + True + + + 1 + 1 + 1 + 1 + + + + + Center + True + True + False + 0 + True + True + left + + + 1 + 2 + 1 + 1 + + + + + Right + True + True + False + 0 + True + True + left + + + 1 + 3 + 1 + 1 + + + + + True + True + margin_top + 2 + True + + + 3 + 1 + 1 + 1 + + + + + True + True + margin_left + 2 + True + + + 2 + 2 + 1 + 1 + + + + + True + True + margin_right + 2 + True + + + 4 + 2 + 1 + 1 + + + + + True + True + margin_bottom + 2 + True + + + 3 + 3 + 1 + 1 + + + + + + + + + True + False + <b>Menu position</b> + True + + + + + False + True + 3 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + vertical + + + True + False + + + True + False + 1 + Font: + + + False + True + 0 + + + + + True + True + True + Sans 12 + + + + True + True + 1 + + + + + False + True + 0 + + + + + True + False + + + True + False + 1 + Color for unselected titles: + + + 0 + 0 + 1 + 1 + + + + + True + False + 1 + Color for shadows: + + + 0 + 1 + 1 + 1 + + + + + True + False + 1 + Color for selected title: + + + 2 + 0 + 1 + 1 + + + + + True + False + 1 + Background color for titles: + + + 2 + 1 + 1 + 1 + + + + + True + True + True + + + 1 + 0 + 1 + 1 + + + + + True + True + True + True + + + 1 + 1 + 1 + 1 + + + + + True + True + True + + + 3 + 0 + 1 + 1 + + + + + True + True + True + True + + + 3 + 1 + 1 + 1 + + + + + False + True + 1 + + + + + + + + + True + False + <b>Menu font and colors</b> + True + + + + + False + True + 4 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + vertical + + + Show menu at disk startup + True + True + False + 0 + True + True + + + False + True + 0 + + + + + Jump to the first title at startup + True + True + False + 0 + True + True + menu_show_at_startup + + + False + True + 1 + + + + + + + + + True + False + <b>Disc startup options</b> + True + + + + + False + True + 5 + + + + + True + False + + + Preview menu + True + True + True + + + + True + True + 0 + + + + + Dynamic preview + True + True + False + 0 + True + + + + False + True + 1 + + + + + False + True + 6 + + + + + False + True + 0 + + + + + True + False + 0 + out + + + True + False + 12 + + + 720 + 576 + True + False + + + + + + + True + False + <b>Menu preview</b> + True + + + + + False + True + 1 + + + + + False + True + 0 + + + + + True + False + end + + + gtk-help + True + True + True + True + + + False + True + 0 + True + + + + + gtk-cancel + True + True + True + True + + + + False + True + 1 + + + + + gtk-ok + True + True + True + True + + + + False + True + 2 + + + + + False + True + 1 + + + + + + diff --git a/src/devede/configuration_data.py b/src/devede/configuration_data.py index fb75aa7..5b2cfe1 100644 --- a/src/devede/configuration_data.py +++ b/src/devede/configuration_data.py @@ -88,6 +88,7 @@ class configuration(GObject.GObject): self.subtitles_font_size = 28 self.sub_language = None self.sub_codepage = None + self.menu_dynamic_preview = False config_path = os.path.join(os.environ.get("HOME"),".devede") try: @@ -136,6 +137,11 @@ class configuration(GObject.GObject): continue if linea[:19]=="subtitle_font_size:": self.subtitles_font_size = int(linea[19:].strip()) + if linea[:21]=="menu_dynamic_preview:": + if linea[21] == '0': + self.menu_dynamic_preview = False + else: + self.menu_dynamic_preview = True config_data.close() except: pass @@ -182,6 +188,11 @@ class configuration(GObject.GObject): config_data.write("sub_codepage:"+str(self.sub_codepage)+"\n") if (self.sub_language != None): config_data.write("sub_language:"+str(self.sub_language)+"\n") + config_data.write("menu_dynamic_preview:") + if (self.menu_dynamic_preview): + config_data.write("1\n") + else: + config_data.write("0\n") config_data.write("subtitle_font_size:"+str(self.subtitles_font_size)+"\n") config_data.close() except: diff --git a/src/devede/dvd_menu.py b/src/devede/dvd_menu.py new file mode 100644 index 0000000..9e03073 --- /dev/null +++ b/src/devede/dvd_menu.py @@ -0,0 +1,85 @@ +# Copyright 2014 (C) Raster Software Vigo (Sergio Costas) +# +# This file is part of DeVeDe-NG +# +# DeVeDe-NG is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# DeVeDe-NG is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see + +from gi.repository import Gtk +import os +import devede.configuration_data +import devede.interface_manager + +class dvd_menu(devede.interface_manager.interface_manager): + + def __init__(self): + + devede.interface_manager.interface_manager.__init__(self) + self.config = devede.configuration_data.configuration.get_config() + + self.add_toggle("dynamic_preview", self.config.menu_dynamic_preview) + + self.add_colorbutton("title_color", (0,0,0,1), self.update_preview) + self.add_colorbutton("title_shadow", (0,0,0,0), self.update_preview) + self.add_colorbutton("unselected_color", (1,1,1,1), self.update_preview) + self.add_colorbutton("shadow_color", (0,0,0,0), self.update_preview) + self.add_colorbutton("selected_color", (0,1,1,1), self.update_preview) + self.add_colorbutton("background_color", (0,0,0,0.75), self.update_preview) + + self.add_text("title_text", None, self.update_preview) + + self.add_group("position_vertical", ["top", "middle", "bottom"], "middle", self.update_preview) + self.add_group("position_horizontal", ["left", "center", "right"], "center", self.update_preview) + + self.add_float_adjustment("margin_left", 10.0, self.update_preview) + self.add_float_adjustment("margin_top", 12.5, self.update_preview) + self.add_float_adjustment("margin_right", 10.0, self.update_preview) + self.add_float_adjustment("margin_bottom", 12.5, self.update_preview) + + self.add_group("at_startup", ["menu_show_at_startup", "play_first_title_at_startup"], "menu_show_at_startup") + + def update_preview(self,b=None): + + print("Cambiado algo") + + def on_dynamic_preview_toggled(self,b): + + self.config.menu_dynamic_preview = self.wdynamic_preview.get_active() + if (self.config.menu_dynamic_preview): + self.wframe_preview.show_all() + else: + self.wframe_preview.hide() + + + def show_configuration(self): + + self.builder = Gtk.Builder() + self.builder.set_translation_domain(self.config.gettext_domain) + + self.builder.add_from_file(os.path.join(self.config.glade,"wmenu.ui")) + self.builder.connect_signals(self) + + self.wdynamic_preview = self.builder.get_object("dynamic_preview") + self.wframe_preview = self.builder.get_object("frame_preview") + self.wmenu = self.builder.get_object("menu") + + self.wmenu.show_all() + + self.update_ui(self.builder) + self.on_dynamic_preview_toggled(None) + + + def on_accept_clicked(self,b): + + self.store_ui(self.builder) + self.wmenu.destroy() \ No newline at end of file diff --git a/src/devede/file_movie.py b/src/devede/file_movie.py index 875ebf7..0e40746 100644 --- a/src/devede/file_movie.py +++ b/src/devede/file_movie.py @@ -29,7 +29,6 @@ class file_movie(devede.interface_manager.interface_manager): def __init__(self,file_name): - GObject.GObject.__init__(self) devede.interface_manager.interface_manager.__init__(self) self.wfile_properties = None diff --git a/src/devede/interface_manager.py b/src/devede/interface_manager.py index d7e2186..9385ff5 100644 --- a/src/devede/interface_manager.py +++ b/src/devede/interface_manager.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -from gi.repository import GObject +from gi.repository import GObject,Gdk class interface_manager(GObject.GObject): """ This class allows to automatically generate variables for a GLADE interface, @@ -24,6 +24,7 @@ class interface_manager(GObject.GObject): def __init__(self): + GObject.GObject.__init__(self) self.interface_groups = {} self.interface_toggles = [] self.interface_labels = [] @@ -33,8 +34,9 @@ class interface_manager(GObject.GObject): self.interface_float_adjustments = [] self.interface_integer_adjustments = [] self.interface_lists = [] + self.interface_colorbuttons = [] - def add_group(self,group_name,radiobutton_list,default_value): + def add_group(self,group_name,radiobutton_list,default_value,callback = None): """ Adds a group of radiobuttons and creates an internal variable with the name group_name, setting it to default_value. The value for the variable will be the name of the active @@ -44,17 +46,17 @@ class interface_manager(GObject.GObject): exec('self.'+group_name+' = "'+str(default_value)+'"') else: exec('self.'+group_name+' = None') - self.interface_groups[group_name] = radiobutton_list + self.interface_groups[group_name] = ( radiobutton_list, callback ) - def add_toggle(self,toggle_name,default_value): + def add_toggle(self,toggle_name,default_value,callback = None): """ Adds an internal variable with the name toggle_name, linked to a widget element with the same name (must be or inherint from Gtk.ToogleButton). The default value can be True of False """ exec('self.'+toggle_name+' = '+str(default_value)) - self.interface_toggles.append(toggle_name) + self.interface_toggles.append( (toggle_name, callback) ) - def add_text(self,text_name,default_value): + def add_text(self,text_name,default_value,callback = None): """ Adds an internal variable with the name text_name, linked to an element with the same name (must be a Gtk.TextEntry or a Gtk.Label). The default value can be a text or None """ @@ -63,7 +65,7 @@ class interface_manager(GObject.GObject): exec('self.'+text_name+' = "'+str(default_value)+'"') else: exec('self.'+text_name+' = None') - self.interface_text.append(text_name) + self.interface_text.append( (text_name, callback) ) def add_label(self,text_name,default_value): """ Adds an internal variable with the name text_name, linked to an @@ -74,26 +76,36 @@ class interface_manager(GObject.GObject): exec('self.'+text_name+' = default_value') self.interface_labels.append(text_name) - def add_integer_adjustment(self,adjustment_name,default_value): + def add_integer_adjustment(self,adjustment_name,default_value,callback = None): """ Adds an internal variable with the name text_name, linked to an element with the same name (must be a Gtk.Adjustment). The default value must be an integer """ exec('self.'+adjustment_name+' = '+str(default_value)) - self.interface_integer_adjustments.append(adjustment_name) + self.interface_integer_adjustments.append( (adjustment_name, callback) ) - def add_float_adjustment(self,adjustment_name,default_value): + def add_float_adjustment(self,adjustment_name,default_value,callback = None): """ Adds an internal variable with the name text_name, linked to an element with the same name (must be a Gtk.Adjustment). The default value must be an float """ exec('self.'+adjustment_name+' = '+str(default_value)) - self.interface_float_adjustments.append(adjustment_name) + self.interface_float_adjustments.append( (adjustment_name, callback)) - def add_list(self,liststore_name): + def add_list(self,liststore_name,callback = None): + """ Adds an internal variable with the name liststore_name, linked to + an element with the same name (must be a Gtk.ListStore). """ exec('self.'+liststore_name+' = []') - self.interface_lists.append(liststore_name) + self.interface_lists.append( (liststore_name, callback )) + + def add_colorbutton(self,colorbutton_name, default_value,callback = None): + """ Adds an internal variable with the name text_name, linked to an + element with the same name (must be a Gtk.ColorButton). + The default value must be a set with RGBA values """ + + exec('self.'+colorbutton_name+' = default_value') + self.interface_colorbuttons.append( (colorbutton_name, callback )) def add_show_hide(self,element_name,to_show,to_hide): """ Adds an element that can be active or inactive, and two lists of elements. @@ -119,17 +131,30 @@ class interface_manager(GObject.GObject): for key in self.interface_groups: obj = eval('self.'+key) builder.get_object(obj).set_active(True) + callback = self.interface_groups[key][1] + if (callback != None): + for element in self.interface_groups[key][0]: + obj = builder.get_object(element) + obj.connect("toggled",callback) for element in self.interface_toggles: - value = eval('self.'+element) - builder.get_object(element).set_active(value) + value = eval('self.'+element[0]) + obj = builder.get_object(element[0]) + obj.set_active(value) + callback = element[1] + if (callback != None): + obj.connect("toggled",callback) for element in self.interface_text: - value = eval('self.'+element) + value = eval('self.'+element[0]) + obj = builder.get_object(element[0]) if (value != None): - builder.get_object(element).set_text(value) + obj.set_text(value) else: - builder.get_object(element).set_text("") + obj.set_text("") + callback = element[1] + if (callback != None): + obj.connect("changed",callback) for element in self.interface_labels: value = eval('self.'+element) @@ -139,19 +164,43 @@ class interface_manager(GObject.GObject): builder.get_object(element).set_text("") for element in self.interface_integer_adjustments: - value = eval('self.'+element) - builder.get_object(element).set_value(float(value)) + value = eval('self.'+element[0]) + obj = builder.get_object(element[0]) + obj.set_value(float(value)) + callback = element[1] + if (callback != None): + obj.connect("value_changed",callback) for element in self.interface_float_adjustments: - value = eval('self.'+element) - builder.get_object(element).set_value(value) + value = eval('self.'+element[0]) + obj = builder.get_object(element[0]) + obj.set_value(value) + callback = element[1] + if (callback != None): + obj.connect("value_changed",callback) for element in self.interface_lists: - obj = eval('self.'+element) - the_liststore = builder.get_object(element) + obj = eval('self.'+element[0]) + the_liststore = builder.get_object(element[0]) the_liststore.clear() for item in obj: the_liststore.append(item) + callback = element[1] + if (callback != None): + the_liststore.connect("row_changed",callback) + the_liststore.connect("row_deleted",callback) + the_liststore.connect("row_inserted",callback) + the_liststore.connect("row_reordered",callback) + + for element in self.interface_colorbuttons: + value = eval('self.'+element[0]) + colorbtn = builder.get_object(element[0]) + objcolor = Gdk.Color(int(value[0]*65535.0),int(value[1]*65535.0),int(value[2]*65535.0)) + colorbtn.set_color(objcolor) + colorbtn.set_alpha(int(value[3]*65535.0)) + callback = element[1] + if (callback != None): + colorbtn.connect("color_set",callback) self.interface_show_hide_obj = {} for element in self.interface_show_hide: @@ -250,39 +299,46 @@ class interface_manager(GObject.GObject): """ Takes the values of the widgets and stores them in the internal variables """ for key in self.interface_groups: - for element in self.interface_groups[key]: + for element in self.interface_groups[key][0]: obj = builder.get_object(element) if obj.get_active(): exec('self.'+key+' = "'+element+'"') break for element in self.interface_toggles: - obj = builder.get_object(element) + obj = builder.get_object(element[0]) if obj.get_active(): - exec('self.'+element+' = True') + exec('self.'+element[0]+' = True') else: - exec('self.'+element+' = False') + exec('self.'+element[0]+' = False') for element in self.interface_text: - obj = builder.get_object(element) - exec('self.'+element+' = obj.get_text()') + obj = builder.get_object(element[0]) + exec('self.'+element[0]+' = obj.get_text()') for element in self.interface_integer_adjustments: - obj = builder.get_object(element) - exec('self.'+element+' = int(obj.get_value())') + obj = builder.get_object(element[0]) + exec('self.'+element[0]+' = int(obj.get_value())') for element in self.interface_float_adjustments: - obj = builder.get_object(element) - exec('self.'+element+' = obj.get_value()') + obj = builder.get_object(element[0]) + exec('self.'+element[0]+' = obj.get_value()') + + for element in self.interface_colorbuttons: + + colorbtn = builder.get_object(element[0]) + objcolor = colorbtn.get_color() + alpha = colorbtn.get_alpha() + exec('self.'+element[0]+' = ((float(objcolor.red))/65535.0, (float(objcolor.green))/65535.0, (float(objcolor.blue))/65535.0, (float(alpha))/65535.0)') for element in self.interface_lists: - exec('self.'+element+' = []') - the_liststore = builder.get_object(element) + exec('self.'+element[0]+' = []') + the_liststore = builder.get_object(element[0]) ncolumns = the_liststore.get_n_columns() for row in the_liststore: final_row = [] for c in range(0,ncolumns): final_row.append(row.model[row.iter][c]) print (final_row) - exec('self.'+element+'.append(final_row)') + exec('self.'+element[0]+'.append(final_row)') \ No newline at end of file diff --git a/src/devede/project.py b/src/devede/project.py index 01e6714..4f83ff8 100644 --- a/src/devede/project.py +++ b/src/devede/project.py @@ -22,6 +22,7 @@ import devede.file_movie import devede.ask import devede.add_files import devede.message +import devede.dvd_menu class devede_project: @@ -30,6 +31,7 @@ class devede_project: self.config = devede.configuration_data.configuration.get_config() self.disc_type = self.config.disc_type + self.menu = devede.dvd_menu.dvd_menu() self.current_title = None @@ -47,9 +49,14 @@ class devede_project: self.wdisc_fill_level = builder.get_object("disc_fill_level") self.wuse_pal = builder.get_object("use_pal") self.wuse_ntsc = builder.get_object("use_ntsc") - self.wcreate_menu = builder.get_object("create_menu") self.wframe_titles = builder.get_object("frame_titles") + self.wframe_menu = builder.get_object("frame_menu") + self.wcreate_menu = builder.get_object("create_menu") + self.wmenu_options = builder.get_object("menu_options") + self.wpreview_menu = builder.get_object("preview_menu") + + self.wadd_file = builder.get_object("add_file") self.wdelete_file = builder.get_object("delete_file") self.wup_file = builder.get_object("up_file") @@ -67,6 +74,8 @@ class devede_project: else: self.wuse_ntsc.set_active(True) + self.wcreate_menu.set_active(True) + self.config.connect('disc_type',self.set_type) if (self.disc_type != None): self.set_type(None, self.disc_type) @@ -88,6 +97,11 @@ class devede_project: else: self.wdisc_size.set_active(3) # 700 MB CD + if (self.disc_type == "dvd"): + self.wframe_menu.show_all() + else: + self.wframe_menu.hide() + def get_current_file(self): @@ -119,6 +133,12 @@ class devede_project: self.wproperties_file.set_sensitive(True) self.wpreview_file.set_sensitive(True) + self.config.PAL = self.wuse_pal.get_active() + + status = self.wcreate_menu.get_active() + self.wmenu_options.set_sensitive(status) + self.wpreview_menu.set_sensitive(status) + (element, position, model, treeiter) = self.get_current_file() if (element == None): self.wdelete_file.set_sensitive(False) @@ -138,7 +158,9 @@ class devede_project: def on_use_pal_toggled(self,b): - self.config.PAL = self.wuse_pal.get_active() + self.set_interface_status(None) + + def on_wmain_window_delete_event(self,b,e=None): @@ -210,8 +232,13 @@ class devede_project: return element.properties() + def on_create_menu_toggled(self,b): + self.set_interface_status(None) + def on_adjust_disc_usage_clicked(self,b): pass + def on_menu_options_clicked(self,b): + self.menu.show_configuration() \ No newline at end of file