# # Copyright (C) 2008 jerous # Copyright (C) 2009 Anton Khirnov # # Nephilim is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Nephilim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Nephilim. If not, see . # from PyQt5 import QtGui, QtWidgets, QtCore from PyQt5.QtCore import pyqtSlot as Slot import logging from .common import APPNAME, sec2min, appIcon from . import icons from . import data class MainWindow(QtWidgets.QMainWindow): """ Application's main window class. """ mpclient = None settings = None " menus" mConnect = None mDisconnect = None __layout_menu = None # Statusbar objects __statuslabel = None __time_slider = None __time_label = None __docks = [] def __init__(self, mpclient): QtWidgets.QMainWindow.__init__(self) self.settings = QtCore.QSettings() self.mpclient = mpclient # statusbar self.statusBar() self.__statuslabel = QtWidgets.QLabel() self.__time_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal, self) self.__time_slider.setMaximumWidth(self.width()/4) self.__time_slider.sliderReleased.connect( self.__on___time_slider_change) self.__time_label = TimeLabel(self, mpclient) self.mpclient.time_changed.connect(self.__on_time_change) self.statusBar().addWidget(self.__statuslabel) self.statusBar().addPermanentWidget(self.__time_label) self.statusBar().addPermanentWidget(self.__time_slider) mBar = QtWidgets.QMenuBar() # create a menubar # Server menu m = mBar.addMenu('&Server') # connect self.mConnect=m.addAction('&Connect.', QtWidgets.QApplication.instance().show_connect_win) self.mConnect.setIcon(QtGui.QIcon(appIcon)) # disconnect self.mDisconnect=m.addAction('&Disconnect', self.mpclient.disconnect_mpd) self.mDisconnect.setIcon(QtGui.QIcon(':icons/disconnect.png')) # separator m.addSeparator() # update/rescan m.addAction('&Update', self.mpclient.update_database) m.addAction('&Rescan', self.mpclient.rescan_database) m.addSeparator() # quit m.addAction("&Quit", QtWidgets.QApplication.instance().quit).setIcon(QtGui.QIcon(':icons/gtk-quit.svg')) # menu options m=mBar.addMenu("Options") # settings m.addAction("Settings", QtWidgets.QApplication.instance().show_settings_win).setIcon(QtGui.QIcon(':icons/gtk-preferences.svg')) # menu layout self.__layout_menu=mBar.addMenu("Layout") # create a toolbar for the main menu menu_toolbar = QtWidgets.QToolBar('Main menu', self) menu_toolbar.addWidget(mBar) self.addToolBar(QtCore.Qt.TopToolBarArea, menu_toolbar) self.__update_layout_menu() self.setDockOptions(self.AllowNestedDocks | self .AllowTabbedDocks | self.VerticalTabs) self.setDockNestingEnabled(True) self.restoreGeometry(self.settings.value('geometry', QtCore.QByteArray())) " add event handlers" self.mpclient.connect_changed.connect(self.__on_connect_changed) self.mpclient.song_changed.connect(self.__on_song_change) self.mpclient.state_changed.connect(self.__update_state_messages) self.__update_state_messages() self.show() def on_quit(self): self.settings.setValue('geometry', self.saveGeometry()) def __update_layout_menu(self): self.__layout_menu.clear() self.__layout_menu.addAction('Save layout', self.save_layout) self.__layout_menu.addAction('Restore layout', self.restore_layout) self.__layout_menu.addSeparator() # create checkable menu a = QtWidgets.QAction('Show titlebars', self) a.setCheckable(True) a.setChecked(int(self.settings.value('show_titlebars', 1))) self.__toggle_titlebars(a.isChecked()) a.toggled.connect(self.__toggle_titlebars) self.__layout_menu.addAction(a) self.__layout_menu.addSeparator() m = self.createPopupMenu() if m: for action in m.actions(): self.__layout_menu.addAction(action) def __toggle_titlebars(self, val): if val: self.settings.setValue('show_titlebars', 1) else: self.settings.setValue('show_titlebars', 0) for dock in self.__docks: if val: dock.setTitleBarWidget(None) else: dock.setTitleBarWidget(QtWidgets.QWidget()) def add_dock(self, dock): if dock: self.__docks.append(dock) self.addDockWidget(QtCore.Qt.TopDockWidgetArea, dock) self.__update_layout_menu() def remove_dock(self, dock): if dock: self.removeDockWidget(dock) if dock in self.__docks: self.__docks.remove(dock) self.__update_layout_menu() def save_layout(self): self.settings.setValue('layout', self.saveState()) def restore_layout(self): layout = self.settings.value('layout') if not layout: l_file = QtCore.QFile(':default_layout') l_file.open(QtCore.QIODevice.ReadOnly) layout = l_file.readAll() self.restoreState(layout) def __on_connect_changed(self, val): if val: self.mDisconnect.setEnabled(True) self.mConnect.setEnabled(False) else: self.mDisconnect.setEnabled(False) self.mConnect.setEnabled(True) def __update_state_messages(self): """Update window title and statusbar""" song = self.mpclient.cur_song state = self.mpclient.status['state'] state = 'playing' if state == 'play' else 'paused' if state == 'pause' else 'stopped' if song: self.setWindowTitle('%s by %s - %s [%s]'%(song['?title'], song['?artist'], APPNAME, state)) self.__statuslabel.setText('%s by %s on %s [%s]'%(song['?title'], song['?artist'],song['?album'], state)) else: self.setWindowTitle(APPNAME) self.__statuslabel.setText('') def __on___time_slider_change(self): self.mpclient.seek(self.__time_slider.value()) def __on_song_change(self): status = self.mpclient.status self.__time_slider.setMaximum(status['time'][1]) self.__time_slider.setEnabled(True) self.__update_state_messages() def __on_time_change(self, new_time): if not self.__time_slider.isSliderDown(): self.__time_slider.setValue(new_time) class TimeLabel(QtWidgets.QLabel): _mpclient = None def __init__(self, parent, mpclient): QtWidgets.QLabel.__init__(self, parent) self._mpclient = mpclient self._mpclient.time_changed.connect(self._update_text) self._update_text(self._mpclient.status['time'][0]) @Slot(int) def _update_text(self, time): self.setText('%s/%s'%(sec2min(time), sec2min(self._mpclient.status['time'][1])))