def __init__(self, program_dir, home_dir): """ **Properties**: *_program_dir* (string): The path to this program. It has to end with the top-level directory swan. *_CACHEDIR* (string): The default path of the cache directory. *_currentdirty* (boolean): Whether or not the current (virtual unit) mapping is dirty because of changes. *_globaldirty* (boolean): Whether or not one or more (virtual unit) mappings are dirty. *_preferences* (dictionary): A dictionary containing all preferences in (key, value) pairs. The dictionary will be loaded at program start or set to default values. *_PREFS* (dictionary): The preferences dictionary containing the default values. *_prodir* (string): The path where the project files will be written to by default. *_mystorage* (:class:`stg.mystorage.MyStorage`): The class which handles the data and the project files. """ QtGui.QMainWindow.__init__(self) self.ui = Ui_Main() self.ui.setupUi(self) #properties{ self._program_dir = program_dir self._CACHEDIR = join(program_dir, "cache") self._currentdirty = False self._globaldirty = False self._preferences = None self._PREFS = { "defaultProName":"swan.txt", "zinStep":24, "cacheDir":self._CACHEDIR, "zoutStep":24, "expandStep":5, "collapseStep":5, } self._prodir = join(home_dir) #preferences have to be present for the storage. self.load_preferences() self._mystorage = MyStorage(program_dir, self._preferences["cacheDir"]) #} self.setWindowTitle(title) #for the virtual unit overview self.vu = VUnits() self.vu.setWindowTitle("Virtual Units") #connect channel selection self.ui.selector.doChannel.connect(self.do_channel) #connect layer selection self.ui.layers.doLayer.connect(self.plot_all) #connect unit selection self.ui.units.doUnits.connect(self.plot_all) #connect view change self.ui.views.currentChanged.connect(self.check_layers) #connect loading progress self._mystorage.progress.connect(self.setProgress) self.ui.view_2.progress.connect(self.setProgress) #connect progress bar showing/hiding self.ui.view_2.progressBar.connect(self.showProgressBar) #connect redraw signal of the views self.ui.view_4.redraw.connect(self.plot_all) self.vu.redraw.connect(self.plot_all) #connect channel loading self.vu.load.connect(self.load_channel) #setting the horizontal widgets with equal sizes self.ui.splitter_2.setSizes([int(self.ui.splitter_2.width()/2) for i in xrange(2)]) #shortcut reference self.plots = self.ui.plotGrid.child self.selector = self.ui.selector self.load_icons() self.check_dirs() self.check_layers(self.ui.views.currentIndex()) #setting up the progress bar self.p = QtGui.QProgressBar() self.p.setRange(0, 100) self.p.setValue(0) self.ui.statusbar.addPermanentWidget(self.p) self.p.hide() if onLinux: #starting memory usage task timer = QtCore.QTimer(self) self.timer = timer self.memorytask = MemoryTask(timer, self.ui.statusbar) self.memorytask.start()
class Main(QtGui.QMainWindow): """ This is the main window. It is the parent widget of all other widgets and closing it quits the application. This class has methods to handle the user actions either by itself or by delegating to the child widgets. **Arguments:** *program_dir* (string): The directory in which the program is located. It has to end with the top-level directory swan. *home_dir* (string): The directory where the project files will be written to by default. If you didn't execute *run.py* with an additional argument this will be your home directory. Otherwise it will be the one you gave as an argument. """ def __init__(self, program_dir, home_dir): """ **Properties**: *_program_dir* (string): The path to this program. It has to end with the top-level directory swan. *_CACHEDIR* (string): The default path of the cache directory. *_currentdirty* (boolean): Whether or not the current (virtual unit) mapping is dirty because of changes. *_globaldirty* (boolean): Whether or not one or more (virtual unit) mappings are dirty. *_preferences* (dictionary): A dictionary containing all preferences in (key, value) pairs. The dictionary will be loaded at program start or set to default values. *_PREFS* (dictionary): The preferences dictionary containing the default values. *_prodir* (string): The path where the project files will be written to by default. *_mystorage* (:class:`stg.mystorage.MyStorage`): The class which handles the data and the project files. """ QtGui.QMainWindow.__init__(self) self.ui = Ui_Main() self.ui.setupUi(self) #properties{ self._program_dir = program_dir self._CACHEDIR = join(program_dir, "cache") self._currentdirty = False self._globaldirty = False self._preferences = None self._PREFS = { "defaultProName":"swan.txt", "zinStep":24, "cacheDir":self._CACHEDIR, "zoutStep":24, "expandStep":5, "collapseStep":5, } self._prodir = join(home_dir) #preferences have to be present for the storage. self.load_preferences() self._mystorage = MyStorage(program_dir, self._preferences["cacheDir"]) #} self.setWindowTitle(title) #for the virtual unit overview self.vu = VUnits() self.vu.setWindowTitle("Virtual Units") #connect channel selection self.ui.selector.doChannel.connect(self.do_channel) #connect layer selection self.ui.layers.doLayer.connect(self.plot_all) #connect unit selection self.ui.units.doUnits.connect(self.plot_all) #connect view change self.ui.views.currentChanged.connect(self.check_layers) #connect loading progress self._mystorage.progress.connect(self.setProgress) self.ui.view_2.progress.connect(self.setProgress) #connect progress bar showing/hiding self.ui.view_2.progressBar.connect(self.showProgressBar) #connect redraw signal of the views self.ui.view_4.redraw.connect(self.plot_all) self.vu.redraw.connect(self.plot_all) #connect channel loading self.vu.load.connect(self.load_channel) #setting the horizontal widgets with equal sizes self.ui.splitter_2.setSizes([int(self.ui.splitter_2.width()/2) for i in xrange(2)]) #shortcut reference self.plots = self.ui.plotGrid.child self.selector = self.ui.selector self.load_icons() self.check_dirs() self.check_layers(self.ui.views.currentIndex()) #setting up the progress bar self.p = QtGui.QProgressBar() self.p.setRange(0, 100) self.p.setValue(0) self.ui.statusbar.addPermanentWidget(self.p) self.p.hide() if onLinux: #starting memory usage task timer = QtCore.QTimer(self) self.timer = timer self.memorytask = MemoryTask(timer, self.ui.statusbar) self.memorytask.start() #self.showMaximized() #### action handler #### ### menu:File ### @QtCore.pyqtSlot(bool) def on_action_New_Project_triggered(self): """ This method is called if you click on *File->New Project*. Shows a :class:`src.file_dialog.File_Dialog` to choose files and after accepting it creates a new project. The project consists of two files. One is a .txt file which contains the data file paths and the other one is a .vum file which contains the :class:`src.virtualunitmap.VirtualUnitMap`. The default names for the files are swan.txt and swan_vum.vum. If they already exist, they will be changed to swan(1).txt and swan(1)_vum.vum. If they exist, too, the number in the brackets will be incremented until the files don't exist. You can choose another default name in the preferences. Look at :class:`src.preferences_dialog.Preferences_Dialog` for more. """ self.dirty_project() dia = File_Dialog() if dia.exec_(): files = dia.get_files() files.sort() channel = self._mystorage.get_channel() success = self._mystorage.load_project(self._prodir, self._preferences["defaultProName"], channel, files) if success and self.do_channel(self._mystorage.get_channel(), self._mystorage.get_last_channel()): filesStr = self._mystorage.get_files(True) #setting filelist detail self.set_detail(4, filesStr) self.save_project() self.update_project() self.reset_dirty() self.selector.select_only(self._mystorage.get_channel()) self.set_status("Created new project successfully.") else: self.set_status("No files given. Nothing loaded.") @QtCore.pyqtSlot(bool) def on_action_Load_Project_triggered(self): """ This method is called if you click on *File->Load Project*. You have to choose a .txt project file which contains correct paths to the data files. Loads the project by reading the .txt file and the .vum file. """ self.dirty_project() filename = str(QtGui.QFileDialog.getOpenFileName(self, QtCore.QString("Choose the file which includes the absolute paths"), QtCore.QString(self._prodir))) if filename: (prodir, proname) = split(filename) channel = self._mystorage.get_channel() success = self._mystorage.load_project(prodir, proname, channel) if success and self.do_channel(self._mystorage.get_channel(), self._mystorage.get_last_channel()): filesStr = self._mystorage.get_files(True) #setting filelist detail self.set_detail(4, filesStr) self.save_project() self.update_project() self.reset_dirty() self.selector.select_only(self._mystorage.get_channel()) self.set_status("Loaded project successfully.") else: self.set_status("No files given. Nothing loaded.") @QtCore.pyqtSlot(bool) def on_action_Save_Project_triggered(self): """ This method is called if you click on *File->Save Project*. Works like :func:`on_action_Save_as_triggered()` but without asking you to type in a save name. """ if self.check_project(): self.save_project() @QtCore.pyqtSlot(bool) def on_action_Save_as_triggered(self): """ This method is called if you click on *File->Save as*. Saves your project under a new name by showing you a dialog where you can type the new project name (the one with the .txt extension). After that your loaded files will be written into that file (the absolute path to the files) so that you can later load them. The :class:`src.virtualunitmap.VirtualUnitMap` will be saved to the file with the .vum extension. """ if self.check_project(): filename = str(QtGui.QFileDialog.getSaveFileName(self, QtCore.QString("Choose a savename"), QtCore.QString(self._prodir))) if filename: self._mystorage.save_project_as(filename) self.update_project() self.save_project() @QtCore.pyqtSlot(bool) def on_action_Load_connector_map_triggered(self): """ This method is called if you click on *File->Load connector map*. Loads a connector map given as a .csv file. Delegates the loading to :func:`load_connector_map`. """ filename = str(QtGui.QFileDialog.getOpenFileName(self, "Choose a file", self._prodir)) try: self.load_connector_map(filename) except ValueError: QtGui.QMessageBox.critical(self, "Loading error", "The connector map could not be loaded") @QtCore.pyqtSlot(bool) def on_action_Export_to_csv_triggered(self): """ This method is called if you click on *File->Export to csv*. Exports the virtual unit mappings to a csv file. """ filename = str(QtGui.QFileDialog.getSaveFileName(self, QtCore.QString("Choose a savename"), QtCore.QString(self._prodir))) if filename: try: if filename.endswith(".csv"): filename = filename[:-4] Export.export_csv(filename, self._mystorage.load_map()) except IOError: QtGui.QMessageBox.critical(self, "Export error", "The virtual unit maps could not be exported") @QtCore.pyqtSlot(bool) def on_action_Export_to_odML_triggered(self): """ This method is called if you click on *File->Export to odML*. Exports the virtual unit mappings to an odML file. """ filename = str(QtGui.QFileDialog.getSaveFileName(self, QtCore.QString("Choose a savename"), QtCore.QString(self._prodir))) if filename: try: if filename.endswith(".odml"): filename = filename[:-5] Export.export_odml(filename, self._mystorage.load_map()) except IOError: QtGui.QMessageBox.critical(self, "Export error", "The virtual unit maps could not be exported") def closeEvent(self, event): """ This method is called if you click on *File->Quit*. Quits the application. If there are unsaved mappings, you will have a chance to save them. The event will be always accepted. **Arguments** *event* (:class:`PyQt4.QtCore.QEvent`) """ self.dirty_project() event.accept() ### menu:Edit ### @QtCore.pyqtSlot(bool) def on_action_Recalculate_mapping_triggered(self): """ This method is called if you click on *Edit->Recalculate mapping*. Delegates the calculating to another class. Updates the overview. See :func:`src.mystorage.MyStorage.recalculate`. """ if self._mystorage.has_project(): answer = QtGui.QMessageBox.question(self, "Recalculate mapping", "Are you sure you want to do this?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, defaultButton=QtGui.QMessageBox.No) if answer == QtGui.QMessageBox.Yes: self._mystorage.recalculate() self._currentdirty = True self._globaldirty = True self.plot_all() @QtCore.pyqtSlot(bool) def on_action_Revert_mapping_triggered(self): """ This method is called if you click on *Edit->Revert mapping*. Delegates the reverting to another class. Updates the overview. See :func:`src.mystorage.MyStorage.revert`. """ if self._mystorage.has_project(): answer = QtGui.QMessageBox.question(self, "Revert mapping", "Are you sure you want to do this?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, defaultButton=QtGui.QMessageBox.No) if answer == QtGui.QMessageBox.Yes: self._mystorage.revert() self.reset_current_dirty() self.plot_all() @QtCore.pyqtSlot(bool) def on_action_Swap_triggered(self): """ This method is called if you click on *Edit->Swap*. Swaps two plots if two are selected. Otherwise nothing will happen. The swapping itself is done somewhere else. See :func:`src.mystorage.MyStorage.swap`. """ plots = self.plots.get_selection() if len(plots) == 2: #get the positions p1 = plots[0] p2 = plots[1] m = p1.pos[1] n1 = p1.pos[0] n2 = p2.pos[0] #swapping self._mystorage.swap(m, n1, n2) self.plot_all() self.plots.reset_selection() #setting tooltips self.plots.set_tooltips(self._mystorage.get_tooltips()) self._currentdirty = True self._globaldirty = True @QtCore.pyqtSlot(bool) def on_action_Zoom_in_triggered(self): """ This method is called if you click on *Edit->Zoom in*. Zooms the overview in. The zoom step can be set in the preferences. See :class:`src.preferences_dialog.Preferences_Dialog`. """ self.plots.zoom_in(self._preferences["zinStep"]) @QtCore.pyqtSlot(bool) def on_action_Zoom_out_triggered(self): """ This method is called if you click on *Edit->Zoom out*. Zooms the overview out. The zoom step can be set in the preferences. See :class:`src.preferences_dialog.Preferences_Dialog`. """ self.plots.zoom_out(self._preferences["zoutStep"]) @QtCore.pyqtSlot(bool) def on_action_Expand_overview_triggered(self): """ This method is called if you click on *Edit->Expand overview*. Increases the y range of the plots in the overview. The step can be set in the preferences. See :class:`src.preferences_dialog.Preferences_Dialog`. """ self.plots.expand(self._preferences["expandStep"]) @QtCore.pyqtSlot(bool) def on_action_Collapse_overview_triggered(self): """ This method is called if you click on *Edit->Collapse overview*. Decreases the y range of the plots in the overview. The step can be set in the preferences. See :class:`src.preferences_dialog.Preferences_Dialog`. """ self.plots.collapse(self._preferences["collapseStep"]) @QtCore.pyqtSlot(bool) def on_action_Preferences_triggered(self): """ This method is called if you click on *Edit->Preferences*. Shows you a :class:`src.preferences_dialog.Preferences_Dialog` to view and change the preferences. """ dia = Preferences_Dialog(self._preferences.copy(), self._PREFS.copy()) if dia.exec_(): pref = dia.get_preferences() self._preferences = pref self.save_preferences() self._mystorage.set_cache_dir(pref["cacheDir"]) ### menu:View ### @QtCore.pyqtSlot(bool) def on_action_Virtual_Units_triggered(self): """ This method is called if you click on *View->Virtual units*. Shows an overview for the virtual units. """ self.vu.show() ### menu:Help ### @QtCore.pyqtSlot(bool) def on_action_Tutorials_triggered(self): """ This method is called if you click on *Help->Tutorials*. Shows you tutorials and help for this application. """ p = join(self._program_dir, "doc", "build", "html", "tutorial.html") d = "file://" + p web.open_new_tab(d) @QtCore.pyqtSlot(bool) def on_action_About_triggered(self): """ This method is called if you click on *Help->About*. Shows you information about the application. """ QtGui.QMessageBox.information(self, "About", about) #### signal handler #### def do_channel(self, channel, lastchannel): """ Loads the data from the given electrode and plots it. **Arguments** *channel* (integer): The electrode channel that will be loaded. *lastchannel* (integer): The channel that was loaded before. **Returns**: boolean Whether or not there was something to load for the electrode. """ if self._mystorage.has_project() and not self._mystorage.is_loading() and not self.ui.view_2.isLoading: #initialize the progress bar self.p.setValue(0) self.p.show() self.check_cache() #let the user know that loading can be take some time if onLinux: self.memorytask.stop_timer() self.set_status("Loading ... This may take a while ...", 0) QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) #checking if the last channel's mapping was dirty if self._currentdirty: self.selector.set_dirty(lastchannel, True) self._currentdirty = False #loading (n, m) = self._mystorage.load_channel(channel) self.ui.units.init_units(n) #deactivate loading the movie data for performance reasons self.ui.view_2.shouldLoad = False #reset the data of the movie self.ui.view_2.reset() #plotting self.plots.make_plots(n, m) data = self._mystorage.get_data() min0, max0 = data.get_yscale() self.plots.set_yranges(min0, max0) self.ui.view_2.set_range(min0, max0) self.plot_all() #setting channel detail self.set_detail(3, str(channel)) #setting tooltips self.plots.set_tooltips(self._mystorage.get_tooltips()) self.p.hide() QtGui.QApplication.restoreOverrideCursor() if onLinux: self.memorytask.start_timer() return True elif self._mystorage.is_loading() or self.ui.view_2.isLoading: self.selector.select_only(self._mystorage.get_channel()) return False def plot_all(self, i=None, visible=None): """ Plots everything that has to be plotted. It is possible to make a row in the :class:`src.virtualunitmap.VirtualUnitMap` (un)visible by passing extra arguments. This method is called every time something has to be plotted or updated. **Arguments** *i* (integer or None): The index of the row you want to make invisible. Default: None *visible* (boolean or None): Whether or not the row given by i should be visible. Default: None """ if self._mystorage.has_project(): QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) vum = self._mystorage.get_map() data = self._mystorage.get_data() vum_all = self._mystorage.get_mappings() if i is not None and visible is not None : vum.set_visible(i, visible) l1 = ["average", "standard deviation"] l2 = ["units-ISI", "session-ISI"] #plotting #plots: pyqtgraph plotwidget overview self.plots.do_plot(vum, data) #view_1: 2D mpl plot self.ui.view_1.do_plot(vum, data, self.ui.layers.get_checked_layers(l1)) #view_2: mpl movie plot #setting the data instead of plotting something because the plotting #will be managed at another place self.ui.view_2.set_data(vum, data) #view_3: 3D mpl plot self.ui.view_3.do_plot(vum, data, self.ui.layers.get_checked_layers(l1)) #view_4: ISI mpl plot self.ui.view_4.do_plot(vum, data, self.ui.layers.get_checked_layers(l2)) #vu: Virtual unit overview self.vu.do_plot(vum_all, data) QtGui.QApplication.restoreOverrideCursor() def check_layers(self, i): """ Checks if there are layers to hide for the current view. **Arguments** *i* (integer): The current view's index. """ l1 = ["average", "standard deviation"] l2 = ["units-ISI", "session-ISI"] if i == 0: #view_1: 2D mpl plot self.ui.layers.enable_layers(False, self.ui.layers.get_layers()) self.ui.layers.enable_layers(True, l1) elif i == 1: #view_2: mpl movie plot self.ui.layers.enable_layers(False, self.ui.layers.get_layers()) elif i == 2: #view_3: 3D mpl plot self.ui.layers.enable_layers(False, self.ui.layers.get_layers()) self.ui.layers.enable_layers(True, l1) elif i == 3: #view_4: ISI mpl plot self.ui.layers.enable_layers(False, self.ui.layers.get_layers()) self.ui.layers.enable_layers(True, l2) def setProgress(self, i): """ Sets the progress in the status bar. **Arguments** *i* (integer): The value to be set. """ self.p.setValue(i) def showProgressBar(self, show): """ Shows or hides the progress bar. **Arguments** *show* (boolean): Whether or not the progress bar should be shown. """ if show: self.p.show() else: self.p.hide() def load_channel(self, channel): """ Loads a channel. This method is connected to the load signal of the :class:`src.VUnits` class. **Arguments** *channel* (integer): The channel to load. """ item = self.selector.get_item(channel) if item is not None: if item.selectable: self.selector.select_channel(item, channel) self.selector.select_only(channel) #### general methods #### def dirty_project(self): """ Lets you save your project before losing your progress. Shows you a confirmation dialog and if you accept, the project will be saved. """ if self._globaldirty: answer = QtGui.QMessageBox.question(self, QtCore.QString("Confirmation"), QtCore.QString("There are changes to be lost.\nDo you want to save your project first?"), buttons = QtGui.QMessageBox.Discard | QtGui.QMessageBox.Yes, defaultButton = QtGui.QMessageBox.Yes) if answer == QtGui.QMessageBox.Yes: self.on_action_Save_Project_triggered() def update_project(self): """ Updates the project data like the project name and the directory. Shows the changed values in the details tab. """ if self._mystorage.has_project(): (prodir, proname) = split(self._mystorage.get_project_path()) vumname = basename(self._mystorage.get_map_path()) #setting project details self.set_detail(0, proname) self.set_detail(1, prodir) self.set_detail(2, vumname) def check_project(self): """ Checks if there is currently a project loaded. **Returns**: boolean Whether or not there is a project loaded. """ if not self._mystorage.has_project(): QtGui.QMessageBox.warning(self, QtCore.QString("Error"), QtCore.QString("No project loaded.")) return False else: return True def save_project(self): """ Saves the project. See :func:`src.mystorage.MyStorage.save_project`. """ self._mystorage.save_project() self.reset_dirty() self.set_status("Saved project successfully") def reset_dirty(self): """ Resets the project to a not dirty state. """ self._currentdirty = False self._globaldirty = False self.selector.reset_dirty() def reset_current_dirty(self): """ Resets the current channel. """ self._currentdirty = False self.selector.set_dirty(self._mystorage.get_channel(), False) if len(self.selector.get_dirty_channels()) == 0: self._globaldirty = False def set_detail(self, i, value): """ Sets a detail in the details tab. **Arguments** *i* (integer): The index of the detail. *value* (string): The value that should be shown. """ self.ui.details.item(i, 0).setText(value) def check_dirs(self): """ Checks if all directories exist which are needed by the program. If not, they will be created. """ data_dir = join(self._program_dir, "data") if not isdir(data_dir): mkdir(data_dir) self.check_cache() def check_cache(self): """ Checks if the cache directory exists. If not, it will be created. """ if not isdir(self._preferences["cacheDir"]): mkdir(self._preferences["cacheDir"]) def load_icons(self): """ Loads the icons. """ try: prefix = ":" + sep + "icons" + sep #File icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(prefix + "new.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.ui.action_New_Project.setIcon(icon) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(prefix + "open.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.ui.action_Load_Project.setIcon(icon) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(prefix + "save.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.ui.action_Save_Project.setIcon(icon) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(prefix + "save_as.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.ui.action_Save_as.setIcon(icon) #Edit icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(prefix + "revert.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.ui.action_Revert_mapping.setIcon(icon) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(prefix + "swap.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.ui.action_Swap.setIcon(icon) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(prefix + "zoom_in.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.ui.action_Zoom_in.setIcon(icon) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(prefix + "zoom_out.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.ui.action_Zoom_out.setIcon(icon) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(prefix + "expand.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.ui.action_Expand_overview.setIcon(icon) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(prefix + "collapse.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.ui.action_Collapse_overview.setIcon(icon) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(prefix + "preferences.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.ui.action_Preferences.setIcon(icon) except: pass def load_connector_map(self, filename): """ Loads a connector map given as a .csv file. The file has to contain two columns. The first will be ignored but must exist (e.g. the numbers 1-100) and the other one has to contain the mapped channel numbers. Choose **,** as delimiter. **Arguments** *filename* (string): The csv file to load. **Raises**: :class:`ValueError` If the connector map could not be loaded. """ if filename: delimiter = ',' try: with open(filename, "rb") as fn: channel_list = [] reader = csv.reader(fn, delimiter=delimiter) for row in reader: #just read the second column channel_list.append(int(row[1])) channels = self.selector.get_dirty_channels() #overwrite existing mapping self.selector.set_channels(channel_list) self.selector.reset_sel() self.selector.reset_dirty() #the dirty channels and the selected one has to be set again for channel in channels: self.selector.set_dirty(channel, True) self.selector.select_only(self._mystorage.get_channel()) except: raise ValueError def load_preferences(self): """ Loads the preferences from the preferences file. If it doesn't exist, defaults are used. """ name = join(self._program_dir, "data", "preferences.pkl") if exists(name): prefs = pkl.load(open(name, "rb")) self._preferences = prefs else: self._preferences = self._PREFS.copy() def save_preferences(self): """ Writes the preferences to a file. """ name = join(self._program_dir, "data", "preferences.pkl") with open(name, "wb") as fn: pkl.dump(self._preferences, fn) def set_status(self, content, duration=5000): """ Shows a message in the status bar for a given duration. **Arguments** *content* (string): The message. *duration* (integer): The duration in ms. Default: 5000 """ self.ui.statusbar.showMessage(QtCore.QString(content), duration)