Lyrics: add a refresh action to toolbar
[nephilim.git] / nephilim / winMain.py
blob0ecd7c4f90c162f3ca1f026e590aa6aca9097091
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 misc 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.connect(self.__time_slider, QtCore.SIGNAL('sliderReleased()'), 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 m.setTearOffEnabled(True)
66 # connect
67 self.mConnect=m.addAction('Connect ...', QtGui.QApplication.instance().show_connect_win)
68 self.mConnect.setIcon(QtGui.QIcon(appIcon))
69 # disconnect
70 self.mDisconnect=m.addAction('Disconnect', self.mpclient.disconnect_mpd)
71 self.mDisconnect.setIcon(QtGui.QIcon('gfx/disconnect.png'))
72 # separator
73 m.addSeparator()
74 # quit
75 m.addAction("Quit", QtGui.QApplication.instance().quit).setIcon(QtGui.QIcon('gfx/gtk-quit.svg'))
77 # menu options
78 m=mBar.addMenu("Options")
79 m.setTearOffEnabled(True)
80 # settings
81 m.addAction("Settings", QtGui.QApplication.instance().show_settings_win).setIcon(QtGui.QIcon('gfx/gtk-preferences.svg'))
83 # menu layout
84 self.__layout_menu=mBar.addMenu("Layout")
85 self.__layout_menu.setTearOffEnabled(True)
87 # create a toolbar for the main menu
88 menu_toolbar = QtGui.QToolBar('Main menu', self)
89 menu_toolbar.addWidget(mBar)
90 self.addToolBar(QtCore.Qt.TopToolBarArea, menu_toolbar)
92 self.__update_layout_menu()
93 self.setDockOptions(QtGui.QMainWindow.AllowNestedDocks \
94 |QtGui.QMainWindow.AllowTabbedDocks \
95 |QtGui.QMainWindow.VerticalTabs)
96 self.setDockNestingEnabled(True)
97 self.restoreGeometry(self.settings.value('geometry').toByteArray())
99 " add event handlers"
100 self.connect(self.mpclient, QtCore.SIGNAL('connect_changed'), self.__on_connect_changed)
101 self.connect(self.mpclient, QtCore.SIGNAL('song_changed'), self.__on_song_change)
102 self.connect(self.mpclient, QtCore.SIGNAL('state_changed'), self.__update_state_messages)
103 self.connect(self.mpclient, QtCore.SIGNAL('time_changed'), self.__on_time_change)
105 self.__update_state_messages()
106 self.show()
108 def on_quit(self):
109 self.settings.setValue('geometry', QVariant(self.saveGeometry()))
111 def __update_layout_menu(self):
112 self.__layout_menu.clear()
113 self.__layout_menu.addAction('Save layout', self.save_layout)
114 self.__layout_menu.addAction('Restore layout', self.restore_layout)
115 self.__layout_menu.addSeparator()
116 # create checkable menu
117 a = QtGui.QAction('Show titlebars', self)
118 a.setCheckable(True)
119 a.setChecked(self.settings.value('show_titlebars', QVariant(True)).toBool())
120 self.__toggle_titlebars(a.isChecked())
121 self.connect(a, QtCore.SIGNAL('toggled(bool)'), self.__toggle_titlebars)
122 self.__layout_menu.addAction(a)
123 self.__layout_menu.addSeparator()
125 m = self.createPopupMenu()
126 if m:
127 for action in m.actions():
128 self.__layout_menu.addAction(action)
130 def __toggle_titlebars(self, val):
131 if val:
132 self.settings.setValue('show_titlebars', QVariant(True))
133 else:
134 self.settings.setValue('show_titlebars', QVariant(False))
135 for dock in self.__docks:
136 if val:
137 dock.setTitleBarWidget(None)
138 else:
139 dock.setTitleBarWidget(QtGui.QWidget())
140 def add_dock(self, dock):
141 if dock:
142 self.__docks.append(dock)
143 self.addDockWidget(QtCore.Qt.TopDockWidgetArea, dock)
144 self.__update_layout_menu()
145 def remove_dock(self, dock):
146 if dock:
147 if dock in self.__docks:
148 self.__docks.remove(dock)
149 self.removeDockWidget(dock)
150 self.__update_layout_menu()
152 def setStatus(self, status):
153 """Set the text of the statusbar."""
154 self.statusBar().showMessage(status, 5000)
155 logging.info(status)
157 def save_layout(self):
158 self.settings.setValue('layout', QVariant(self.saveState()))
159 def restore_layout(self):
160 layout = self.settings.value('layout').toByteArray()
161 if not layout:
162 try:
163 layout = open(DEFAULT_LAYOUT_FILE, 'rb').read()
164 except IOError:
165 logging.error("Error reading default layout.")
166 return
167 self.restoreState(layout)
170 def __on_connect_changed(self, val):
171 if val:
172 self.mDisconnect.setEnabled(True)
173 self.mConnect.setEnabled(False)
174 else:
175 self.mDisconnect.setEnabled(False)
176 self.mConnect.setEnabled(True)
178 def __update_state_messages(self):
179 """Update window title and statusbar"""
180 song = self.mpclient.current_song()
181 state = self.mpclient.status()['state']
182 state = 'playing' if state == 'play' else 'paused' if state == 'pause' else 'stopped'
183 if song:
184 self.setWindowTitle('%s by %s - %s [%s]'%(song.title(), song.artist(), APPNAME, state))
185 self.__statuslabel.setText('%s by %s on %s [%s]'%(song.title(), song.artist(),song.album(), state))
186 else:
187 self.setWindowTitle(APPNAME)
188 self.__statuslabel.setText('')
190 def __on___time_slider_change(self):
191 self.mpclient.seek(self.__time_slider.value())
193 def __on_song_change(self):
194 status = self.mpclient.status()
195 self.__time_slider.setMaximum(status['length'])
196 self.__time_slider.setEnabled(True)
197 self.__time_label.duration = sec2min(status['length'])
198 self.__update_state_messages()
200 def __on_time_change(self, new_time):
201 if not self.__time_slider.isSliderDown():
202 self.__time_slider.setValue(new_time)
203 self.__time_label.setText(sec2min(new_time) + '/' + self.__time_label.duration)