switch to new-style PyQt4 signals.
[nephilim.git] / nephilim / winMain.py
blob31ab17fc81928df848c06a46b545cdacd2067aec
2 # Copyright (C) 2008 jerous <jerous@gmail.com>
3 # Copyright (C) 2009 Anton Khirnov <wyskas@gmail.com>
5 # Nephilim is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # Nephilim is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with Nephilim. If not, see <http://www.gnu.org/licenses/>.
19 from PyQt4 import QtGui, QtCore
20 from PyQt4.QtCore import QVariant
21 import logging
23 from common import APPNAME, sec2min, appIcon
25 DEFAULT_LAYOUT_FILE = 'default_layout'
27 class winMain(QtGui.QMainWindow):
28 """The winMain class is mpc's main window, showing the playlists and control-interface"""
29 mpclient = None
30 settings = None
31 " menus"
32 mConnect = None
33 mDisconnect = None
34 __layout_menu = None
36 # Statusbar objects
37 __statuslabel = None
38 __time_slider = None
39 __time_label = None
41 __docks = []
43 def __init__(self, mpclient):
44 QtGui.QWidget.__init__(self)
45 self.settings = QtCore.QSettings()
46 self.mpclient = mpclient
49 # statusbar
50 self.statusBar()
51 self.__statuslabel = QtGui.QLabel()
52 self.__time_slider = QtGui.QSlider(QtCore.Qt.Horizontal, self)
53 self.__time_slider.setMaximumWidth(self.width()/4)
54 self.__time_slider.sliderReleased.connect( self.__on___time_slider_change)
55 self.__time_label = QtGui.QLabel()
56 self.__time_label.duration = '0:00'
58 self.statusBar().addWidget(self.__statuslabel)
59 self.statusBar().addPermanentWidget(self.__time_label)
60 self.statusBar().addPermanentWidget(self.__time_slider)
62 mBar = QtGui.QMenuBar() # create a menubar
63 # File menu
64 m = mBar.addMenu("File")
65 # connect
66 self.mConnect=m.addAction('Connect ...', QtGui.QApplication.instance().show_connect_win)
67 self.mConnect.setIcon(QtGui.QIcon(appIcon))
68 # disconnect
69 self.mDisconnect=m.addAction('Disconnect', self.mpclient.disconnect_mpd)
70 self.mDisconnect.setIcon(QtGui.QIcon('gfx/disconnect.png'))
71 # separator
72 m.addSeparator()
73 # quit
74 m.addAction("Quit", QtGui.QApplication.instance().quit).setIcon(QtGui.QIcon('gfx/gtk-quit.svg'))
76 # menu options
77 m=mBar.addMenu("Options")
78 # settings
79 m.addAction("Settings", QtGui.QApplication.instance().show_settings_win).setIcon(QtGui.QIcon('gfx/gtk-preferences.svg'))
81 # menu layout
82 self.__layout_menu=mBar.addMenu("Layout")
84 # create a toolbar for the main menu
85 menu_toolbar = QtGui.QToolBar('Main menu', self)
86 menu_toolbar.addWidget(mBar)
87 self.addToolBar(QtCore.Qt.TopToolBarArea, menu_toolbar)
89 self.__update_layout_menu()
90 self.setDockOptions(QtGui.QMainWindow.AllowNestedDocks \
91 |QtGui.QMainWindow.AllowTabbedDocks \
92 |QtGui.QMainWindow.VerticalTabs)
93 self.setDockNestingEnabled(True)
94 self.restoreGeometry(self.settings.value('geometry').toByteArray())
96 " add event handlers"
97 self.mpclient.connect_changed.connect(self.__on_connect_changed)
98 self.mpclient.song_changed.connect(self.__on_song_change)
99 self.mpclient.state_changed.connect(self.__update_state_messages)
100 self.mpclient.time_changed.connect(self.__on_time_change)
102 self.__update_state_messages()
103 self.show()
105 def on_quit(self):
106 self.settings.setValue('geometry', QVariant(self.saveGeometry()))
108 def __update_layout_menu(self):
109 self.__layout_menu.clear()
110 self.__layout_menu.addAction('Save layout', self.save_layout)
111 self.__layout_menu.addAction('Restore layout', self.restore_layout)
112 self.__layout_menu.addSeparator()
113 # create checkable menu
114 a = QtGui.QAction('Show titlebars', self)
115 a.setCheckable(True)
116 a.setChecked(self.settings.value('show_titlebars', QVariant(True)).toBool())
117 self.__toggle_titlebars(a.isChecked())
118 a.toggled.connect(self.__toggle_titlebars)
119 self.__layout_menu.addAction(a)
120 self.__layout_menu.addSeparator()
122 m = self.createPopupMenu()
123 if m:
124 for action in m.actions():
125 self.__layout_menu.addAction(action)
127 def __toggle_titlebars(self, val):
128 if val:
129 self.settings.setValue('show_titlebars', QVariant(True))
130 else:
131 self.settings.setValue('show_titlebars', QVariant(False))
132 for dock in self.__docks:
133 if val:
134 dock.setTitleBarWidget(None)
135 else:
136 dock.setTitleBarWidget(QtGui.QWidget())
137 def add_dock(self, dock):
138 if dock:
139 self.__docks.append(dock)
140 self.addDockWidget(QtCore.Qt.TopDockWidgetArea, dock)
141 self.__update_layout_menu()
142 def remove_dock(self, dock):
143 if dock:
144 if dock in self.__docks:
145 self.__docks.remove(dock)
146 self.removeDockWidget(dock)
147 self.__update_layout_menu()
149 def setStatus(self, status):
150 """Set the text of the statusbar."""
151 self.statusBar().showMessage(status, 5000)
152 logging.info(status)
154 def save_layout(self):
155 self.settings.setValue('layout', QVariant(self.saveState()))
156 def restore_layout(self):
157 layout = self.settings.value('layout').toByteArray()
158 if not layout:
159 try:
160 layout = open(DEFAULT_LAYOUT_FILE, 'rb').read()
161 except IOError:
162 logging.error("Error reading default layout.")
163 return
164 self.restoreState(layout)
167 def __on_connect_changed(self, val):
168 if val:
169 self.mDisconnect.setEnabled(True)
170 self.mConnect.setEnabled(False)
171 else:
172 self.mDisconnect.setEnabled(False)
173 self.mConnect.setEnabled(True)
175 def __update_state_messages(self):
176 """Update window title and statusbar"""
177 song = self.mpclient.current_song()
178 state = self.mpclient.status()['state']
179 state = 'playing' if state == 'play' else 'paused' if state == 'pause' else 'stopped'
180 if song:
181 self.setWindowTitle('%s by %s - %s [%s]'%(song.title(), song.artist(), APPNAME, state))
182 self.__statuslabel.setText('%s by %s on %s [%s]'%(song.title(), song.artist(),song.album(), state))
183 else:
184 self.setWindowTitle(APPNAME)
185 self.__statuslabel.setText('')
187 def __on___time_slider_change(self):
188 self.mpclient.seek(self.__time_slider.value())
190 def __on_song_change(self):
191 status = self.mpclient.status()
192 self.__time_slider.setMaximum(status['length'])
193 self.__time_slider.setEnabled(True)
194 self.__time_label.duration = sec2min(status['length'])
195 self.__update_state_messages()
197 def __on_time_change(self, new_time):
198 if not self.__time_slider.isSliderDown():
199 self.__time_slider.setValue(new_time)
200 self.__time_label.setText(sec2min(new_time) + '/' + self.__time_label.duration)