コード例 #1
0
ファイル: main.py プロジェクト: augfab/Foo.cd
	def addFolderToLibrary(self):
		dir = QFileDialog.getExistingDirectory(None,
				"Open Directory",
				Foo.readConfig('options')['music_folder'],
				QFileDialog.ShowDirsOnly
				| QFileDialog.DontResolveSymlinks)
		self.thread = WorkThread(dir, True)
		self.thread.finished.connect(self.tree.initUI)
		self.thread.start()
コード例 #2
0
ファイル: main.py プロジェクト: newmonade/Foo.cd
 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()
コード例 #3
0
    def train_model1(self):
        if self.Data.columns[0] != 'date':
            self.label_current_message.setText(
                '請確認資料欄位名稱,第一個欄位為date,且格式為yyyy/mm/dd或yyyy-mm-dd')
        else:
            self.label_current_message.setText('模型計算中,請稍後...')
            self.Data.loc[:, 'date'] = pd.to_datetime(self.Data.loc[:, 'date'])
            self.Data = self.Data.sort_values('date')
            self.column_name = self.Data.columns[1:]
            # self.p_range, self.d_range, self.q_range = range(0, 4), range(0, 2), range(0, 4)###############
            pdq, self.column_model_dict = list(
                itertools.product(self.p_range, self.d_range,
                                  self.q_range)), {}
            self.value_bar = 0
            self.bar_upload.setValue(self.value_bar)

            # TODO: new threadl class.
            self.work = WorkThread(self.Data, self.column_name, pdq,
                                   self.model, self.model_fit)
            self.work.start()
            self.work.processbar_trigger.connect(self.set_processbar_value)
            self.work.result_trigger.connect(self.complete_slot)
コード例 #4
0
ファイル: main.py プロジェクト: newmonade/Foo.cd
 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()
コード例 #5
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        # 設定持續使用的變數
        self.Data = None  # 輸入資料
        self.column_name = None  # 輸入資料需要建立模型的變數名稱
        self.model = None  # 未訓練的模型,只有參數
        self.column_model_dict = None
        self.worker = None
        self.model_fit = None  # 已訓練的模型
        self.result = None  # 訓練預測結果整理
        self.value_bar = 0
        self.p_range, self.d_range, self.q_range = range(0, 7), range(
            0, 3), range(0, 7)

        #【設定初始化,UI標題與視窗大小】
        self.setWindowTitle('Marketing model ver 1.0')
        self.setWindowIcon(QIcon("favicon.ico"))
        self.resize(QSize(1300, 950))

        #【設定UI中的元件】
        # 按鍵顯示
        self.btn_upload_csv = QPushButton('載入csv資料')
        self.btn_run_model = QPushButton('執行預測')
        self.btn_run_break = QPushButton('動作中斷')
        self.btn_download_result = QPushButton('下載預測結果')
        # 字元顯示
        self.label_maintitle = QLabel('銷售模型預測程式')
        self.label_upload_filename = QLabel()  # 如果一開始沒有要設定內容,可直接設定初始為空白
        self.label_input_data = QLabel('輸入資料')
        self.label_output_plot = QLabel('預測結果折線圖')
        self.label_output_data = QLabel('預測兩期結果')
        self.label_current_message = QLabel('')
        # self.version_number = QLabel('V1.0')
        # 進度條顯示
        self.bar_upload = QProgressBar()
        # 表格顯示
        self.table_input_data = QTableView()
        self.table_output_data = QTableView()
        # 圖片顯示
        self.plot_output_result = MplWidget()
        ### 字型設定
        self.label_maintitle.setStyleSheet(
            "QLabel{font-family: Microsoft JhengHei; color: rgb(0, 0, 0); font-size: 15pt; font-weight: bold;}"
        )
        self.label_input_data.setStyleSheet(
            "QLabel{font-family: Microsoft JhengHei; color: rgb(0, 0, 0); font-size: 12pt; font-weight: bold;}"
        )
        self.label_output_plot.setStyleSheet(
            "QLabel{font-family: Microsoft JhengHei; color: rgb(0, 0, 0); font-size: 12pt; font-weight: bold;}"
        )
        self.label_output_data.setStyleSheet(
            "QLabel{font-family: Microsoft JhengHei; color: rgb(0, 0, 0); font-size: 12pt; font-weight: bold;}"
        )
        self.label_upload_filename.setStyleSheet(
            "QLabel{font-family: Microsoft JhengHei; color: rgb(0, 0, 0); font-size: 9pt}"
        )
        self.label_current_message.setStyleSheet(
            "QLabel{font-family: Microsoft JhengHei; color: rgb(0, 0, 0); font-size: 10pt;}"
        )
        self.label_upload_filename.setWordWrap(True)  # 自動換行
        self.label_current_message.setWordWrap(True)
        ### 按鍵字元設定
        self.btn_upload_csv.setStyleSheet(
            "QPushButton{font-family: Microsoft JhengHei;}")
        self.btn_run_model.setStyleSheet(
            "QPushButton{font-family: Microsoft JhengHei;}")
        self.btn_run_break.setStyleSheet(
            "QPushButton{font-family: Microsoft JhengHei;}")
        self.btn_download_result.setStyleSheet(
            "QPushButton{font-family: Microsoft JhengHei;}")

        ### 進度條設定
        self.bar_upload.setRange(0, 4)
        self.bar_upload.setValue(0)
        self.bar_upload.setStyleSheet("""
            QProgressBar{
                font-family: Microsoft JhengHei; 
                background-color: rgb(255, 230, 204); 
                text-align: center;
                } 
            QProgressBar::chunk{
                background-color: rgb(230, 132, 0);
                }
            """)
        ### 表格大小設定
        self.table_input_data.horizontalHeader().setSectionResizeMode(
            QHeaderView.ResizeToContents)  # 把顯示表格的寬調整到最小
        self.table_output_data.setMinimumHeight(105)  # 設定顯示的最小高度
        self.table_output_data.setMaximumHeight(110)  # 設定顯示的最大高度
        ### 圖片大小設定
        self.plot_output_result.setMinimumHeight(475)

        #【設定佈局(layout)】
        # main layout
        layout = QHBoxLayout(
        )  # 建立layout並指定layout為水平切分 # 建立layout之後要定義一個widget讓layout設定進去(註*1)

        # left layout
        left_layout = QVBoxLayout()  # 設定此layout為垂直切分
        left_layout.addWidget(self.label_maintitle)  # 建立layout之後就可以塞元件了
        left_layout.addWidget(self.btn_upload_csv)
        left_layout.addWidget(self.bar_upload)
        left_layout.addWidget(self.label_upload_filename)
        left_layout.addWidget(self.label_input_data)
        left_layout.addWidget(self.table_input_data)
        left_widget = QWidget()
        left_widget.setLayout(
            left_layout)  # 建立left layout的widget(參考main layout的註*1)

        # right layout
        right_layout = QVBoxLayout()
        right_layout.addWidget(self.label_output_plot)
        right_layout.addWidget(self.plot_output_result)
        right_layout.addWidget(self.label_output_data)
        right_layout.addWidget(self.table_output_data)
        # 在right layout裡面加入一個水平切分的子layout
        run_output_layout = QHBoxLayout()  ###
        run_output_layout.addWidget(self.btn_run_model)
        run_output_layout.addWidget(self.btn_run_break)
        run_output_layout.addWidget(self.btn_download_result)
        run_output_widget = QWidget()
        run_output_widget.setLayout(run_output_layout)  # 子layout收尾成widget
        run_process_layout = QHBoxLayout()  ###
        run_process_layout.addWidget(self.label_current_message)
        run_process_layout.addWidget(self.bar_upload)
        # run_process_layout.addWidget(self.version_number)
        run_process_layout.setStretchFactor(self.label_current_message, 3)
        run_process_layout.setStretchFactor(self.bar_upload, 2)
        # run_process_layout.setStretchFactor(self.version_number, 1)
        run_process_widget = QWidget()
        run_process_widget.setLayout(run_process_layout)  # 子layout收尾成widget
        right_layout.addWidget(
            run_output_widget
        )  # 在right_layout加入run_output_widget與run_process_widget
        right_layout.addWidget(run_process_widget)

        right_widget = QWidget()
        right_widget.setLayout(right_layout)  # 建立right layout的widget

        layout.addWidget(
            left_widget)  # 設定好left與right layout的widget之後加入在main layout
        layout.addWidget(right_widget)
        layout.setStretchFactor(left_widget,
                                1)  # 設定left_widget與right_widget的比例
        layout.setStretchFactor(right_widget, 3)
        main_widget = QWidget()  # (註*1)每一次建layout後要用widget包
        main_widget.setLayout(layout)  # (註*1)每一次建layout後要用widget包
        self.setCentralWidget(main_widget)  # 設定main_widget為中心視窗

        #【設定button觸發的slot(function)】
        self.btn_upload_csv.clicked.connect(self.upload_data_slot)
        self.btn_run_model.clicked.connect(self.run_model_slot)
        self.btn_run_break.clicked.connect(self.break_slot)
        self.btn_download_result.clicked.connect(self.download_data_slot)

        # 【設定thread】
        self.work = None
        self.stopped = None  # 暫停thread標籤

    def upload_data_slot(self):
        """Slot of uploading data (with btn_upload_csv)"""
        file, _ = QFileDialog.getOpenFileName(
            self, "Open file", "", "Data Files (*.csv)")  # 建立開啟檔案的對話盒(dialog)
        if file:
            print('file path: {}'.format(file))
            self.label_upload_filename.setText(
                file)  # 將label_upload_filename複寫為檔名(file)
            self.Data = pd.read_table(r'{}'.format(file), sep=',')  # 寫入檔案
            self.table_input_data.setModel(pandasModel(
                self.Data))  # 在table_input_data顯示輸入資料的表格

    def run_model_slot(self):
        """Slot of running model (with btn_run_model)"""
        if self.Data is None:
            self.label_current_message.setText('尚未有資料以執行!請確認是否已載入資料。')
        else:
            self.stopped = False
            self.train_model1()
            self.btn_run_model.setEnabled(False)

    def break_slot(self):
        """Slot of stopping (with btn_run_break)"""
        if (self.Data is None) or (self.stopped != False):
            print('正常不反應')
            self.label_current_message.setText('')
        else:
            print('Thread stopped.')
            self.work.stopped = True
            self.bar_upload.reset()
            self.label_current_message.setText('程序中斷。')
            self.btn_run_model.setEnabled(True)

    def complete_slot(self, data):
        """Slot of stopping (with btn_run_break)"""
        # Show result
        self.result = data
        self.table_output_data.setModel(
            pandasModel(data.loc[:, ['date'] + [i for i in self.column_name]])
        )  # 顯示表格在table_output_data
        self.show_plot()  # 參照show_plot()

        self.label_current_message.setText('模型計算完畢!')
        self.stopped = False
        self.btn_run_model.setEnabled(True)

    def download_data_slot(self):
        """Slot of downloading data (with btn_download_result)"""
        if self.result is None:
            self.label_current_message.setText('尚未有預測結果!請確認是否已載入資料並執行預測。')
        else:
            fileName, _ = QFileDialog.getSaveFileName(
                self, 'Save file', '', '*.csv')  # 建立儲存檔案的對話盒(dialog)
            if fileName:
                self.result['date'] = pd.to_datetime(self.result['date'])
                raw_input_data = self.Data.copy(
                )  # 需要把原資料copy,否則直接取用的話,輸出結果會隨著下載次數而無謂增加
                output_data = raw_input_data.append(
                    self.result.loc[:,
                                    ['date'] + [i for i in self.column_name]])
                output_data.to_csv(fileName, index=None)

    def train_model1(self):
        if self.Data.columns[0] != 'date':
            self.label_current_message.setText(
                '請確認資料欄位名稱,第一個欄位為date,且格式為yyyy/mm/dd或yyyy-mm-dd')
        else:
            self.label_current_message.setText('模型計算中,請稍後...')
            self.Data.loc[:, 'date'] = pd.to_datetime(self.Data.loc[:, 'date'])
            self.Data = self.Data.sort_values('date')
            self.column_name = self.Data.columns[1:]
            # self.p_range, self.d_range, self.q_range = range(0, 4), range(0, 2), range(0, 4)###############
            pdq, self.column_model_dict = list(
                itertools.product(self.p_range, self.d_range,
                                  self.q_range)), {}
            self.value_bar = 0
            self.bar_upload.setValue(self.value_bar)

            # TODO: new threadl class.
            self.work = WorkThread(self.Data, self.column_name, pdq,
                                   self.model, self.model_fit)
            self.work.start()
            self.work.processbar_trigger.connect(self.set_processbar_value)
            self.work.result_trigger.connect(self.complete_slot)

    def set_processbar_value(self, value):
        self.bar_upload.setValue(value)

    def show_plot(self):
        """Slot of showing plot"""
        if self.result is None:
            print('目前無結果。')
        else:
            self.plot_output_result.setRows(len(
                self.column_name))  # 設定subplot的列數
            for i, column in enumerate(self.column_name):
                self.plot_output_result.canvas.ax[
                    i].plot(  # 畫原資料 + 預測結果,以紅色線表示
                        range(1,
                              len(self.Data) + 3),
                        [i for i in self.Data.loc[:, column]] +
                        [i for i in self.result.loc[:, column]],
                        linewidth=1,
                        color='firebrick')
                self.plot_output_result.canvas.ax[
                    i].plot(  # 畫原資料,以藍色線表示(使得只有預測曲線是紅的)
                        range(1,
                              len(self.Data) + 1),
                        self.Data.loc[:, column],
                        color='steelblue')
                self.plot_output_result.canvas.ax[i].fill_between(  # 畫信賴區間的背景
                    range(len(self.Data),
                          len(self.Data) + 3),
                    [self.Data.loc[:, column].values[-1]] +
                    [i for i in self.result.loc[:, column + '_LB']],
                    [self.Data.loc[:, column].values[-1]] +
                    [i for i in self.result.loc[:, column + '_UB']],
                    facecolor='salmon',
                    alpha=0.6,
                    interpolate=True)
                self.plot_output_result.canvas.ax[i].set_ylabel(column)
            self.plot_output_result.canvas.ax[-1].set_xlabel(
                'Week',
                fontproperties=FontProperties(fname="SimHei.ttf", size=14))
            self.plot_output_result.canvas.figure.subplots_adjust(
                wspace=0.1, hspace=0.5)  # 調整子圖間距
            self.plot_output_result.canvas.draw()  # 類似plt.show()
コード例 #6
0
ファイル: main.py プロジェクト: augfab/Foo.cd
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.scrollSlider = widget.createScrollSlider(self)
		self.scrollSlider.sliderMoved.connect(self.player.seek)
		self.scrollSlider.sliderPressed.connect(self.player.toggle)
		self.scrollSlider.sliderReleased.connect(self.player.toggle)
		self.volumeSlider.sliderMoved.connect(self.player.setVolume)

		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,3)
		self.splitterTopBottom.setStretchFactor(1,1)

		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)

		pipeWorker = WorkThreadPipe()
		pipeWorker.hotKey.connect(self.onHotKey)
		pipeWorker.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 !')

	# 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)
		self.toggleRadioAction= QtGui.QAction('Switch to Radio mode',self)
		if not self.radio:
			self.toggleRadioAction.setText('Switch to Radio mode')
		else:
			self.toggleRadioAction.setText('Switch to Library mode')
		#scanMusicFolderAction.setShortcut('Ctrl+N')
		#scanMusicFolderAction.setStatusTip('Create new file')
		scanMusicFolderAction.triggered.connect(self.scanMusicFolder)
		actionMenu.addAction(scanMusicFolderAction)
		showShortcutAction.triggered.connect(self.showShortcut)
		actionMenu.addAction(showShortcutAction)
		addFolderToLibraryAction.triggered.connect(self.addFolderToLibrary)
		actionMenu.addAction(addFolderToLibraryAction)
		self.toggleRadioAction.triggered.connect(self.toggleRadio)
		actionMenu.addAction(self.toggleRadioAction)


	# Menu Action 1
	def scanMusicFolder(self):
		self.thread = WorkThread(Foo.readConfig('options')['music_folder'], False)
		self.thread.finished.connect(self.tree.initUI)
		self.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)
		self.thread = WorkThread(dir, True)
		self.thread.finished.connect(self.tree.initUI)
		self.thread.start()

	# Menu Action4
	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.splitterTopBottom.setStretchFactor(0,3)
		self.splitterTopBottom.setStretchFactor(1,1)
		self.table.runAction.connect(self.tableAction)
		self.setTabOrder(self.tree, self.table)

	@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)
コード例 #7
0
ファイル: main.py プロジェクト: augfab/Foo.cd
	def scanMusicFolder(self):
		self.thread = WorkThread(Foo.readConfig('options')['music_folder'], False)
		self.thread.finished.connect(self.tree.initUI)
		self.thread.start()