Beispiel #1
0
    def test_init(self):
        aTree1 = Tree(3)
        self.assertEqual(3, aTree1.getNode())
        self.assertEqual([], aTree1.getChildren())

        aTree2 = Tree(4, [Tree(3), Tree(5)])
        self.assertEqual(4, aTree2.getNode())
        self.assertEqual(2, len(aTree2.getChildren()))
Beispiel #2
0
class Foo(QtGui.QMainWindow):
    def __init__(self):
        super(Foo, self).__init__()
        self.initUI()

    def initUI(self):
        config = Foo.readConfig('options')
        self.timeOut = -1
        self.radio = False
        self.statusBar().showMessage('Ready')
        self.createMenu()
        self.setWindowTitle("Foo.cd")

        self.player = Player(Foo.readConfig('audio'))
        self.player.bus.connect('message::eos', self.stop)
        self.player.bus.connect('message::duration-changed',
                                self.onDurationChanged)

        self.tree = Tree(self, config['tree_order'])
        self.tree.addSongs.connect(self.addSongsFromTree)
        self.tree.customContextMenuRequested.connect(self.tmpTag)

        if not self.radio:
            self.table = Table(self, config)
            self.handlerATF = self.player.playbin.connect(
                "about-to-finish", self.onAboutToFinish)
            self.table.runAction.connect(self.tableAction)
        else:
            configRadio = Foo.readConfigRadios()
            self.table = TableRadio(self, configRadio)
            self.table.runAction.connect(self.tableAction)
            self.handlerT = self.player.bus.connect('message::tag',
                                                    self.table.onTag)

        self.playbackButtons = PlaybackButtons(None)
        self.playbackButtons.buttonPlay.clicked.connect(self.toggleSong)
        self.playbackButtons.buttonStop.clicked.connect(self.stop)
        self.playbackButtons.buttonPrev.clicked.connect(self.previous)
        self.playbackButtons.buttonNext.clicked.connect(self.next)

        self.volumeSlider = VolumeSlider(self)
        self.volumeSlider.sliderMoved.connect(self.player.setVolume)
        self.scrollSlider = ScrollSlider(self)
        self.scrollSlider.sliderPressed.connect(self.player.toggle)
        self.scrollSlider.sliderReleased.connect(self.player.toggle)
        self.scrollSlider.sliderMoved.connect(self.player.seek)

        self.pixmap = Image(self, config['cover_names'], config['extensions'])

        # Album cover connections
        self.tree.selectionModel().selectionChanged.connect(
            lambda: self.pixmap.onSelectionChanged(self.tree.getChildren()[0].
                                                   get('file', None)))
        self.table.selectionModel().selectionChanged.connect(
            lambda: self.pixmap.onSelectionChanged(self.table.getSelection().
                                                   get('file', None)))

        self.searchArea = SearchArea(self)
        self.searchArea.searchLine.returnPressed.connect(self.startSearch)

        self.playbackButtons.addWidget(self.volumeSlider)
        self.playbackButtons.addWidget(self.scrollSlider)

        splitterLeftRight = QtGui.QSplitter()
        self.splitterTopBottom = QtGui.QSplitter(Qt.Vertical, self)

        self.infoFrame = QtGui.QFrame()
        infoLayout = QtGui.QVBoxLayout()
        infoLayout.setContentsMargins(0, 0, 0, 0)
        infoLayout.addLayout(self.playbackButtons)
        infoLayout.addWidget(self.pixmap)
        self.infoFrame.setLayout(infoLayout)

        libLayout = QtGui.QVBoxLayout()
        libLayout.setContentsMargins(0, 0, 0, 0)
        libLayout.addWidget(self.tree)
        libLayout.addLayout(self.searchArea)
        libFrame = QtGui.QFrame()
        libFrame.setLayout(libLayout)

        self.splitterTopBottom.addWidget(self.table)
        self.splitterTopBottom.addWidget(self.infoFrame)
        self.splitterTopBottom.setStretchFactor(0, 1)
        #self.splitterTopBottom.setStretchFactor(1,0)

        splitterLeftRight.addWidget(libFrame)
        splitterLeftRight.addWidget(self.splitterTopBottom)
        splitterLeftRight.setStretchFactor(0, 2)
        splitterLeftRight.setStretchFactor(1, 3)

        mainLayout = QtGui.QGridLayout()
        mainLayout.setContentsMargins(4, 4, 4, 4)
        mainLayout.addWidget(splitterLeftRight)

        dummyWidget = QtGui.QWidget()
        dummyWidget.setLayout(mainLayout)
        self.setCentralWidget(dummyWidget)

        self.setTabOrder(self.tree, self.table)

        dictShortcuts = self.readConfig('shortcuts')
        modifier = dictShortcuts['modifier'] + '+'
        self.shortQuit = QtGui.QShortcut(
            QtGui.QKeySequence(modifier + dictShortcuts['quit']), self,
            self.close)
        self.shortStop = QtGui.QShortcut(
            QtGui.QKeySequence(modifier + dictShortcuts['stop']), self,
            self.stop)
        self.shortPlayPause = QtGui.QShortcut(
            QtGui.QKeySequence(modifier + dictShortcuts['play_pause']), self,
            self.toggleSong)
        self.shortSongPrevious = QtGui.QShortcut(
            QtGui.QKeySequence(modifier + dictShortcuts['previous']), self,
            self.previous)
        self.shortSongNext = QtGui.QShortcut(
            QtGui.QKeySequence(modifier + dictShortcuts['next']), self,
            self.next)
        self.shortVolDown = QtGui.QShortcut(
            QtGui.QKeySequence(modifier + dictShortcuts['volume_down']), self,
            self.volumeSlider.decr)
        self.shortVolUp = QtGui.QShortcut(
            QtGui.QKeySequence(modifier + dictShortcuts['volume_up']), self,
            self.volumeSlider.incr)
        self.shortRadioMode = QtGui.QShortcut(
            QtGui.QKeySequence(modifier + dictShortcuts['radio_mode']), self,
            self.toggleRadio)
        self.shortEqualizer = QtGui.QShortcut(
            QtGui.QKeySequence(modifier + dictShortcuts['equalizer']), self,
            self.openEqualizer)

        thread = QtCore.QThread(self)
        thread.worker = WorkThreadPipe()
        thread.worker.moveToThread(thread)
        thread.started.connect(thread.worker.process)
        thread.worker.hotKey.connect(self.onHotKey)
        thread.worker.finished.connect(thread.quit)
        thread.worker.finished.connect(thread.worker.deleteLater)
        thread.finished.connect(thread.deleteLater)
        thread.start()

        self.show()

    def keyReleaseEvent(self, event):
        if event.key() == Qt.Key_Alt:
            self.menuBar().setVisible(not self.menuBar().isVisible())
        else:
            QWidget.keyPressEvent(self, event)

    # Triggered by player end of stream event
    # or called by hand to stop the stream
    def stop(self, bus=None, msg=None):
        self.player.stop()
        self.scrollSlider.setValue(0)
        self.table.displayPlayToStop()
        self.stopStatusEmission('Ready')

    def previous(self):
        if self.table.playingId > 0:
            self.player.stop()
            self.table.playingId -= 1
            self.player.add(self.table.model().item(self.table.playingId,
                                                    0).data()['file'])
            self.player.play()

    def next(self):
        if self.table.model().rowCount() - 1 > self.table.playingId:
            self.player.stop()
            self.table.playingId += 1
            self.player.add(self.table.model().item(self.table.playingId,
                                                    0).data()['file'])
            self.player.play()

    def toggleSong(self):
        state = self.player.playbin.get_state(Gst.State.NULL)
        if state[1] == Gst.State.PLAYING:
            self.table.displayPlayToPause()
            self.player.toggle()

            status = self.statusBar().currentMessage().replace(
                'Playing', 'Paused')
            self.stopStatusEmission(status)
        else:
            self.table.displayPauseToPlay(self.table.playingId)
            self.player.toggle()
            #self.onDurationChanged(0,0)
            status = self.table.getStatus()
            self.setStatusEmission(status)

    # Triggered by player when a song starts
    def onDurationChanged(self, bus, msg):
        self.table.displayNext()
        print('Duration changed signal !')
        filename = self.table.model().item(self.table.playingId,
                                           0).data()['file'][7:]
        data = wave.getDBData(filename)
        wave.createImg(data)
        self.scrollSlider.setStyleSheet("border-image: url(./wave.png)")

    # Triggered by player at the end of a song
    def onAboutToFinish(self, bus):
        if self.table.model().rowCount() - 1 > self.table.playingId:
            print('About to finish !')
            self.table.playingId += 1
            self.player.add(self.table.model().item(self.table.playingId,
                                                    0).data()['file'])

    def addSongsFromTree(self, list, play):
        if not self.radio:
            i = self.table.model().rowCount()
            for l in list:
                self.table.addRow(l)
            self.table.resizeRowsToContents()
            if play:
                self.stop()
                self.player.add(list[0]['file'])
                self.player.play()
                self.table.displayStopToPlay(i)
                status = self.table.getStatus()
                self.setStatusEmission(status)

    def setStatusEmission(self, status):
        if self.timeOut > 0:
            GObject.source_remove(self.timeOut)
        self.timeOut = GObject.timeout_add(1000, self.update, status)

    def stopStatusEmission(self, status):
        if self.timeOut > 0:
            GObject.source_remove(self.timeOut)
        self.timeOut = GObject.timeout_add(0, self.update, status)
        self.timeOut = -1

    def update(self, status):
        print('.')
        try:
            duration_nanosecs = self.player.getDuration()
            duration = float(duration_nanosecs) / 1000000000
            self.scrollSlider.setRange(0, duration)

            nanosecs = self.player.getPosition()
            position = float(nanosecs) // 1000000000
            self.scrollSlider.setValue(position)
            m, s = divmod(position, 60)
            self.statusBar().showMessage(
                status.replace('%', "%02d:%02d" % (m, s)))
        except Exception as e:
            print(e)
            pass
        if 'Playing' in status:
            return True
        else:
            return False

    def tableAction(self, str):
        if str == 'stop':
            self.stop()
        elif str == 'play':
            if self.table.selectedIndexes():
                index = self.table.selectedIndexes()[0]
            else:
                index = self.table.model().index(
                    self.table.selectionModel().currentIndex().row(), 0)
            songURI = index.model().itemFromIndex(index).data()['file']

            self.player.stop()
            self.player.add(songURI)
            self.player.play()
            self.table.displayStopToPlay(index.row())
            status = self.table.getStatus()
            self.setStatusEmission(status)

    @staticmethod
    def readConfig(section):
        parser = RawConfigParser()
        if getattr(sys, 'frozen', False):
            # frozen
            parser.read(
                os.path.dirname(os.path.realpath(sys.executable)) + '/config')
        else:
            # unfrozen
            parser.read(
                os.path.dirname(os.path.realpath(__file__)) + '/config')

        return dict(parser.items(section))

    #Create menu bar
    def createMenu(self):
        self.menuBar()
        self.menuBar().setVisible(False)
        actionMenu = self.menuBar().addMenu('&Action')
        scanMusicFolderAction = QtGui.QAction('Scan Music Folder', self)
        showShortcutAction = QtGui.QAction('Show Shortcut', self)
        addFolderToLibraryAction = QtGui.QAction('Add Folder to Library', self)
        scanWaveformsAction = QtGui.QAction('Scan wave froms', self)
        #self.toggleRadioAction= QtGui.QAction('Switch to Radio mode',self)
        if not self.radio:
            self.toggleRadioAction = QtGui.QAction('Switch to Radio mode',
                                                   self)
        else:
            self.toggleRadioAction = QtGui.QAction('Switch to Library mode',
                                                   self)
        scanMusicFolderAction.triggered.connect(self.scanMusicFolder)
        actionMenu.addAction(scanMusicFolderAction)
        showShortcutAction.triggered.connect(self.showShortcut)
        actionMenu.addAction(showShortcutAction)
        addFolderToLibraryAction.triggered.connect(self.addFolderToLibrary)
        actionMenu.addAction(addFolderToLibraryAction)
        scanWaveformsAction.triggered.connect(self.scanWaveforms)
        actionMenu.addAction(scanWaveformsAction)
        self.toggleRadioAction.triggered.connect(self.toggleRadio)
        actionMenu.addAction(self.toggleRadioAction)

    # Menu Action 1
    def scanMusicFolder(self):
        thread = QtCore.QThread(self)
        thread.worker = WorkThread(
            Foo.readConfig('options')['music_folder'], False)
        thread.worker.moveToThread(thread)
        thread.started.connect(thread.worker.process)
        thread.worker.finished.connect(thread.quit)
        thread.worker.finished.connect(thread.worker.deleteLater)
        thread.finished.connect(thread.deleteLater)
        thread.finished.connect(self.tree.initUI)
        thread.start()

    # Menu Action 2
    def showShortcut(self):
        dictSC = Foo.readConfig('shortcuts')
        message = '''<b>''' + dictSC['modifier'] + '''+''' + dictSC[
            'stop'] + '''</b> : Stop<br/>''' + '''
		<b>''' + dictSC['modifier'] + '''+''' + dictSC['quit'] + '''</b> : Quit<br/>''' + '''
		<b>''' + dictSC['modifier'] + '''+''' + dictSC[
                'play_pause'] + '''</b> : Play/Pause    <br/>''' + '''
		<b>''' + dictSC['modifier'] + '''+''' + dictSC[
                    'previous'] + '''</b> : Previous<br/>''' + '''
		<b>''' + dictSC['modifier'] + '''+''' + dictSC['next'] + '''</b> : Next<br/>''' + '''
		<b>''' + dictSC['modifier'] + '''+''' + dictSC[
                        'volume_down'] + '''</b> : Volume down<br/>''' + '''
		<b>''' + dictSC['modifier'] + '''+''' + dictSC[
                            'volume_up'] + '''</b> : Volume up<br/>''' + '''
		<b>''' + dictSC['modifier'] + '''+''' + dictSC[
                                'radio_mode'] + '''</b> : Toggle radio mode<br/>''' + '''
		<b>''' + dictSC['modifier'] + '''+''' + dictSC[
                                    'equalizer'] + '''</b> : Equalizer<br/>'''
        print(len(self.findChildren(QtCore.QObject)))
        box = QMessageBox.about(self, 'About Shortcuts', message)
        print(len(self.findChildren(QtCore.QObject)))
        print('must delete')

    # Menu Action3
    # Must be subdirectory of music folder otherwise wont be rescanned
    def addFolderToLibrary(self):
        dir = QFileDialog.getExistingDirectory(
            None, "Open Directory",
            Foo.readConfig('options')['music_folder'], QFileDialog.ShowDirsOnly
            | QFileDialog.DontResolveSymlinks)
        thread = QtCore.QThread(self)
        thread.worker = WorkThread(dir, True)
        thread.worker.moveToThread(thread)
        thread.started.connect(thread.worker.process)
        thread.worker.finished.connect(thread.quit)
        thread.worker.finished.connect(thread.worker.deleteLater)
        thread.finished.connect(thread.deleteLater)
        thread.finished.connect(self.tree.initUI)
        thread.start()

    # Menu action 4
    def scanWaveforms(self):
        from wave import Wave
        thread = QtCore.QThread(self)
        thread.worker = Wave(Foo.readConfig('options')['music_folder'])
        thread.worker.moveToThread(thread)
        thread.started.connect(thread.worker.processScan)
        thread.worker.finished.connect(thread.quit)
        thread.worker.finished.connect(thread.worker.deleteLater)
        thread.finished.connect(thread.deleteLater)
        thread.finished.connect(self.tree.initUI)
        thread.start()

    # Menu Action5
    def toggleRadio(self):
        self.table.deleteLater()
        self.table.close()
        if not self.radio:
            configRadio = Foo.readConfig('radios')
            self.table = TableRadio(self.tree, configRadio)
            self.toggleRadioAction.setText('Switch to Library mode')
            self.radio = True
            self.player.playbin.disconnect(self.handlerATF)
            self.handlerT = self.player.bus.connect('message::tag',
                                                    self.table.onTag)
        else:
            config = Foo.readConfig('options')
            self.table = Table(self.tree, config)
            self.toggleRadioAction.setText('Switch to Radio mode')
            self.radio = False
            self.handlerATF = self.player.playbin.connect(
                "about-to-finish", self.onAboutToFinish)
            self.player.bus.disconnect(self.handlerT)

        self.splitterTopBottom.addWidget(self.table)
        # Since the frame is already attached to the splitter,
        # it only moves it to the new position
        self.splitterTopBottom.addWidget(self.infoFrame)
        self.table.runAction.connect(self.tableAction)
        self.setTabOrder(self.tree, self.table)
        self.splitterTopBottom.setStretchFactor(0, 10)
        #self.splitterTopBottom.setStretchFactor(3,1)

    @QtCore.pyqtSlot()
    def startSearch(self):
        input = self.searchArea.searchLine.text()

        db = thread.load()
        songList = []
        songGenerator = (Song(self.tree.comm, **dict) for dict in db)
        self.tree.model().removeRows(0, self.tree.model().rowCount())

        if self.searchArea.searchExact.isChecked():
            songList = [e for e in songGenerator if e.exactMatch(input)]
        elif self.searchArea.searchPrecise.isChecked():
            songList = [e for e in songGenerator if e.preciseMatch(input)]
        else:
            songList = [e for e in songGenerator if e.fuzzyMatch(input)]

        del db[:]
        songList.sort(key=self.tree.sortFunc)
        self.tree.populateTree(songList)

    @QtCore.pyqtSlot(str)
    def onHotKey(self, key):
        print('Hotkey was pressed', key)
        if key == 'quit':
            self.shortQuit.activated.emit()
        if key == 'stop':
            self.shortStop.activated.emit()
        if key == 'play_pause':
            self.shortPlayPause.activated.emit()
        if key == 'volume_up':
            self.shortVolUp.activated.emit()
        if key == 'volume_down':
            self.shortVolDown.activated.emit()
        if key == 'song_next':
            self.shortSongNext.activated.emit()
        if key == 'song_prev':
            self.shortSongPrev.activated.emit()
        if key == 'tree_up':
            if self.radio:
                self.table.keyPressEvent(
                    QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Up,
                                    Qt.KeyboardModifier(), ''))
            else:
                self.tree.keyPressEvent(
                    QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Up,
                                    Qt.KeyboardModifier(), ''))
        if key == 'tree_down':
            if self.radio:
                self.table.keyPressEvent(
                    QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Down,
                                    Qt.KeyboardModifier(), ''))
            else:
                self.tree.keyPressEvent(
                    QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Down,
                                    Qt.KeyboardModifier(), ''))
        if key == 'tree_left':
            if not self.radio:
                self.tree.keyPressEvent(
                    QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Left,
                                    Qt.KeyboardModifier(), ''))
        if key == 'tree_right':
            if not self.radio:
                self.tree.keyPressEvent(
                    QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Right,
                                    Qt.KeyboardModifier(), ''))
        if key == 'tree_validate':
            if self.radio:
                self.table.keyPressEvent(
                    QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Return,
                                    Qt.KeyboardModifier(), ''))
            else:
                self.tree.keyPressEvent(
                    QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Return,
                                    Qt.KeyboardModifier(), ''))
        if key == 'tree_append':
            if not self.radio:
                self.tree.keyPressEvent(
                    QtGui.QKeyEvent(
                        QtCore.QEvent.KeyPress, Qt.Key_Return,
                        Qt.KeyboardModifier(QtCore.Qt.ShiftModifier), ''))
        if key == 'radio_mode':
            self.shortRadioMode.activated.emit()

    def tmpTag(self, position):
        menu = QtGui.QMenu()
        tagging = QtGui.QAction('Tagging', self)
        replayGain = QtGui.QAction('ReplayGain', self)

        tagging.triggered.connect(self.openTagging)
        replayGain.triggered.connect(self.startReplayGain)
        menu.addAction(tagging)
        menu.addAction(replayGain)
        menu.exec_(self.tree.viewport().mapToGlobal(position))

    def startReplayGain(self):
        children = self.tree.getChildren()
        self.RG = ReplayGain([x['file'] for x in children])
        self.RG.exec_()

    def openTagging(self):
        children = self.tree.getChildren()
        #[7:] to drop the 'file://' appended for gstreamer
        retag = Retagging([x['file'][7:] for x in children])
        res = retag.exec_()
        if res:
            self.tree.initUI()
        print(res)

    def openEqualizer(self):
        from configparser import RawConfigParser
        equa = Equalizer(self, Foo.readConfig('audio'))
        equa.equalize.connect(self.applyEqua)
        if equa.exec_():
            parser = RawConfigParser()
            parser.read(
                os.path.dirname(os.path.realpath(__file__)) + '/config')
            parser['audio']['settings'] = str(equa.config)
            with open(
                    os.path.dirname(os.path.realpath(__file__)) + '/config',
                    'w') as configfile:
                parser.write(configfile)

    def applyEqua(self, band, value):
        print('receiving equa', str(band), value)
        if str(band) == 'band0' and value == 0:
            self.player.equalizer.set_property('band0', 0.01)
        else:
            self.player.equalizer.set_property(str(band), value)
Beispiel #3
0
class Foo(QtGui.QMainWindow):

	def __init__(self):
		super(Foo, self).__init__()
		self.initUI()
        
	def initUI(self):
		config = Foo.readConfig('options')
		self.timeOut = -1
		self.radio = False
		self.statusBar().showMessage('Ready')
		self.createMenu()
		self.setWindowTitle("Foo.cd")
        
		self.player = Player(Foo.readConfig('audio'))
		self.player.bus.connect('message::eos', self.stop)
		self.player.bus.connect('message::duration-changed', self.onDurationChanged)
		   
		self.tree = Tree(self, config['tree_order'])
		self.tree.addSongs.connect(self.addSongsFromTree)
		self.tree.customContextMenuRequested.connect(self.tmpTag)
		
		if not self.radio:
			self.table=Table( self, config)
			self.handlerATF = self.player.playbin.connect("about-to-finish", self.onAboutToFinish)   
			self.table.runAction.connect(self.tableAction)
		else:
			configRadio = Foo.readConfigRadios()
			self.table=TableRadio( self, configRadio)
			self.table.runAction.connect(self.tableAction)
			self.handlerT = self.player.bus.connect('message::tag', self.table.onTag)
		
		self.playbackButtons = PlaybackButtons(None)
		self.playbackButtons.buttonPlay.clicked.connect(self.toggleSong)
		self.playbackButtons.buttonStop.clicked.connect(self.stop)
		self.playbackButtons.buttonPrev.clicked.connect(self.previous)
		self.playbackButtons.buttonNext.clicked.connect(self.next)
		
		self.volumeSlider = VolumeSlider(self)
		self.volumeSlider.sliderMoved.connect(self.player.setVolume)
		self.scrollSlider = ScrollSlider(self)
		self.scrollSlider.sliderPressed.connect(self.player.toggle)
		self.scrollSlider.sliderReleased.connect(self.player.toggle)
		self.scrollSlider.sliderMoved.connect(self.player.seek)

		self.pixmap = Image(self, config['cover_names'], config['extensions'])
		
		# Album cover connections
		self.tree.selectionModel().selectionChanged.connect(lambda: self.pixmap.onSelectionChanged(self.tree.getChildren()[0].get('file', None)))
		self.table.selectionModel().selectionChanged.connect(lambda:  self.pixmap.onSelectionChanged(self.table.getSelection().get('file', None)))
		
		self.searchArea = SearchArea(self)
		self.searchArea.searchLine.returnPressed.connect(self.startSearch)	
		
		self.playbackButtons.addWidget(self.volumeSlider)
		self.playbackButtons.addWidget(self.scrollSlider)
		
		splitterLeftRight = QtGui.QSplitter()
		self.splitterTopBottom = QtGui.QSplitter(Qt.Vertical, self)
		
		self.infoFrame = QtGui.QFrame()
		infoLayout = QtGui.QVBoxLayout()
		infoLayout.setContentsMargins(0,0,0,0)
		infoLayout.addLayout(self.playbackButtons)
		infoLayout.addWidget(self.pixmap)
		self.infoFrame.setLayout(infoLayout)
		
		libLayout = QtGui.QVBoxLayout()
		libLayout.setContentsMargins(0,0,0,0)
		libLayout.addWidget(self.tree)
		libLayout.addLayout(self.searchArea)
		libFrame = QtGui.QFrame()
		libFrame.setLayout(libLayout)
		
		self.splitterTopBottom.addWidget(self.table)
		self.splitterTopBottom.addWidget(self.infoFrame)
		self.splitterTopBottom.setStretchFactor(0,1)
		#self.splitterTopBottom.setStretchFactor(1,0)

		splitterLeftRight.addWidget(libFrame)
		splitterLeftRight.addWidget(self.splitterTopBottom)
		splitterLeftRight.setStretchFactor(0,2)
		splitterLeftRight.setStretchFactor(1,3)

		mainLayout = QtGui.QGridLayout()
		mainLayout.setContentsMargins(4, 4, 4, 4)
		mainLayout.addWidget(splitterLeftRight)
		
		dummyWidget = QtGui.QWidget()
		dummyWidget.setLayout(mainLayout)  
		self.setCentralWidget(dummyWidget)
		
		self.setTabOrder(self.tree, self.table)

		dictShortcuts = self.readConfig('shortcuts')
		modifier = dictShortcuts['modifier']+'+'
		self.shortQuit = QtGui.QShortcut(QtGui.QKeySequence(modifier+dictShortcuts['quit']), self, self.close)
		self.shortStop = QtGui.QShortcut(QtGui.QKeySequence(modifier+dictShortcuts['stop']), self, self.stop)
		self.shortPlayPause = QtGui.QShortcut(QtGui.QKeySequence(modifier+dictShortcuts['play_pause']), self, self.toggleSong)
		self.shortSongPrevious = QtGui.QShortcut(QtGui.QKeySequence(modifier+dictShortcuts['previous']), self, self.previous)
		self.shortSongNext = QtGui.QShortcut(QtGui.QKeySequence(modifier+dictShortcuts['next']), self, self.next)
		self.shortVolDown = QtGui.QShortcut(QtGui.QKeySequence(modifier+dictShortcuts['volume_down']), self, self.volumeSlider.decr)
		self.shortVolUp = QtGui.QShortcut(QtGui.QKeySequence(modifier+dictShortcuts['volume_up']), self, self.volumeSlider.incr)
		self.shortRadioMode = QtGui.QShortcut(QtGui.QKeySequence(modifier+dictShortcuts['radio_mode']), self, self.toggleRadio)
		self.shortEqualizer = QtGui.QShortcut(QtGui.QKeySequence(modifier+dictShortcuts['equalizer']), self, self.openEqualizer)
		
		thread = QtCore.QThread(self)
		thread.worker = WorkThreadPipe()
		thread.worker.moveToThread(thread);
		thread.started.connect(thread.worker.process)
		thread.worker.hotKey.connect(self.onHotKey)
		thread.worker.finished.connect(thread.quit)
		thread.worker.finished.connect(thread.worker.deleteLater)
		thread.finished.connect(thread.deleteLater)
		thread.start()
			
		self.show()
	
	def keyReleaseEvent(self, event):
		if event.key() == Qt.Key_Alt:
			self.menuBar().setVisible(not self.menuBar().isVisible())
		else:
			QWidget.keyPressEvent(self, event)
		
	# Triggered by player end of stream event
	# or called by hand to stop the stream
	def stop(self, bus=None, msg=None):
		self.player.stop()
		self.scrollSlider.setValue(0)
		self.table.displayPlayToStop()
		self.stopStatusEmission('Ready')

	def previous(self):
		if self.table.playingId > 0:
			self.player.stop()
			self.table.playingId-=1
			self.player.add(self.table.model().item(self.table.playingId,0).data()['file'])
			self.player.play()
			
	def next(self):
		if self.table.model().rowCount()-1 > self.table.playingId:
			self.player.stop()
			self.table.playingId+=1
			self.player.add(self.table.model().item(self.table.playingId,0).data()['file'])
			self.player.play()
	
	def toggleSong(self):			
		state = self.player.playbin.get_state(Gst.State.NULL)
		if state[1] == Gst.State.PLAYING:
			self.table.displayPlayToPause()
			self.player.toggle()
			
			status = self.statusBar().currentMessage().replace('Playing', 'Paused')
			self.stopStatusEmission(status)	
		else:
			self.table.displayPauseToPlay(self.table.playingId)
			self.player.toggle()
			#self.onDurationChanged(0,0)
			status = self.table.getStatus()
			self.setStatusEmission(status)
			
	# Triggered by player when a song starts
	def onDurationChanged(self, bus, msg):
		self.table.displayNext()
		print('Duration changed signal !')
		filename = self.table.model().item(self.table.playingId,0).data()['file'][7:]
		data = wave.getDBData(filename)
		wave.createImg(data)
		self.scrollSlider.setStyleSheet("border-image: url(./wave.png)")
		

	# Triggered by player at the end of a song
	def onAboutToFinish(self, bus):
		if self.table.model().rowCount()-1 > self.table.playingId:
			print('About to finish !')
			self.table.playingId+=1
			self.player.add(self.table.model().item(self.table.playingId,0).data()['file'])

	def addSongsFromTree(self, list, play):
		if not self.radio:
			i = self.table.model().rowCount()
			for l in  list:
				self.table.addRow(l)
			self.table.resizeRowsToContents()
			if play:
				self.stop()
				self.player.add(list[0]['file'])
				self.player.play()
				self.table.displayStopToPlay(i)
				status = self.table.getStatus()
				self.setStatusEmission(status)
	
	def setStatusEmission(self, status):
		if self.timeOut > 0:
			GObject.source_remove(self.timeOut)
		self.timeOut =  GObject.timeout_add(1000, self.update, status)	
		
	def stopStatusEmission(self, status):
		if self.timeOut > 0:
			GObject.source_remove(self.timeOut)
		self.timeOut = GObject.timeout_add(0, self.update, status)
		self.timeOut=-1
	
	def update(self, status):
		print('.')
		try:
			duration_nanosecs = self.player.getDuration()
			duration = float(duration_nanosecs) / 1000000000
			self.scrollSlider.setRange(0, duration)
			
			nanosecs = self.player.getPosition()
			position = float(nanosecs) // 1000000000	
			self.scrollSlider.setValue(position)
			m, s = divmod(position, 60)
			self.statusBar().showMessage(status.replace('%',"%02d:%02d" % (m, s)))
		except Exception as e:
			print(e)
			pass	
		if 'Playing' in status:
			return True
		else:
			return False


	def tableAction(self, str):
		if str == 'stop':
			self.stop()
		elif str == 'play':
			if self.table.selectedIndexes():
				index = self.table.selectedIndexes()[0]
			else:
				index= self.table.model().index(self.table.selectionModel().currentIndex().row(),0)
			songURI = index.model().itemFromIndex(index).data()['file']
			
			self.player.stop()
			self.player.add(songURI)
			self.player.play()
			self.table.displayStopToPlay(index.row())
			status = self.table.getStatus()
			self.setStatusEmission(status)
			
	@staticmethod
	def readConfig(section):
		parser = RawConfigParser()
		if getattr(sys, 'frozen', False):
			# frozen
			parser.read(os.path.dirname(os.path.realpath(sys.executable))+'/config')
		else:
			# unfrozen
			parser.read(os.path.dirname(os.path.realpath(__file__))+'/config')
		
		return dict(parser.items(section))

	#Create menu bar
	def createMenu(self):
		self.menuBar()
		self.menuBar().setVisible(False)
		actionMenu = self.menuBar().addMenu('&Action')
		scanMusicFolderAction = QtGui.QAction('Scan Music Folder', self) 
		showShortcutAction = QtGui.QAction('Show Shortcut',self)
		addFolderToLibraryAction = QtGui.QAction('Add Folder to Library',self)
		scanWaveformsAction = QtGui.QAction('Scan wave froms',self)
		#self.toggleRadioAction= QtGui.QAction('Switch to Radio mode',self)
		if not self.radio: 
			self.toggleRadioAction= QtGui.QAction('Switch to Radio mode',self)
		else:
			self.toggleRadioAction= QtGui.QAction('Switch to Library mode',self)
		scanMusicFolderAction.triggered.connect(self.scanMusicFolder)
		actionMenu.addAction(scanMusicFolderAction)
		showShortcutAction.triggered.connect(self.showShortcut)
		actionMenu.addAction(showShortcutAction)
		addFolderToLibraryAction.triggered.connect(self.addFolderToLibrary)
		actionMenu.addAction(addFolderToLibraryAction)
		scanWaveformsAction.triggered.connect(self.scanWaveforms)
		actionMenu.addAction(scanWaveformsAction)
		self.toggleRadioAction.triggered.connect(self.toggleRadio)
		actionMenu.addAction(self.toggleRadioAction)
		
		
	# Menu Action 1
	def scanMusicFolder(self):
		thread = QtCore.QThread(self)
		thread.worker = WorkThread(Foo.readConfig('options')['music_folder'], False)
		thread.worker.moveToThread(thread)
		thread.started.connect(thread.worker.process)
		thread.worker.finished.connect(thread.quit)
		thread.worker.finished.connect(thread.worker.deleteLater)
		thread.finished.connect(thread.deleteLater)
		thread.finished.connect(self.tree.initUI)
		thread.start()
		
	# Menu Action 2
	def showShortcut(self):
		dictSC = Foo.readConfig('shortcuts')
		message = '''<b>'''+dictSC['modifier']+'''+'''+dictSC['stop']+'''</b> : Stop<br/>''' + '''
		<b>'''+dictSC['modifier']+'''+'''+dictSC['quit']+'''</b> : Quit<br/>''' + '''
		<b>'''+dictSC['modifier']+'''+'''+dictSC['play_pause']+'''</b> : Play/Pause    <br/>''' + '''
		<b>'''+dictSC['modifier']+'''+'''+dictSC['previous']+'''</b> : Previous<br/>''' + '''
		<b>'''+dictSC['modifier']+'''+'''+dictSC['next']+'''</b> : Next<br/>''' + '''
		<b>'''+dictSC['modifier']+'''+'''+dictSC['volume_down']+'''</b> : Volume down<br/>''' + '''
		<b>'''+dictSC['modifier']+'''+'''+dictSC['volume_up']+'''</b> : Volume up<br/>''' + '''
		<b>'''+dictSC['modifier']+'''+'''+dictSC['radio_mode']+'''</b> : Toggle radio mode<br/>''' + '''
		<b>'''+dictSC['modifier']+'''+'''+dictSC['equalizer']+'''</b> : Equalizer<br/>'''
		print(len(self.findChildren(QtCore.QObject)))
		box = QMessageBox.about(self, 'About Shortcuts',
		message)
		print(len(self.findChildren(QtCore.QObject)))
		print('must delete')

	# Menu Action3
	# Must be subdirectory of music folder otherwise wont be rescanned
	def addFolderToLibrary(self):
		dir = QFileDialog.getExistingDirectory(None,
				"Open Directory",
				Foo.readConfig('options')['music_folder'],
				QFileDialog.ShowDirsOnly
				| QFileDialog.DontResolveSymlinks)		
		thread = QtCore.QThread(self)
		thread.worker = WorkThread(dir, True)
		thread.worker.moveToThread(thread)
		thread.started.connect(thread.worker.process)
		thread.worker.finished.connect(thread.quit)
		thread.worker.finished.connect(thread.worker.deleteLater)
		thread.finished.connect(thread.deleteLater)
		thread.finished.connect(self.tree.initUI)
		thread.start()
		
	# Menu action 4
	def scanWaveforms(self):
		from wave import Wave
		thread = QtCore.QThread(self)
		thread.worker = Wave(Foo.readConfig('options')['music_folder'])
		thread.worker.moveToThread(thread)
		thread.started.connect(thread.worker.processScan)
		thread.worker.finished.connect(thread.quit)
		thread.worker.finished.connect(thread.worker.deleteLater)
		thread.finished.connect(thread.deleteLater)
		thread.finished.connect(self.tree.initUI)
		thread.start()
	
	# Menu Action5
	def toggleRadio(self):
		self.table.deleteLater()
		self.table.close()
		if not self.radio:
			configRadio = Foo.readConfig('radios')
			self.table=TableRadio(self.tree, configRadio)
			self.toggleRadioAction.setText('Switch to Library mode')
			self.radio=True
			self.player.playbin.disconnect(self.handlerATF)
			self.handlerT=self.player.bus.connect('message::tag', self.table.onTag)		
		else:
			config = Foo.readConfig('options')
			self.table=Table( self.tree, config)
			self.toggleRadioAction.setText('Switch to Radio mode')
			self.radio=False
			self.handlerATF = self.player.playbin.connect("about-to-finish",self.onAboutToFinish)
			self.player.bus.disconnect(self.handlerT)

		self.splitterTopBottom.addWidget(self.table)
		# Since the frame is already attached to the splitter, 
		# it only moves it to the new position
		self.splitterTopBottom.addWidget(self.infoFrame)
		self.table.runAction.connect(self.tableAction)
		self.setTabOrder(self.tree, self.table)
		self.splitterTopBottom.setStretchFactor(0,10)
		#self.splitterTopBottom.setStretchFactor(3,1)
		
	@QtCore.pyqtSlot()
	def startSearch(self):
		input = self.searchArea.searchLine.text()
		
		db = thread.load()
		songList = []
		songGenerator = (Song(self.tree.comm, **dict) for dict in db)
		self.tree.model().removeRows(0, self.tree.model().rowCount())
		
		if self.searchArea.searchExact.isChecked():
			songList = [ e for e in songGenerator if e.exactMatch(input) ]
		elif self.searchArea.searchPrecise.isChecked():
			songList = [ e for e in songGenerator if e.preciseMatch(input) ]
		else:
			songList = [ e for e in songGenerator if e.fuzzyMatch(input) ]	
		
		del db[:]
		songList.sort(key=self.tree.sortFunc)
		self.tree.populateTree(songList)
		
	@QtCore.pyqtSlot(str)
	def onHotKey(self, key):
		print('Hotkey was pressed', key)
		if key == 'quit':
			self.shortQuit.activated.emit()
		if key == 'stop':
			self.shortStop.activated.emit()
		if key == 'play_pause':
			self.shortPlayPause.activated.emit()
		if key == 'volume_up':
			self.shortVolUp.activated.emit()
		if key == 'volume_down':
			self.shortVolDown.activated.emit()
		if key == 'song_next':
			self.shortSongNext.activated.emit()
		if key == 'song_prev':
			self.shortSongPrev.activated.emit()
		if key == 'tree_up':
			if self.radio:
				self.table.keyPressEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Up, Qt.KeyboardModifier(), ''))
			else:
				self.tree.keyPressEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Up, Qt.KeyboardModifier(), ''))
		if key == 'tree_down':
			if self.radio:
				self.table.keyPressEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Down, Qt.KeyboardModifier(), ''))
			else:
				self.tree.keyPressEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Down, Qt.KeyboardModifier(), ''))
		if key == 'tree_left':
			if not self.radio:
				self.tree.keyPressEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Left, Qt.KeyboardModifier(), ''))
		if key == 'tree_right':
			if not self.radio:
				self.tree.keyPressEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Right, Qt.KeyboardModifier(), ''))
		if key == 'tree_validate':
			if self.radio:
				self.table.keyPressEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Return, Qt.KeyboardModifier(), ''))
			else:
				self.tree.keyPressEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Return, Qt.KeyboardModifier(), ''))
		if key == 'tree_append':
			if not self.radio:
				self.tree.keyPressEvent(QtGui.QKeyEvent(QtCore.QEvent.KeyPress, Qt.Key_Return, Qt.KeyboardModifier(QtCore.Qt.ShiftModifier), ''))
		if key == 'radio_mode':
			self.shortRadioMode.activated.emit()

	def tmpTag(self, position):
		menu = QtGui.QMenu()
		tagging = QtGui.QAction('Tagging',self)
		replayGain = QtGui.QAction('ReplayGain',self)
		
		tagging.triggered.connect(self.openTagging)
		replayGain.triggered.connect(self.startReplayGain)
		menu.addAction(tagging)
		menu.addAction(replayGain)
		menu.exec_(self.tree.viewport().mapToGlobal(position))

	def startReplayGain(self):
		children = self.tree.getChildren()
		self.RG = ReplayGain([x['file'] for x in children])
		self.RG.exec_()
	
	def openTagging(self):
		children = self.tree.getChildren()
		#[7:] to drop the 'file://' appended for gstreamer
		retag = Retagging([x['file'][7:] for x in children])
		res = retag.exec_()
		if res:
			self.tree.initUI()
		print(res)
	
	def openEqualizer(self):
		from configparser import RawConfigParser
		equa = Equalizer(self, Foo.readConfig('audio'))
		equa.equalize.connect(self.applyEqua)
		if equa.exec_():
			parser = RawConfigParser()
			parser.read(os.path.dirname(os.path.realpath(__file__))+'/config')
			parser['audio']['settings']= str(equa.config)
			with open(os.path.dirname(os.path.realpath(__file__))+'/config', 'w') as configfile:
				parser.write(configfile)
		
	def applyEqua(self,band, value):
		print('receiving equa', str(band), value)
		if str(band) == 'band0' and value == 0:
			self.player.equalizer.set_property('band0', 0.01)
		else:
			self.player.equalizer.set_property(str(band), value)
Beispiel #4
0
class TestTree(unittest.TestCase):
    def setUp(self):
        self.root = Tree(NAME)
        self.tree2 = None
        self.tree3 = None
        self.tree4 = None

    def _AddChild(self, name):
        new_tree = Tree(name)
        self.root.addChild(new_tree)
        return new_tree

    def _createComplexTree(self, root_name=NAME):
        """
    Creates the following tree
      NAME1
        NAME2
          NAME4
        NAME3
    :param str root_name: name of the root node
    """
        self.tree2 = self._AddChild(NAME2)
        self.tree3 = self._AddChild(NAME3)
        self.tree4 = Tree(NAME4)
        self.tree2.addChild(self.tree4)
        self.root.setName(root_name)

    def testConstructor(self):
        if IGNORE_TEST:
            return
        self.assertEqual(self.root._name, NAME)
        self.assertEqual(len(self.root._children), 0)

    def testAddChild(self):
        if IGNORE_TEST:
            return
        new_tree = self._AddChild(NAME2)
        self.assertEqual(len(self.root._children), 1)
        self.assertEqual(self.root._children[0], new_tree)
        newer_tree = self._AddChild(NAME3)
        self.assertEqual(len(self.root._children), 2)
        self.assertEqual(self.root._children[1], newer_tree)

    def testAddChildComplex(self):
        if IGNORE_TEST:
            return
        self._createComplexTree()
        self.assertTrue(self.tree4 in self.tree2.getChildren())

    def testGetAllNodes(self):
        """
      NAME1->NAME2->NAME4
      NAME1->NAME3
    """
        if IGNORE_TEST:
            return
        root = Tree(NEW_NAME)
        nodes = root.getAllNodes()
        self.assertEqual(len(nodes), 1)
        self.assertEqual(nodes[0]._name, NEW_NAME)
        self._createComplexTree()
        names = [n._name for n in self.root.getAllNodes()]
        _verifyComplexTreeDepthFirstList(names, root_name=NAME)

    def testRemoveChildSimple(self):
        if IGNORE_TEST:
            return
        new_tree = self._AddChild(NAME2)
        new_tree.removeTree()
        self.assertIsNone(new_tree._parent)
        self.assertEqual(len(self.root._children), 0)

    def testRemoveChildComplex(self):
        if IGNORE_TEST:
            return
        self._createComplexTree()
        self.tree4.removeTree()
        self.assertIsNone(self.tree4._parent)
        self.assertEqual(len(self.tree2._children), 0)
        self.assertEqual(len(self.root._children), 2)

    def testGetRoot(self):
        if IGNORE_TEST:
            return
        self._createComplexTree()
        self.assertEqual(self.tree2._children[0], self.tree4)
        root = self.tree4.getRoot()
        self.assertEqual(root, self.root)
        root = self.root.getRoot()
        self.assertEqual(root, self.root)
        root = self.tree3.getRoot()
        self.assertEqual(root, self.root)

    def testGetChildrenFromRoot(self):
        if IGNORE_TEST:
            return
        self._createComplexTree()
        children = self.tree2.getChildren(is_from_root=False)
        self.assertEqual(children, [self.tree4])
        children = self.tree4.getChildren(is_from_root=True, is_recursive=True)
        self.assertEqual(len(children), 3)
        self.assertFalse(self.root in children)
        self.assertTrue(self.tree2 in children)
        self.assertTrue(self.tree4 in children)

    def testGetChildrenFromSelf(self):
        """
    NAME1:
      NAME2
        NAME4
          NAME4.1
          NAME4.2
      NAME3
    """
        if IGNORE_TEST:
            return
        self._createComplexTree()
        self.tree4.addChild(Tree(NAME4 + ".1"))
        self.tree4.addChild(Tree(NAME4 + ".2"))
        children = self.tree2.getChildren(is_from_root=False,
                                          is_recursive=True)
        grandchildren = self.tree4.getChildren(is_from_root=False)
        self.assertEqual(len(children), 3)
        self.assertEqual(len(grandchildren), 2)
        self.assertTrue(self.tree4 in children)

    def testFindPathFromRoot(self):
        if IGNORE_TEST:
            return
        self._createComplexTree()
        path = self.tree2.findPathFromRoot()
        self.assertEqual(path, [NAME, NAME2])
        path = self.tree4.findPathFromRoot()
        self.assertEqual(path, [NAME, NAME2, NAME4])

    def testFindName(self):
        if IGNORE_TEST:
            return
        self._createComplexTree()
        trees = self.tree2.findChildrenWithName(NAME3, is_from_root=True)
        self.assertEqual(trees, [self.tree3])
        trees = self.tree2.findChildrenWithName(NAME3, is_from_root=False)
        self.assertEqual(trees, [])

    def _checkNodeLists(self, list1, list2):
        names1 = [l.getName() for l in list1]
        names2 = [l.getName() for l in list2]
        return set(names1) == set(names2)

    def testGetLeaves(self):
        if IGNORE_TEST:
            return
        self._createComplexTree()
        leaves = self.tree2.getLeaves(is_from_root=True)
        self.assertTrue(self._checkNodeLists(leaves, [self.tree3, self.tree4]))
        leaves = self.tree2.getLeaves(is_from_root=False)
        self.assertTrue(self._checkNodeLists(leaves, [self.tree4]))

    def testToString(self):
        if IGNORE_TEST:
            return
        self._createComplexTree()
        self.root.setName(NEW_NAME)
        print_string = self.root.toString()
        _verifyComplexTreeDepthFirstList(print_string)

    def testIsAlwaysLeaf(self):
        if IGNORE_TEST:
            return
        self._createComplexTree()
        self.assertFalse(self.tree2.isAlwaysLeaf())

    def testCopy(self):
        if IGNORE_TEST:
            return
        self._createComplexTree()
        new_tree = self.root.copy()
        self.assertTrue(self.root.isEquivalent(new_tree))

    def testComplexCopy(self):
        if IGNORE_TEST:
            return
        tree = Tree.createRandomTree(100, 0.8)
        new_tree = tree.copy()
        self.assertTrue(tree.isEquivalent(new_tree))

    def testGetReverseOrderListOfNodes(self):
        if IGNORE_TEST:
            return
        self._createComplexTree()
        reverse_nodes = self.root.getReverseOrderListOfNodes()
        forward_nodes = [n for n in self.root]
        forward_nodes.reverse()
        self.assertEqual(forward_nodes, reverse_nodes)

    def _testRandomTrees(self,
                         leaf_cls=None,
                         nonleaf_cls=None,
                         tree_test=lambda x: True):
        num_nodes = [3, 100, 20, 1]
        branching_probabilities = [0.5, 0.2, 0.8]
        for nn in num_nodes:
            for pp in branching_probabilities:
                tree = Tree.createRandomTree(nn,
                                             pp,
                                             seed=0.3,
                                             leaf_cls=leaf_cls,
                                             nonleaf_cls=nonleaf_cls)
                nodes = [n for n in tree]
                diff = abs(len(nodes) - nn)
                if diff > 1:
                    import pdb
                    pdb.set_trace()
                self.assertTrue(diff < 2)
                if not tree_test(tree):
                    import pdb
                    pdb.set_trace()
                self.assertTrue(tree_test(tree))

    def testRandomTrees(self):
        if IGNORE_TEST:
            return
        self._testRandomTrees()

    def testGetUniqueName(self):
        if IGNORE_TEST:
            return
        self._createComplexTree()
        unique_name = self.tree4.getUniqueName()
        self.assertEqual(unique_name, 'NAME1.NAME2.NAME4')

    def testGetChldrenAsDict(self):
        if IGNORE_TEST:
            return
        self._createComplexTree()
        children_dict = self.root.getChildrenBreadthFirst()
        self.assertEqual(children_dict["node"], self.root)
        self.assertEqual(len(children_dict["children"]), 2)
        #
        children_dict = self.root.getChildrenBreadthFirst(
            excludes=[self.tree2])
        self.assertEqual(children_dict["node"], self.root)
        self.assertEqual(len(children_dict["children"]), 1)
        #
        children_dict = self.root.getChildrenBreadthFirst(
            includes=[self.root, self.tree2])
        self.assertEqual(children_dict["node"], self.root)
        self.assertEqual(len(children_dict["children"]), 1)
        #
        children_dict = self.root.getChildrenBreadthFirst(
            includes=[self.tree2])
        self.assertEqual(len(children_dict.keys()), 0)

    def testGetAttachedNodes(self):
        """
      NAME1
        NAME2
          NAME4
        NAME3
    """
        if IGNORE_TEST:
            return
        # All leaves
        self._createComplexTree()
        all_leaves = self.root.getLeaves()
        leaves = self.root.getAttachedNodes(all_leaves)
        self.assertEqual(set(leaves), set([self.tree4, self.tree3]))
        # Eliminate NAME4
        self.tree2.setIsAttached(False)
        leaves = self.root.getAttachedNodes(all_leaves)
        self.assertEqual(leaves, [self.tree3])
        # Detaching the root shouldn't matter
        self.root.setIsAttached(False)
        leaves = self.root.getAttachedNodes(all_leaves)
        self.assertEqual(leaves, [self.tree3])
Beispiel #5
0
class TestTree(unittest.TestCase):

  
  def setUp(self):
    self.root = Tree(NAME)
    self.tree2 = None
    self.tree3 = None
    self.tree4 = None

  def _AddChild(self, name):
    new_tree = Tree(name)
    self.root.addChild(new_tree)
    return new_tree

  def _createComplexTree(self):
    """
    Creates the following tree
      NAME1->NAME2->NAME4
      NAME1->NAME3
    """
    self.tree2 = self._AddChild(NAME2)
    self.tree3 = self._AddChild(NAME3)
    self.tree4 = Tree(NAME4)
    self.tree2.addChild(self.tree4)

  def testConstructor(self):
    if IGNORE_TEST:
      return
    self.assertEqual(self.root._name, NAME)
    self.assertEqual(len(self.root._children), 0)

  def testAddChild(self):
    if IGNORE_TEST:
      return
    new_tree = self._AddChild(NAME2)
    self.assertEqual(len(self.root._children), 1)
    self.assertEqual(self.root._children[0], new_tree)
    newer_tree = self._AddChild(NAME3)
    self.assertEqual(len(self.root._children), 2)
    self.assertEqual(self.root._children[1], newer_tree)

  def testAddChildComplex(self):
    if IGNORE_TEST:
      return
    self._createComplexTree()
    self.assertTrue(self.tree4 in self.tree2.getChildren())

  def testRemoveChildSimple(self):
    if IGNORE_TEST:
      return
    new_tree = self._AddChild(NAME2)
    new_tree.removeTree()
    self.assertIsNone(new_tree._parent)
    self.assertEqual(len(self.root._children), 0)

  def testRemoveChildComplex(self):
    if IGNORE_TEST:
      return
    self._createComplexTree()
    self.tree4.removeTree()
    self.assertIsNone(self.tree4._parent)
    self.assertEqual(len(self.tree2._children), 0)
    self.assertEqual(len(self.root._children), 2)

  def testGetRoot(self):
    if IGNORE_TEST:
      return
    self._createComplexTree()
    self.assertEqual(self.tree2._children[0], self.tree4)
    root = self.tree4.getRoot()
    self.assertEqual(root, self.root)
    root = self.root.getRoot()
    self.assertEqual(root, self.root)
    root = self.tree3.getRoot()
    self.assertEqual(root, self.root)

  def testGetChildrenFromRoot(self):
    if IGNORE_TEST:
      return
    self._createComplexTree()
    children = self.tree2.getChildren(is_from_root=False)
    self.assertEqual(children, [self.tree4])
    children = self.tree4.getChildren(is_from_root=True, 
        is_recursive=True)
    self.assertEqual(len(children), 3)
    self.assertFalse(self.root in children)
    self.assertTrue(self.tree2 in children)
    self.assertTrue(self.tree4 in children)

  def testGetChildrenFromSelf(self):
    if IGNORE_TEST:
      return
    self._createComplexTree()
    children = self.tree2.getChildren(is_from_root=False)
    grandchildren = self.tree4.getChildren(is_from_root=False)
    self.assertEqual(len(children), 1)
    self.assertEqual(len(grandchildren), 0)
    self.assertTrue(self.tree4 in children)

  def testFindPathFromRoot(self):
    if IGNORE_TEST:
      return
    self._createComplexTree()
    path = self.tree2.findPathFromRoot()
    self.assertEqual(path, [NAME, NAME2])
    path = self.tree4.findPathFromRoot()
    self.assertEqual(path, [NAME, NAME2, NAME4])

  def testFindName(self):
    if IGNORE_TEST:
      return
    self._createComplexTree()
    trees = self.tree2.findChildrenWithName(NAME3, is_from_root=True)
    self.assertEqual(trees, [self.tree3])
    trees = self.tree2.findChildrenWithName(NAME3, is_from_root=False)
    self.assertEqual(trees, [])

  def _checkNodeLists(self, list1, list2):
    names1 = [l.getName() for l in list1]
    names2 = [l.getName() for l in list2]
    return set(names1) == set(names2)

  def testGetLeaves(self):
    if IGNORE_TEST:
      return
    self._createComplexTree()
    leaves = self.tree2.getLeaves(is_from_root=True)
    self.assertTrue(self._checkNodeLists(leaves, [self.tree3, self.tree4]))
    leaves = self.tree2.getLeaves(is_from_root=False)
    self.assertTrue(self._checkNodeLists(leaves, [self.tree4]))

  def testToString(self):
    if IGNORE_TEST:
      return
    self._createComplexTree()
    print_string = self.root.toString()
    self.assertTrue("%s->%s" % (NAME, NAME3) in print_string)
    self.assertTrue("%s->%s" % (NAME, NAME2) in print_string)
    self.assertTrue("%s->%s" % (NAME2, NAME4) in print_string)

  def testIsAlwaysLeaf(self):
    if IGNORE_TEST:
      return
    self._createComplexTree()
    self.assertFalse(self.tree2.isAlwaysLeaf())

  def testCopy(self):
    if IGNORE_TEST:
      return
    new_tree = self.root.copy()
    self.assertTrue(self.root.isEquivalent(new_tree))
Beispiel #6
0
    if menu_input == str(1):
        # Fresh output
        output = []
        name_to_search = input("Enter name to find\n")
        output.extend(tree.searchName(name_to_search))
        tree.displayInfo(output)

    elif menu_input == str(2):
        name_to_search = input("Enter name to find father\n")
        output.append(tree.findRelativeOf(name_to_search, "father"))
        tree.displayInfo(output)

    elif menu_input == str(3):
        name_to_search = input("Enter name to find mother\n")
        output.append(tree.findRelativeOf(name_to_search, "mother"))
        tree.displayInfo(output)

    elif menu_input == str(4):
        name_to_search = input("Enter name to find children\n")
        output.extend(tree.getChildren(name_to_search))
        tree.displayInfo(output)

    elif menu_input == str(5):
        break

    else:
        print("Choose a valid option")

    os.system("clear")