# Copyright (C) 2009, Tutorius.org # # This program 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 2 of the License, or # (at your option) any later version. # # This program 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, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import gtk import gobject from Rating import Rating from WorkshopModel import WorkshopModel from WorkshopController import WorkshopController from dialogs import InfoDialog import operator import logging class WorkshopView(gtk.Alignment): """ Main container for the Workshop Mytutorial Part """ def __init__(self,model): """ Constructor """ gtk.Alignment.__init__(self,0.0,0.0,1.0,1.0) #Register Rating as a gobject gobject.type_register(Rating) #create the model and the controller self.controller = WorkshopController(self,model) #Create the main view self.mainView = WorkshopMain(self.controller) self.detailView = None #display the main view self.add(self.mainView) self.mainView.show() def set_categories(self,categories): self.categories = categories def set_tutorial_list(self,tutorial_list): """ Set the list of tutorial to display in the main View Refresh the View @param tutorial_list the list of tutorial """ self.mainView.set_tutorial_list(tutorial_list) def change_sorting(self,sorting_key): """ Sort the list of tutorial base on the sorting_key @param sorting_key the tutorial metadata to use to sort the tutorials """ self.mainView.change_sorting(sorting_key) def display_detail(self,tutorial): """ Displays the detail view of a tutorial @param tutorial the tutorial to display """ #hide the main view self.mainView.hide() self.remove(self.mainView) #create the detail view and show it self.detailView = MyTutorialDetail(tutorial,self.controller) self.add(self.detailView) self.detailView.show() def display_main_view(self): """ Displays the main view of the Workshop """ #hide the detail view self.detailView.hide() self.remove(self.detailView) #display the main view self.add(self.mainView) self.mainView.show() def display_info_dialog(self,tutorial): """ Displays the infos dialog on a tutorial @param tutorial the tutorial to edit """ infoDialog = InfoDialog(tutorial,self.controller,self.categories) infoDialog.run() infoDialog.destroy() def refresh_content(self): """ Refresh the data displayed """ #refresh the tutorial list self.mainView.refresh_tutorial_display() #refresh the detail view if self.detailView is not None: self.detailView.refresh_content() class WorkshopMain(gtk.VBox): """ Contains the main view for the Workshop My tutorial """ def __init__(self,controller): """Constructor @param controller The controller to attach the view to """ gtk.VBox.__init__(self,False,10) self.controller = controller self.tutorial_list = [] #by default tutorials are sorted by name self.sorting_key = 'Name' self.set_border_width(10) #The searchbar is displayed at the top self.search_bar = SearchBar(self.controller) self.pack_start(self.search_bar,False,False) #Add a separator after the search bar sep = gtk.HSeparator() self.pack_start(sep,False,False) #create the list item container with a scroll bar if necessary self.main_container = gtk.ScrolledWindow() self.main_container.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC) self.list_container= gtk.VBox() self.main_container.add_with_viewport(self.list_container) self.pack_start(self.main_container) #Show the components self.search_bar.show() self.list_container.show() self.main_container.show() sep.show() def change_sorting(self,sorting): """ Changes the property by which tutorial are sorted @param sorting The property by which tutorials will be sorted """ self.sorting_key = sorting self.sort_tutorial() def sort_tutorial(self): """ Sorts the tutorials """ #if tutorials are sorted by rating they are in the reverse order self.tutorial_list.sort(key=operator.attrgetter(self.sorting_key.lower())) self.refresh_tutorial_display() def set_tutorial_list(self,tutorial_list): """ Set the list of tutorial to display @param tutorial_list the tutorial list """ self.tutorial_list = tutorial_list self.sort_tutorial() def refresh_tutorial_display(self): """ Refresh the tutorial content by deleting every item and recreating them """ #delete every tutorial list item for child in self.list_container.get_children(): self.list_container.remove(child) #Creates and add a new item for every tutorial for tuto in self.tutorial_list: item = MyTutorialListItem(tuto,self.controller) self.list_container.pack_start(item) item.show() if self.tutorial_list[-1] != tuto: sep = gtk.HSeparator() self.list_container.pack_start(sep) sep.show() class SearchBar(gtk.HBox): """ The search bar control for the Workshop My tutorial """ def __init__(self,controller): """ Constructor @param controller The controller to link the view to """ gtk.HBox.__init__(self,False,10) self.set_border_width(5) self.controller = controller #creating and configuring the controls self.search_entry = gtk.Entry(400) self.search_button = gtk.Button("Go") self.separator = gtk.VSeparator() self.sort_label = gtk.Label("Sort by") self.sort_combo = gtk.combo_box_new_text() self.sort_combo.insert_text(0,"Name") self.sort_combo.insert_text(1,"Rating") self.sort_combo.set_active(0) self.selected_sorting = self.sort_combo.get_active_text() #Adding the controls to the view self.pack_start(self.search_entry,padding=5) self.pack_start(self.search_button,False,False,padding=10) self.pack_start(self.separator,False,False,padding=10) self.pack_start(self.sort_label,False,False,padding=5) self.pack_start(self.sort_combo,) #showing the controls self.search_entry.show() self.search_button.show() self.separator.show() self.sort_label.show() self.sort_combo.show() #connecting the events self.search_button.connect("clicked",self.controller.tutorial_query,self.search_entry) self.sort_combo.connect("changed",self.controller.sort_selection_changed,None) class WorkshopDetail(gtk.VBox): def __init__(self,tutorial,controller): """ Constructor @param tutorial The tutorial to display @param controller The controller to link the view with """ #Used for string formatting self.title_text = '%(title)s' self.author_text = 'by %(author)s' self.desc_text = 'Description: %(description)s' self.controller = controller self.tutorial = tutorial gtk.VBox.__init__(self,False,10) self.set_border_width(10) #The first row contains the back button first_row = gtk.HBox(False) back_image = gtk.Image() back_image.set_from_file('arrow_back.png') self.back_button = gtk.Button("Back") self.back_button.set_image(back_image) first_row.pack_start(self.back_button,False,False) #The second row contains the activity icon, the title label, #the author label and the star rating icon = gtk.Image() icon.set_from_file('icon.svg') label_holder = gtk.VBox(False,10) self.title_label = gtk.Label("") self.author_label = gtk.Label("") #Add a small offsert for author's label alignement because it's cute self.author_label.set_alignment(0.05,0.5) self.title_label.set_alignment(0.0,0.5) label_holder.pack_start(self.title_label) label_holder.pack_start(self.author_label) self.rating = Rating(tutorial,controller,rating = tutorial.rating) second_row = gtk.HBox(False) second_row.pack_start(icon,False,False) second_row.pack_start(label_holder) second_row.pack_end(self.rating,False,False) #The middle of the screen contains an area for the description self.desc_view = gtk.TextView() self.desc_buff = gtk.TextBuffer() self.desc_buff.set_text(tutorial.description) self.desc_view.set_buffer(self.desc_buff) self.desc_view.set_editable(False) self.desc_view.set_wrap_mode(gtk.WRAP_WORD) self.desc_view.set_cursor_visible(False) self.desc_view.connect("realize",self.realize_cb,None) self.desc_view.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse("gray") ) #The description view contains all the extra space self.pack_start(first_row,False,False) self.pack_start(second_row,False,False) self.pack_start(self.desc_view) #show everything self.back_button.show() first_row.show() self.title_label.show() self.author_label.show() self.rating.show() label_holder.show() second_row.show() icon.show() self.desc_view.show() #set some text with markup self.title_label.set_markup(self.title_text % {"title":tutorial.name}) self.author_label.set_markup(self.author_text % {"author":tutorial.author}) def realize_cb(self,widget,data=None): """ This fucntion changes the cursor over the description view So we see an arrow and not the insert text cursor """ widget.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR)) def refresh_content(self): """ Refresh the labels' text based on the tutorial object """ self.title_label.set_markup(self.title_text % {"title":self.tutorial.name}) self.author_label.set_markup(self.author_text % {"author":self.tutorial.author}) self.desc_buff.set_text(self.tutorial.description) class WorkshopListItem(gtk.Alignment): """ A list item containing the details of a tutorial """ def __init__(self,tutorial,controller): """ Constructor @param controller The controller to link the view to """ #logging.info(tutorial.updated_metadata) gtk.Alignment.__init__(self,0.0,0.0,1.0,1.0) self.tutorial = tutorial self.controller = controller self.set_border_width(10) #The table will contain everything else self.table = gtk.Table(3,3,False) self.table.set_row_spacing(1,10) #Create the controls self.lbl_title = gtk.Label('') self.lbl_title.set_alignment(0.0,0.5) self.title_text = '%(title)s' self.lbl_title.set_markup(self.title_text % {'title':tutorial.name}) self.lbl_desc = gtk.Label(tutorial.description) self.lbl_desc.set_line_wrap(True) self.lbl_desc.set_alignment(0.0,0.5) self.icon = gtk.Image() self.icon.set_from_file('icon.svg') self.rating = Rating(tutorial,controller,tutorial.rating, True) #Add the controls to the table self.table.attach(self.icon,0,1,0,1,0,0) self.table.attach(self.lbl_title,1,2,0,1,yoptions=0) self.table.attach(self.lbl_desc,1,2,1,2,xoptions=gtk.FILL,yoptions=gtk.EXPAND) self.table.attach(self.rating,2,3,0,2,0,0) #show everything self.table.show() self.icon.show() self.lbl_title.show() self.lbl_desc.show() self.rating.show() self.add(self.table) class MyTutorialListItem(WorkshopListItem): def __init__(self,tutorial,controller): WorkshopListItem.__init__(self,tutorial,controller) self.last_row = gtk.HBox(False,15) self.btn_launch = gtk.Button('Launch') self.btn_detail = gtk.Button('Details') self.last_row.pack_start(self.btn_launch,False,False) self.last_row.pack_end(self.btn_detail,False,False) self.table.attach(self.last_row,1,3,2,3,yoptions = 0) self.last_row.show_all() #connect the buttons self.btn_detail.connect("clicked",self.controller.show_details,self.tutorial) self.btn_launch.connect("clicked",self.controller.launch_tutorial,self.tutorial) class MyTutorialDetail(WorkshopDetail): def __init__(self,tutorial,controller): WorkshopDetail.__init__(self,tutorial,controller) #The bottom of the screen contains the button(fourth and fifth row self.launch_button = gtk.Button('Launch') self.launch_button.get_child().set_markup(self.title_text %{"title":"Launch"}) self.edit_button = gtk.Button('Edit') self.edit_button.get_child().set_markup(self.title_text %{"title":"Edit"}) self.update_button = gtk.Button('Update') self.update_button.get_child().set_markup(self.title_text %{"title":"Update"}) self.info_button = gtk.Button('Infos') self.info_button.get_child().set_markup(self.title_text %{"title":"Infos"}) self.delete_button = gtk.Button('Delete') self.delete_button.get_child().set_markup(self.title_text %{"title":"Delete"}) fourth_row = gtk.HBox(False,15) fourth_row.pack_start(self.launch_button,False,False) fourth_row.pack_start(self.edit_button,False,False) fourth_row.pack_start(self.update_button,False,False) fourth_row.pack_start(self.info_button,False,False) fourth_row.pack_end(self.delete_button,False,False) self.publish_button = gtk.Button('') self.publish_button.get_child().set_markup(self.title_text %{"title":"Publish"}) self.unpublish_button = gtk.Button('') self.unpublish_button.get_child().set_markup(self.title_text %{"title":"Unpublish"}) fifth_row = gtk.HBox(False,15) fifth_row.pack_start(self.publish_button,False,False) fifth_row.pack_start(self.unpublish_button,False,False) self.pack_end(fifth_row,False,False) self.pack_end(fourth_row,False,False) fifth_row.show_all() fourth_row.show_all() #connect the clicked events of the buttons self.back_button.connect("clicked",self.controller.back_pressed,None) self.publish_button.connect("clicked",self.controller.publish_tutorial,self.tutorial) self.unpublish_button.connect("clicked",self.controller.unpublish_tutorial,self.tutorial) self.launch_button.connect("clicked",self.controller.launch_tutorial,self.tutorial) self.edit_button.connect("clicked",self.controller.edit_tutorial,self.tutorial) self.update_button.connect("clicked",self.controller.update_tutorial,self.tutorial) self.info_button.connect("clicked",self.controller.info_tutorial,self.tutorial) self.delete_button.connect("clicked",self.controller.delete_tutorial,self.tutorial) self.controller.get_categories()