Exemple #1
0
class MainWidget(QMainWindow):


    def __init__(self, parent=None):
        super(MainWidget, self).__init__(
                parent,
                windowTitle='GithubRemote',
                windowIcon=QIcon(image_path('git.png')),
                geometry=QRect(300, 300, 600, 372))

        self.repo_pixmap = QPixmap(image_path('book_16.png'))
        self.big_repo_pixmap = QPixmap(image_path('book_32.png'))
        self.repo_fork_pixmap = QPixmap(image_path('book_fork_16.png'))
        self.star_pixmap = QPixmap(image_path('star_16.png'))
        self.big_star_pixmap = QPixmap(image_path('star_32.png'))
        self.fork_pixmap = QPixmap(image_path('fork_16.png'))
        self.eye_pixmap = QPixmap(image_path('eye_16.png'))

        self.github = None        

        # Actions

        self.repoAddAction = QAction(
                QIcon(image_path('plus_48.png')),
                '&Add Repo', self,
                statusTip='Add a new repo')
        self.repoAddAction.triggered.connect(self.repoAdd)
        
        self.repoRemoveAction = QAction(
                QIcon(image_path('minus.png')),
                '&Remove Repo', self,
                statusTip='Remove repo')
        self.repoRemoveAction.triggered.connect(self.repoRemove)

        self.repoRefreshAction = QAction(
                QIcon(image_path('refresh.png')),
                'Refresh', self,
                statusTip='Refresh list of repos')
        self.repoRefreshAction.triggered.connect(self.reposRefresh)
        self.repoRefreshAction.triggered.connect(self.starsRefresh)

        self.addAccountAction = QAction(
                'Add Account', self,
                statusTip='Add Account')
        self.addAccountAction.triggered.connect(self.addAccount)

        # userPushButton - Displays the current active username and 
        # image on the top right of the toolbar.
        
        self.userButtonMenu = UserButtonMenu(32,32)

        # ToolBar

        self.toolBar = self.addToolBar('Main')
        self.toolBar.setMovable(False)
        self.toolBar.setFloatable(False)
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.toolBar.addAction(self.repoAddAction)
        self.toolBar.addAction(self.repoRemoveAction)
        self.toolBar.addAction(self.repoRefreshAction)
        self.toolBar.addWidget(spacer)
        self.toolBar.addWidget(self.userButtonMenu)

        # Menu

        menuBar = self.menuBar()
        fileMenu = menuBar.addMenu('&File')
        actionMenu = menuBar.addMenu('&Action')
        fileMenu.addAction(self.addAccountAction)
        actionMenu.addAction(self.repoAddAction)
        actionMenu.addAction(self.repoRemoveAction)
        actionMenu.addAction(self.repoRefreshAction)

        # StatusBar

        statusBar = self.statusBar()
        self.setStatusBar(statusBar)

        # reposTableWidget - Displays a list of the users repositories

        self.reposTableWidget = QTableWidget(0, 5,
                selectionBehavior = QAbstractItemView.SelectRows,
                selectionMode = QAbstractItemView.SingleSelection,
                editTriggers = QAbstractItemView.NoEditTriggers,
                itemSelectionChanged = self.actionsUpdate)
        self.reposTableWidget.horizontalHeader().setResizeMode(
                QHeaderView.ResizeToContents)
        self.reposTableWidget.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)
        self.reposTableWidget.horizontalHeader().setVisible(False)
        self.reposTableWidget.verticalHeader().setVisible(False)
        self.reposTableWidget.setShowGrid(False)
        self.reposTableWidget.verticalHeader().setMinimumSectionSize(25)

        # repoTab - Layout
        reposTab = QWidget()
        reposTabLayout = QVBoxLayout(reposTab)
        reposTabLayout.addWidget(self.reposTableWidget)
        reposTab.setLayout(reposTabLayout)

        # starsTableWidget - Displays a list of the users repositories

        self.starsTableWidget = QTableWidget(0, 5,
                selectionBehavior = QAbstractItemView.SelectRows,
                selectionMode = QAbstractItemView.SingleSelection,
                editTriggers = QAbstractItemView.NoEditTriggers,
                itemSelectionChanged = self.actionsUpdate)
        self.starsTableWidget.horizontalHeader().setResizeMode(
                QHeaderView.ResizeToContents)
        self.starsTableWidget.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)
        self.starsTableWidget.horizontalHeader().setVisible(False)
        self.starsTableWidget.verticalHeader().setVisible(False)
        self.starsTableWidget.setShowGrid(False)
        self.starsTableWidget.verticalHeader().setMinimumSectionSize(25)

        # repoTab - Layout
        starsTab = QWidget()
        starsTabLayout = QVBoxLayout(starsTab)
        starsTabLayout.addWidget(self.starsTableWidget)
        starsTab.setLayout(starsTabLayout)
        
        # Tab Widget
        self.tabs = QTabWidget()
        self.tabs.setTabBar(FlippedTabBar(self))
        self.tabs.addTab(reposTab, QIcon(self.big_repo_pixmap), "repos")
        self.tabs.addTab(starsTab, QIcon(self.big_star_pixmap), "stars")
        self.tabs.setTabPosition(QTabWidget.West)

        # Layout

        self.setCentralWidget(self.tabs)
        self.actionsUpdate()
        self.show()
        
        # Update

        self.loadUserMenu()
        if self.activeUserAction:
            self.activeUserAction.setVisible(False)
        self.authenticate()
        self.actionsUpdate()
        self.reposRefresh()
        self.starsRefresh()
        self.updateImage()

    
    @waiting_effects
    def updateImage(self):

        try:
            url = self.github.get_user().avatar_url
        except (GithubException, AttributeError): 
            return 
        data = urllib.urlopen(url).read()
        pixmap = QPixmap()
        pixmap.loadFromData(data)
        self.activeUserAction.setIcon(QIcon(pixmap))
        self.userButtonMenu.setPixmap(pixmap)
        self.userButtonMenu.setText(self.github.get_user().login)
   
    @waiting_effects
    def loadUserMenu(self):
        
        action = None
        for _, username, token in generate_tokens(CONFIG_PATH, 'github'):
            
            try:
                url = Github(token).get_user().avatar_url
            except (GithubException, AttributeError): 
                action = QAction(username, self, triggered=self.changeActive)
                self.userButtonMenu.addAction(action)
                continue
            data = urllib.urlopen(url).read()
            pixmap = QPixmap()
            pixmap.loadFromData(data)
            action = QAction(QIcon(pixmap), username, self,
                    triggered=self.changeActive)
            action.setIconVisibleInMenu(True)
            self.userButtonMenu.addAction(action)
        
        self.activeUserAction = action
    
    def changeActive(self):

        sender = self.sender()

        self.activeUserAction.setVisible(True)
        self.activeUserAction = sender
        self.activeUserAction.setVisible(False)
        self.authenticate()
        self.actionsUpdate()
        self.reposRefresh()
        self.starsRefresh()
        self.updateImage()

    @waiting_effects
    def reposRefresh(self):

        self.reposTableWidget.clearContents()

        try:
            repos = self.github.get_user().get_repos()
            self.reposTableWidget.setRowCount(self.github.get_user().public_repos)
        except (GithubException, AttributeError):
            return
        for row, repo in enumerate(repos):
            imageLabel = QLabel()
            if repo.fork:
                imageLabel.setPixmap(self.repo_fork_pixmap)
            else:
                imageLabel.setPixmap(self.repo_pixmap)
            imageLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            imageLabel.setMargin(5)

            self.reposTableWidget.setCellWidget(row, 0, imageLabel)
            label = QLabel('<b>{}</b><br />{}'.format(
                        str(repo.name), str(repo.description)))
            label.setAlignment(Qt.AlignVCenter)
            label.setMargin(5)
            label.setWordWrap(True)
            self.reposTableWidget.setCellWidget(row, 1, label)
            self.reposTableWidget.setItem(row, 2, 
                    QTableWidgetItem(QIcon(self.star_pixmap), str(repo.stargazers_count)))
            self.reposTableWidget.setItem(row, 3, 
                    QTableWidgetItem(QIcon(self.eye_pixmap), str(repo.watchers_count)))
            self.reposTableWidget.setItem(row, 4, 
                    QTableWidgetItem(QIcon(self.fork_pixmap), str(repo.forks_count)))

        self.reposTableWidget.resizeRowsToContents()

    @waiting_effects
    def starsRefresh(self):

        self.starsTableWidget.clearContents()

        try:
            starred = self.github.get_user().get_starred()
            self.starsTableWidget.setRowCount(self.github.get_user().public_repos)
        except (GithubException, AttributeError):
            return
        for row, repo in enumerate(starred):
            imageLabel = QLabel()
            if repo.fork:
                imageLabel.setPixmap(self.repo_fork_pixmap)
            else:
                imageLabel.setPixmap(self.repo_pixmap)
            imageLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            imageLabel.setMargin(5)

            self.starsTableWidget.setCellWidget(row, 0, imageLabel)
            label = QLabel(u'<b>{}/{}</b><br />{}'.format(
                unicode(repo.owner.login), unicode(repo.name), unicode(repo.description)))
            label.setAlignment(Qt.AlignVCenter)
            label.setMargin(5)
            label.setWordWrap(True)
            self.starsTableWidget.setCellWidget(row, 1, label)
            self.starsTableWidget.setItem(row, 2, 
                    QTableWidgetItem(QIcon(self.star_pixmap), '0'))
            self.starsTableWidget.setItem(row, 3, 
                    QTableWidgetItem(QIcon(self.eye_pixmap), str(repo.watchers_count)))
            self.starsTableWidget.setItem(row, 4, 
                    QTableWidgetItem(QIcon(self.fork_pixmap), str(repo.forks_count)))

        self.starsTableWidget.resizeRowsToContents()

    @waiting_effects
    def authenticate(self):
        
        if self.activeUserAction:
            username = str(self.activeUserAction.text())
            token = load_token(CONFIG_PATH, 'github', username) 
            self.github = Github(token)
        else:
            self.github = None

    
    def actionsUpdate(self):
        # TODO disable if no user is logged in
        if self.github is None:
            self.repoAddAction.setEnabled(False)
            self.repoRemoveAction.setEnabled(False)
            self.repoRefreshAction.setEnabled(False)
        else:
            self.repoAddAction.setEnabled(True)
            self.repoRefreshAction.setEnabled(True)
            if self._isARepoSelected():
                self.repoRemoveAction.setEnabled(True)
            else:
                self.repoRemoveAction.setEnabled(False)

    def addAccount(self):
        wizard = AddAccountWizard(self)
        if wizard.exec_():
            username = str(wizard.field('username').toString())
            token = str(wizard.field('token').toString())
            store_token(CONFIG_PATH, 'github', username, token)
            self.authenticate()
            self.reposRefresh()
            self.updateImage()
            self.actionsUpdate()

    def repoAdd(self):
        wizard = AddRepoWizard(self.github, self)
        if wizard.exec_():
            self.github.get_user().create_repo(
                str(wizard.field('name').toString()),
                description=str(wizard.field('description').toString()),
                private=bool(wizard.field('private').toBool()),
                auto_init=bool(wizard.field('auto_init').toBool()),
                gitignore_template=str(wizard.field('gitignore').toString()),
                homepage=str(wizard.field('homepage').toString()),
                has_wiki=bool(wizard.field('has_wiki').toBool()),
                has_downloads=bool(wizard.field('has_downloads').toBool()),
                has_issues=bool(wizard.field('has_issues').toBool()))
            self.reposRefresh()
    
    def repoRemove(self):
        
        row = self._selectedRepoRow()
        name = self.reposTableWidget.item(row, 0).text()
        dialog = RepoRemoveDialog(self.github, name)
        if dialog.exec_():
            self.github.get_user().get_repo(str(name)).delete()
            self.reposRefresh()

    def _isARepoSelected(self):
        """ Return True if a repo is selected else False """
        if len(self.reposTableWidget.selectedItems()) > 0:
            return True
        else:
            return False

    def _selectedRepoRow(self):
        """ Return the currently select repo """
        # TODO - figure out what happens if no repo is selected
        selectedModelIndexes = \
            self.reposTableWidget.selectionModel().selectedRows()
        for index in selectedModelIndexes:
            return index.row()
Exemple #2
0
class MainWidget(QMainWindow):
    def __init__(self, parent=None):
        super(MainWidget,
              self).__init__(parent,
                             windowTitle='GithubRemote',
                             windowIcon=QIcon(image_path('git.png')),
                             geometry=QRect(300, 300, 600, 372))

        self.repo_pixmap = QPixmap(image_path('book_16.png'))
        self.big_repo_pixmap = QPixmap(image_path('book_32.png'))
        self.repo_fork_pixmap = QPixmap(image_path('book_fork_16.png'))
        self.star_pixmap = QPixmap(image_path('star_16.png'))
        self.big_star_pixmap = QPixmap(image_path('star_32.png'))
        self.fork_pixmap = QPixmap(image_path('fork_16.png'))
        self.eye_pixmap = QPixmap(image_path('eye_16.png'))

        self.github = None

        # Actions

        self.repoAddAction = QAction(QIcon(image_path('plus_48.png')),
                                     '&Add Repo',
                                     self,
                                     statusTip='Add a new repo')
        self.repoAddAction.triggered.connect(self.repoAdd)

        self.repoRemoveAction = QAction(QIcon(image_path('minus.png')),
                                        '&Remove Repo',
                                        self,
                                        statusTip='Remove repo')
        self.repoRemoveAction.triggered.connect(self.repoRemove)

        self.repoRefreshAction = QAction(QIcon(image_path('refresh.png')),
                                         'Refresh',
                                         self,
                                         statusTip='Refresh list of repos')
        self.repoRefreshAction.triggered.connect(self.reposRefresh)
        self.repoRefreshAction.triggered.connect(self.starsRefresh)

        self.addAccountAction = QAction('Add Account',
                                        self,
                                        statusTip='Add Account')
        self.addAccountAction.triggered.connect(self.addAccount)

        # userPushButton - Displays the current active username and
        # image on the top right of the toolbar.

        self.userButtonMenu = UserButtonMenu(32, 32)

        # ToolBar

        self.toolBar = self.addToolBar('Main')
        self.toolBar.setMovable(False)
        self.toolBar.setFloatable(False)
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.toolBar.addAction(self.repoAddAction)
        self.toolBar.addAction(self.repoRemoveAction)
        self.toolBar.addAction(self.repoRefreshAction)
        self.toolBar.addWidget(spacer)
        self.toolBar.addWidget(self.userButtonMenu)

        # Menu

        menuBar = self.menuBar()
        fileMenu = menuBar.addMenu('&File')
        actionMenu = menuBar.addMenu('&Action')
        fileMenu.addAction(self.addAccountAction)
        actionMenu.addAction(self.repoAddAction)
        actionMenu.addAction(self.repoRemoveAction)
        actionMenu.addAction(self.repoRefreshAction)

        # StatusBar

        statusBar = self.statusBar()
        self.setStatusBar(statusBar)

        # reposTableWidget - Displays a list of the users repositories

        self.reposTableWidget = QTableWidget(
            0,
            5,
            selectionBehavior=QAbstractItemView.SelectRows,
            selectionMode=QAbstractItemView.SingleSelection,
            editTriggers=QAbstractItemView.NoEditTriggers,
            itemSelectionChanged=self.actionsUpdate)
        self.reposTableWidget.horizontalHeader().setResizeMode(
            QHeaderView.ResizeToContents)
        self.reposTableWidget.horizontalHeader().setResizeMode(
            1, QHeaderView.Stretch)
        self.reposTableWidget.horizontalHeader().setVisible(False)
        self.reposTableWidget.verticalHeader().setVisible(False)
        self.reposTableWidget.setShowGrid(False)
        self.reposTableWidget.verticalHeader().setMinimumSectionSize(25)

        # repoTab - Layout
        reposTab = QWidget()
        reposTabLayout = QVBoxLayout(reposTab)
        reposTabLayout.addWidget(self.reposTableWidget)
        reposTab.setLayout(reposTabLayout)

        # starsTableWidget - Displays a list of the users repositories

        self.starsTableWidget = QTableWidget(
            0,
            5,
            selectionBehavior=QAbstractItemView.SelectRows,
            selectionMode=QAbstractItemView.SingleSelection,
            editTriggers=QAbstractItemView.NoEditTriggers,
            itemSelectionChanged=self.actionsUpdate)
        self.starsTableWidget.horizontalHeader().setResizeMode(
            QHeaderView.ResizeToContents)
        self.starsTableWidget.horizontalHeader().setResizeMode(
            1, QHeaderView.Stretch)
        self.starsTableWidget.horizontalHeader().setVisible(False)
        self.starsTableWidget.verticalHeader().setVisible(False)
        self.starsTableWidget.setShowGrid(False)
        self.starsTableWidget.verticalHeader().setMinimumSectionSize(25)

        # repoTab - Layout
        starsTab = QWidget()
        starsTabLayout = QVBoxLayout(starsTab)
        starsTabLayout.addWidget(self.starsTableWidget)
        starsTab.setLayout(starsTabLayout)

        # Tab Widget
        self.tabs = QTabWidget()
        self.tabs.setTabBar(FlippedTabBar(self))
        self.tabs.addTab(reposTab, QIcon(self.big_repo_pixmap), "repos")
        self.tabs.addTab(starsTab, QIcon(self.big_star_pixmap), "stars")
        self.tabs.setTabPosition(QTabWidget.West)

        # Layout

        self.setCentralWidget(self.tabs)
        self.actionsUpdate()
        self.show()

        # Update

        self.loadUserMenu()
        if self.activeUserAction:
            self.activeUserAction.setVisible(False)
        self.authenticate()
        self.actionsUpdate()
        self.reposRefresh()
        self.starsRefresh()
        self.updateImage()

    @waiting_effects
    def updateImage(self):

        try:
            url = self.github.get_user().avatar_url
        except (GithubException, AttributeError):
            return
        data = urllib.urlopen(url).read()
        pixmap = QPixmap()
        pixmap.loadFromData(data)
        self.activeUserAction.setIcon(QIcon(pixmap))
        self.userButtonMenu.setPixmap(pixmap)
        self.userButtonMenu.setText(self.github.get_user().login)

    @waiting_effects
    def loadUserMenu(self):

        action = None
        for _, username, token in generate_tokens(CONFIG_PATH, 'github'):

            try:
                url = Github(token).get_user().avatar_url
            except (GithubException, AttributeError):
                action = QAction(username, self, triggered=self.changeActive)
                self.userButtonMenu.addAction(action)
                continue
            data = urllib.urlopen(url).read()
            pixmap = QPixmap()
            pixmap.loadFromData(data)
            action = QAction(QIcon(pixmap),
                             username,
                             self,
                             triggered=self.changeActive)
            action.setIconVisibleInMenu(True)
            self.userButtonMenu.addAction(action)

        self.activeUserAction = action

    def changeActive(self):

        sender = self.sender()

        self.activeUserAction.setVisible(True)
        self.activeUserAction = sender
        self.activeUserAction.setVisible(False)
        self.authenticate()
        self.actionsUpdate()
        self.reposRefresh()
        self.starsRefresh()
        self.updateImage()

    @waiting_effects
    def reposRefresh(self):

        self.reposTableWidget.clearContents()

        try:
            repos = self.github.get_user().get_repos()
            self.reposTableWidget.setRowCount(
                self.github.get_user().public_repos)
        except (GithubException, AttributeError):
            return
        for row, repo in enumerate(repos):
            imageLabel = QLabel()
            if repo.fork:
                imageLabel.setPixmap(self.repo_fork_pixmap)
            else:
                imageLabel.setPixmap(self.repo_pixmap)
            imageLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            imageLabel.setMargin(5)

            self.reposTableWidget.setCellWidget(row, 0, imageLabel)
            label = QLabel('<b>{}</b><br />{}'.format(str(repo.name),
                                                      str(repo.description)))
            label.setAlignment(Qt.AlignVCenter)
            label.setMargin(5)
            label.setWordWrap(True)
            self.reposTableWidget.setCellWidget(row, 1, label)
            self.reposTableWidget.setItem(
                row, 2,
                QTableWidgetItem(QIcon(self.star_pixmap),
                                 str(repo.stargazers_count)))
            self.reposTableWidget.setItem(
                row, 3,
                QTableWidgetItem(QIcon(self.eye_pixmap),
                                 str(repo.watchers_count)))
            self.reposTableWidget.setItem(
                row, 4,
                QTableWidgetItem(QIcon(self.fork_pixmap),
                                 str(repo.forks_count)))

        self.reposTableWidget.resizeRowsToContents()

    @waiting_effects
    def starsRefresh(self):

        self.starsTableWidget.clearContents()

        try:
            starred = self.github.get_user().get_starred()
            self.starsTableWidget.setRowCount(
                self.github.get_user().public_repos)
        except (GithubException, AttributeError):
            return
        for row, repo in enumerate(starred):
            imageLabel = QLabel()
            if repo.fork:
                imageLabel.setPixmap(self.repo_fork_pixmap)
            else:
                imageLabel.setPixmap(self.repo_pixmap)
            imageLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            imageLabel.setMargin(5)

            self.starsTableWidget.setCellWidget(row, 0, imageLabel)
            label = QLabel(u'<b>{}/{}</b><br />{}'.format(
                unicode(repo.owner.login), unicode(repo.name),
                unicode(repo.description)))
            label.setAlignment(Qt.AlignVCenter)
            label.setMargin(5)
            label.setWordWrap(True)
            self.starsTableWidget.setCellWidget(row, 1, label)
            self.starsTableWidget.setItem(
                row, 2, QTableWidgetItem(QIcon(self.star_pixmap), '0'))
            self.starsTableWidget.setItem(
                row, 3,
                QTableWidgetItem(QIcon(self.eye_pixmap),
                                 str(repo.watchers_count)))
            self.starsTableWidget.setItem(
                row, 4,
                QTableWidgetItem(QIcon(self.fork_pixmap),
                                 str(repo.forks_count)))

        self.starsTableWidget.resizeRowsToContents()

    @waiting_effects
    def authenticate(self):

        if self.activeUserAction:
            username = str(self.activeUserAction.text())
            token = load_token(CONFIG_PATH, 'github', username)
            self.github = Github(token)
        else:
            self.github = None

    def actionsUpdate(self):
        # TODO disable if no user is logged in
        if self.github is None:
            self.repoAddAction.setEnabled(False)
            self.repoRemoveAction.setEnabled(False)
            self.repoRefreshAction.setEnabled(False)
        else:
            self.repoAddAction.setEnabled(True)
            self.repoRefreshAction.setEnabled(True)
            if self._isARepoSelected():
                self.repoRemoveAction.setEnabled(True)
            else:
                self.repoRemoveAction.setEnabled(False)

    def addAccount(self):
        wizard = AddAccountWizard(self)
        if wizard.exec_():
            username = str(wizard.field('username').toString())
            token = str(wizard.field('token').toString())
            store_token(CONFIG_PATH, 'github', username, token)
            self.authenticate()
            self.reposRefresh()
            self.updateImage()
            self.actionsUpdate()

    def repoAdd(self):
        wizard = AddRepoWizard(self.github, self)
        if wizard.exec_():
            self.github.get_user().create_repo(
                str(wizard.field('name').toString()),
                description=str(wizard.field('description').toString()),
                private=bool(wizard.field('private').toBool()),
                auto_init=bool(wizard.field('auto_init').toBool()),
                gitignore_template=str(wizard.field('gitignore').toString()),
                homepage=str(wizard.field('homepage').toString()),
                has_wiki=bool(wizard.field('has_wiki').toBool()),
                has_downloads=bool(wizard.field('has_downloads').toBool()),
                has_issues=bool(wizard.field('has_issues').toBool()))
            self.reposRefresh()

    def repoRemove(self):

        row = self._selectedRepoRow()
        name = self.reposTableWidget.item(row, 0).text()
        dialog = RepoRemoveDialog(self.github, name)
        if dialog.exec_():
            self.github.get_user().get_repo(str(name)).delete()
            self.reposRefresh()

    def _isARepoSelected(self):
        """ Return True if a repo is selected else False """
        if len(self.reposTableWidget.selectedItems()) > 0:
            return True
        else:
            return False

    def _selectedRepoRow(self):
        """ Return the currently select repo """
        # TODO - figure out what happens if no repo is selected
        selectedModelIndexes = \
            self.reposTableWidget.selectionModel().selectedRows()
        for index in selectedModelIndexes:
            return index.row()
Exemple #3
0
class TemplateWindow(QMainWindow):

    def __init__(self, params_pipe, number_pipe, templates_pipe, spikes_pipe,
                 probe_path=None, screen_resolution=None):

        QMainWindow.__init__(self)

        # Receive parameters.
        params = params_pipe[0].recv()
        self.probe = load_probe(probe_path)
        self._nb_samples = params['nb_samples']
        self._sampling_rate = params['sampling_rate']
        self._display_list = []

        self._params = {
            'nb_samples': self._nb_samples,
            'sampling_rate': self._sampling_rate,
            'time': {
                'min': 10.0,  # ms
                'max': 100.0,  # ms
                'init': 100.0,  # ms
            },
            'voltage': {
                'min': -200,  # µV
                'max': 20e+1,  # µV
                'init': 50.0,  # µV
            },
            'templates': self._display_list
        }

        self._canvas_mea = MEACanvas(probe_path=probe_path, params=self._params)
        self._canvas_template = TemplateCanvas(probe_path=probe_path, params=self._params)
        self._canvas_rate = RateCanvas(probe_path=probe_path, params=self._params)
        self._canvas_isi = ISICanvas(probe_path=probe_path, params=self._params)

        self.cells = Cells({})
        self._nb_buffer = 0

        # TODO ISI
        self.isi_bin_width, self.isi_x_max = 2, 25.0

        canvas_template_widget = self._canvas_template.native
        canvas_mea = self._canvas_mea.native
        canvas_rate = self._canvas_rate.native
        canvas_isi = self._canvas_isi.native

        # Create controls widgets.
        label_time = QLabel()
        label_time.setText(u"time")
        label_time_unit = QLabel()
        label_time_unit.setText(u"ms")

        self._dsp_time = QDoubleSpinBox()
        self._dsp_time.setMinimum(self._params['time']['min'])
        self._dsp_time.setMaximum(self._params['time']['max'])
        self._dsp_time.setValue(self._params['time']['init'])
        self._dsp_time.valueChanged.connect(self._on_time_changed)

        label_voltage = QLabel()
        label_voltage.setText(u"voltage")
        label_voltage_unit = QLabel()
        label_voltage_unit.setText(u"µV")
        self._dsp_voltage = QDoubleSpinBox()
        self._dsp_voltage.setMinimum(self._params['voltage']['min'])
        self._dsp_voltage.setMaximum(self._params['voltage']['max'])
        self._dsp_voltage.setValue(self._params['voltage']['init'])
        self._dsp_voltage.valueChanged.connect(self._on_voltage_changed)

        label_binsize = QLabel()
        label_binsize.setText(u"Bin size")
        label_binsize_unit = QLabel()
        label_binsize_unit.setText(u"second")
        self._dsp_binsize = QDoubleSpinBox()
        self._dsp_binsize.setRange(0.1, 10)
        self._dsp_binsize.setSingleStep(0.1)
        self.bin_size = 1
        self._dsp_binsize.setValue(self.bin_size)
        self._dsp_binsize.valueChanged.connect(self._on_binsize_changed)

        label_zoomrates = QLabel()
        label_zoomrates.setText(u'Zoom rates')
        self._zoom_rates = QDoubleSpinBox()
        self._zoom_rates.setRange(1, 50)
        self._zoom_rates.setSingleStep(0.1)
        self._zoom_rates.setValue(1)
        self._zoom_rates.valueChanged.connect(self._on_zoomrates_changed)

        label_time_window = QLabel()
        label_time_window.setText(u'Time window rates')
        label_time_window_unit = QLabel()
        label_time_window_unit.setText(u'second')
        self._dsp_tw_rate = QDoubleSpinBox()
        self._dsp_tw_rate.setRange(1, 50)
        self._dsp_tw_rate.setSingleStep(self.bin_size)
        self._dsp_tw_rate.setValue(50 * self.bin_size)
        self._dsp_tw_rate.valueChanged.connect(self._on_time_window_changed)

        label_tw_from_start = QLabel()
        label_tw_from_start.setText('Time scale from start')
        self._tw_from_start = QCheckBox()
        self._tw_from_start.setChecked(True)

        self._selection_templates = QTableWidget()
        self._selection_templates.setSelectionMode(
            QAbstractItemView.ExtendedSelection
        )
        self._selection_templates.setColumnCount(3)
        self._selection_templates.setVerticalHeaderLabels(['Nb template', 'Channel', 'Amplitude'])
        self._selection_templates.insertRow(0)
        self._selection_templates.setItem(0, 0, QTableWidgetItem('Nb template'))
        self._selection_templates.setItem(0, 1, QTableWidgetItem('Channel'))
        self._selection_templates.setItem(0, 2, QTableWidgetItem('Amplitude'))

        # self._selection_channels.setGeometry(QtCore.QRect(10, 10, 211, 291))
        # for i in range(self.nb_templates):
        #     numRows = self.tableWidget.rowCount()
        #     self.tableWidget.insertRow(numRows)

        #     item = QTableWidgetItem("Template %i" % i)
        #     self._selection_templates.addItem(item)
        #     self._selection_templates.item(i).setSelected(False)

        spacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)

        # Create controls grid.
        grid = QGridLayout()
        # # Add time row.
        grid.addWidget(label_time, 0, 0)
        grid.addWidget(self._dsp_time, 0, 1)
        grid.addWidget(label_time_unit, 0, 2)
        # # Add voltage row.
        grid.addWidget(label_voltage, 1, 0)
        grid.addWidget(self._dsp_voltage, 1, 1)
        grid.addWidget(label_voltage_unit, 1, 2)

        # # Add binsize row.
        grid.addWidget(label_binsize, 2, 0)
        grid.addWidget(self._dsp_binsize, 2, 1)
        grid.addWidget(label_binsize_unit, 2, 2)

        # # Add zoom rate
        grid.addWidget(label_zoomrates, 3, 0)
        grid.addWidget(self._zoom_rates, 3, 1)

        # Add a double checkbox for time window
        grid.addWidget(label_time_window, 4, 0)
        grid.addWidget(self._dsp_tw_rate, 4, 1)
        grid.addWidget(label_time_window_unit, 4, 2)

        ## Add checkbox to display the rates from start
        grid.addWidget(label_tw_from_start, 5, 0)
        grid.addWidget(self._tw_from_start, 5, 1)

        # # Add spacer.
        grid.addItem(spacer)

        # # Create info group.
        controls_group = QGroupBox()
        controls_group.setLayout(grid)

        # Create info grid.
        templates_grid = QGridLayout()
        # # Add Channel selection
        # grid.addWidget(label_selection, 3, 0)
        templates_grid.addWidget(self._selection_templates, 0, 1)

        def add_template():
            items = self._selection_templates.selectedItems()
            self._display_list = []
            for i in range(len(items)):
                self._display_list.append(i)
            self._on_templates_changed()

        # self._selection_templates.itemClicked.connect(add_template)

        # Template selection signals
        self._selection_templates.itemSelectionChanged.connect(lambda: self.selected_templates(
            self.nb_templates))

        # Checkbox to display all the rates
        self._tw_from_start.stateChanged.connect(self.time_window_rate_full)
        # self._selection_templates.itemPressed(0, 1).connect(self.sort_template())

        # # Add spacer.
        templates_grid.addItem(spacer)

        # Create controls group.
        templates_group = QGroupBox()
        templates_group.setLayout(templates_grid)

        # # Create controls dock.
        templates_dock = QDockWidget()
        templates_dock.setWidget(templates_group)
        templates_dock.setWindowTitle("Channels selection")

        # # Create controls dock.
        control_dock = QDockWidget()
        control_dock.setWidget(controls_group)
        control_dock.setWindowTitle("Controls")

        # Create info widgets.
        label_time = QLabel()
        label_time.setText(u"time")
        self._label_time_value = QLineEdit()
        self._label_time_value.setText(u"0")
        self._label_time_value.setReadOnly(True)
        self._label_time_value.setAlignment(Qt.AlignRight)
        label_time_unit = QLabel()
        label_time_unit.setText(u"s")
        info_buffer_label = QLabel()
        info_buffer_label.setText(u"buffer")
        self._info_buffer_value_label = QLineEdit()
        self._info_buffer_value_label.setText(u"0")
        self._info_buffer_value_label.setReadOnly(True)
        self._info_buffer_value_label.setAlignment(Qt.AlignRight)
        info_buffer_unit_label = QLabel()
        info_buffer_unit_label.setText(u"")
        info_probe_label = QLabel()
        info_probe_label.setText(u"probe")
        info_probe_value_label = QLineEdit()
        info_probe_value_label.setText(u"{}".format(probe_path))
        info_probe_value_label.setReadOnly(True)
        # TODO place the following info in another grid?
        info_probe_unit_label = QLabel()
        info_probe_unit_label.setText(u"")

        info_spacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)

        # Create info grid.
        info_grid = QGridLayout()
        # # Time row.
        info_grid.addWidget(label_time, 0, 0)
        info_grid.addWidget(self._label_time_value, 0, 1)
        info_grid.addWidget(label_time_unit, 0, 2)
        # # Buffer row.
        info_grid.addWidget(info_buffer_label, 1, 0)
        info_grid.addWidget(self._info_buffer_value_label, 1, 1)
        info_grid.addWidget(info_buffer_unit_label, 1, 2)
        # # Probe row.
        info_grid.addWidget(info_probe_label, 2, 0)
        info_grid.addWidget(info_probe_value_label, 2, 1)
        info_grid.addWidget(info_probe_unit_label, 2, 2)
        # # Spacer.
        info_grid.addItem(info_spacer)

        # Create info group.
        info_group = QGroupBox()
        info_group.setLayout(info_grid)

        # Create info dock.
        info_dock = QDockWidget()
        info_dock.setWidget(info_group)
        info_dock.setWindowTitle("Info")

        # Create thread.
        thread = Thread(number_pipe, templates_pipe, spikes_pipe)
        thread.number_signal.connect(self._number_callback)
        thread.reception_signal.connect(self._reception_callback)
        thread.start()

        # Add dockable windows.
        self.addDockWidget(Qt.LeftDockWidgetArea, control_dock)
        self.addDockWidget(Qt.LeftDockWidgetArea, info_dock)
        self.addDockWidget(Qt.LeftDockWidgetArea, templates_dock)

        # Add Grid Layout for canvas
        canvas_grid = QGridLayout()

        group_canv_temp = QDockWidget()
        group_canv_temp.setWidget(canvas_template_widget)
        group_canv_mea = QDockWidget()
        group_canv_mea.setWidget(canvas_mea)
        group_canv_rate = QDockWidget()
        group_canv_rate.setWidget(canvas_rate)
        group_canv_isi = QDockWidget()
        group_canv_isi.setWidget(canvas_isi)

        canvas_grid.addWidget(group_canv_temp, 0, 0)
        canvas_grid.addWidget(group_canv_mea, 0, 1)
        canvas_grid.addWidget(group_canv_rate, 1, 1)
        canvas_grid.addWidget(group_canv_isi, 1, 0)
        canvas_group = QGroupBox()
        canvas_group.setLayout(canvas_grid)

        # Set central widget.
        self.setCentralWidget(canvas_group)
        # Set window size.
        if screen_resolution is not None:
            screen_width = screen_resolution.width()
            screen_height = screen_resolution.height()
            self.resize(screen_width, screen_height)
        # Set window title.
        self.setWindowTitle("SpyKING Circus ORT - Read 'n' Qt display")

        print(" ")  # TODO remove?

    @property
    def nb_templates(self):
        return len(self.cells)

    def _number_callback(self, number):

        self._nb_buffer = float(number)
        text = u"{}".format(number)
        self._info_buffer_value_label.setText(text)

        text = u"{:8.3f}".format(self._nb_buffer * float(self._nb_samples) / self._sampling_rate)
        self._label_time_value.setText(text)

        return

    def _reception_callback(self, templates, spikes):
        bar = None
        if templates is not None:
            bar = []
            for i in range(len(templates)):
                mask = spikes['templates'] == i
                template = load_template_from_dict(templates[i], self.probe)

                new_cell = Cell(template, Train([]), Amplitude([], []))
                self.cells.append(new_cell)
                self._selection_templates.insertRow(self.nb_templates)

                bar += [template.center_of_mass(self.probe)]
                channel = template.channel
                amplitude = template.peak_amplitude()
                # self._selection_templates.setItem(self.nb_templates, 0, QTableWidgetItem("Template %d" %self.nb_templates))
                # self._selection_templates.setItem(self.nb_templates, 1, QTableWidgetItem(str(bar)))
                self._selection_templates.setItem(self.nb_templates, 0, QTableWidgetItem(str(self.nb_templates)))
                self._selection_templates.setItem(self.nb_templates, 1, QTableWidgetItem(str(channel)))
                self._selection_templates.setItem(self.nb_templates, 2, QTableWidgetItem(str(amplitude)))
                # item = QListWidgetItem("Template %i" % self.nb_templates)
                # self._selection_templates.addItem(item)
                # self._selection_templates.item(i).setSelected(False)
                # self.nb_templates += 1
                # print(bar.shape, bar)

        if spikes is not None:
            self.cells.add_spikes(spikes['spike_times'], spikes['amplitudes'], spikes['templates'])
            self.cells.set_t_max(self._nb_samples * self._nb_buffer / self._sampling_rate)
            to_display = self.cells.rate(self.bin_size)

        self._canvas_template.on_reception(templates, self.nb_templates)
        self._canvas_mea.on_reception_bary(bar, self.nb_templates)
        # TODO Cells rate
        self._canvas_rate.on_reception_rates(self.cells.rate(self.bin_size))

        # TODO : ISI If we want to display the ISI also
        # isi = self.cells.interspike_interval_histogram(self.isi_bin_width, self.isi_x_max=25.0)
        isi = self.cells.interspike_interval_histogram(self.isi_bin_width, self.isi_x_max)
        self._canvas_isi.on_reception_isi(isi)

        return

    def _on_time_changed(self):

        time = self._dsp_time.value()
        self._canvas_template.set_time(time)

        self._dsp_tw_rate.setRange(1, int(time))

        return

    def _on_binsize_changed(self):

        time = self._dsp_binsize.value()
        self.bin_size = time

        self._dsp_tw_rate.setSingleStep(self.bin_size)

        return

    def _on_zoomrates_changed(self):

        zoom_value = self._zoom_rates.value()
        self._canvas_rate.zoom_rates(zoom_value)
        return

    def _on_voltage_changed(self):

        voltage = self._dsp_voltage.value()
        self._canvas_template.set_voltage(voltage)

        return

    def _on_peaks_display(self):

        value = self._display_peaks.isChecked()
        self._canvas_template.show_peaks(value)

        return

    def _on_templates_changed(self):
        self._canvas_template.set_templates(self._display_list)

        return

    def selected_templates(self, max_templates):
        list_templates = []
        list_channels = []
        for i in range(max_templates + 1):
            if i != 0 and \
                    self._selection_templates.item(i, 0).isSelected() and \
                    self._selection_templates.item(i, 1).isSelected() and \
                    self._selection_templates.item(i, 2).isSelected():
                list_templates.append(i - 1)
                list_channels.append(int(self._selection_templates.item(i, 1).text()))
        self._canvas_template.selected_templates(list_templates)
        self._canvas_mea.selected_channels(list_channels)
        self._canvas_mea.selected_templates(list_templates)
        self._canvas_rate.selected_cells(list_templates)
        self._canvas_isi.selected_cells(list_templates)
        return

    def time_window_rate_full(self):
        value = self._tw_from_start.isChecked()
        self._canvas_rate.time_window_full(value)
        return

    def _on_time_window_changed(self):
        tw_value = self._dsp_tw_rate.value()
        self._canvas_rate.time_window_value(tw_value, self.bin_size)
        return
Exemple #4
0
class phonesDialog(QDialog):
    def __init__(self, parent):
        QDialog.__init__(self, parent)
        self.prm = self.parent().prm
        self.currLocale = self.parent().prm['currentLocale']
        self.currLocale.setNumberOptions(
            self.currLocale.OmitGroupSeparator
            | self.currLocale.RejectGroupSeparator)
        screen = QDesktopWidget().screenGeometry()
        self.resize(screen.width() / 2.5, screen.height() / 3)
        self.isPlaying = False
        #self.audioManager = audioManager(self)
        #self.playThread = threadedPlayer(self)

        self.sizer = QGridLayout()
        self.v1Sizer = QVBoxLayout()
        self.v2Sizer = QVBoxLayout()
        self.calibSizer = QGridLayout()

        self.phonesTableWidget = QTableWidget()
        self.phonesTableWidget.setColumnCount(4)
        self.phonesTableWidget.setSelectionBehavior(
            QAbstractItemView.SelectRows)
        self.phonesTableWidget.setSelectionMode(
            QAbstractItemView.ExtendedSelection)

        self.phonesTableWidget.setHorizontalHeaderLabels([
            self.tr('Phones'),
            self.tr('Max Level'),
            self.tr('Default'), 'id'
        ])
        self.phonesTableWidget.hideColumn(3)
        self.phonesTableWidget.cellDoubleClicked[int, int].connect(
            self.onCellDoubleClicked)

        #RENAME Phones BUTTON
        self.renamePhonesButton = QPushButton(self.tr("Rename Phones"), self)
        self.renamePhonesButton.clicked.connect(self.onEditLabel)
        #Change Level Phones BUTTON
        self.changeLevelPhonesButton = QPushButton(self.tr("Change Max Level"),
                                                   self)
        self.changeLevelPhonesButton.clicked.connect(self.onEditMaxLevel)

        #ADD Phones BUTTON
        self.addPhonesButton = QPushButton(self.tr("Add Phones"), self)
        self.addPhonesButton.clicked.connect(self.onClickAddPhonesButton)
        #REMOVE Phones BUTTON
        self.removePhonesButton = QPushButton(self.tr("Remove Phones"), self)
        self.removePhonesButton.clicked.connect(self.onClickRemovePhonesButton)
        #Set Default Phones BUTTON
        self.setDefaultPhonesButton = QPushButton(self.tr("Set Default"), self)
        self.setDefaultPhonesButton.clicked.connect(self.onEditDefault)

        self.v1Sizer.addWidget(self.renamePhonesButton)
        self.v1Sizer.addWidget(self.changeLevelPhonesButton)
        self.v1Sizer.addWidget(self.addPhonesButton)
        self.v1Sizer.addWidget(self.removePhonesButton)
        self.v1Sizer.addWidget(self.setDefaultPhonesButton)
        self.v1Sizer.addStretch()
        self.phonesList = {}

        for i in range(len(self.prm['phones']['phonesChoices'])):
            currCount = i + 1
            thisID = self.prm['phones']['phonesID'][i]
            self.phonesList[thisID] = {}
            self.phonesList[thisID]['label'] = self.prm['phones'][
                'phonesChoices'][i]
            self.phonesList[thisID]['maxLevel'] = self.prm['phones'][
                'phonesMaxLevel'][i]
            self.phonesList[thisID]['default'] = self.prm['phones'][
                'defaultPhones'][i]
            self.phonesTableWidget.setRowCount(currCount)
            newItem = QTableWidgetItem(self.phonesList[thisID]['label'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable
                             | QtCore.Qt.ItemIsEnabled)
            self.phonesTableWidget.setItem(currCount - 1, 0, newItem)
            newItem = QTableWidgetItem(
                self.currLocale.toString(self.phonesList[thisID]['maxLevel']))
            newItem.setFlags(QtCore.Qt.ItemIsSelectable
                             | QtCore.Qt.ItemIsEnabled)
            self.phonesTableWidget.setItem(currCount - 1, 1, newItem)
            newItem = QTableWidgetItem(self.phonesList[thisID]['default'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable
                             | QtCore.Qt.ItemIsEnabled)
            self.phonesTableWidget.setItem(currCount - 1, 2, newItem)
            self.phonesList[thisID]['qid'] = QTableWidgetItem(thisID)
            self.phonesTableWidget.setItem(currCount - 1, 3,
                                           self.phonesList[thisID]['qid'])

        ##CALIBRATION TONE
        n = 0
        self.calLabel = QLabel(self.tr('Calibration Tone:'), self)
        self.calibSizer.addWidget(self.calLabel, n, 0, 1, 2)
        n = n + 1
        self.toneFreqLabel = QLabel(self.tr('Frequency (Hz)'), self)
        self.toneFreqTF = QLineEdit("1000")
        self.toneFreqTF.setValidator(QDoubleValidator(self))
        self.calibSizer.addWidget(self.toneFreqLabel, n, 0)
        self.calibSizer.addWidget(self.toneFreqTF, n, 1)
        n = n + 1
        self.toneLevLabel = QLabel(self.tr('Level (dB)'), self)
        self.toneLevTF = QLineEdit("60")
        self.toneLevTF.setValidator(QDoubleValidator(self))
        self.calibSizer.addWidget(self.toneLevLabel, n, 0)
        self.calibSizer.addWidget(self.toneLevTF, n, 1)
        n = n + 1
        self.toneDurLabel = QLabel(self.tr('Duration (ms)'), self)
        self.toneDurTF = QLineEdit("980")
        self.toneDurTF.setValidator(QDoubleValidator(self))
        self.calibSizer.addWidget(self.toneDurLabel, n, 0)
        self.calibSizer.addWidget(self.toneDurTF, n, 1)
        n = n + 1
        self.toneRampsLabel = QLabel(self.tr('Ramps (ms)'), self)
        self.toneRampsTF = QLineEdit("10")
        self.toneRampsTF.setValidator(QDoubleValidator(self))
        self.calibSizer.addWidget(self.toneRampsLabel, n, 0)
        self.calibSizer.addWidget(self.toneRampsTF, n, 1)
        n = n + 1
        self.earLabel = QLabel(self.tr('Ear:'), self)
        self.earChooser = QComboBox()
        self.earChooser.addItems(
            [self.tr("Right"),
             self.tr("Left"),
             self.tr("Both")])
        self.calibSizer.addWidget(self.earLabel, n, 0)
        self.calibSizer.addWidget(self.earChooser, n, 1)
        n = n + 1
        self.playCalibButton = QPushButton(self.tr("Play"), self)
        self.playCalibButton.clicked.connect(self.onClickPlayCalibButton)
        self.playCalibButton.setIcon(
            QIcon.fromTheme("media-playback-start",
                            QIcon(":/media-playback-start")))
        self.calibSizer.addWidget(self.playCalibButton, n, 0, 1, 2)
        n = n + 1
        self.stopCalibButton = QPushButton(self.tr("Stop"), self)
        self.stopCalibButton.clicked.connect(self.onClickStopCalibButton)
        self.stopCalibButton.setIcon(
            QIcon.fromTheme("media-playback-stop",
                            QIcon(":/media-playback-stop")))
        self.calibSizer.addWidget(self.stopCalibButton, n, 0, 1, 2)
        if self.prm['pref']['sound']['playCommand'] in [
                "alsaaudio", "pyaudio"
        ]:
            self.stopCalibButton.show()
        else:
            self.stopCalibButton.hide()

        buttonBox = QDialogButtonBox(QDialogButtonBox.Apply
                                     | QDialogButtonBox.Ok
                                     | QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.reject)
        buttonBox.button(QDialogButtonBox.Apply).clicked.connect(
            self.permanentApply)

        self.sizer.addLayout(self.v1Sizer, 0, 0)
        self.v2Sizer.addLayout(self.calibSizer)
        self.v2Sizer.addStretch()
        self.sizer.addWidget(self.phonesTableWidget, 0, 1)
        self.sizer.addLayout(self.v2Sizer, 0, 2)
        self.sizer.addWidget(buttonBox, 1, 1, 1, 2)
        self.sizer.setColumnStretch(1, 2)
        self.setLayout(self.sizer)
        self.setWindowTitle(self.tr("Edit Phones"))
        self.show()

    def onCellDoubleClicked(self, row, col):
        if col == 0:
            self.onEditLabel()
        elif col == 1:
            self.onEditMaxLevel()
        elif col == 2:
            self.onEditDefault()

    def onEditLabel(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(
                self, self.tr('Warning'),
                self.tr('Only one label can be renamed at a time'))
        elif len(ids) < 1:
            pass
        else:
            selectedSound = ids[0]
            msg = self.tr('New name:')
            text, ok = QInputDialog.getText(self, self.tr('Input Dialog'), msg)
            if ok:
                self.phonesTableWidget.item(
                    self.phonesList[selectedSound]['qid'].row(),
                    0).setText(text)
                self.phonesList[selectedSound]['label'] = text

    def onEditMaxLevel(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(
                self, self.tr('Warning'),
                self.tr('Only one item can be edited at a time'))
        elif len(ids) < 1:
            pass
        else:
            selectedSound = ids[0]
            msg = self.tr('Level:')
            text, ok = QInputDialog.getDouble(
                self, self.tr('Input Dialog'), msg,
                self.phonesList[selectedSound]['maxLevel'])
            if ok:
                self.phonesTableWidget.item(
                    self.phonesList[selectedSound]['qid'].row(),
                    1).setText(self.currLocale.toString(text))
                self.phonesList[selectedSound]['maxLevel'] = text

    def onEditDefault(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(
                self, self.tr('Warning'),
                self.tr('Only one item can be edited at a time'))
        elif len(ids) < 1:
            pass
        else:
            selectedSound = ids[0]
            for i in range(self.phonesTableWidget.rowCount()):
                self.phonesTableWidget.item(i, 2).setText("\u2012")
                self.phonesList[str(self.phonesTableWidget.item(
                    i, 3).text())]['default'] = "\u2012"
            self.phonesTableWidget.item(
                self.phonesList[selectedSound]['qid'].row(),
                2).setText("\u2713")
            self.phonesList[selectedSound]['default'] = "\u2713"

    def findSelectedItemIds(self):
        selItems = self.phonesTableWidget.selectedItems()
        selItemsRows = []
        for i in range(len(selItems)):
            selItemsRows.append(selItems[i].row())
        selItemsRows = unique(selItemsRows)
        selItemsIds = []
        for i in range(len(selItemsRows)):
            selItemsIds.append(
                str(self.phonesTableWidget.item(selItemsRows[i], 3).text()))
        return selItemsIds

    def permanentApply(self):
        self.prm['phones']['phonesChoices'] = []
        self.prm['phones']['phonesMaxLevel'] = []
        self.prm['phones']['defaultPhones'] = []
        self.prm['phones']['phonesID'] = []

        keys = sorted(self.phonesList.keys())
        for key in keys:
            self.prm['phones']['phonesChoices'].append(
                str(self.phonesList[key]['label']))
            self.prm['phones']['phonesMaxLevel'].append(
                self.phonesList[key]['maxLevel'])
            self.prm['phones']['defaultPhones'].append(
                self.phonesList[key]['default'])
            self.prm['phones']['phonesID'].append(key)
        f = open(self.parent().prm['phonesPrefFile'], 'wb')
        pickle.dump(self.parent().prm['phones'], f)
        f.close()
        for i in range(self.parent().phonesChooser.count()):
            self.parent().phonesChooser.removeItem(0)
        self.parent().phonesChooser.addItems(
            self.prm['phones']['phonesChoices'])

    def onClickAddPhonesButton(self):
        keys = sorted(self.phonesList.keys())
        thisID = str(int(keys[-1]) + 1)
        currCount = self.phonesTableWidget.rowCount() + 1

        self.phonesList[thisID] = {}
        self.phonesList[thisID]['label'] = 'Phones' + ' ' + str(currCount)
        self.phonesList[thisID]['maxLevel'] = 100
        self.phonesList[thisID]['default'] = "\u2012"
        self.phonesTableWidget.setRowCount(currCount)
        newItem = QTableWidgetItem(self.phonesList[thisID]['label'])
        newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        self.phonesTableWidget.setItem(currCount - 1, 0, newItem)
        newItem = QTableWidgetItem(
            self.currLocale.toString(self.phonesList[thisID]['maxLevel']))
        newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        self.phonesTableWidget.setItem(currCount - 1, 1, newItem)
        newItem = QTableWidgetItem(self.phonesList[thisID]['default'])
        newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        self.phonesTableWidget.setItem(currCount - 1, 2, newItem)
        self.phonesList[thisID]['qid'] = QTableWidgetItem(thisID)
        self.phonesTableWidget.setItem(currCount - 1, 3,
                                       self.phonesList[thisID]['qid'])

    def onClickRemovePhonesButton(self):
        if self.phonesTableWidget.rowCount() == 1:
            ret = QMessageBox.warning(
                self, self.tr("Warning"),
                self.tr("Only one phone left. Cannot remove!"), QMessageBox.Ok)
        else:
            ids = self.findSelectedItemIds()
            wasDefault = False
            for i in range(len(ids)):
                selectedPhones = ids[i]
                if self.phonesTableWidget.item(
                        self.phonesList[selectedPhones]['qid'].row(),
                        2).text() == "\u2713":
                    wasDefault = True
                self.phonesTableWidget.removeRow(
                    self.phonesList[selectedPhones]['qid'].row())
                del self.phonesList[selectedPhones]
            if wasDefault == True:
                self.phonesTableWidget.item(0, 2).setText("\u2713")
                self.phonesList[str(self.phonesTableWidget.item(
                    0, 3).text())]['default'] = "\u2713"

    def onClickPlayCalibButton(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(
                self, self.tr('Warning'),
                self.tr('Only one label can be renamed at a time'))
            return
        elif len(ids) < 1:
            QMessageBox.warning(self, self.tr('Warning'),
                                self.tr('Please, select a phone in the table'))
            return
        else:
            selectedSound = ids[0]
            calMaxLev = self.phonesList[selectedSound]['maxLevel']
            frequency = self.currLocale.toDouble(self.toneFreqTF.text())[0]
            level = self.currLocale.toDouble(self.toneLevTF.text())[0]
            duration = self.currLocale.toDouble(self.toneDurTF.text())[0]
            ramp = self.currLocale.toDouble(self.toneRampsTF.text())[0]
            channel = self.earChooser.currentText()
            fs = self.currLocale.toInt(self.parent().sampRateTF.text())[0]
            nBits = self.currLocale.toInt(
                self.parent().nBitsChooser.currentText())[0]
            calTone = pureTone(frequency, 0, level, duration, ramp, channel,
                               fs, calMaxLev)
            self.isPlaying = True
            if self.prm['pref']['sound']['playCommand'] in [
                    "alsaaudio", "pyaudio"
            ]:
                self.playThread = threadedAudioPlayer(self.parent())
            else:
                self.playThread = threadedExternalAudioPlayer(self.parent())
            self.playThread.playThreadedSound(
                calTone, fs, nBits, self.prm['pref']['sound']['playCommand'],
                True, 'calibrationTone.wav')
            if self.playThread.isFinished() == True:
                self.isPlaying = False

    def onClickStopCalibButton(self):
        if self.isPlaying == True:
            self.playThread.terminate()
            #self.playThread.__del__()

    def closeEvent(self, event):
        if self.isPlaying == True:
            #self.playThread.__del__()
            self.playThread.terminate()
        event.accept()

    def accept(self):  #reimplement accept (i.e. ok button)
        if self.isPlaying == True:
            #self.playThread.__del__()
            self.playThread.terminate()
        QDialog.accept(self)

    def reject(self):  #reimplement reject
        if self.isPlaying == True:
            #self.playThread.__del__()
            self.playThread.terminate()
        QDialog.reject(self)
Exemple #5
0
class wavListDialog(QDialog):
    def __init__(self, parent):
        QDialog.__init__(self, parent)
        self.prm = self.parent().parent().prm
        self.audioManager = audioManager(self)
        self.currLocale = self.parent().parent().prm['currentLocale']
        self.currLocale.setNumberOptions(
            self.currLocale.OmitGroupSeparator
            | self.currLocale.RejectGroupSeparator)
        self.isPlaying = False

        self.sizer = QGridLayout()
        self.v1Sizer = QVBoxLayout()

        self.wavsTableWidget = QTableWidget()
        self.wavsTableWidget.setColumnCount(4)
        self.wavsTableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.wavsTableWidget.setSelectionMode(
            QAbstractItemView.ExtendedSelection)

        self.wavsTableWidget.setHorizontalHeaderLabels(
            [self.tr("File"),
             self.tr('Use'),
             self.tr("RMS Level"), 'id'])
        self.quidColumn = 3
        self.wavsTableWidget.hideColumn(self.quidColumn)
        self.wavsTableWidget.cellDoubleClicked[int, int].connect(
            self.onCellDoubleClicked)

        #ADD wav BUTTON
        self.addWavButton = QPushButton(self.tr("Add Wav"), self)
        self.addWavButton.clicked.connect(self.onClickAddWavButton)
        #REMOVE wav BUTTON
        self.removeWavButton = QPushButton(self.tr("Remove Wav"), self)
        self.removeWavButton.clicked.connect(self.onClickRemoveWavButton)

        #PLAY wav BUTTON
        self.playWavButton = QPushButton(self.tr("Play Wav"), self)
        self.playWavButton.clicked.connect(self.onClickPlayWavButton)
        #STOP wav BUTTON
        self.stopWavButton = QPushButton(self.tr("Stop Playing"), self)
        self.stopWavButton.clicked.connect(self.onClickStopWavButton)

        self.v1Sizer.addWidget(self.addWavButton)
        self.v1Sizer.addWidget(self.removeWavButton)
        self.v1Sizer.addWidget(self.playWavButton)
        self.v1Sizer.addWidget(self.stopWavButton)

        self.v1Sizer.addStretch()

        self.wavsList = {}

        for i in range(len(self.parent().wavsPref['endMessageFiles'])):
            currCount = i + 1
            thisID = self.parent().wavsPref['endMessageFilesID'][i]
            self.wavsList[thisID] = {}
            self.wavsList[thisID]['file'] = self.parent(
            ).wavsPref['endMessageFiles'][i]
            self.wavsList[thisID]['use'] = self.parent(
            ).wavsPref['endMessageFilesUse'][i]
            self.wavsList[thisID]['level'] = self.parent(
            ).wavsPref['endMessageLevels'][i]
            self.wavsTableWidget.setRowCount(currCount)
            n = 0
            newItem = QTableWidgetItem(self.wavsList[thisID]['file'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable
                             | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount - 1, n, newItem)
            n = n + 1
            newItem = QTableWidgetItem(self.wavsList[thisID]['use'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable
                             | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount - 1, n, newItem)
            n = n + 1
            newItem = QTableWidgetItem(
                self.currLocale.toString(self.wavsList[thisID]['level']))
            newItem.setFlags(QtCore.Qt.ItemIsSelectable
                             | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount - 1, n, newItem)
            n = n + 1
            self.wavsList[thisID]['qid'] = QTableWidgetItem(thisID)
            self.wavsTableWidget.setItem(currCount - 1, n,
                                         self.wavsList[thisID]['qid'])

        buttonBox = QDialogButtonBox(QDialogButtonBox.Apply
                                     | QDialogButtonBox.Ok
                                     | QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.reject)

        self.sizer.addLayout(self.v1Sizer, 0, 0)
        self.sizer.addWidget(self.wavsTableWidget, 0, 1)
        self.sizer.addWidget(buttonBox, 1, 1)
        self.setLayout(self.sizer)
        self.setWindowTitle(self.tr("Edit Wavs"))
        self.show()

    def onCellDoubleClicked(self, row, col):
        if col == 0:
            pass
        elif col == 1:
            self.onEditUse()
        elif col == 2:
            self.onEditLevel()

    def onEditLevel(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(
                self, self.tr('Warning'),
                self.tr('Only one item can be edited at a time'))
        elif len(ids) < 1:
            pass
        else:
            selectedSound = ids[0]
            msg = self.tr('RMS Level:')
            text, ok = QInputDialog.getDouble(
                self, self.tr('Input Dialog'), msg,
                self.wavsList[selectedSound]['level'])
            if ok:
                self.wavsTableWidget.item(
                    self.wavsList[selectedSound]['qid'].row(),
                    2).setText(self.currLocale.toString(text))
                self.wavsList[selectedSound]['level'] = text

    def onEditUse(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(
                self, self.tr('Warning'),
                self.tr('Only one item can be edited at a time'))
        elif len(ids) < 1:
            pass
        else:
            selectedSound = ids[0]
            if self.wavsTableWidget.item(
                    self.wavsList[selectedSound]['qid'].row(),
                    1).text() == "\u2012":
                self.wavsTableWidget.item(
                    self.wavsList[selectedSound]['qid'].row(),
                    1).setText("\u2713")
                self.wavsList[selectedSound]['use'] = "\u2713"
            else:
                self.wavsTableWidget.item(
                    self.wavsList[selectedSound]['qid'].row(),
                    1).setText("\u2012")
                self.wavsList[selectedSound]['use'] = "\u2012"

    def findSelectedItemIds(self):
        selItems = self.wavsTableWidget.selectedItems()
        selItemsRows = []
        for i in range(len(selItems)):
            selItemsRows.append(selItems[i].row())
        selItemsRows = unique(selItemsRows)
        selItemsIds = []
        for i in range(len(selItemsRows)):
            selItemsIds.append(
                str(
                    self.wavsTableWidget.item(selItemsRows[i],
                                              self.quidColumn).text()))
        return selItemsIds

    def permanentApply(self):
        self.wavListToPass = {}
        self.wavListToPass['endMessageFiles'] = []
        self.wavListToPass['endMessageFilesUse'] = []
        self.wavListToPass['endMessageFilesID'] = []
        self.wavListToPass['endMessageLevels'] = []

        keys = sorted(self.wavsList.keys())
        for key in keys:
            self.wavListToPass['endMessageFiles'].append(
                str(self.wavsList[key]['file']))
            self.wavListToPass['endMessageFilesUse'].append(
                self.wavsList[key]['use'])
            self.wavListToPass['endMessageLevels'].append(
                self.wavsList[key]['level'])
            self.wavListToPass['endMessageFilesID'].append(key)

    def onClickAddWavButton(self):
        fName = QFileDialog.getOpenFileName(
            self, self.tr("Choose wav file to load"), '',
            self.tr("wav files (*.wav);;All Files (*)"))[0]
        if len(fName) > 0:  #if the user didn't press cancel

            if len(self.wavsList.keys()) > 0:
                keys = sorted(self.wavsList.keys())
                thisID = str(int(keys[-1]) + 1)
            else:
                thisID = "1"
            currCount = self.wavsTableWidget.rowCount() + 1

            self.wavsList[thisID] = {}
            self.wavsList[thisID]['file'] = fName
            self.wavsList[thisID]['use'] = "\u2713"
            self.wavsList[thisID]['level'] = 60
            self.wavsTableWidget.setRowCount(currCount)
            n = 0
            newItem = QTableWidgetItem(self.wavsList[thisID]['file'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable
                             | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount - 1, n, newItem)
            n = n + 1
            newItem = QTableWidgetItem(self.wavsList[thisID]['use'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable
                             | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount - 1, n, newItem)
            n = n + 1
            newItem = QTableWidgetItem(
                self.currLocale.toString(self.wavsList[thisID]['level']))
            newItem.setFlags(QtCore.Qt.ItemIsSelectable
                             | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount - 1, n, newItem)
            n = n + 1
            self.wavsList[thisID]['qid'] = QTableWidgetItem(thisID)
            self.wavsTableWidget.setItem(currCount - 1, n,
                                         self.wavsList[thisID]['qid'])

    def onClickRemoveWavButton(self):
        ids = self.findSelectedItemIds()
        for i in range(len(ids)):
            selectedWavs = ids[i]
            self.wavsTableWidget.removeRow(
                self.wavsList[selectedWavs]['qid'].row())
            del self.wavsList[selectedWavs]

    def onClickPlayWavButton(self):
        ids = self.findSelectedItemIds()
        if len(ids) < 1:
            QMessageBox.warning(self, self.tr('Warning'),
                                self.tr('No files selected for playing'))
        else:
            if len(ids) > 1:
                pass  #maybe say on the status bar that only the first one will be played
            selectedWav = ids[0]
            fName = self.wavsList[selectedWav]['file']
            level = self.wavsList[selectedWav]['level']
            nBits = self.currLocale.toInt(
                self.parent().parent().nBitsChooser.currentText())[0]
            maxLevel = float(self.prm['phones']['phonesMaxLevel'][
                self.parent().parent().phonesChooser.currentIndex()])
            msgSnd, fs = self.audioManager.loadWavFile(fName, level, maxLevel,
                                                       'Both')
            self.isPlaying = True
            if self.prm['pref']['sound']['playCommand'] in [
                    "alsaaudio", "pyaudio"
            ]:
                self.playThread = threadedAudioPlayer(self.parent().parent())
            else:
                self.playThread = threadedExternalAudioPlayer(
                    self.parent().parent())
            self.playThread.playThreadedSound(
                msgSnd, fs, nBits, self.prm['pref']['sound']['playCommand'],
                False, 'tmp.wav')
            if self.playThread.isFinished == True:
                self.isPlaying = False

    def onClickStopWavButton(self):
        if self.isPlaying == True:
            self.playThread.terminate()

    def closeEvent(self, event):
        if self.isPlaying == True:
            self.playThread.terminate()
        event.accept()

    def accept(self):  #reimplement accept (i.e. ok button)
        if self.isPlaying == True:
            self.playThread.terminate()
        QDialog.accept(self)

    def reject(self):  #reimplement reject
        if self.isPlaying == True:
            self.playThread.terminate()
        QDialog.reject(self)
Exemple #6
0
class SpreadSheet(QMainWindow):

   dateFormats = ["dd/M/yyyy", "yyyy/M/dd", "dd.MM.yyyy"]

   currentDateFormat = dateFormats[0]

   def __init__(self, rows, cols, parent = None):
      super(SpreadSheet, self).__init__(parent)

      self.toolBar = QToolBar()
      self.addToolBar(self.toolBar)
      self.formulaInput = QLineEdit()
      self.cellLabel = QLabel(self.toolBar)
      self.cellLabel.setMinimumSize(80, 0)
      self.toolBar.addWidget(self.cellLabel)
      self.toolBar.addWidget(self.formulaInput)
      self.table = QTableWidget(rows, cols, self)
      for c in range(cols):
         character = chr(ord('A') + c)
         self.table.setHorizontalHeaderItem(c, QTableWidgetItem(character))

      self.table.setItemPrototype(self.table.item(rows - 1, cols - 1))
      self.table.setItemDelegate(SpreadSheetDelegate(self))
      self.createActions()
      self.updateColor(0)
      self.setupMenuBar()
      self.setupContents()
      self.setupContextMenu()
      self.setCentralWidget(self.table)
      self.statusBar()
      self.table.currentItemChanged.connect(self.updateStatus)
      self.table.currentItemChanged.connect(self.updateColor)
      self.table.currentItemChanged.connect(self.updateLineEdit)
      self.table.itemChanged.connect(self.updateStatus)
      self.formulaInput.returnPressed.connect(self.returnPressed)
      self.table.itemChanged.connect(self.updateLineEdit)
      self.setWindowTitle("Spreadsheet")

   def createActions(self):
      self.cell_sumAction = QAction("Sum", self)
      self.cell_sumAction.triggered.connect(self.actionSum)

      self.cell_addAction = QAction("&Add", self)
      self.cell_addAction.setShortcut(Qt.CTRL | Qt.Key_Plus)
      self.cell_addAction.triggered.connect(self.actionAdd)

      self.cell_subAction = QAction("&Subtract", self)
      self.cell_subAction.setShortcut(Qt.CTRL | Qt.Key_Minus)
      self.cell_subAction.triggered.connect(self.actionSubtract)

      self.cell_mulAction = QAction("&Multiply", self)
      self.cell_mulAction.setShortcut(Qt.CTRL | Qt.Key_multiply)
      self.cell_mulAction.triggered.connect(self.actionMultiply)

      self.cell_divAction = QAction("&Divide", self)
      self.cell_divAction.setShortcut(Qt.CTRL | Qt.Key_division)
      self.cell_divAction.triggered.connect(self.actionDivide)

      self.fontAction = QAction("Font...", self)
      self.fontAction.setShortcut(Qt.CTRL | Qt.Key_F)
      self.fontAction.triggered.connect(self.selectFont)

      self.colorAction = QAction(QIcon(QPixmap(16, 16)), "Background &Color...", self)
      self.colorAction.triggered.connect(self.selectColor)

      self.clearAction = QAction("Clear", self)
      self.clearAction.setShortcut(Qt.Key_Delete)
      self.clearAction.triggered.connect(self.clear)

      self.aboutSpreadSheet = QAction("About Spreadsheet", self)
      self.aboutSpreadSheet.triggered.connect(self.showAbout)

      self.exitAction = QAction("E&xit", self)
      self.exitAction.setShortcut(QKeySequence.Quit)
      self.exitAction.triggered.connect(QApplication.instance().quit)

      self.printAction = QAction("&Print", self)
      self.printAction.setShortcut(QKeySequence.Print)
      self.printAction.triggered.connect(self.print_)

      self.firstSeparator = QAction(self)
      self.firstSeparator.setSeparator(True)

      self.secondSeparator = QAction(self)
      self.secondSeparator.setSeparator(True)

   def setupMenuBar(self):
      self.fileMenu = self.menuBar().addMenu("&File")
      self.dateFormatMenu = self.fileMenu.addMenu("&Date format")
      self.dateFormatGroup = QActionGroup(self)
      for f in self.dateFormats:
         action = QAction(f, self, checkable=True,
                 triggered=self.changeDateFormat)
         self.dateFormatGroup.addAction(action)
         self.dateFormatMenu.addAction(action)
         if f == self.currentDateFormat:
            action.setChecked(True)
              
      self.fileMenu.addAction(self.printAction)
      self.fileMenu.addAction(self.exitAction)
      self.cellMenu = self.menuBar().addMenu("&Cell")
      self.cellMenu.addAction(self.cell_addAction)
      self.cellMenu.addAction(self.cell_subAction)
      self.cellMenu.addAction(self.cell_mulAction)
      self.cellMenu.addAction(self.cell_divAction)
      self.cellMenu.addAction(self.cell_sumAction)
      self.cellMenu.addSeparator()
      self.cellMenu.addAction(self.colorAction)
      self.cellMenu.addAction(self.fontAction)
      self.menuBar().addSeparator()
      self.aboutMenu = self.menuBar().addMenu("&Help")
      self.aboutMenu.addAction(self.aboutSpreadSheet)

   def changeDateFormat(self):
      action = self.sender()
      oldFormat = self.currentDateFormat
      newFormat = self.currentDateFormat = action.text()
      for row in range(self.table.rowCount()):
         item = self.table.item(row, 1)
         date = QDate.fromString(item.text(), oldFormat)
         item.setText(date.toString(newFormat))

   def updateStatus(self, item):
      if item and item == self.table.currentItem():
         self.statusBar().showMessage(item.data(Qt.StatusTipRole).toString(), 1000)
         self.cellLabel.setText("Cell: (%s)" % encode_pos(self.table.row(item),
                                                                    self.table.column(item)))

   def updateColor(self, item):
      pixmap = QPixmap(16, 16)
      color = QColor()
      if item:
         color = item.backgroundColor()
      if not color.isValid():
         color = self.palette().base().color()
      painter = QPainter(pixmap)
      painter.fillRect(0, 0, 16, 16, color)
      lighter = color.lighter()
      painter.setPen(lighter)
      # light frame
      painter.drawPolyline(QPoint(0, 15), QPoint(0, 0), QPoint(15, 0))
      painter.setPen(color.darker())
      # dark frame
      painter.drawPolyline(QPoint(1, 15), QPoint(15, 15), QPoint(15, 1))
      painter.end()
      self.colorAction.setIcon(QIcon(pixmap))

   def updateLineEdit(self, item):
      if item != self.table.currentItem():
         return
      if item:
         self.formulaInput.setText(item.data(Qt.EditRole).toString())
      else:
         self.formulaInput.clear()

   def returnPressed(self):
      text = self.formulaInput.text()
      row = self.table.currentRow()
      col = self.table.currentColumn()
      item = self.table.item(row, col)
      if not item:
         self.table.setItem(row, col, SpreadSheetItem(text))
      else:
         item.setData(Qt.EditRole, text)
      self.table.viewport().update()

   def selectColor(self):
      item = self.table.currentItem()
      color = item and QColor(item.background()) or self.table.palette().base().color()
      color = QColorDialog.getColor(color, self)
      if not color.isValid():
         return
      selected = self.table.selectedItems()
      if not selected:
         return
      for i in selected:
         i and i.setBackground(color)
      self.updateColor(self.table.currentItem())

   def selectFont(self):
      selected = self.table.selectedItems()
      if not selected:
         return
      font, ok = QFontDialog.getFont(self.font(), self)
      if not ok:
         return
      for i in selected:
         i and i.setFont(font)

   def runInputDialog(self, title, c1Text, c2Text, opText,
                      outText, cell1, cell2, outCell):
      rows = []
      cols = []
      for r in range(self.table.rowCount()):
         rows.append(str(r + 1))
      for c in range(self.table.columnCount()):
         cols.append(chr(ord('A') + c))
      addDialog = QDialog(self)
      addDialog.setWindowTitle(title)
      group = QGroupBox(title, addDialog)
      group.setMinimumSize(250, 100)
      cell1Label = QLabel(c1Text, group)
      cell1RowInput = QComboBox(group)
      c1Row, c1Col = decode_pos(cell1)
      cell1RowInput.addItems(rows)
      cell1RowInput.setCurrentIndex(c1Row)
      cell1ColInput = QComboBox(group)
      cell1ColInput.addItems(cols)
      cell1ColInput.setCurrentIndex(c1Col)
      operatorLabel = QLabel(opText, group)
      operatorLabel.setAlignment(Qt.AlignHCenter)
      cell2Label = QLabel(c2Text, group)
      cell2RowInput = QComboBox(group)
      c2Row, c2Col = decode_pos(cell2)
      cell2RowInput.addItems(rows)
      cell2RowInput.setCurrentIndex(c2Row)
      cell2ColInput = QComboBox(group)
      cell2ColInput.addItems(cols)
      cell2ColInput.setCurrentIndex(c2Col)
      equalsLabel = QLabel("=", group)
      equalsLabel.setAlignment(Qt.AlignHCenter)
      outLabel = QLabel(outText, group)
      outRowInput = QComboBox(group)
      outRow, outCol = decode_pos(outCell)
      outRowInput.addItems(rows)
      outRowInput.setCurrentIndex(outRow)
      outColInput = QComboBox(group)
      outColInput.addItems(cols)
      outColInput.setCurrentIndex(outCol)

      cancelButton = QPushButton("Cancel", addDialog)
      cancelButton.clicked.connect(addDialog.reject)
      okButton = QPushButton("OK", addDialog)
      okButton.setDefault(True)
      okButton.clicked.connect(addDialog.accept)
      buttonsLayout = QHBoxLayout()
      buttonsLayout.addStretch(1)
      buttonsLayout.addWidget(okButton)
      buttonsLayout.addSpacing(10)
      buttonsLayout.addWidget(cancelButton)

      dialogLayout = QVBoxLayout(addDialog)
      dialogLayout.addWidget(group)
      dialogLayout.addStretch(1)
      dialogLayout.addItem(buttonsLayout)

      cell1Layout = QHBoxLayout()
      cell1Layout.addWidget(cell1Label)
      cell1Layout.addSpacing(10)
      cell1Layout.addWidget(cell1ColInput)
      cell1Layout.addSpacing(10)
      cell1Layout.addWidget(cell1RowInput)

      cell2Layout = QHBoxLayout()
      cell2Layout.addWidget(cell2Label)
      cell2Layout.addSpacing(10)
      cell2Layout.addWidget(cell2ColInput)
      cell2Layout.addSpacing(10)
      cell2Layout.addWidget(cell2RowInput)
      outLayout = QHBoxLayout()
      outLayout.addWidget(outLabel)
      outLayout.addSpacing(10)
      outLayout.addWidget(outColInput)
      outLayout.addSpacing(10)
      outLayout.addWidget(outRowInput)
      vLayout = QVBoxLayout(group)
      vLayout.addItem(cell1Layout)
      vLayout.addWidget(operatorLabel)
      vLayout.addItem(cell2Layout)
      vLayout.addWidget(equalsLabel)
      vLayout.addStretch(1)
      vLayout.addItem(outLayout)
      if addDialog.exec_():
         cell1 = cell1ColInput.currentText() + cell1RowInput.currentText()
         cell2 = cell2ColInput.currentText() + cell2RowInput.currentText()
         outCell = outColInput.currentText() + outRowInput.currentText()
         return True, cell1, cell2, outCell

      return False, None, None, None

   def actionSum(self):
      row_first = 0
      row_last = 0
      row_cur = 0
      col_first = 0
      col_last = 0
      col_cur = 0
      selected = self.table.selectedItems()
      if selected:
         first = selected[0]
         last = selected[-1]
         row_first = self.table.row(first)
         row_last = self.table.row(last)
         col_first = self.table.column(first)
         col_last = self.table.column(last)

      current = self.table.currentItem()
      if current:
         row_cur = self.table.row(current)
         col_cur = self.table.column(current)

      cell1 = encode_pos(row_first, col_first)
      cell2 = encode_pos(row_last, col_last)
      out = encode_pos(row_cur, col_cur)
      ok, cell1, cell2, out = self.runInputDialog("Sum cells", "First cell:",
              "Last cell:", u"\N{GREEK CAPITAL LETTER SIGMA}", "Output to:",
              cell1, cell2, out)
      if ok:
         row, col = decode_pos(out)
         self.table.item(row, col).setText("sum %s %s" % (cell1, cell2))

   def actionMath_helper(self, title, op):
      cell1 = "C1"
      cell2 = "C2"
      out = "C3"
      current = self.table.currentItem()
      if current:
         out = encode_pos(self.table.currentRow(), self.table.currentColumn())
      ok, cell1, cell2, out = self.runInputDialog(title, "Cell 1", "Cell 2",
              op, "Output to:", cell1, cell2, out)
      if ok:
         row, col = decode_pos(out)
         self.table.item(row, col).setText("%s %s %s" % (op, cell1, cell2))

   def actionAdd(self):
      self.actionMath_helper("Addition", "+")

   def actionSubtract(self):
      self.actionMath_helper("Subtraction", "-")

   def actionMultiply(self):
      self.actionMath_helper("Multiplication", "*")

   def actionDivide(self):
      self.actionMath_helper("Division", "/")

   def clear(self):
      for i in self.table.selectedItems():
         i.setText("")

   def setupContextMenu(self):
      self.addAction(self.cell_addAction)
      self.addAction(self.cell_subAction)
      self.addAction(self.cell_mulAction)
      self.addAction(self.cell_divAction)
      self.addAction(self.cell_sumAction)
      self.addAction(self.firstSeparator)
      self.addAction(self.colorAction)
      self.addAction(self.fontAction)
      self.addAction(self.secondSeparator)
      self.addAction(self.clearAction)
      self.setContextMenuPolicy(Qt.ActionsContextMenu)

   def setupContents(self):
      titleBackground = QColor(Qt.lightGray)
      titleFont = self.table.font()
      titleFont.setBold(True)
      # column 0
      self.table.setItem(0, 0, SpreadSheetItem("Item"))
      self.table.item(0, 0).setBackground(titleBackground)
      self.table.item(0, 0).setToolTip("This column shows the purchased item/service")
      self.table.item(0, 0).setFont(titleFont)
      self.table.setItem(1, 0, SpreadSheetItem("AirportBus"))
      self.table.setItem(2, 0, SpreadSheetItem("Flight (Munich)"))
      self.table.setItem(3, 0, SpreadSheetItem("Lunch"))
      self.table.setItem(4, 0, SpreadSheetItem("Flight (LA)"))
      self.table.setItem(5, 0, SpreadSheetItem("Taxi"))
      self.table.setItem(6, 0, SpreadSheetItem("Dinner"))
      self.table.setItem(7, 0, SpreadSheetItem("Hotel"))
      self.table.setItem(8, 0, SpreadSheetItem("Flight (Oslo)"))
      self.table.setItem(9, 0, SpreadSheetItem("Total:"))
      self.table.item(9, 0).setFont(titleFont)
      self.table.item(9, 0).setBackground(Qt.lightGray)
      # column 1
      self.table.setItem(0, 1, SpreadSheetItem("Date"))
      self.table.item(0, 1).setBackground(titleBackground)
      self.table.item(0, 1).setToolTip("This column shows the purchase date, double click to change")
      self.table.item(0, 1).setFont(titleFont)
      self.table.setItem(1, 1, SpreadSheetItem("15/6/2006"))
      self.table.setItem(2, 1, SpreadSheetItem("15/6/2006"))
      self.table.setItem(3, 1, SpreadSheetItem("15/6/2006"))
      self.table.setItem(4, 1, SpreadSheetItem("21/5/2006"))
      self.table.setItem(5, 1, SpreadSheetItem("16/6/2006"))
      self.table.setItem(6, 1, SpreadSheetItem("16/6/2006"))
      self.table.setItem(7, 1, SpreadSheetItem("16/6/2006"))
      self.table.setItem(8, 1, SpreadSheetItem("18/6/2006"))
      self.table.setItem(9, 1, SpreadSheetItem())
      self.table.item(9, 1).setBackground(Qt.lightGray)
      # column 2
      self.table.setItem(0, 2, SpreadSheetItem("Price"))
      self.table.item(0, 2).setBackground(titleBackground)
      self.table.item(0, 2).setToolTip("This column shows the price of the purchase")
      self.table.item(0, 2).setFont(titleFont)
      self.table.setItem(1, 2, SpreadSheetItem("150"))
      self.table.setItem(2, 2, SpreadSheetItem("2350"))
      self.table.setItem(3, 2, SpreadSheetItem("-14"))
      self.table.setItem(4, 2, SpreadSheetItem("980"))
      self.table.setItem(5, 2, SpreadSheetItem("5"))
      self.table.setItem(6, 2, SpreadSheetItem("120"))
      self.table.setItem(7, 2, SpreadSheetItem("300"))
      self.table.setItem(8, 2, SpreadSheetItem("1240"))
      self.table.setItem(9, 2, SpreadSheetItem())
      self.table.item(9, 2).setBackground(Qt.lightGray)
      # column 3
      self.table.setItem(0, 3, SpreadSheetItem("Currency"))
      self.table.item(0, 3).setBackgroundColor(titleBackground)
      self.table.item(0, 3).setToolTip("This column shows the currency")
      self.table.item(0, 3).setFont(titleFont)
      self.table.setItem(1, 3, SpreadSheetItem("NOK"))
      self.table.setItem(2, 3, SpreadSheetItem("NOK"))
      self.table.setItem(3, 3, SpreadSheetItem("EUR"))
      self.table.setItem(4, 3, SpreadSheetItem("EUR"))
      self.table.setItem(5, 3, SpreadSheetItem("USD"))
      self.table.setItem(6, 3, SpreadSheetItem("USD"))
      self.table.setItem(7, 3, SpreadSheetItem("USD"))
      self.table.setItem(8, 3, SpreadSheetItem("USD"))
      self.table.setItem(9, 3, SpreadSheetItem())
      self.table.item(9,3).setBackground(Qt.lightGray)
      # column 4
      self.table.setItem(0, 4, SpreadSheetItem("Ex. Rate"))
      self.table.item(0, 4).setBackground(titleBackground)
      self.table.item(0, 4).setToolTip("This column shows the exchange rate to NOK")
      self.table.item(0, 4).setFont(titleFont)
      self.table.setItem(1, 4, SpreadSheetItem("1"))
      self.table.setItem(2, 4, SpreadSheetItem("1"))
      self.table.setItem(3, 4, SpreadSheetItem("8"))
      self.table.setItem(4, 4, SpreadSheetItem("8"))
      self.table.setItem(5, 4, SpreadSheetItem("7"))
      self.table.setItem(6, 4, SpreadSheetItem("7"))
      self.table.setItem(7, 4, SpreadSheetItem("7"))
      self.table.setItem(8, 4, SpreadSheetItem("7"))
      self.table.setItem(9, 4, SpreadSheetItem())
      self.table.item(9,4).setBackground(Qt.lightGray)
      # column 5
      self.table.setItem(0, 5, SpreadSheetItem("NOK"))
      self.table.item(0, 5).setBackground(titleBackground)
      self.table.item(0, 5).setToolTip("This column shows the expenses in NOK")
      self.table.item(0, 5).setFont(titleFont)
      self.table.setItem(1, 5, SpreadSheetItem("* C2 E2"))
      self.table.setItem(2, 5, SpreadSheetItem("* C3 E3"))
      self.table.setItem(3, 5, SpreadSheetItem("* C4 E4"))
      self.table.setItem(4, 5, SpreadSheetItem("* C5 E5"))
      self.table.setItem(5, 5, SpreadSheetItem("* C6 E6"))
      self.table.setItem(6, 5, SpreadSheetItem("* C7 E7"))
      self.table.setItem(7, 5, SpreadSheetItem("* C8 E8"))
      self.table.setItem(8, 5, SpreadSheetItem("* C9 E9"))
      self.table.setItem(9, 5, SpreadSheetItem("sum F2 F9"))
      self.table.item(9,5).setBackground(Qt.lightGray)

   def showAbout(self):
      QMessageBox.about(self, "About Spreadsheet", """
          <HTML>
          <p><b>This demo shows use of <c>QTableWidget</c> with custom handling for
           individual cells.</b></p>
          <p>Using a customized table item we make it possible to have dynamic
           output in different cells. The content that is implemented for this
           particular demo is:
          <ul>
          <li>Adding two cells.</li>
          <li>Subtracting one cell from another.</li>
          <li>Multiplying two cells.</li>
          <li>Dividing one cell with another.</li>
          <li>Summing the contents of an arbitrary number of cells.</li>
          </HTML>
      """)

   def print_(self):
      pass
class wavListDialog(QDialog):
    def __init__(self, parent):
        QDialog.__init__(self, parent)
        self.prm = self.parent().parent().prm
        self.audioManager = audioManager(self)
        self.currLocale = self.parent().parent().prm['currentLocale']
        self.currLocale.setNumberOptions(self.currLocale.OmitGroupSeparator | self.currLocale.RejectGroupSeparator)
        self.isPlaying = False
      
        self.sizer = QGridLayout() 
        self.v1Sizer = QVBoxLayout()
        
        self.wavsTableWidget = QTableWidget()
        self.wavsTableWidget.setColumnCount(4)
        self.wavsTableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.wavsTableWidget.setSelectionMode(QAbstractItemView.ExtendedSelection)
        
        self.wavsTableWidget.setHorizontalHeaderLabels([self.tr("File"), self.tr('Use'), self.tr("RMS Level"), 'id'])
        self.quidColumn = 3
        self.wavsTableWidget.hideColumn(self.quidColumn)
        self.wavsTableWidget.cellDoubleClicked[int,int].connect(self.onCellDoubleClicked)

        
        #ADD wav BUTTON
        self.addWavButton = QPushButton(self.tr("Add Wav"), self)
        self.addWavButton.clicked.connect(self.onClickAddWavButton)
        #REMOVE wav BUTTON
        self.removeWavButton = QPushButton(self.tr("Remove Wav"), self)
        self.removeWavButton.clicked.connect(self.onClickRemoveWavButton)

        #PLAY wav BUTTON
        self.playWavButton = QPushButton(self.tr("Play Wav"), self)
        self.playWavButton.clicked.connect(self.onClickPlayWavButton)
        #STOP wav BUTTON
        self.stopWavButton = QPushButton(self.tr("Stop Playing"), self)
        self.stopWavButton.clicked.connect(self.onClickStopWavButton)
       
        self.v1Sizer.addWidget(self.addWavButton)
        self.v1Sizer.addWidget(self.removeWavButton)
        self.v1Sizer.addWidget(self.playWavButton)
        self.v1Sizer.addWidget(self.stopWavButton)
     
        self.v1Sizer.addStretch()

        self.wavsList = {}
    
        for i in range(len(self.parent().wavsPref['endMessageFiles'])):
            currCount = i+1
            thisID = self.parent().wavsPref['endMessageFilesID'][i]
            self.wavsList[thisID] = {}
            self.wavsList[thisID]['file'] = self.parent().wavsPref['endMessageFiles'][i]
            self.wavsList[thisID]['use'] = self.parent().wavsPref['endMessageFilesUse'][i]
            self.wavsList[thisID]['level'] = self.parent().wavsPref['endMessageLevels'][i]
            self.wavsTableWidget.setRowCount(currCount)
            n = 0
            newItem = QTableWidgetItem(self.wavsList[thisID]['file'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount-1, n, newItem)
            n = n+1
            newItem = QTableWidgetItem(self.wavsList[thisID]['use'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount-1, n, newItem)
            n = n+1
            newItem = QTableWidgetItem(self.currLocale.toString(self.wavsList[thisID]['level']))
            newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount-1, n, newItem)
            n = n+1
            self.wavsList[thisID]['qid'] = QTableWidgetItem(thisID)
            self.wavsTableWidget.setItem(currCount-1, n, self.wavsList[thisID]['qid'])

     
        buttonBox = QDialogButtonBox(QDialogButtonBox.Apply|QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.reject)

        self.sizer.addLayout(self.v1Sizer, 0, 0)
        self.sizer.addWidget(self.wavsTableWidget,0,1)
        self.sizer.addWidget(buttonBox, 1,1)
        self.setLayout(self.sizer)
        self.setWindowTitle(self.tr("Edit Wavs"))
        self.show()


    def onCellDoubleClicked(self, row, col):
        if col == 0:
            pass
        elif col == 1:
            self.onEditUse()
        elif col == 2:
            self.onEditLevel()

    def onEditLevel(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(self, self.tr('Warning'), self.tr('Only one item can be edited at a time'))
        elif len(ids) < 1:
            pass
        else:
            selectedSound = ids[0]
            msg = self.tr('RMS Level:')
            text, ok = QInputDialog.getDouble(self, self.tr('Input Dialog'), msg, self.wavsList[selectedSound]['level'])
            if ok:
                self.wavsTableWidget.item(self.wavsList[selectedSound]['qid'].row(), 2).setText(self.currLocale.toString(text))
                self.wavsList[selectedSound]['level'] = text

    def onEditUse(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(self, self.tr('Warning'), self.tr('Only one item can be edited at a time'))
        elif len(ids) < 1:
            pass
        else:
            selectedSound = ids[0]
            if self.wavsTableWidget.item(self.wavsList[selectedSound]['qid'].row(), 1).text() == "\u2012":
                self.wavsTableWidget.item(self.wavsList[selectedSound]['qid'].row(), 1).setText("\u2713")
                self.wavsList[selectedSound]['use'] = "\u2713"
            else:
                self.wavsTableWidget.item(self.wavsList[selectedSound]['qid'].row(), 1).setText("\u2012")
                self.wavsList[selectedSound]['use'] = "\u2012"
    def findSelectedItemIds(self):
        selItems = self.wavsTableWidget.selectedItems()
        selItemsRows = []
        for i in range(len(selItems)):
            selItemsRows.append(selItems[i].row())
        selItemsRows = unique(selItemsRows)
        selItemsIds = []
        for i in range(len(selItemsRows)):
            selItemsIds.append(str(self.wavsTableWidget.item(selItemsRows[i], self.quidColumn).text()))
        return selItemsIds

    def permanentApply(self):
        self.wavListToPass = {}
        self.wavListToPass['endMessageFiles'] = []
        self.wavListToPass['endMessageFilesUse'] = []
        self.wavListToPass['endMessageFilesID'] = []
        self.wavListToPass['endMessageLevels'] = []

        keys = sorted(self.wavsList.keys())
        for key in keys:
            self.wavListToPass['endMessageFiles'].append(str(self.wavsList[key]['file']))
            self.wavListToPass['endMessageFilesUse'].append(self.wavsList[key]['use'])
            self.wavListToPass['endMessageLevels'].append(self.wavsList[key]['level'])
            self.wavListToPass['endMessageFilesID'].append(key)
      

    def onClickAddWavButton(self):
        fName = QFileDialog.getOpenFileName(self, self.tr("Choose wav file to load"), '', self.tr("wav files (*.wav);;All Files (*)"))[0]
        if len(fName) > 0: #if the user didn't press cancel

            if len(self.wavsList.keys()) > 0:
                keys = sorted(self.wavsList.keys())
                thisID = str(int(keys[-1])+1)
            else:
                thisID = "1"
            currCount = self.wavsTableWidget.rowCount() + 1

            self.wavsList[thisID] = {}
            self.wavsList[thisID]['file'] = fName
            self.wavsList[thisID]['use'] = "\u2713"
            self.wavsList[thisID]['level'] = 60
            self.wavsTableWidget.setRowCount(currCount)
            n = 0
            newItem = QTableWidgetItem(self.wavsList[thisID]['file'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount-1, n, newItem)
            n = n+1
            newItem = QTableWidgetItem(self.wavsList[thisID]['use'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount-1, n, newItem)
            n = n+1
            newItem = QTableWidgetItem(self.currLocale.toString(self.wavsList[thisID]['level']))
            newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount-1, n, newItem)
            n = n+1
            self.wavsList[thisID]['qid'] = QTableWidgetItem(thisID)
            self.wavsTableWidget.setItem(currCount-1, n, self.wavsList[thisID]['qid'])
      

    def onClickRemoveWavButton(self):
        ids = self.findSelectedItemIds()
        for i in range(len(ids)):
            selectedWavs = ids[i]
            self.wavsTableWidget.removeRow(self.wavsList[selectedWavs]['qid'].row())
            del self.wavsList[selectedWavs]

    def onClickPlayWavButton(self):
        ids = self.findSelectedItemIds()
        if len(ids) < 1:
            QMessageBox.warning(self, self.tr('Warning'), self.tr('No files selected for playing'))
        else:
            if len(ids) > 1:
                pass #maybe say on the status bar that only the first one will be played
            selectedWav = ids[0]
            fName = self.wavsList[selectedWav]['file']
            level = self.wavsList[selectedWav]['level']
            nBits = self.currLocale.toInt(self.parent().parent().nBitsChooser.currentText())[0]
            maxLevel = float(self.prm['phones']['phonesMaxLevel'][self.parent().parent().phonesChooser.currentIndex()])
            msgSnd, fs = self.audioManager.loadWavFile(fName, level, maxLevel, 'Both')
            self.isPlaying = True
            if self.prm['pref']['sound']['playCommand'] in ["alsaaudio","pyaudio"]:
                self.playThread = threadedAudioPlayer(self.parent().parent())
            else:
                self.playThread = threadedExternalAudioPlayer(self.parent().parent())
            self.playThread.playThreadedSound(msgSnd, fs, nBits, self.prm['pref']['sound']['playCommand'], False, 'tmp.wav')
            if self.playThread.isFinished == True:
                self.isPlaying = False
    def onClickStopWavButton(self):
        if self.isPlaying == True:
            self.playThread.terminate()
          
        
    def closeEvent(self, event):
        if self.isPlaying == True:
            self.playThread.terminate()
        event.accept()
        
    def accept(self): #reimplement accept (i.e. ok button)
        if self.isPlaying == True:
            self.playThread.terminate()
        QDialog.accept(self)
    def reject(self): #reimplement reject
        if self.isPlaying == True:
            self.playThread.terminate()
        QDialog.reject(self)
class phonesDialog(QDialog):
    def __init__(self, parent):
        QDialog.__init__(self, parent)
        self.prm = self.parent().prm
        self.currLocale = self.parent().prm['currentLocale']
        self.currLocale.setNumberOptions(self.currLocale.OmitGroupSeparator | self.currLocale.RejectGroupSeparator)
        screen = QDesktopWidget().screenGeometry()
        self.resize(screen.width()/2.5,screen.height()/3)
        self.isPlaying = False
        #self.audioManager = audioManager(self)
        #self.playThread = threadedPlayer(self)
   
        self.sizer = QGridLayout() 
        self.v1Sizer = QVBoxLayout()
        self.v2Sizer = QVBoxLayout()
        self.calibSizer = QGridLayout()
        
        self.phonesTableWidget = QTableWidget()
        self.phonesTableWidget.setColumnCount(4)
        self.phonesTableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.phonesTableWidget.setSelectionMode(QAbstractItemView.ExtendedSelection)
        
        self.phonesTableWidget.setHorizontalHeaderLabels([self.tr('Phones'), self.tr('Max Level'), self.tr('Default'), 'id'])
        self.phonesTableWidget.hideColumn(3)
        self.phonesTableWidget.cellDoubleClicked[int,int].connect(self.onCellDoubleClicked)

        #RENAME Phones BUTTON
        self.renamePhonesButton = QPushButton(self.tr("Rename Phones"), self)
        self.renamePhonesButton.clicked.connect(self.onEditLabel)
        #Change Level Phones BUTTON
        self.changeLevelPhonesButton = QPushButton(self.tr("Change Max Level"), self)
        self.changeLevelPhonesButton.clicked.connect(self.onEditMaxLevel)
        
        #ADD Phones BUTTON
        self.addPhonesButton = QPushButton(self.tr("Add Phones"), self)
        self.addPhonesButton.clicked.connect(self.onClickAddPhonesButton)
        #REMOVE Phones BUTTON
        self.removePhonesButton = QPushButton(self.tr("Remove Phones"), self)
        self.removePhonesButton.clicked.connect(self.onClickRemovePhonesButton)
        #Set Default Phones BUTTON
        self.setDefaultPhonesButton = QPushButton(self.tr("Set Default"), self)
        self.setDefaultPhonesButton.clicked.connect(self.onEditDefault)

        self.v1Sizer.addWidget(self.renamePhonesButton)
        self.v1Sizer.addWidget(self.changeLevelPhonesButton)
        self.v1Sizer.addWidget(self.addPhonesButton)
        self.v1Sizer.addWidget(self.removePhonesButton)
        self.v1Sizer.addWidget(self.setDefaultPhonesButton)
        self.v1Sizer.addStretch()
        self.phonesList = {}
    
        for i in range(len(self.prm['phones']['phonesChoices'])):
            currCount = i+1
            thisID = self.prm['phones']['phonesID'][i]
            self.phonesList[thisID] = {}
            self.phonesList[thisID]['label'] = self.prm['phones']['phonesChoices'][i]
            self.phonesList[thisID]['maxLevel'] = self.prm['phones']['phonesMaxLevel'][i]
            self.phonesList[thisID]['default'] = self.prm['phones']['defaultPhones'][i]
            self.phonesTableWidget.setRowCount(currCount)
            newItem = QTableWidgetItem(self.phonesList[thisID]['label'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.phonesTableWidget.setItem(currCount-1, 0, newItem)
            newItem = QTableWidgetItem(self.currLocale.toString(self.phonesList[thisID]['maxLevel']))
            newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.phonesTableWidget.setItem(currCount-1, 1, newItem)
            newItem = QTableWidgetItem(self.phonesList[thisID]['default'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.phonesTableWidget.setItem(currCount-1, 2, newItem)
            self.phonesList[thisID]['qid'] = QTableWidgetItem(thisID)
            self.phonesTableWidget.setItem(currCount-1, 3, self.phonesList[thisID]['qid'])

        ##CALIBRATION TONE
        n = 0
        self.calLabel = QLabel(self.tr('Calibration Tone:'), self)
        self.calibSizer.addWidget(self.calLabel, n, 0, 1, 2)
        n = n+1
        self.toneFreqLabel = QLabel(self.tr('Frequency (Hz)'), self)
        self.toneFreqTF = QLineEdit("1000")
        self.toneFreqTF.setValidator(QDoubleValidator(self))
        self.calibSizer.addWidget(self.toneFreqLabel, n, 0)
        self.calibSizer.addWidget(self.toneFreqTF, n, 1)
        n = n+1
        self.toneLevLabel = QLabel(self.tr('Level (dB)'), self)
        self.toneLevTF = QLineEdit("60")
        self.toneLevTF.setValidator(QDoubleValidator(self))
        self.calibSizer.addWidget(self.toneLevLabel, n, 0)
        self.calibSizer.addWidget(self.toneLevTF, n, 1)
        n = n+1
        self.toneDurLabel = QLabel(self.tr('Duration (ms)'), self)
        self.toneDurTF = QLineEdit("4980")
        self.toneDurTF.setValidator(QDoubleValidator(self))
        self.calibSizer.addWidget(self.toneDurLabel, n, 0)
        self.calibSizer.addWidget(self.toneDurTF, n, 1)
        n = n+1
        self.toneRampsLabel = QLabel(self.tr('Ramps (ms)'), self)
        self.toneRampsTF = QLineEdit("10")
        self.toneRampsTF.setValidator(QDoubleValidator(self))
        self.calibSizer.addWidget(self.toneRampsLabel, n, 0)
        self.calibSizer.addWidget(self.toneRampsTF, n, 1)
        n = n+1
        self.earLabel = QLabel(self.tr('Ear:'), self)
        self.earChooser = QComboBox()
        self.earChooser.addItems([self.tr("Right"), self.tr("Left"), self.tr("Both")])
        self.calibSizer.addWidget(self.earLabel, n, 0)
        self.calibSizer.addWidget(self.earChooser, n, 1)
        n = n+1
        self.playCalibButton = QPushButton(self.tr("Play"), self)
        self.playCalibButton.clicked.connect(self.onClickPlayCalibButton)
        self.playCalibButton.setIcon(QIcon.fromTheme("media-playback-start", QIcon(":/media-playback-start")))
        self.calibSizer.addWidget(self.playCalibButton, n, 0, 1, 2)
        n = n+1
        self.stopCalibButton = QPushButton(self.tr("Stop"), self)
        self.stopCalibButton.clicked.connect(self.onClickStopCalibButton)
        self.stopCalibButton.setIcon(QIcon.fromTheme("media-playback-stop", QIcon(":/media-playback-stop")))
        self.calibSizer.addWidget(self.stopCalibButton, n, 0, 1, 2)
        if self.prm['pref']['sound']['playCommand'] in ["alsaaudio","pyaudio"]:
            self.stopCalibButton.show()
        else:
            self.stopCalibButton.hide()
        
        buttonBox = QDialogButtonBox(QDialogButtonBox.Apply|QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.reject)
        buttonBox.button(QDialogButtonBox.Apply).clicked.connect(self.permanentApply)

        self.sizer.addLayout(self.v1Sizer, 0, 0)
        self.v2Sizer.addLayout(self.calibSizer)
        self.v2Sizer.addStretch()
        self.sizer.addWidget(self.phonesTableWidget, 0, 1)
        self.sizer.addLayout(self.v2Sizer, 0, 2)
        self.sizer.addWidget(buttonBox, 1,1,1,2)
        self.sizer.setColumnStretch(1,2)
        self.setLayout(self.sizer)
        self.setWindowTitle(self.tr("Edit Phones"))
        self.show()

    def onCellDoubleClicked(self, row, col):
        if col == 0:
            self.onEditLabel()
        elif col == 1:
            self.onEditMaxLevel()
        elif col == 2:
            self.onEditDefault()

    def onEditLabel(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(self, self.tr('Warning'), self.tr('Only one label can be renamed at a time'))
        elif len(ids) < 1:
            pass
        else:
            selectedSound = ids[0]
            msg = self.tr('New name:')
            text, ok = QInputDialog.getText(self, self.tr('Input Dialog'), msg)
            if ok:
                self.phonesTableWidget.item(self.phonesList[selectedSound]['qid'].row(), 0).setText(text)
                self.phonesList[selectedSound]['label'] = text
    def onEditMaxLevel(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(self, self.tr('Warning'), self.tr('Only one item can be edited at a time'))
        elif len(ids) < 1:
            pass
        else:
            selectedSound = ids[0]
            msg = self.tr('Level:')
            text, ok = QInputDialog.getDouble(self, self.tr('Input Dialog'), msg, self.phonesList[selectedSound]['maxLevel'])
            if ok:
                self.phonesTableWidget.item(self.phonesList[selectedSound]['qid'].row(), 1).setText(self.currLocale.toString(text))
                self.phonesList[selectedSound]['maxLevel'] = text

    def onEditDefault(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(self, self.tr('Warning'), self.tr('Only one item can be edited at a time'))
        elif len(ids) < 1:
            pass
        else:
            selectedSound = ids[0]
            for i in range(self.phonesTableWidget.rowCount()):
                 self.phonesTableWidget.item(i, 2).setText("\u2012")
                 self.phonesList[str(self.phonesTableWidget.item(i, 3).text())]['default'] = "\u2012"
            self.phonesTableWidget.item(self.phonesList[selectedSound]['qid'].row(), 2).setText("\u2713")
            self.phonesList[selectedSound]['default'] = "\u2713"

    def findSelectedItemIds(self):
        selItems = self.phonesTableWidget.selectedItems()
        selItemsRows = []
        for i in range(len(selItems)):
            selItemsRows.append(selItems[i].row())
        selItemsRows = unique(selItemsRows)
        selItemsIds = []
        for i in range(len(selItemsRows)):
            selItemsIds.append(str(self.phonesTableWidget.item(selItemsRows[i], 3).text()))
        return selItemsIds

    def permanentApply(self):
        self.prm['phones']['phonesChoices'] = []
        self.prm['phones']['phonesMaxLevel'] = []
        self.prm['phones']['defaultPhones'] = []
        self.prm['phones']['phonesID'] = []

        keys = sorted(self.phonesList.keys())
        for key in keys:
            self.prm['phones']['phonesChoices'].append(str(self.phonesList[key]['label']))
            self.prm['phones']['phonesMaxLevel'].append(self.phonesList[key]['maxLevel'])
            self.prm['phones']['defaultPhones'].append(self.phonesList[key]['default'])
            self.prm['phones']['phonesID'].append(key)
        f = open(self.parent().prm['phonesPrefFile'], 'wb')
        pickle.dump(self.parent().prm['phones'], f)
        f.close()
        for i in range(self.parent().phonesChooser.count()):
            self.parent().phonesChooser.removeItem(0)
        self.parent().phonesChooser.addItems(self.prm['phones']['phonesChoices'])

    def onClickAddPhonesButton(self):
        keys = sorted(self.phonesList.keys())
        thisID = str(int(keys[-1])+1)
        currCount = self.phonesTableWidget.rowCount() + 1

        self.phonesList[thisID] = {}
        self.phonesList[thisID]['label'] = 'Phones' + ' ' + str(currCount)
        self.phonesList[thisID]['maxLevel'] = 100
        self.phonesList[thisID]['default'] = "\u2012"
        self.phonesTableWidget.setRowCount(currCount)
        newItem = QTableWidgetItem(self.phonesList[thisID]['label'])
        newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        self.phonesTableWidget.setItem(currCount-1, 0, newItem)
        newItem = QTableWidgetItem(self.currLocale.toString(self.phonesList[thisID]['maxLevel']))
        newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        self.phonesTableWidget.setItem(currCount-1, 1, newItem)
        newItem = QTableWidgetItem(self.phonesList[thisID]['default'])
        newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        self.phonesTableWidget.setItem(currCount-1, 2, newItem)
        self.phonesList[thisID]['qid'] = QTableWidgetItem(thisID)
        self.phonesTableWidget.setItem(currCount-1, 3, self.phonesList[thisID]['qid'])
      

    def onClickRemovePhonesButton(self):
        if self.phonesTableWidget.rowCount() == 1:
            ret = QMessageBox.warning(self, self.tr("Warning"),
                                            self.tr("Only one phone left. Cannot remove!"),
                                            QMessageBox.Ok)
        else:
            ids = self.findSelectedItemIds()
            wasDefault = False
            for i in range(len(ids)):
                selectedPhones = ids[i]
                if self.phonesTableWidget.item(self.phonesList[selectedPhones]['qid'].row(), 2).text() == "\u2713":
                    wasDefault = True 
                self.phonesTableWidget.removeRow(self.phonesList[selectedPhones]['qid'].row())
                del self.phonesList[selectedPhones]
            if wasDefault == True:
                self.phonesTableWidget.item(0, 2).setText("\u2713")
                self.phonesList[str(self.phonesTableWidget.item(0, 3).text())]['default'] = "\u2713"


    def onClickPlayCalibButton(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(self, self.tr('Warning'), self.tr('Only one label can be renamed at a time'))
            return
        elif len(ids) < 1:
            QMessageBox.warning(self, self.tr('Warning'), self.tr('Please, select a phone in the table'))
            return
        else:
            selectedSound = ids[0]
            calMaxLev = self.phonesList[selectedSound]['maxLevel']
            frequency = self.currLocale.toDouble(self.toneFreqTF.text())[0]
            level = self.currLocale.toDouble(self.toneLevTF.text())[0]
            duration = self.currLocale.toDouble(self.toneDurTF.text())[0]
            ramp = self.currLocale.toDouble(self. toneRampsTF.text())[0]
            channel =  self.earChooser.currentText()
            fs = self.currLocale.toInt(self.parent().sampRateTF.text())[0]
            nBits = self.currLocale.toInt(self.parent().nBitsChooser.currentText())[0]
            calTone = pureTone(frequency, 0, level, duration, ramp, channel, fs, calMaxLev)
            self.isPlaying = True
            if self.prm['pref']['sound']['playCommand'] in ["alsaaudio","pyaudio"]:
                self.playThread = threadedAudioPlayer(self.parent())
            else:
                self.playThread = threadedExternalAudioPlayer(self.parent())
            self.playThread.playThreadedSound(calTone, fs, nBits, self.prm['pref']['sound']['playCommand'], True, 'calibrationTone.wav')
            if self.playThread.isFinished() == True:
                self.isPlaying = False

    def onClickStopCalibButton(self):
        if self.isPlaying == True:
            self.playThread.terminate()
            #self.playThread.__del__()

    def closeEvent(self, event):
        if self.isPlaying == True:
            #self.playThread.__del__()
            self.playThread.terminate()
        event.accept()
        
    def accept(self): #reimplement accept (i.e. ok button)
        if self.isPlaying == True:
            #self.playThread.__del__()
            self.playThread.terminate()
        QDialog.accept(self)
    def reject(self): #reimplement reject
        if self.isPlaying == True:
            #self.playThread.__del__()
            self.playThread.terminate()
        QDialog.reject(self)