Ejemplo n.º 1
0
    def __init__(self, modelset=None, modelset_path=None):
        '''Vytvori hlavne okno, nacita konfiguracny subor a nastavy velkost'''
        path = join(os.path.dirname(os.path.abspath(__file__)), 'glade')
        gtklib.ObjGetter.__init__(self, join(path, 'main.glade'), self.get_signals())
        self.config = configparser.ConfigParser()
        self.config.read(expanduser('~/.config/hmmlab.conf'))
        self.window.set_default_size(int(self.config['mainwindow']['width']), int(self.config['mainwindow']['height']))
        self.file_context_id = self.statusbar.get_context_id("Načítavanie súboru")
        self.MODEL_WIDTH = int(self.config['model']['width'])
        self.MODEL_HEIGHT = int(self.config['model']['height'])
        self.MODEL_CHECK = cairo.ImageSurface.create_from_png(join(path, 'check.png'))
        self.MODEL_UNCHECK = cairo.ImageSurface.create_from_png(join(path, 'uncheck.png'))
        self.mice = {'mouse_down':False, 'x': 0, 'y': 0, 'drag' : False}
        self.selection_rectangle = {'x1' : 0, 'y1' : 0, 'x2' : 0, 'y2' : 0} 
        
        self.modelset = modelset
        self.modelset_path = modelset_path
        self.data_table = FilesTab(modelset, self)
        self.modelset_modified = False
        self.visual_win = VisualWindow(self, self.modelset)
        if self.modelset is not None:
            self.fill_models()
            self.models_sidebar.set_sensitive(True)
            self.opened()
        self.edited = False

        self.models_canvas = []
        self.models_selected = []
        self.models_windows = []
        self.treeview1.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, [], Gdk.DragAction.COPY)
        self.drawarea.drag_dest_set(Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY)
        self.treeview1.drag_source_add_text_targets()
        self.drawarea.drag_dest_add_text_targets()
        
        self.window.show()
Ejemplo n.º 2
0
class MainWindow(gtklib.ObjGetter):
    '''Trieda hlavneho okna'''
    def __init__(self, modelset=None, modelset_path=None):
        '''Vytvori hlavne okno, nacita konfiguracny subor a nastavy velkost'''
        path = join(os.path.dirname(os.path.abspath(__file__)), 'glade')
        gtklib.ObjGetter.__init__(self, join(path, 'main.glade'), self.get_signals())
        self.config = configparser.ConfigParser()
        self.config.read(expanduser('~/.config/hmmlab.conf'))
        self.window.set_default_size(int(self.config['mainwindow']['width']), int(self.config['mainwindow']['height']))
        self.file_context_id = self.statusbar.get_context_id("Načítavanie súboru")
        self.MODEL_WIDTH = int(self.config['model']['width'])
        self.MODEL_HEIGHT = int(self.config['model']['height'])
        self.MODEL_CHECK = cairo.ImageSurface.create_from_png(join(path, 'check.png'))
        self.MODEL_UNCHECK = cairo.ImageSurface.create_from_png(join(path, 'uncheck.png'))
        self.mice = {'mouse_down':False, 'x': 0, 'y': 0, 'drag' : False}
        self.selection_rectangle = {'x1' : 0, 'y1' : 0, 'x2' : 0, 'y2' : 0} 
        
        self.modelset = modelset
        self.modelset_path = modelset_path
        self.data_table = FilesTab(modelset, self)
        self.modelset_modified = False
        self.visual_win = VisualWindow(self, self.modelset)
        if self.modelset is not None:
            self.fill_models()
            self.models_sidebar.set_sensitive(True)
            self.opened()
        self.edited = False

        self.models_canvas = []
        self.models_selected = []
        self.models_windows = []
        self.treeview1.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, [], Gdk.DragAction.COPY)
        self.drawarea.drag_dest_set(Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY)
        self.treeview1.drag_source_add_text_targets()
        self.drawarea.drag_dest_add_text_targets()
        
        self.window.show()

    def get_signals(self):
        signals = {"about" : self.about,
                   "destroy" : self.destroy,
                   "drawarea_button_press_event_cb" : self.drawarea_button_press_event, 
                   "drawarea_button_release_event_cb" : self.drawarea_button_release_event,
                   "drawarea_draw_cb" : self.draw,
                   "drawarea_drag_data_received_cb" : self.drawarea_drag_data_received, 
                   "drawarea_motion_notify_event_cb" : self.drawarea_motion_notify_event,
                   "export_activate" : self.export_activate,
                   "gnuplot" : self.gnuplot,
                   "gnuplot3d" : self.gnuplot3D,
                   "load_data" : self.load_data,
                   "models_drag_get" : self.models_drag_get,
                   "open_activate" : self.open_activate,
                   "save_activate" : self.save_activate,
                   "save_as_activate" : self.save_as_activate,
                   "open_data_table" : self.open_data_table,
                   "add_model" : self.add_model,
                   "remove_model" : self.remove_model,
                   "graphviz" : self.graphviz,
                   "new_modelset" : self.new_modelset}
        return signals

    def destroy(self, widget = None, event=None):
        if widget is not None and self.modelset is not None and self.edited:
            dialog = Gtk.MessageDialog(self.window,
                                       0,
                                       Gtk.MessageType.QUESTION,
                                       Gtk.ButtonsType.YES_NO,
                                       "Uložiť zmeny do súboru '%s' pred zatvorením?" % self.modelset.name)
            dialog.format_secondary_text("Ak neuložíte, zmeny budú stratené.")
            response = dialog.run()
            if response == Gtk.ResponseType.YES:
                #bude treba otvorit save okno
                pass
            dialog.destroy()
        self.config['mainwindow']['width'] = str(self.window.get_allocated_width())
        self.config['mainwindow']['height'] = str(self.window.get_allocated_height())
        with open(expanduser('~/.config/hmmlab.conf'), 'w') as configfile:
            self.config.write(configfile)
        Gtk.main_quit()

    def draw(self, drawarea, cr):
        if self.modelset is not None:
            for model in self.models_canvas:
                if model in self.models_selected:
                    cr.set_source_rgba(0,80,0,0.5)
                else:
                    cr.set_source_rgba(0,0,0,0.6)
                gtklib.cairo_rounded_rectangle(cr, model.x, model.y, self.MODEL_WIDTH, self.MODEL_HEIGHT, 1, self.MODEL_HEIGHT/10)
                cr.fill_preserve()
                cr.fill()
                cr.select_font_face("Sans", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
                cr.set_font_size(12.0)
                extents = cr.text_extents(model.model.name)
                x = model.x + self.MODEL_WIDTH / 2 - extents[2] / 2 - extents[0]
                y = model.y + self.MODEL_HEIGHT / 2 - extents[3] / 2 - extents[1]
                cr.move_to(x, y)
                cr.set_source_rgb(255,255,255)
                cr.show_text(model.model.name)
                if model.checked:
                    cr.set_source_surface(self.MODEL_CHECK, model.x+1, model.y+1)
                else:
                    cr.set_source_surface(self.MODEL_UNCHECK, model.x+1, model.y+1)
                cr.paint()
                
            if self.mice['mouse_down'] and not self.mice['drag']:
                cr.set_source_rgba(0,0,180,0.1)
                cr.rectangle(self.selection_rectangle['x1'],
                             self.selection_rectangle['y1'],
                             self.selection_rectangle['x2'] - self.selection_rectangle['x1'],
                             self.selection_rectangle['y2'] - self.selection_rectangle['y1'])
                cr.fill()
                cr.set_source_rgba(0,0,180,0.5)
                cr.rectangle(self.selection_rectangle['x1'],
                             self.selection_rectangle['y1'],
                             self.selection_rectangle['x2'] - self.selection_rectangle['x1'],
                             self.selection_rectangle['y2'] - self.selection_rectangle['y1'])
                cr.stroke()

    def opened(self):
        self.imagemenuitem3.set_sensitive(True)
        self.imagemenuitem4.set_sensitive(True)
        self.imagemenuitem11.set_sensitive(True)
        self.action1.set_sensitive(True)
        self.action2.set_sensitive(True)
        self.action3.set_sensitive(True)
        self.modelset_modified = False

    def save_activate(self, item):
        if self.modelset_modified:
            if self.modelset is None:
                self.save('xml')
            else:
                self.modelset.save(self.modelset_path, 'xml')

    def save_as_activate(self, item=None):
        self.save('xml')
        self.modelset_modified = False

    def export_activate(self, item=None):
        self.save('htk')

    def save(self, file_format):
        dialog = Gtk.FileChooserDialog("Vyberte súbor",
                                       self.window,
                                       Gtk.FileChooserAction.SAVE,
                                       (Gtk.STOCK_CANCEL,
                                       Gtk.ResponseType.CANCEL,
                                       Gtk.STOCK_OPEN,
                                       Gtk.ResponseType.OK))
        dialog.set_do_overwrite_confirmation(True)
        self.add_filters(dialog, file_format)
        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            filename = dialog.get_filename()
            dialog.destroy()
            self.modelset.save(filename, file_format)
        else:
            dialog.destroy()

    def load_data(self, item):
        dialog = Gtk.FileChooserDialog("Vyberte súbor",
                                       self.window,
                                       Gtk.FileChooserAction.OPEN,
                                       (Gtk.STOCK_CANCEL,
                                       Gtk.ResponseType.CANCEL,
                                       Gtk.STOCK_OPEN,
                                       Gtk.ResponseType.OK))
        filter_wav = Gtk.FileFilter()
        filter_wav.set_name("WAV súbor")
        filter_wav.add_pattern('*.wav')
        dialog.add_filter(filter_wav)
        dialog.set_select_multiple(True)
        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            filenames = dialog.get_filenames()
            self.modelset.load_data(filenames)
            self.visual_win.refresh()
        dialog.destroy()

    def open_data_table(self, item):
        self.data_table.modelset = self.modelset
        self.data_table.load_data()
        self.data_table.window.show()

    def open_activate(self, item):
        dialog = Gtk.FileChooserDialog("Vyberte súbor",
                                        self.window,
                                        Gtk.FileChooserAction.OPEN,
                                        (Gtk.STOCK_CANCEL,
                                        Gtk.ResponseType.CANCEL,
                                        Gtk.STOCK_OPEN,
                                        Gtk.ResponseType.OK))
        self.add_filters(dialog)
        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            filename = dialog.get_filename()
            file_type = filename[filename.index('.')+1:]
            dialog.destroy()
            self.statusbar.push(self.file_context_id,'Načítavam súbor '+filename)
            if self.modelset is not None:
                self.modelset.destroy()
            self.modelset = libhmm.ModelSet(filename, file_type)
            self.visual_win.set_modelset(self.modelset)
            self.statusbar.pop(self.file_context_id)
            self.window.set_title('HMMLab - '+self.modelset.name)
            self.drawarea.queue_draw()
            self.fill_models()
            self.models_sidebar.set_sensitive(True)
            self.opened()
        else:
            dialog.destroy()

    def add_filters(self, dialog, file_format=None):
        if file_format == 'htk' or file_format is None:
            filter_hmm = Gtk.FileFilter()
            filter_hmm.set_name("HTK HMM súbor")
            filter_hmm.add_pattern('*.hmm')
            dialog.add_filter(filter_hmm)

        if file_format == 'xml' or file_format is None:
            filter_xml = Gtk.FileFilter()
            filter_xml.set_name("XML súbory")
            filter_xml.add_mime_type("text/xml")
            dialog.add_filter(filter_xml)

        filter_any = Gtk.FileFilter()
        filter_any.set_name("Všetky súbory")
        filter_any.add_pattern("*")
        dialog.add_filter(filter_any)

    def fill_models(self):
        if self.modelset is not None:
            self.models_store.clear()
            for model in self.modelset.models:
                self.models_store.append([model.name])

    def models_drag_get(self, widget, drag_context, data, info, time):
        if self.modelset is not None:
            model, it = self.treeview1.get_selection().get_selected()
            item = self.models_store.get_value(it, 0)
            data.set_text(item, -1)

    def drawarea_drag_data_received(self, widget, drag_context, x, y, data, info, time):
        if self.modelset is not None:
            model_name = data.get_text()
            model = self.modelset.get_model(model_name)
            m = None
            for modelm in self.models_canvas:
                if modelm.x <= x <= modelm.x + self.MODEL_WIDTH and modelm.y <= y <= modelm.y + self.MODEL_HEIGHT:
                    m = modelm
            if m is not None:
                joined_model = m.model.join_model(model)
                self.models_canvas.remove(m)
                self.models_selected = []
                self.models_canvas.append(CanvasModel(joined_model, m.x, m.y, self.modelset.reset_pos_gauss))
            else:
                self.models_canvas.append(CanvasModel(model, x, y, self.modelset.reset_pos_gauss))
                self.modelset.drawarea_models_append(model)
                self.modelset_modified = True
            self.drawarea.queue_draw()

    def drawarea_button_press_event(self, eb, event):
        if self.modelset is not None:
            model = self.get_model_at(event.x, event.y)
            if model is None:
                self.models_selected = []
                self.mice['drag'] = False
                self.selection_rectangle['x1'] = event.x
                self.selection_rectangle['y1'] = event.y
                self.selection_rectangle['x2'] = event.x
                self.selection_rectangle['y2'] = event.y
            else:
                if event.type == Gdk.EventType.BUTTON_PRESS and event.button == 3:
                    self.open_menu(event, model)
                elif event.type == Gdk.EventType._2BUTTON_PRESS:
                    if model.model.name not in [mw.model.name for mw in self.models_windows]:
                        mw = ModelWindow(model, self)
                        self.models_windows.append(mw)
                    else:
                        for mw in self.models_windows:
                            if model.model.name == mw.model.name:
                                mw.window.present()
                                break
                if model not in self.models_selected:
                    self.models_selected = [model]
                if model.x <= event.x <= model.x + self.MODEL_CHECK.get_width():
                    if model.y <= event.y <= model.y + self.MODEL_CHECK.get_height():
                        model.checked = not model.checked
                        model.gaussians()                        
                        for mw in self.models_windows:
                            if model.model.name == mw.model.name:
                                mw.fill_states_table()
                        self.visual_win.refresh()
                self.mice['drag'] = True
            self.mice['mouse_down'] = True
            self.mice['x'] = event.x
            self.mice['y'] = event.y
            self.drawarea.queue_draw()

    def drawarea_button_release_event(self, eb, event):
        if self.modelset is not None:
            self.mice['mouse_down'] = False
            self.mice['x'] = event.x
            self.mice['y'] = event.y
            if not self.mice['drag']:
                self.update_selected_models()
            self.mice['drag'] = False
            for k in self.selection_rectangle:
                self.selection_rectangle[k] = -1
            if len(self.models_selected) == 1:
                m = None
                for model in self.models_canvas:
                    if model.x <= event.x <= model.x + self.MODEL_WIDTH and model.y <= event.y <= model.y + self.MODEL_HEIGHT:
                        if model != self.models_selected[0]:
                            m = model
                            break
                if m is not None:
                    joined_model = m.model.join_model(self.models_selected[0].model)
                    self.models_canvas.remove(m)
                    self.models_canvas.remove(self.models_selected[0])
                    self.models_selected = []
                    self.models_canvas.append(CanvasModel(joined_model, m.x, m.y, self.modelset.reset_pos_gauss))
            self.drawarea.queue_draw()

    def drawarea_motion_notify_event(self, eb, event):
        if self.modelset is not None:
            if self.mice['mouse_down']:
                alloc = self.drawarea.get_allocation()
                if self.mice['drag']:
                    for model in self.models_selected:
                        model.x = max(0, min(alloc.width - self.MODEL_WIDTH, model.x - self.mice['x'] + event.x))
                        model.y = max(0, min(alloc.height - self.MODEL_HEIGHT, model.y - self.mice['y'] + event.y))
                    if len(self.models_selected) > 0:
                        self.drawarea.queue_draw()
                elif len(self.models_selected) == 0:
                        self.selection_rectangle['x2'] = max(0, min(alloc.width - self.MODEL_WIDTH,event.x))
                        self.selection_rectangle['y2'] = max(0, min(alloc.height - self.MODEL_HEIGHT, event.y))
                        self.drawarea.queue_draw()
            self.mice['x'] = event.x
            self.mice['y'] = event.y
        
    def update_selected_models(self):
        self.models_selected = []
        for model in self.models_canvas:
            if self.selection_rectangle['x1'] > self.selection_rectangle['x2']:
                if self.selection_rectangle['x1'] >= (model.x+self.MODEL_WIDTH) and self.selection_rectangle['x2'] <= model.x:
                    self.models_selected.append(model)
            else:
                if self.selection_rectangle['x2'] >= (model.x+self.MODEL_WIDTH) and self.selection_rectangle['x1'] <= model.x:
                    self.models_selected.append(model)

    def get_model_at(self, x, y):
        for model in self.models_canvas:
            if model.x <= x <= model.x + self.MODEL_WIDTH and model.y <= y <= model.y + self.MODEL_HEIGHT:
                return model
        return None

    def about(self, item):
        resp = self.aboutdialog.run()
        if resp == Gtk.ResponseType.DELETE_EVENT or resp == Gtk.ResponseType.CANCEL:
            self.aboutdialog.hide()

    def gnuplot(self, item):
        Select2DWindow(self.modelset, self.window)

    def gnuplot3D(self, item):
        SelectDraw2DWindow(self.modelset, self)
    
    def open_window_from_gauss(self, gauss):
        for model in self.modelset.get_models_with_gaussian(gauss):
            mw = None
            if model.name not in [mw.model.name for mw in self.models_windows]:
                mw = ModelWindow(model, self)
                self.models_windows.append(mw)
            else:
                for mwin in self.models_windows:
                    if model.name == mwin.model.name:
                        mwin.window.present()
                        mw = mwin
                        break

            if mw is not None:
                for i, state in enumerate(model.states):
                    if state.has_gaussian(gauss):
                        selection = mw.states_view.get_selection()
                        if selection is not None:
                            selection.select_path(i)
                            mw.load_state(state)
                            for j, data in enumerate(mw.gaussians_store):
                                if data[2] == gauss.name:
                                    selection = mw.gaussians_view.get_selection()
                                    if selection is not None:
                                        selection.select_path(j)

    def add_model(self, button):
        trans_mat = libhmm.TransMatrix(self.modelset.get_unique_name("trans_mat"), self.modelset, 3, 1.0)
        m = libhmm.Model(self.modelset.get_unique_name("model"), self.modelset)
        m.trans_mat = trans_mat
        s = libhmm.State("%s_state_1" % m.name, self.modelset)
        for i, stream in enumerate(s.streams):
            g = libhmm.Gaussian(stream.name + "_gaussian0", self.modelset, i, 1)
            dimension = self.modelset.streams_distribution[i]
            g.mean = libhmm.SVector(g.name+"_mean", self.modelset, dimension, 0.0)
            g.mean.randomize()
            g.covariance = libhmm.SMatrix(g.name+"_covariance", self.modelset, dimension, dimension, 0.0)
            g.inv_covariance = libhmm.SMatrix(g.covariance.name+"_inv", self.modelset, dimension, dimension, 0.0);
            g.covariance.randomize()
            for i in range(dimension):
                for j in range(dimension):
                    if i != j:
                        g.covariance(i, j, 0.0)
                    else:
                        g.inv_covariance(i, j, 1.0 / g.covariance(i,j))
            g.calc_gconst()
            stream.add_gaussian(g, 1.0)
        s.inc_ref_num()
        m.states.append(s)
        self.modelset.add_model(m)
        self.modelset.drawarea_models_append(m)
        alloc = self.drawarea.get_allocation()
        model = CanvasModel(m, randint(20, alloc.width - 20), randint(20, alloc.height - 20), self.modelset.reset_pos_gauss)
        self.models_canvas.append(model)
        mw = ModelWindow(model, self)
        self.models_windows.append(mw)
        self.fill_models()

    def remove_model(self, button):
        _, it = self.treeview1.get_selection().get_selected()
        m = self.modelset.get_model(self.models_store[it][0])
        self.modelset.remove_model(m)
        self.fill_models()

    def open_menu(self, event, model):
        menu = Gtk.Menu()
        if model.model.is_joined():
            menu_item = Gtk.MenuItem('Rozdeliť model')
            menu.append(menu_item)
            menu_item.show()
            menu_item.connect("activate", self.disjoint_model, model)
        else:
            menu_item = Gtk.MenuItem('Zmazať z plochy')
            menu.append(menu_item)
            menu_item.show()
            menu_item.connect("activate", self.remove_model_from_drawarea, model)
        menu.popup(None,
                   None, 
                   lambda menu, data: (event.get_root_coords()[0],
                                       event.get_root_coords()[1],
                                       True),
                   None,
                   event.button,
                   event.time)

    def disjoint_model(self, widget, model):
        model_list = model.model.disjoint_model()
        alloc = self.drawarea.get_allocation()
        self.models_canvas.remove(model)
        for m in model_list:
            self.models_canvas.append(CanvasModel(m,
                                                  randint(self.MODEL_WIDTH, alloc.width - self.MODEL_WIDTH),
                                                  randint(model.y - 10, model.y + 10),
                                                  self.modelset.reset_pos_gauss))
            self.modelset.drawarea_models_append(m)
        self.drawarea.queue_draw()

    def remove_model_from_drawarea(self, widget, model):
        self.models_canvas.remove(model)
        self.modelset.drawarea_models.erase(model.model)
        model.model.unselect_gaussians()
        self.modelset.reset_pos_gauss()
        self.drawarea.queue_draw()

    def graphviz(self, item):
        for s in self.modelset.stream_areas:
            s.graphviz = item.get_active()

    def new_modelset(self, item):
        if self.modelset is None:
            NewModelsetWin(self)