コード例 #1
0
 def update_menu(self, widget=None):	
     pref_menu=gtk.Menu()
     self.add_submenu_items( pref_menu, Config.default_preferred_apps )
 	self.build_menu_separator( pref_menu )
     self.add_submenu_items( pref_menu, DesktopFileSet().get_configured_from_check() )
     pref_menu.show()
     self.prefered_app_submenu.set_submenu(pref_menu)
コード例 #2
0
ファイル: AppSettings.py プロジェクト: Lukypie/bumblebeeui
    def __init__(self):
        #FIXME Seems not to be clean or shorter enough
        self.file_set=DesktopFileSet()
        self.icon_set=IconSet()
        # MAIN WINDOW
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.connect("delete_event", self.delete_event)
        self.window.connect("destroy", self.destroy)
        self.window.set_title("Bumblebee - Applications Settings")
        self.window.set_border_width(0)
        self.window.set_size_request(600,600)
        # MAIN WINDOW ICON : monitor and launcher
        self.window.set_icon(self.icon_set.get_pixbuf('bumblebee', 48))
        		
        # NOTEBOOK
        self.notebook= gtk.Notebook()
        self.notebook.set_tab_pos(gtk.POS_TOP)
        self.notebook.set_border_width(10)
        self.window.add(self.notebook)
        		
        # SELECT APPLICATION 
            # LIST
        self.build_app_list()
        
            # VIEW
        self.select_app_view = gtk.TreeView(self.app_list)
        self.treeselection = self.select_app_view.get_selection()
        self.treeselection.set_mode(gtk.SELECTION_NONE)
        self.select_app_view.set_rules_hint(True)
        self.select_app_view.show()
        self.build_select_view()
        
            # EXPAND CATEGORIES WITH CHILD
        try : 
            for categorie in self.categories_iter_with_child:
                categorie_iter,count= self.categories_iter_with_child[categorie]
                self.select_app_view.expand_to_path(self.app_list.get_path(categorie_iter))
        except : self.select_app_view.expand_all()
        
            # PAGE
        self.select_page = self.build_notebook_page( 
            tab_title = "Select applications",
            instruction_text = "Choose the application you want to configure to use with the discrete graphic card.",
            view = self.select_app_view ,
            button_list = [self.action_button(stock=gtk.STOCK_APPLY, action=self.apply_app_set),self.action_button(label="Apply Now",action=self.apply_app_set)] )
#TODO Create an apply now button which relaunch unity with unity --replace or use dynamic desktop configuration (See Ubuntu desktop specification)
        # CONFIGURE APPLICATION
            # LIST
        self.configured_apps = self.app_list.filter_new(root=None)
        self.configured_apps.set_visible_column(5)
        
            # VIEW
        self.config_app_view = gtk.TreeView(self.configured_apps)
        self.config_app_view.set_rules_hint(True)
        self.build_config_view()
        self.config_app_view.show()
        
            # PAGE
        self.configure_page = self.build_notebook_page(
            tab_title="Configure applications", 
            instruction_text="Choose the configuration for each application.\n Depending on mode the discrete card will be launched: always (Performance),\n only when plugged (Power Save) or with launcher shortcuts (Option)" ,
            view=self.config_app_view )
        
#FIXME : Set the focus on configure page doesn't work
        if self.configured_file_exist==True: self.notebook.set_current_page(self.configure_page)
        else: self.select_app_view.expand_all()
        
        #SHOW ALL
        self.window.show_all()
コード例 #3
0
ファイル: AppSettings.py プロジェクト: Lukypie/bumblebeeui
class Applications_settings():
#TODO This initialization should be avoid or rethinked
    to_modify_file=[]
    to_configure_file={}
    to_unconfigure_file={}
    categories_iter_with_child={}
    configured_file_exist=False
	
    def delete_event(self,widget,event,data=None):
        return False

    def destroy(self,widget): 
        if __name__=="__main__": gtk.main_quit()
        else : self.window.destroy()
		
    def __init__(self):
        #FIXME Seems not to be clean or shorter enough
        self.file_set=DesktopFileSet()
        self.icon_set=IconSet()
        # MAIN WINDOW
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.connect("delete_event", self.delete_event)
        self.window.connect("destroy", self.destroy)
        self.window.set_title("Bumblebee - Applications Settings")
        self.window.set_border_width(0)
        self.window.set_size_request(600,600)
        # MAIN WINDOW ICON : monitor and launcher
        self.window.set_icon(self.icon_set.get_pixbuf('bumblebee', 48))
        		
        # NOTEBOOK
        self.notebook= gtk.Notebook()
        self.notebook.set_tab_pos(gtk.POS_TOP)
        self.notebook.set_border_width(10)
        self.window.add(self.notebook)
        		
        # SELECT APPLICATION 
            # LIST
        self.build_app_list()
        
            # VIEW
        self.select_app_view = gtk.TreeView(self.app_list)
        self.treeselection = self.select_app_view.get_selection()
        self.treeselection.set_mode(gtk.SELECTION_NONE)
        self.select_app_view.set_rules_hint(True)
        self.select_app_view.show()
        self.build_select_view()
        
            # EXPAND CATEGORIES WITH CHILD
        try : 
            for categorie in self.categories_iter_with_child:
                categorie_iter,count= self.categories_iter_with_child[categorie]
                self.select_app_view.expand_to_path(self.app_list.get_path(categorie_iter))
        except : self.select_app_view.expand_all()
        
            # PAGE
        self.select_page = self.build_notebook_page( 
            tab_title = "Select applications",
            instruction_text = "Choose the application you want to configure to use with the discrete graphic card.",
            view = self.select_app_view ,
            button_list = [self.action_button(stock=gtk.STOCK_APPLY, action=self.apply_app_set),self.action_button(label="Apply Now",action=self.apply_app_set)] )
#TODO Create an apply now button which relaunch unity with unity --replace or use dynamic desktop configuration (See Ubuntu desktop specification)
        # CONFIGURE APPLICATION
            # LIST
        self.configured_apps = self.app_list.filter_new(root=None)
        self.configured_apps.set_visible_column(5)
        
            # VIEW
        self.config_app_view = gtk.TreeView(self.configured_apps)
        self.config_app_view.set_rules_hint(True)
        self.build_config_view()
        self.config_app_view.show()
        
            # PAGE
        self.configure_page = self.build_notebook_page(
            tab_title="Configure applications", 
            instruction_text="Choose the configuration for each application.\n Depending on mode the discrete card will be launched: always (Performance),\n only when plugged (Power Save) or with launcher shortcuts (Option)" ,
            view=self.config_app_view )
        
#FIXME : Set the focus on configure page doesn't work
        if self.configured_file_exist==True: self.notebook.set_current_page(self.configure_page)
        else: self.select_app_view.expand_all()
        
        #SHOW ALL
        self.window.show_all()
    	
    def build_notebook_page(self , tab_title, instruction_text , view , button_list=[]):
        # INSTRUCTION FRAME
        instruction_frame = self.return_instruction_frame(instruction_text)
        # SCROLL FRAME
        scrolled_window=gtk.ScrolledWindow()
        scrolled_window.add(view)
        # ACTION AREA
        hbox=gtk.HBox(homogeneous=False, spacing=10)
        # SPECIFIC BUTTON
        for button in button_list : hbox.pack_start(button, False, False, 10)
        # CLOSE BUTTON
        hbox.pack_end(self.action_button(stock=gtk.STOCK_CLOSE, action=self.destroy), False, False, 10)
        # CONTAINER
        vbox= gtk.VBox(homogeneous=False)
        vbox.pack_start(instruction_frame, False, False, 0)
        vbox.pack_start(scrolled_window, True, True, 10)
        vbox.pack_end(hbox, False, False, 10)
        # NOTEBOOK PAGE
        notebook_label= gtk.Label(tab_title)
        return self.notebook.append_page(vbox, notebook_label)
    
    def return_instruction_frame(self,text):
        """Return an instruction frame with the text given"""
        instruction_frame = gtk.Frame()
        instruction = gtk.Label(text)
        #instruction.set_justify(gtk.JUSTIFY_LEFT)
        instruction_frame.set_border_width(10)
#FIXME : There is a problem with the instruction frame text rendering : use size_allocate to dynamicaly set the size of label
        #instruction.set_line_wrap(True)
        instruction_frame.add(instruction)
        return instruction_frame
    
    def action_button(self, action, label=None, stock=None):
        button= gtk.Button(label,stock)
        button.set_size_request(width=100,height=-1)
        button.connect("clicked",action)
        return button
	
    def build_app_list(self):
        """Function to build the store with this columns :
        *Application Name or Categorie Name, *File Name, *Application Categorie, *Application Icon Path, Is Not Category, Configured, (Selected by default), Mode,  32bits, Compression, Background display, Background color
        for categories : Categorie Name, None, None, Icon Path, False , Has child configured, False, None, 
        """
        self.app_list = gtk.TreeStore(str,str,str,gtk.gdk.Pixbuf,bool,bool,bool,str,bool,str,bool,str)
        self.categorie_iter={}
        # CATEFORIE ROWS
        for [categorie, icon_name] in Config.categorie_list + [Config.unmatch_categorie, Config.uncategorized_categorie]:
            iter=self.app_list.append(None, [categorie,None,None] + [self.icon_set.get_pixbuf(icon_name)] + 3*[False] + 3*[None] + [False, Config.to_configure_color])
            self.categorie_iter.update({categorie:iter})
        # APPLICATIONS ROWS
        for app_info in self.file_set.get_apps_info():
            parent_iter=self.categorie_iter.get(app_info[2])
            app_info[3]=self.icon_set.get_pixbuf(app_info[3])
            if app_info[5] == True:
                self.configured_file_exist=True
                self.app_list.append(parent_iter, app_info + [True, Config.configured_color])
                self.app_list[parent_iter][5]=True #Used to only show the categories with configured child
                self.add_child_for_categorie(app_info[2])
            else : self.app_list.append(parent_iter, app_info + [False, Config.to_configure_color])

    def build_select_view(self):
        # APPLICATION OR CATEGORIE NAME COLUMN
        self.column = gtk.TreeViewColumn('Applications')

        # SELECT CHECKBOX
        rendererToggle = gtk.CellRendererToggle()
        self.column.pack_start(rendererToggle, True)
        self.column.set_attributes(rendererToggle, active=6, visible=4)
        rendererToggle.set_property('activatable', True)
        rendererToggle.connect('toggled', self.on_select_app)
		
        # APPLICATION ICON
        rendererIcon=gtk.CellRendererPixbuf()
        self.column.pack_start(rendererIcon, True)
        self.column.set_attributes(rendererIcon, pixbuf=3)

        # APPLICATION NAME
        rendererText=gtk.CellRendererText()
        self.column.pack_start(rendererText, True)
        self.column.set_attributes(rendererText, text=0)

        # BACKGROUND COLOR SET
        for renderer in [rendererToggle, rendererIcon, rendererText]:
            self.column.add_attribute(renderer, "cell-background-set", 10)
            self.column.add_attribute(renderer, "cell-background", 11)
        #self.column.set_min_width(300) : cause problem with the pack start
#FIXME : the style must be refined in order to have a better display for the user : size if the icon, name of the application and categorie display
#FIXME : there must be a better way also to change the row color depending on state (this color can be changed by a color id that can be used to know the state of the application ??? in order to have a smoother treestore
        self.column.set_max_width(350) 
		
        #FILE NAME COLUMN
        self.select_app_view.append_column(self.column)
        rendererText2=gtk.CellRendererText()
        column1 = gtk.TreeViewColumn('File Name',rendererText2, text=1)
        column1.add_attribute(rendererText2, "cell-background-set",10)
        column1.add_attribute(rendererText2, "cell-background",11)
        self.select_app_view.append_column(column1)
        self.select_app_view.set_level_indentation(10)
        
    def on_select_app(self, cell, row):
#TODO : Find a better way to manage row color change
        self.app_list[row][6] = not self.app_list[row][6]
        Configured, Selected= self.app_list[row][5], self.app_list[row][6]
        if Configured==True and Selected==False : #The app will be Unconfigured
            self.app_list[row][10],self.app_list[row][11]=True,Config.to_unconfigure_color
            self.to_unconfigure_file.update({self.app_list[row][1]:self.app_list.get_iter(row)})
        elif Configured==True and Selected==True : #The configured app is reselected: Nothing to apply
            self.app_list[row][10],self.app_list[row][11]=True,Config.configured_color
            del self.to_unconfigure_file[self.app_list[row][1]]
        elif Configured==False and Selected==True : #The app will be Configured
            self.app_list[row][10],self.app_list[row][11]=True,Config.to_configure_color
            self.to_configure_file.update({self.app_list[row][1]:self.app_list.get_iter(row)})
        elif Configured==False and Selected==False : #The app is not configured and unselected: Nothing to apply
            self.app_list[row][10]=False
            del self.to_configure_file[self.app_list[row][1]]
	
    def build_config_view(self):
        """Function to create a setting list for applications configured for Bumblebee"""
        # APPLICATION NAME COLUMNS
        self.column=gtk.TreeViewColumn('Applications')
        
        rendererIcon=gtk.CellRendererPixbuf()
        self.column.pack_start(rendererIcon, False)
        self.column.set_attributes(rendererIcon, pixbuf=3)
        rendererText=gtk.CellRendererText()
        self.column.pack_start(rendererText, False)
        self.column.set_attributes(rendererText, text=0)
        
        self.config_app_view.append_column(self.column)
        
        # MODE, DRIVER AND COMPRESSION COLUMN
        self.build_combo_column("Mode", 7, Config.mode_keys.values())
        
        self.build_config_column ("32bits Driver", 8)
        
        self.build_combo_column("Compression", 9, ["default"] + Config.compression_list)
        
        self.config_app_view.set_level_indentation(20)
        self.config_app_view.expand_all()
        self.config_app_view.set_show_expanders(False)

    def build_combo_column(self, column_name, column_id, value_list):
        """Function to build the columns with selection from a list"""
        # COMBOBOX CELL
        combo_list = gtk.ListStore(str)
        for value in value_list: combo_list.append([value])
        rendererCombo = gtk.CellRendererCombo()
        rendererCombo.set_properties(model=combo_list, editable=True)
        rendererCombo.set_property("has-entry", False)
        rendererCombo.set_property("text-column", 0)
        rendererCombo.connect("edited", self.on_combo_edit, column_id)
        # COMBOBOX COLUMN
        column = gtk.TreeViewColumn(column_name)
        column.pack_start(rendererCombo, False)
        column.add_attribute(rendererCombo, "text", column_id)
        column.add_attribute(rendererCombo, "visible", 4)
        self.config_app_view.append_column(column)

    def on_combo_edit(self, cell , path , new_text, column_id):
        filter_iter = self.configured_apps.get_iter(path)
        iter = self.configured_apps.convert_iter_to_child_iter(filter_iter)
        self.app_list[iter][column_id] = new_text
        DesktopFile(self.app_list[iter][1]).set_exec_config(self.app_list[iter][7],self.app_list[iter][8],self.app_list[iter][9])

    def build_config_column(self, column_name, column_id):
        rendererToggle = gtk.CellRendererToggle()
        rendererToggle.set_property('activatable', True)
        rendererToggle.connect('toggled', self.on_config_check ,(self.configured_apps, column_id))
        
        column = gtk.TreeViewColumn(column_name, rendererToggle, active=column_id, visible=4)
        self.config_app_view.append_column(column)
	
    def on_config_check(self, cell, row, user_data):
        model, column = user_data
        iter = model.convert_iter_to_child_iter(model.get_iter(row))
        self.app_list[iter][column] = not self.app_list[iter][column]
        DesktopFile(self.app_list[iter][1]).set_exec_config(self.app_list[iter][7],self.app_list[iter][8],self.app_list[iter][9])

    def apply_app_set (self,widget,data=None):
        for file_name, iter in self.to_configure_file.iteritems(): #The app is to configure
            self.apply_app_change ( iter, file_name, [self.file_set.configure_file, self.add_child_for_categorie], 
                                    True, Config.mode_keys['option'], True, Config.configured_color)
        self.to_configure_file.clear()
        for file_name, iter in self.to_unconfigure_file.iteritems(): #The app is to unconfigure
            self.apply_app_change ( iter, file_name, [self.file_set.unconfigure_file, self.remove_child_for_categorie],
                                    False, False, False, Config.to_configure_color)
        self.to_unconfigure_file.clear()
        self.config_app_view.expand_all()

    def apply_app_change (self, iter, file_name, actions, configured, mode, display_bg, bg_color):
        actions[0](file_name)
        self.app_list.set(iter, 5, configured, 7, mode, 10, display_bg, 11, bg_color)
        actions[1](self.app_list.get_value(iter,2))

#TODO There must be thing done to deal with categories having configured child : simplify this function
    def add_child_for_categorie(self,categorie_name):
        if self.categories_iter_with_child.has_key(categorie_name): 
            parent_iter, count=self.categories_iter_with_child[categorie_name]
            child_count= count+1
        else: child_count=1
        self.categories_iter_with_child.update({categorie_name:[self.categorie_iter[categorie_name], child_count]})
        self.app_list.set(self.categorie_iter[categorie_name], 5, True)
	
    def remove_child_for_categorie(self,categorie_name):
        if self.categories_iter_with_child.has_key(categorie_name):
            parent_iter, count=self.categories_iter_with_child[categorie_name]
            child_count= count-1
            self.categories_iter_with_child.update({categorie_name:[parent_iter, child_count]})
            if child_count==0 : 
                del self.categories_iter_with_child[categorie_name]
                self.app_list.set(self.categorie_iter[categorie_name], 5, False)
		
    def main(self):
        gtk.main()
        return 0			
コード例 #4
0
    def __init__(self):
        #FIXME Seems not to be clean or shorter enough
        self.file_set = DesktopFileSet()
        self.icon_set = IconSet()
        # MAIN WINDOW
        self.window = Gtk.Window.new(Gtk.WindowType.TOPLEVEL)
        self.window.connect("delete_event", self.delete_event)
        self.window.connect("destroy", self.destroy)
        self.window.set_title("Bumblebee - Applications Settings")
        self.window.set_border_width(0)
        self.window.set_size_request(600, 600)
        # MAIN WINDOW ICON : monitor and launcher
        self.window.set_icon(self.icon_set.get_pixbuf('bumblebee', 48))

        # NOTEBOOK
        self.notebook = Gtk.Notebook()
        self.notebook.set_tab_pos(Gtk.PositionType.TOP)
        self.notebook.set_border_width(10)
        self.window.add(self.notebook)

        # SELECT APPLICATION
        # LIST
        self.build_app_list()

        # VIEW
        self.select_app_view = Gtk.TreeView(self.app_list)
        self.treeselection = self.select_app_view.get_selection()
        self.treeselection.set_mode(Gtk.SelectionMode.NONE)
        self.select_app_view.set_rules_hint(True)
        self.select_app_view.show()
        self.build_select_view()

        # EXPAND CATEGORIES WITH CHILD
        try:
            for categorie in self.categories_iter_with_child:
                categorie_iter, count = self.categories_iter_with_child[
                    categorie]
                self.select_app_view.expand_to_path(
                    self.app_list.get_path(categorie_iter))
        except:
            self.select_app_view.expand_all()

        # PAGE
        self.select_page = self.build_notebook_page(
            tab_title="Select applications",
            instruction_text=
            "Choose the application you want to configure to use with the discrete graphic card.",
            view=self.select_app_view,
            button_list=[
                self.action_button(stock=Gtk.STOCK_APPLY,
                                   action=self.apply_app_set),
                self.action_button(label="Apply Now",
                                   action=self.apply_app_set)
            ])
        #TODO Create an apply now button which relaunch unity with unity --replace or use dynamic desktop configuration (See Ubuntu desktop specification)
        # CONFIGURE APPLICATION
        # LIST
        self.configured_apps = self.app_list.filter_new(root=None)
        self.configured_apps.set_visible_column(5)

        # VIEW
        self.config_app_view = Gtk.TreeView(self.configured_apps)
        self.config_app_view.set_rules_hint(True)
        self.build_config_view()
        self.config_app_view.show()

        # PAGE
        self.configure_page = self.build_notebook_page(
            tab_title="Configure applications",
            instruction_text=
            "Choose the configuration for each application.\n Depending on mode the discrete card will be launched: always (Performance),\n only when plugged (Power Save) or with launcher shortcuts (Option)",
            view=self.config_app_view)

        #FIXME : Set the focus on configure page doesn't work
        if self.configured_file_exist == True:
            self.notebook.set_current_page(self.configure_page)
        else:
            self.select_app_view.expand_all()

        #SHOW ALL
        self.window.show_all()
コード例 #5
0
class Applications_settings():
    #TODO This initialization should be avoid or rethinked
    to_modify_file = []
    to_configure_file = {}
    to_unconfigure_file = {}
    categories_iter_with_child = {}
    configured_file_exist = False

    def delete_event(self, widget, event, data=None):
        return False

    def destroy(self, widget):
        if __name__ == "__main__": Gtk.main_quit()
        else: self.window.destroy()

    def __init__(self):
        #FIXME Seems not to be clean or shorter enough
        self.file_set = DesktopFileSet()
        self.icon_set = IconSet()
        # MAIN WINDOW
        self.window = Gtk.Window.new(Gtk.WindowType.TOPLEVEL)
        self.window.connect("delete_event", self.delete_event)
        self.window.connect("destroy", self.destroy)
        self.window.set_title("Bumblebee - Applications Settings")
        self.window.set_border_width(0)
        self.window.set_size_request(600, 600)
        # MAIN WINDOW ICON : monitor and launcher
        self.window.set_icon(self.icon_set.get_pixbuf('bumblebee', 48))

        # NOTEBOOK
        self.notebook = Gtk.Notebook()
        self.notebook.set_tab_pos(Gtk.PositionType.TOP)
        self.notebook.set_border_width(10)
        self.window.add(self.notebook)

        # SELECT APPLICATION
        # LIST
        self.build_app_list()

        # VIEW
        self.select_app_view = Gtk.TreeView(self.app_list)
        self.treeselection = self.select_app_view.get_selection()
        self.treeselection.set_mode(Gtk.SelectionMode.NONE)
        self.select_app_view.set_rules_hint(True)
        self.select_app_view.show()
        self.build_select_view()

        # EXPAND CATEGORIES WITH CHILD
        try:
            for categorie in self.categories_iter_with_child:
                categorie_iter, count = self.categories_iter_with_child[
                    categorie]
                self.select_app_view.expand_to_path(
                    self.app_list.get_path(categorie_iter))
        except:
            self.select_app_view.expand_all()

        # PAGE
        self.select_page = self.build_notebook_page(
            tab_title="Select applications",
            instruction_text=
            "Choose the application you want to configure to use with the discrete graphic card.",
            view=self.select_app_view,
            button_list=[
                self.action_button(stock=Gtk.STOCK_APPLY,
                                   action=self.apply_app_set),
                self.action_button(label="Apply Now",
                                   action=self.apply_app_set)
            ])
        #TODO Create an apply now button which relaunch unity with unity --replace or use dynamic desktop configuration (See Ubuntu desktop specification)
        # CONFIGURE APPLICATION
        # LIST
        self.configured_apps = self.app_list.filter_new(root=None)
        self.configured_apps.set_visible_column(5)

        # VIEW
        self.config_app_view = Gtk.TreeView(self.configured_apps)
        self.config_app_view.set_rules_hint(True)
        self.build_config_view()
        self.config_app_view.show()

        # PAGE
        self.configure_page = self.build_notebook_page(
            tab_title="Configure applications",
            instruction_text=
            "Choose the configuration for each application.\n Depending on mode the discrete card will be launched: always (Performance),\n only when plugged (Power Save) or with launcher shortcuts (Option)",
            view=self.config_app_view)

        #FIXME : Set the focus on configure page doesn't work
        if self.configured_file_exist == True:
            self.notebook.set_current_page(self.configure_page)
        else:
            self.select_app_view.expand_all()

        #SHOW ALL
        self.window.show_all()

    def build_notebook_page(self,
                            tab_title,
                            instruction_text,
                            view,
                            button_list=[]):
        # INSTRUCTION FRAME
        instruction_frame = self.return_instruction_frame(instruction_text)
        # SCROLL FRAME
        scrolled_window = Gtk.ScrolledWindow()
        scrolled_window.add(view)
        # ACTION AREA
        hbox = Gtk.HBox(homogeneous=False, spacing=10)
        # SPECIFIC BUTTON
        for button in button_list:
            hbox.pack_start(button, False, False, 10)
        # CLOSE BUTTON
        hbox.pack_end(
            self.action_button(stock=Gtk.STOCK_CLOSE, action=self.destroy),
            False, False, 10)
        # CONTAINER
        vbox = Gtk.VBox(homogeneous=False)
        vbox.pack_start(instruction_frame, False, False, 0)
        vbox.pack_start(scrolled_window, True, True, 10)
        vbox.pack_end(hbox, False, False, 10)
        # NOTEBOOK PAGE
        notebook_label = Gtk.Label(label=tab_title)
        return self.notebook.append_page(vbox, notebook_label)

    def return_instruction_frame(self, text):
        """Return an instruction frame with the text given"""
        instruction_frame = Gtk.Frame()
        instruction = Gtk.Label(label=text)
        #instruction.set_justify(Gtk.Justification.LEFT)
        instruction_frame.set_border_width(10)
        #FIXME : There is a problem with the instruction frame text rendering : use size_allocate to dynamicaly set the size of label
        #instruction.set_line_wrap(True)
        instruction_frame.add(instruction)
        return instruction_frame

    def action_button(self, action, label=None, stock=None):
        button = Gtk.Button(label, stock)
        button.set_size_request(width=100, height=-1)
        button.connect("clicked", action)
        return button

    def build_app_list(self):
        """Function to build the store with this columns :
        *Application Name or Categorie Name, *File Name, *Application Categorie, *Application Icon Path, Is Not Category, Configured, (Selected by default), Mode,  32bits, Compression, Background display, Background color
        for categories : Categorie Name, None, None, Icon Path, False , Has child configured, False, None, 
        """
        self.app_list = Gtk.TreeStore(str, str, str, GdkPixbuf.Pixbuf, bool,
                                      bool, bool, str, bool, str, bool, str)
        self.categorie_iter = {}

        # CATEGORIE ROWS
        for [categorie, icon_name] in Config.categorie_list + [
                Config.unmatch_categorie, Config.uncategorized_categorie
        ]:
            iter = self.app_list.append(None, [categorie, None, None] +
                                        [self.icon_set.get_pixbuf(icon_name)] +
                                        3 * [False] + 3 * [None] +
                                        [False, Config.to_configure_color])
            self.categorie_iter.update({categorie: iter})

        # APPLICATIONS ROWS
        for app_info in self.file_set.get_apps_info():
            parent_iter = self.categorie_iter.get(app_info[2])
            app_info[3] = self.icon_set.get_pixbuf(app_info[3])
            if app_info[5] == True:
                self.configured_file_exist = True
                #print ['if: '] + app_info + [True, Config.configured_color]
                self.app_list.append(
                    parent_iter, app_info + [True, Config.configured_color])
                self.app_list[parent_iter][
                    5] = True  #Used to only show the categories with configured child
                self.add_child_for_categorie(app_info[2])
            else:
                #print ['else: '] + app_info + [False, Config.to_configure_color]
                self.app_list.append(
                    parent_iter, app_info + [False, Config.to_configure_color])

    def build_select_view(self):
        # APPLICATION OR CATEGORIE NAME COLUMN
        self.column = Gtk.TreeViewColumn('Applications')

        # SELECT CHECKBOX
        rendererToggle = Gtk.CellRendererToggle()
        self.column.pack_start(rendererToggle, True)
        self.column.add_attribute(rendererToggle, 'active', 6)
        self.column.add_attribute(rendererToggle, 'visible', 4)
        rendererToggle.set_property('activatable', True)
        rendererToggle.connect('toggled', self.on_select_app)

        # APPLICATION ICON
        rendererIcon = Gtk.CellRendererPixbuf()
        self.column.pack_start(rendererIcon, True)
        self.column.add_attribute(rendererIcon, 'pixbuf', 3)

        # APPLICATION NAME
        rendererText = Gtk.CellRendererText()
        self.column.pack_start(rendererText, True)
        self.column.add_attribute(rendererText, 'text', 0)

        # BACKGROUND COLOR SET
        for renderer in [rendererToggle, rendererIcon, rendererText]:
            self.column.add_attribute(renderer, "cell-background-set", 10)
            self.column.add_attribute(renderer, "cell-background", 11)
        #self.column.set_min_width(300) : cause problem with the pack start
#FIXME : the style must be refined in order to have a better display for the user : size if the icon, name of the application and categorie display
#FIXME : there must be a better way also to change the row color depending on state (this color can be changed by a color id that can be used to know the state of the application ??? in order to have a smoother treestore
        self.column.set_max_width(350)

        #FILE NAME COLUMN
        self.select_app_view.append_column(self.column)
        rendererText2 = Gtk.CellRendererText()
        column1 = Gtk.TreeViewColumn('File Name', rendererText2, text=1)
        column1.add_attribute(rendererText2, "cell-background-set", 10)
        column1.add_attribute(rendererText2, "cell-background", 11)
        self.select_app_view.append_column(column1)
        self.select_app_view.set_level_indentation(10)

    def on_select_app(self, cell, row):
        #TODO : Find a better way to manage row color change
        self.app_list[row][6] = not self.app_list[row][6]
        Configured, Selected = self.app_list[row][5], self.app_list[row][6]
        if Configured == True and Selected == False:  #The app will be Unconfigured
            self.app_list[row][10], self.app_list[row][
                11] = True, Config.to_unconfigure_color
            self.to_unconfigure_file.update(
                {self.app_list[row][1]: self.app_list.get_iter(row)})
        elif Configured == True and Selected == True:  #The configured app is reselected: Nothing to apply
            self.app_list[row][10], self.app_list[row][
                11] = True, Config.configured_color
            del self.to_unconfigure_file[self.app_list[row][1]]
        elif Configured == False and Selected == True:  #The app will be Configured
            self.app_list[row][10], self.app_list[row][
                11] = True, Config.to_configure_color
            self.to_configure_file.update(
                {self.app_list[row][1]: self.app_list.get_iter(row)})
        elif Configured == False and Selected == False:  #The app is not configured and unselected: Nothing to apply
            self.app_list[row][10] = False
            del self.to_configure_file[self.app_list[row][1]]

    def build_config_view(self):
        """Function to create a setting list for applications configured for Bumblebee"""
        # APPLICATION NAME COLUMNS
        self.column = Gtk.TreeViewColumn('Applications')

        rendererIcon = Gtk.CellRendererPixbuf()
        self.column.pack_start(rendererIcon, False)
        self.column.add_attribute(rendererIcon, 'pixbuf', 3)
        rendererText = Gtk.CellRendererText()
        self.column.pack_start(rendererText, False)
        self.column.add_attribute(rendererText, 'text', 0)

        self.config_app_view.append_column(self.column)

        # MODE, DRIVER AND COMPRESSION COLUMN
        self.build_combo_column("Mode", 7, Config.mode_keys.values())

        self.build_config_column("32bits Driver", 8)

        self.build_combo_column("Compression", 9,
                                ["default"] + Config.compression_list)

        self.config_app_view.set_level_indentation(20)
        self.config_app_view.expand_all()
        self.config_app_view.set_show_expanders(False)

    def build_combo_column(self, column_name, column_id, value_list):
        """Function to build the columns with selection from a list"""
        # COMBOBOX CELL
        combo_list = Gtk.ListStore(str)
        for value in value_list:
            combo_list.append([value])
        rendererCombo = Gtk.CellRendererCombo()
        rendererCombo.set_properties(model=combo_list, editable=True)
        rendererCombo.set_property("has-entry", False)
        rendererCombo.set_property("text-column", 0)
        rendererCombo.connect("edited", self.on_combo_edit, column_id)
        # COMBOBOX COLUMN
        column = Gtk.TreeViewColumn(column_name)
        column.pack_start(rendererCombo, False)
        column.add_attribute(rendererCombo, "text", column_id)
        column.add_attribute(rendererCombo, "visible", 4)
        self.config_app_view.append_column(column)

    def on_combo_edit(self, cell, path, new_text, column_id):
        filter_iter = self.configured_apps.get_iter(path)
        iter = self.configured_apps.convert_iter_to_child_iter(filter_iter)
        self.app_list[iter][column_id] = new_text
        DesktopFile(self.app_list[iter][1]).set_exec_config(
            self.app_list[iter][7], self.app_list[iter][8],
            self.app_list[iter][9])

    def build_config_column(self, column_name, column_id):
        rendererToggle = Gtk.CellRendererToggle()
        rendererToggle.set_property('activatable', True)
        rendererToggle.connect('toggled', self.on_config_check,
                               (self.configured_apps, column_id))

        column = Gtk.TreeViewColumn(column_name,
                                    rendererToggle,
                                    active=column_id,
                                    visible=4)
        self.config_app_view.append_column(column)

    def on_config_check(self, cell, row, user_data):
        model, column = user_data
        iter = model.convert_iter_to_child_iter(model.get_iter(row))
        self.app_list[iter][column] = not self.app_list[iter][column]
        DesktopFile(self.app_list[iter][1]).set_exec_config(
            self.app_list[iter][7], self.app_list[iter][8],
            self.app_list[iter][9])

    def apply_app_set(self, widget, data=None):
        for file_name, iter in self.to_configure_file.iteritems(
        ):  #The app is to configure
            self.apply_app_change(
                iter, file_name,
                [self.file_set.configure_file, self.add_child_for_categorie],
                True, Config.mode_keys['option'], True,
                Config.configured_color)
        self.to_configure_file.clear()
        for file_name, iter in self.to_unconfigure_file.iteritems(
        ):  #The app is to unconfigure
            self.apply_app_change(iter, file_name, [
                self.file_set.unconfigure_file, self.remove_child_for_categorie
            ], False, False, False, Config.to_configure_color)
        self.to_unconfigure_file.clear()
        self.config_app_view.expand_all()

    def apply_app_change(self, iter, file_name, actions, configured, mode,
                         display_bg, bg_color):
        actions[0](file_name)
        self.app_list.set(iter, 5, configured, 7, mode, 10, display_bg, 11,
                          bg_color)
        actions[1](self.app_list.get_value(iter, 2))


#TODO There must be thing done to deal with categories having configured child : simplify this function

    def add_child_for_categorie(self, categorie_name):
        if self.categories_iter_with_child.has_key(categorie_name):
            parent_iter, count = self.categories_iter_with_child[
                categorie_name]
            child_count = count + 1
        else:
            child_count = 1
        self.categories_iter_with_child.update({
            categorie_name: [self.categorie_iter[categorie_name], child_count]
        })
        self.app_list.set(self.categorie_iter[categorie_name], 5, True)

    def remove_child_for_categorie(self, categorie_name):
        if self.categories_iter_with_child.has_key(categorie_name):
            parent_iter, count = self.categories_iter_with_child[
                categorie_name]
            child_count = count - 1
            self.categories_iter_with_child.update(
                {categorie_name: [parent_iter, child_count]})
            if child_count == 0:
                del self.categories_iter_with_child[categorie_name]
                self.app_list.set(self.categorie_iter[categorie_name], 5,
                                  False)

    def main(self):
        Gtk.main()
        return 0