Esempio n. 1
0
    def __init__(self):
        '''Init main window for Potku.
        '''
        super().__init__()
        self.ui = uic.loadUi(os.path.join("ui_files", "ui_main_window.ui"), self)
        self.title = self.ui.windowTitle()
        self.ui.treeWidget.setHeaderLabel("")
        
        self.icon_manager = IconManager()
        self.settings = GlobalSettings()
        self.project = None
        self.masses = Masses(os.path.join("external", "Potku-data", "masses.dat"))
        
        # Holds references to all the tab widgets in "tab_measurements" 
        # (even when they are removed from the QTabWidget)
        self.measurement_tab_widgets = {}  
        self.tab_id = 0  # identification for each tab

        # Set up connections within UI
        self.ui.actionNew_Measurement.triggered.connect(self.open_new_measurement)
        self.ui.projectSettingsButton.clicked.connect(self.open_project_settings)
        self.ui.globalSettingsButton.clicked.connect(self.open_global_settings)
        self.ui.tab_measurements.tabCloseRequested.connect(self.remove_tab)
        self.ui.treeWidget.itemDoubleClicked.connect(self.focus_selected_tab)
        
        self.ui.projectNewButton.clicked.connect(self.make_new_project)
        self.ui.projectOpenButton.clicked.connect(self.open_project)
        self.ui.actionNew_Project.triggered.connect(self.make_new_project)
        self.ui.actionOpen_Project.triggered.connect(self.open_project)
        self.ui.addNewMeasurementButton.clicked.connect(self.open_new_measurement)
        self.ui.actionNew_measurement_2.triggered.connect(self.open_new_measurement)
        self.ui.actionImport_pelletron.triggered.connect(self.import_pelletron)
        self.ui.actionBinary_data_lst.triggered.connect(self.import_binary)
        self.ui.action_manual.triggered.connect(self.__open_manual)
        
        self.ui.actionSave_cuts.triggered.connect(
                                self.current_measurement_save_cuts)
        self.ui.actionAnalyze_elemental_losses.triggered.connect(
                                self.current_measurement_analyze_elemental_losses)
        self.ui.actionCreate_energy_spectrum.triggered.connect(
                                self.current_measurement_create_energy_spectrum)
        self.ui.actionCreate_depth_profile.triggered.connect(
                                self.current_measurement_create_depth_profile)
        self.ui.actionGlobal_Settings.triggered.connect(self.open_global_settings)
        self.ui.actionProject_Settings.triggered.connect(self.open_project_settings)
        self.ui.actionAbout.triggered.connect(self.open_about_dialog)
        
        self.ui.actionNew_Project_2.triggered.connect(self.make_new_project)
        self.ui.actionOpen_Project_2.triggered.connect(self.open_project)
        self.ui.actionExit.triggered.connect(self.close)
        
        self.ui.menuImport.setEnabled(False)
        self.panel_shown = True
        self.ui.hidePanelButton.clicked.connect(lambda: self.hide_panel())
        
        # Add the context menu to the treewidget.
        delete_measurement = QtGui.QAction("Delete", self.ui.treeWidget)
        delete_measurement.triggered.connect(self.delete_selections)
        master_measurement = QtGui.QAction("Make master", self.ui.treeWidget)
        master_measurement.triggered.connect(self.__make_master_measurement)
        master_measurement_rem = QtGui.QAction("Remove master", self.ui.treeWidget)
        master_measurement_rem.triggered.connect(self.__remove_master_measurement)
        slave_measurement = QtGui.QAction("Exclude from slaves", self.ui.treeWidget)
        slave_measurement.triggered.connect(self.__make_nonslave_measurement)
        slave_measurement_rem = QtGui.QAction("Include as slave", self.ui.treeWidget)
        slave_measurement_rem.triggered.connect(self.__make_slave_measurement)
        self.ui.treeWidget.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
        self.ui.treeWidget.addAction(master_measurement)
        self.ui.treeWidget.addAction(master_measurement_rem)
        # self.ui.treeWidget.addSeparator() TODO: This should have separator
        # but doesn't work for QTreeWidget().
        self.ui.treeWidget.addAction(slave_measurement)
        self.ui.treeWidget.addAction(slave_measurement_rem)
        # self.ui.treeWidget.addSeparator() TODO: This should have separator
        # but doesn't work for QTreeWidget().
        self.ui.treeWidget.addAction(delete_measurement)
        
        # Set up styles for main window 
        bg_blue = "images/background_blue.svg"  # Cannot use os.path.join (PyQT+css)
        bg_green = "images/background_green.svg"
        style_intro = "QWidget#introduceTab {border-image: url(" + bg_blue + ");}"
        style_mesinfo = ("QWidget#measurementInfoTab {border-image: url(" + 
                         bg_green + ");}")
        self.ui.introduceTab.setStyleSheet(style_intro)
        self.ui.measurementInfoTab.setStyleSheet(style_mesinfo)
        self.__remove_measurement_info_tab()
        
        self.ui.setWindowIcon(self.icon_manager.get_icon("potku_icon.ico"))        
        
        # Set main window's icons to place
        self.__set_icons()
        self.ui.showMaximized()
Esempio n. 2
0
class Potku(QtGui.QMainWindow):
    '''Potku is main window class.
    '''
    
    def __init__(self):
        '''Init main window for Potku.
        '''
        super().__init__()
        self.ui = uic.loadUi(os.path.join("ui_files", "ui_main_window.ui"), self)
        self.title = self.ui.windowTitle()
        self.ui.treeWidget.setHeaderLabel("")
        
        self.icon_manager = IconManager()
        self.settings = GlobalSettings()
        self.project = None
        self.masses = Masses(os.path.join("external", "Potku-data", "masses.dat"))
        
        # Holds references to all the tab widgets in "tab_measurements" 
        # (even when they are removed from the QTabWidget)
        self.measurement_tab_widgets = {}  
        self.tab_id = 0  # identification for each tab

        # Set up connections within UI
        self.ui.actionNew_Measurement.triggered.connect(self.open_new_measurement)
        self.ui.projectSettingsButton.clicked.connect(self.open_project_settings)
        self.ui.globalSettingsButton.clicked.connect(self.open_global_settings)
        self.ui.tab_measurements.tabCloseRequested.connect(self.remove_tab)
        self.ui.treeWidget.itemDoubleClicked.connect(self.focus_selected_tab)
        
        self.ui.projectNewButton.clicked.connect(self.make_new_project)
        self.ui.projectOpenButton.clicked.connect(self.open_project)
        self.ui.actionNew_Project.triggered.connect(self.make_new_project)
        self.ui.actionOpen_Project.triggered.connect(self.open_project)
        self.ui.addNewMeasurementButton.clicked.connect(self.open_new_measurement)
        self.ui.actionNew_measurement_2.triggered.connect(self.open_new_measurement)
        self.ui.actionImport_pelletron.triggered.connect(self.import_pelletron)
        self.ui.actionBinary_data_lst.triggered.connect(self.import_binary)
        self.ui.action_manual.triggered.connect(self.__open_manual)
        
        self.ui.actionSave_cuts.triggered.connect(
                                self.current_measurement_save_cuts)
        self.ui.actionAnalyze_elemental_losses.triggered.connect(
                                self.current_measurement_analyze_elemental_losses)
        self.ui.actionCreate_energy_spectrum.triggered.connect(
                                self.current_measurement_create_energy_spectrum)
        self.ui.actionCreate_depth_profile.triggered.connect(
                                self.current_measurement_create_depth_profile)
        self.ui.actionGlobal_Settings.triggered.connect(self.open_global_settings)
        self.ui.actionProject_Settings.triggered.connect(self.open_project_settings)
        self.ui.actionAbout.triggered.connect(self.open_about_dialog)
        
        self.ui.actionNew_Project_2.triggered.connect(self.make_new_project)
        self.ui.actionOpen_Project_2.triggered.connect(self.open_project)
        self.ui.actionExit.triggered.connect(self.close)
        
        self.ui.menuImport.setEnabled(False)
        self.panel_shown = True
        self.ui.hidePanelButton.clicked.connect(lambda: self.hide_panel())
        
        # Add the context menu to the treewidget.
        delete_measurement = QtGui.QAction("Delete", self.ui.treeWidget)
        delete_measurement.triggered.connect(self.delete_selections)
        master_measurement = QtGui.QAction("Make master", self.ui.treeWidget)
        master_measurement.triggered.connect(self.__make_master_measurement)
        master_measurement_rem = QtGui.QAction("Remove master", self.ui.treeWidget)
        master_measurement_rem.triggered.connect(self.__remove_master_measurement)
        slave_measurement = QtGui.QAction("Exclude from slaves", self.ui.treeWidget)
        slave_measurement.triggered.connect(self.__make_nonslave_measurement)
        slave_measurement_rem = QtGui.QAction("Include as slave", self.ui.treeWidget)
        slave_measurement_rem.triggered.connect(self.__make_slave_measurement)
        self.ui.treeWidget.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
        self.ui.treeWidget.addAction(master_measurement)
        self.ui.treeWidget.addAction(master_measurement_rem)
        # self.ui.treeWidget.addSeparator() TODO: This should have separator
        # but doesn't work for QTreeWidget().
        self.ui.treeWidget.addAction(slave_measurement)
        self.ui.treeWidget.addAction(slave_measurement_rem)
        # self.ui.treeWidget.addSeparator() TODO: This should have separator
        # but doesn't work for QTreeWidget().
        self.ui.treeWidget.addAction(delete_measurement)
        
        # Set up styles for main window 
        bg_blue = "images/background_blue.svg"  # Cannot use os.path.join (PyQT+css)
        bg_green = "images/background_green.svg"
        style_intro = "QWidget#introduceTab {border-image: url(" + bg_blue + ");}"
        style_mesinfo = ("QWidget#measurementInfoTab {border-image: url(" + 
                         bg_green + ");}")
        self.ui.introduceTab.setStyleSheet(style_intro)
        self.ui.measurementInfoTab.setStyleSheet(style_mesinfo)
        self.__remove_measurement_info_tab()
        
        self.ui.setWindowIcon(self.icon_manager.get_icon("potku_icon.ico"))        
        
        # Set main window's icons to place
        self.__set_icons()
        self.ui.showMaximized()


    def current_measurement_create_depth_profile(self):
        """Opens the depth profile analyzation tool for the current open 
        measurement tab widget.
        """
        widget = self.ui.tab_measurements.currentWidget()
        if hasattr(widget, "measurement"):
            widget.open_depth_profile(widget)
        else:
            QtGui.QMessageBox.question(self,
              "Notification",
              "An open measurement is required to do this action.",
              QtGui.QMessageBox.Ok)
        
        
    def current_measurement_analyze_elemental_losses(self):
        """Opens the element losses analyzation tool for the current open 
        measurement tab widget.
        """
        widget = self.ui.tab_measurements.currentWidget()
        if hasattr(widget, "measurement"):
            widget.open_element_losses(widget)
        else:
            QtGui.QMessageBox.question(self,
              "Notification",
              "An open measurement is required to do this action.",
              QtGui.QMessageBox.Ok)
        
        
    def current_measurement_create_energy_spectrum(self):
        """Opens the energy spectrum analyzation tool for the current open 
        measurement tab widget.
        """
        widget = self.ui.tab_measurements.currentWidget()
        if hasattr(widget, "measurement"):
            widget.open_energy_spectrum(widget)
        else:
            QtGui.QMessageBox.question(self,
              "Notification",
              "An open measurement is required to do this action.",
              QtGui.QMessageBox.Ok)


    def current_measurement_save_cuts(self):
        """Saves the current open measurement tab widget's selected cuts 
        to cut files.
        """
        widget = self.ui.tab_measurements.currentWidget()
        if hasattr(widget, "measurement"):
            widget.measurement_save_cuts()
        else:
            QtGui.QMessageBox.question(self,
              "Notification",
              "An open measurement is required to do this action.",
              QtGui.QMessageBox.Ok)
    
    
    def delete_selections(self):
        '''Deletes the selected tree widget items.
        '''
        # TODO: Memory isn't released correctly. Maybe because of matplotlib.
        # TODO: Remove 'measurement_tab_widgets' variable and add tab reference
        # to treewidgetitem.
        selected_tabs = [self.measurement_tab_widgets[item.tab_id] for 
                         item in self.ui.treeWidget.selectedItems()]
        if selected_tabs:  # Ask user a confirmation.
            reply = QtGui.QMessageBox.question(self,
                   "Confirmation",
                   "Deleting selected measurements will " \
                   + "delete all files and folders under" \
                   + " selected measurement directories." + \
                   "\n\nAre you sure you want to delete selected measurements?",
                   QtGui.QMessageBox.Yes,
                   QtGui.QMessageBox.No,
                   QtGui.QMessageBox.Cancel)
            if reply == QtGui.QMessageBox.No or reply == QtGui.QMessageBox.Cancel:
                return  # If clicked Yes, then continue normally
        
        for tab in selected_tabs:
            measurement = self.project.measurements.get_key_value(tab.tab_id)
            try:
                # Close and remove logs
                measurement.remove_and_close_log(measurement.defaultlog)
                measurement.remove_and_close_log(measurement.errorlog)
                
                # Remove measurement's directory tree
                shutil.rmtree(measurement.directory)
                os.remove(os.path.join(self.project.directory,
                                       measurement.measurement_file))
            except:
                print("Error with removing files")
                QtGui.QMessageBox.question(self, "Confirmation",
                               "Problem with deleting files.",
                               QtGui.QMessageBox.Ok)
                measurement.set_loggers()
                return
            
            self.project.measurements.remove_by_tab_id(tab.tab_id)
            remove_index = self.ui.tab_measurements.indexOf(tab)
            self.remove_tab(remove_index)  # Remove measurement from open tabs 
            
            tab.histogram.matplotlib.delete()
            tab.elemental_losses_widget.matplotlib.delete()
            tab.energy_spectrum_widget.matplotlib.delete()
            tab.depth_profile_widget.matplotlib.delete()
            
            tab.mdiArea.closeAllSubWindows()
            del self.measurement_tab_widgets[tab.tab_id]
            tab.close() 
            tab.deleteLater()
            
        # Remove selected from tree widget
        root = self.ui.treeWidget.invisibleRootItem()
        for item in self.ui.treeWidget.selectedItems():
            (item.parent() or root).removeChild(item)
        gc.collect()  # Suggest garbage collector to clean.
            

    def focus_selected_tab(self, clicked_item):
        '''Focus to selected tab (in tree widget) and if it isn't open, open it.
        
        Args:
            clicked_item: TreeWidgetItem with tab_id attribute (int) that connects
            the item to the corresponding MeasurementTabWidget
        '''
        # TODO: This doesn't work. There is no list/dictionary of references to the
        # tab widgets once they are removed from the QTabWidget. 
        # tab = self.project_measurements[clicked_item.tab_id]
        tab = self.measurement_tab_widgets[clicked_item.tab_id]
        name = tab.measurement.measurement_name
        
        # Check that the data is read.
        if not tab.data_loaded:
            tab.data_loaded = True
            progress_bar = QtGui.QProgressBar()
            loading_bar = QtGui.QProgressBar()
            loading_bar.setMinimum(0)
            loading_bar.setMaximum(0)
            self.statusbar.addWidget(progress_bar, 1)
            self.statusbar.addWidget(loading_bar, 2)
            progress_bar.show()
            loading_bar.show()
            progress_bar.setValue(5)
            QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents) 
            
            tab.measurement.load_data()
            progress_bar.setValue(35)
            QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents) 
            
            tab.add_histogram()
            loading_bar.hide()
            self.statusbar.removeWidget(loading_bar)
            
            progress_bar.setValue(50)
            QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents) 
            tab.check_previous_state_files(progress_bar)  # Load previous states.
            self.statusbar.removeWidget(progress_bar)
            progress_bar.hide()
            self.__change_tab_icon(clicked_item)
            master_mea = tab.measurement.project.get_master()
            if master_mea and tab.measurement.measurement_name == \
                              master_mea.measurement_name:
                name = "{0} (master)".format(name)
        
        # Check that the tab to be focused exists.
        if not self.__tab_exists(clicked_item.tab_id): 
            self.ui.tab_measurements.addTab(tab, name)
        self.ui.tab_measurements.setCurrentWidget(tab)
  

    def hide_panel(self, enable_hide=None):
        """Sets the frame (including measurement navigation view, global 
        settings and project settings buttons) visible.
        
        Args:
            enable_hide: If True, sets the frame visible and vice versa. 
            If not given, sets the frame visible or hidden depending its 
            previous state.
        """
        if enable_hide != None:
            self.panel_shown = enable_hide
        else:
            self.panel_shown = not self.panel_shown    
        if self.panel_shown:
            self.ui.hidePanelButton.setText('<')
        else:
            self.ui.hidePanelButton.setText('>')

        self.ui.frame.setShown(self.panel_shown)


    def import_pelletron(self):
        '''Import Pelletron's measurements into project.
        
        Import Pelletron's measurements from 
        '''
        if not self.project: 
            return
        import_dialog = ImportMeasurementsDialog(self.project,
                                                 self.icon_manager,
                                                 self.statusbar,
                                                 self)  # For loading measurements.
        if import_dialog.imported:
            self.__remove_measurement_info_tab()
            
            
    def import_binary(self):
        '''Import binary measurements into project.
        
        Import binary measurements from 
        '''
        if not self.project: 
            return
        import_dialog = ImportDialogBinary(self.project,
                                           self.icon_manager,
                                           self.statusbar,
                                           self)  # For loading measurements.
        if import_dialog.imported:
            self.__remove_measurement_info_tab()
                

    def load_project_measurements(self, measurements=[]):
        '''Load measurement files in the project.
        
        Args:
            measurements: A list representing loadable measurements when importing
                          measurements to the project.
        '''
        if measurements:
            measurements_in_project = measurements
            load_data = True
        else:
            measurements_in_project = self.project.get_measurements_files()
            load_data = False
        progress_bar = QtGui.QProgressBar()
        self.statusbar.addWidget(progress_bar, 1)
        progress_bar.show()
        
        count = len(measurements_in_project)
        dirtyinteger = 0
        for measurement_file in measurements_in_project:
            self.__add_new_tab(measurement_file, progress_bar,
                               dirtyinteger, count, load_data=load_data)
            dirtyinteger += 1

        self.statusbar.removeWidget(progress_bar)
        progress_bar.hide()
        

    def make_new_project(self):
        """Opens a dialog for creating a new project.
        """
        dialog = ProjectNewDialog(self)
        # TODO: regex check for directory. I.E. do not allow asd/asd
        if dialog.directory:
            self.__close_project()
            title = "{0} - Project: {1}".format(self.title, dialog.name)
            self.ui.setWindowTitle(title)
            self.ui.treeWidget.setHeaderLabel("Project: {0}".format(dialog.name))
            self.project = Project(dialog.directory, dialog.name, self.masses,
                                   self.statusbar, self.settings,
                                   self.measurement_tab_widgets)
            self.settings.set_project_directory_last_open(dialog.directory)
            # Project made, close introduction tab
            self.__remove_introduction_tab()
            self.__open_measurement_info_tab()
            self.__set_project_buttons_enabled(True)

       
    def open_about_dialog(self):
        '''Show Potku program about dialog.
        '''
        AboutDialog()
    
    
    def open_global_settings(self):
        """Opens global settings dialog.
        """
        GlobalSettingsDialog(self.masses, self.settings)
        
    
    def open_new_measurement(self):
        '''Opens file an open dialog and if filename is given opens new measurement 
        from it.
        '''
        if not self.project: 
            return
        filename = open_file_dialog(self,
                                    self.project.directory,
                                    "Select a measurement to load",
                                    "Raw Measurement (*.asc)")
        if filename:
            try:
                self.ui.tab_measurements.removeTab(self.ui.tab_measurements.indexOf(
                                                   self.measurement_info_tab))
            except: 
                pass  # If there is no info tab, no need to worry about.
                # print("Can't find an info tab to remove")
            progress_bar = QtGui.QProgressBar()
            self.statusbar.addWidget(progress_bar, 1)
            progress_bar.show()
            self.__add_new_tab(filename, progress_bar, load_data=True)
            self.__remove_measurement_info_tab()
            self.statusbar.removeWidget(progress_bar)
            progress_bar.hide()


    def open_project(self):
        '''Shows a dialog to open a project.
        '''
        file = open_file_dialog(self,
                                self.settings.get_project_directory_last_open(),
                                "Open an existing project", "Project file (*.proj)")
        if file:
            self.__close_project()
            folder = os.path.split(file)[0]
            tmp_name = os.path.splitext(os.path.basename(file))[0]
            self.project = Project(folder, tmp_name, self.masses,
                                   self.statusbar, self.settings,
                                   self.measurement_tab_widgets)
            self.ui.setWindowTitle("{0} - Project: {1}".format(
                                                       self.title,
                                                       self.project.get_name()))
            self.ui.treeWidget.setHeaderLabel(
                                 "Project: {0}".format(self.project.get_name()))
            self.settings.set_project_directory_last_open(folder)
            
            self.load_project_measurements()
            self.__remove_introduction_tab()
            self.__set_project_buttons_enabled(True)
            
            master_measurement_name = self.project.has_master()
            nonslaves = self.project.get_nonslaves()
            if master_measurement_name:
                master_measurement = None
                keys = self.project.measurements.measurements.keys()
                for key in keys:
                    measurement = self.project.measurements.measurements[key]
                    if measurement.measurement_name == master_measurement_name:
                        master_measurement = measurement
                        self.project.set_master(measurement)
                        break
            root = self.treeWidget.invisibleRootItem()
            root_child_count = root.childCount()
            for i in range(root_child_count):
                item = root.child(i)
                tab_widget = self.measurement_tab_widgets[item.tab_id]
                tab_name = tab_widget.measurement.measurement_name
                if master_measurement_name and \
                   item.tab_id == master_measurement.tab_id:
                    item.setText(0,
                                 "{0} (master)".format(master_measurement_name))
                elif tab_name in nonslaves or not master_measurement_name:
                    item.setText(0, tab_name)
                else:
                    item.setText(0, "{0} (slave)".format(tab_name))
                
                       
                

    def open_project_settings(self):
        """Opens project settings dialog.
        """
        ProjectSettingsDialog(self.masses, self.project)
          

    def remove_tab(self, tab_index):
        '''Remove tab which's close button has been pressed.
        
        Args:
            tab_index: Integer representing index of the current tab
        '''
        self.ui.tab_measurements.removeTab(tab_index)
    

    def __add_measurement_to_tree(self, measurement_name, load_data):
        '''Add measurement to tree where it can be opened.
        
        Args:
            measurement_name: A string representing measurement's name.
            load_data: A boolean representing if measurement data is loaded.
        '''
        tree_item = QtGui.QTreeWidgetItem()
        tree_item.setText(0, measurement_name)
        tree_item.tab_id = self.tab_id
        # tree_item.setIcon(0, self.icon_manager.get_icon("folder_open.svg"))
        if load_data:
            self.__change_tab_icon(tree_item, "folder_open.svg")
        else:
            self.__change_tab_icon(tree_item, "folder_locked.svg")
        self.ui.treeWidget.addTopLevelItem(tree_item)
        
        
    def __add_new_tab(self, filename, progress_bar=None,
                      file_current=0, file_count=1, load_data=False):
        '''Add new tab into measurement TabWidget.
        
        Adds a new tab into program's tabWidget. Makes a new measurement for 
        said tab.
        
        Args:
            filename: A string representing measurement file.
            progress_bar: A QtGui.QProgressBar to be updated.
            file_current: An integer representing which number is currently being
                          read. (for GUI)
            file_count: An integer representing how many files will be loaded.
            load_data: A boolean representing whether to load data or not. This is
                       to save time when loading a project and we do not want to
                       load every measurement.
        '''
        if progress_bar:
            progress_bar.setValue((100 / file_count) * file_current)
            QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents) 
        measurement = self.project.measurements.add_measurement_file(filename,
                                                                     self.tab_id)
        if measurement:  # TODO: Finish this (load_data)
            tab = MeasurementTabWidget(self.tab_id, measurement,
                                       self.masses, self.icon_manager)
            self.connect(tab,
                         QtCore.SIGNAL("issueMaster"),
                         self.__master_issue_commands)
            tab.setAttribute(QtCore.Qt.WA_DeleteOnClose)
            self.measurement_tab_widgets[self.tab_id] = tab
            tab.add_log()
            tab.data_loaded = load_data
            if load_data:
                loading_bar = QtGui.QProgressBar()
                loading_bar.setMinimum(0)
                loading_bar.setMaximum(0)
                self.statusbar.addWidget(loading_bar, 1)
                loading_bar.show()
                
                measurement.load_data()  
                tab.add_histogram()  
                self.ui.tab_measurements.addTab(tab, measurement.measurement_name)
                self.ui.tab_measurements.setCurrentWidget(tab)
                
                loading_bar.hide()
                self.statusbar.removeWidget(loading_bar)
            self.__add_measurement_to_tree(measurement.measurement_name, load_data)
            self.tab_id += 1
    
    
    def __change_tab_icon(self, tree_item, icon="folder_open.svg"):
        '''Change tab icon in QTreeWidgetItem.
        
        Args:
            tree_item: A QtGui.QTreeWidgetItem class object.
            icon: A string representing the icon name.
        '''
        tree_item.setIcon(0, self.icon_manager.get_icon(icon))
    
    
    def __close_project(self):
        """Closes the project for opening a new one.
        """
        if self.project:
            # TODO: Doesn't release memory
            # Clear the treewidget
            self.ui.treeWidget.clear()
            self.ui.tab_measurements.clear()
            self.project = None
            self.measurement_tab_widgets = {}  
            self.tab_id = 0
        
        
    def __make_nonslave_measurement(self):
        """Exclude selected measurements from slave category.
        """
        items = self.ui.treeWidget.selectedItems()
        if not items:
            return
        master = self.project.get_master()
        # Remove (slave) text from tree titles
        for item in items:
            tab_widget = self.measurement_tab_widgets[item.tab_id]
            tab_measurement = tab_widget.measurement
            tab_name = tab_measurement.measurement_name
            if master and tab_name != master.measurement_name:
                self.project.exclude_slave(tab_measurement)
                item.setText(0, tab_name)
    
    
    def __make_slave_measurement(self):
        """Exclude selected measurements from slave category.
        """
        items = self.ui.treeWidget.selectedItems()
        if not items:
            return
        master = self.project.get_master()
        # Add (slave) text from tree titles
        for item in items:
            tab_widget = self.measurement_tab_widgets[item.tab_id]
            tab_measurement = tab_widget.measurement
            tab_name = tab_measurement.measurement_name
            if master and tab_name != master.measurement_name:
                self.project.include_slave(tab_measurement)
                item.setText(0, "{0} (slave)".format(tab_name))
        
               
    def __make_master_measurement(self):
        """Make selected or first of the selected measurements 
        a master measurement.
        """
        items = self.ui.treeWidget.selectedItems()
        if not items:
            return
        master_tree = items[0]
        master_tab = self.measurement_tab_widgets[master_tree.tab_id]
        self.project.set_master(master_tab.measurement)
        # old_master = self.project.get_master()
        nonslaves = self.project.get_nonslaves()
        
        # if old_master:
        #    old_master_name = old_master.measurement_name
        #    self.ui.tab_measurements.setTabText(old_master.tab_id, old_master_name)
        root = self.treeWidget.invisibleRootItem()
        root_child_count = root.childCount()
        for i in range(root_child_count):
            item = root.child(i)
            tab_widget = self.measurement_tab_widgets[item.tab_id]
            tab_name = tab_widget.measurement.measurement_name
            if item.tab_id == master_tab.tab_id:
                item.setText(0, "{0} (master)".format(tab_name))
            elif tab_name in nonslaves:
                item.setText(0, tab_name)
            else:
                item.setText(0, "{0} (slave)".format(tab_name))
            tab_widget.toggle_master_button()
        # master_tab.toggle_master_button()
        # QtGui.QTabWidget().count()
        for i in range(self.ui.tab_measurements.count()):
            tab = self.ui.tab_measurements.widget(i)
            tab_name = tab.measurement.measurement_name
            if tab.tab_id == master_tab.tab_id:
                tab_name = "{0} (master)".format(tab_name)
                self.ui.tab_measurements.setTabText(tab.tab_id, tab_name)
            else:
                self.ui.tab_measurements.setTabText(tab.tab_id, tab_name)
    
    
    def __master_issue_commands(self):
        """Issue commands from master measurement to all slave measurements in 
        the project.
        """
        reply = QtGui.QMessageBox.question(self,
                "Confirmation",
                "You are about to issue actions from master measurement to all " + \
                "slave measurements in the project. This can take several " + \
                "minutes. Please wait until notification is shown." + \
                "\nDo you wish to continue?",
                QtGui.QMessageBox.Yes,
                QtGui.QMessageBox.No)
        if reply == QtGui.QMessageBox.No:
            return
        
        time_start = datetime.now()
        progress_bar = QtGui.QProgressBar()
        self.statusbar.addWidget(progress_bar, 1)
        progress_bar.show()
        nonslaves = self.project.get_nonslaves()
        master = self.project.get_master()
        master_tab = self.measurement_tab_widgets[master.tab_id]
        master_name = master.measurement_name
        directory = master.directory
        progress_bar.setValue(1)
        QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents) 
        # Load selections and save cut files
        # TODO: Make a check for these if identical already -> don't redo.
        self.project.save_selection(master)
        progress_bar.setValue(10)
        QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents) 
        
        self.project.save_cuts(master)
        progress_bar.setValue(25)
        QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents) 
        
        root = self.treeWidget.invisibleRootItem()
        root_child_count = root.childCount()
        i = 1
        for i in range(root_child_count):
            item = root.child(i)
            tab = self.measurement_tab_widgets[item.tab_id]
            tab_measurement = tab.measurement
            tab_name = tab_measurement.measurement_name
            if tab_name == master_name or tab_name in nonslaves:
                continue
            # Load measurement data if the slave is
            if not tab.data_loaded:
                tab.data_loaded = True
                progress_bar_data = QtGui.QProgressBar()
                self.statusbar.addWidget(progress_bar_data, 1)
                progress_bar_data.show()
                progress_bar_data.setValue(5)
                QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents) 
                
                tab.measurement.load_data()
                progress_bar_data.setValue(35)
                QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents) 
                
                tab.add_histogram()
                progress_bar_data.hide()
                self.statusbar.removeWidget(progress_bar_data)
                QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents)
                # Update tree item icon to open folder
                tree_item = None
                root = self.treeWidget.invisibleRootItem()
                root_child_count = root.childCount()
                for i in range(root_child_count):
                    item = root.child(i)
                    if item.tab_id == tab.tab_id:
                        tree_item = item
                        break
                if tree_item:
                    self.__change_tab_icon(tree_item)
            # Check all widgets of master and do them for slaves.
            if master_tab.depth_profile_widget and tab.data_loaded:
                if tab.depth_profile_widget:
                    tab.del_widget(tab.depth_profile_widget)
                tab.make_depth_profile(directory, master_name)
                tab.depth_profile_widget.save_to_file()
            if master_tab.elemental_losses_widget and tab.data_loaded:
                if tab.elemental_losses_widget:
                    tab.del_widget(tab.elemental_losses_widget)
                tab.make_elemental_losses(directory, master_name)
                tab.elemental_losses_widget.save_to_file()
            if master_tab.energy_spectrum_widget and tab.data_loaded:
                if tab.energy_spectrum_widget:
                    tab.del_widget(tab.energy_spectrum_widget)
                tab.make_energy_spectrum(directory, master_name)
                tab.energy_spectrum_widget.save_to_file()
            progress_bar.setValue(25 + (i / root_child_count) * 75)
            QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents)
            i += 1
        self.statusbar.removeWidget(progress_bar)
        progress_bar.hide()
        time_end = datetime.now()
        time_duration = (time_end - time_start).seconds
        time_str = timedelta(seconds=time_duration)
        QtGui.QMessageBox.question(self,
                "Notification",
                "Master measurement's actions have been issued to slaves. " + \
                "\nElapsed time: {0}".format(time_str),
                QtGui.QMessageBox.Ok)
        
        
    def __open_measurement_info_tab(self):
        """Opens an info tab to the QTabWidget 'tab_measurements' that guides the 
        user to add a new measurement to the project.
        """
        self.ui.tab_measurements.addTab(self.ui.measurementInfoTab, "Info")
    

    def __remove_introduction_tab(self):
        """Removes an info tab from the QTabWidget 'tab_measurements' that guides
        the user to create a new project.
        """
        index = self.ui.tab_measurements.indexOf(self.ui.introduceTab)
        if index >= 0:
            self.ui.tab_measurements.removeTab(index)
    
    
    def __remove_master_measurement(self):
        """Remove master measurement
        """
        old_master = self.project.get_master()
        self.project.set_master()  # No master measurement
        root = self.treeWidget.invisibleRootItem()
        root_child_count = root.childCount()
        for i in range(root_child_count):
            item = root.child(i)
            tab_widget = self.measurement_tab_widgets[item.tab_id]
            tab_name = tab_widget.measurement.measurement_name
            item.setText(0, tab_name)
            tab_widget.toggle_master_button()
        if old_master:
            measurement_name = old_master.measurement_name
            self.ui.tab_measurements.setTabText(old_master.tab_id, measurement_name)
            old_master_tab = self.measurement_tab_widgets[old_master.tab_id]
            old_master_tab.toggle_master_button()
        self.project.set_master()  # No master measurement
        
             
    def __remove_measurement_info_tab(self):
        """Removes an info tab from the QTabWidget 'tab_measurements' that guides
        the user to add a new measurement to the project.
        """
        index = self.ui.tab_measurements.indexOf(self.ui.measurementInfoTab)
        if index >= 0:
            self.ui.tab_measurements.removeTab(index)
        
 
    def __set_icons(self):
        """Adds icons to the main window.
        """
        self.icon_manager.set_icon(self.ui.projectSettingsButton, "gear.svg")
        self.icon_manager.set_icon(self.ui.globalSettingsButton, "gear.svg")
        self.icon_manager.set_icon(self.ui.actionNew_Project, "file.svg")
        self.icon_manager.set_icon(self.ui.actionOpen_Project, "folder_open.svg")
        self.icon_manager.set_icon(self.ui.actionSave_Project, "amarok_save.svg")
        self.icon_manager.set_icon(self.ui.actionNew_Measurement, "log.svg")
        
               
    def __set_project_buttons_enabled(self, state=False):
        """Enables 'project settings', 'save project' and 'new measurement' buttons.
        
        Args:
            state: True/False enables or disables buttons
        """
        self.ui.projectSettingsButton.setEnabled(state)
        self.ui.actionSave_Project.setEnabled(state)
        self.ui.actionNew_Measurement.setEnabled(state)
        self.ui.actionNew_measurement_2.setEnabled(state)
        self.ui.menuImport.setEnabled(state)
        self.ui.actionProject_Settings.setEnabled(state)
        # TODO: Should these only be enabled when there is measurement open?
        self.ui.actionAnalyze_elemental_losses.setEnabled(state)
        self.ui.actionCreate_energy_spectrum.setEnabled(state)
        self.ui.actionCreate_depth_profile.setEnabled(state)


    def __tab_exists(self, tab_id):
        '''Check if there is an open tab with the tab_id (identifier).
        
        Args:
            tab_id: Identifier (int) for the MeasurementTabWidget
            
        Returns:
            True if tab is found, False if not
        '''
        # Try to find the clicked item from QTabWidget.
        for i in range(0, self.ui.tab_measurements.count()):
            if self.ui.tab_measurements.widget(i).tab_id == tab_id:
                return True
        return False
        
        
    def __open_manual(self):
        '''Open user manual.
        '''
        manual_filename = os.path.join('manual', 'Potku-manual.pdf');
        used_os = platform.system()
        if used_os == 'Windows':
            os.startfile(manual_filename)
        elif used_os == 'Linux':
            subprocess.call(('xdg-open', manual_filename))
        elif used_os == 'Darwin':
            subprocess.call(('open', manual_filename))