common: split MetadataFetcher into its own file
[nephilim.git] / nephilim / main_window.py
blob8f3377b39cfdd45bfeecb1f25562613d120500a7
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 pyqtSlot as Slot
21 import logging
23 from common import APPNAME, sec2min, appIcon
24 import icons
25 import data
27 class MainWindow(QtGui.QMainWindow):
28 """
29 Application's main window class.
30 """
31 mpclient = None
32 settings = None
33 " menus"
34 mConnect = None
35 mDisconnect = None
36 __layout_menu = None
38 # Statusbar objects
39 __statuslabel = None
40 __time_slider = None
41 __time_label = None
43 __docks = []
45 def __init__(self, mpclient):
46 QtGui.QMainWindow.__init__(self)
47 self.settings = QtCore.QSettings()
48 self.mpclient = mpclient
51 # statusbar
52 self.statusBar()
53 self.__statuslabel = QtGui.QLabel()
54 self.__time_slider = QtGui.QSlider(QtCore.Qt.Horizontal, self)
55 self.__time_slider.setMaximumWidth(self.width()/4)
56 self.__time_slider.sliderReleased.connect( self.__on___time_slider_change)
57 self.__time_label = TimeLabel(self, mpclient)
58 self.mpclient.time_changed.connect(self.__on_time_change)
60 self.statusBar().addWidget(self.__statuslabel)
61 self.statusBar().addPermanentWidget(self.__time_label)
62 self.statusBar().addPermanentWidget(self.__time_slider)
64 mBar = QtGui.QMenuBar() # create a menubar
65 # Server menu
66 m = mBar.addMenu('&Server')
67 # connect
68 self.mConnect=m.addAction('&Connect.', QtGui.QApplication.instance().show_connect_win)
69 self.mConnect.setIcon(QtGui.QIcon(appIcon))
70 # disconnect
71 self.mDisconnect=m.addAction('&Disconnect', self.mpclient.disconnect_mpd)
72 self.mDisconnect.setIcon(QtGui.QIcon(':icons/disconnect.png'))
73 # separator
74 m.addSeparator()
75 # update/rescan
76 m.addAction('&Update', self.mpclient.update_database)
77 m.addAction('&Rescan', self.mpclient.rescan_database)
78 m.addSeparator()
79 # quit
80 m.addAction("&Quit", QtGui.QApplication.instance().quit).setIcon(QtGui.QIcon(':icons/gtk-quit.svg'))
82 # menu options
83 m=mBar.addMenu("Options")
84 # settings
85 m.addAction("Settings", QtGui.QApplication.instance().show_settings_win).setIcon(QtGui.QIcon(':icons/gtk-preferences.svg'))
87 # menu layout
88 self.__layout_menu=mBar.addMenu("Layout")
90 # create a toolbar for the main menu
91 menu_toolbar = QtGui.QToolBar('Main menu', self)
92 menu_toolbar.addWidget(mBar)
93 self.addToolBar(QtCore.Qt.TopToolBarArea, menu_toolbar)
95 self.__update_layout_menu()
96 self.setDockOptions(QtGui.QMainWindow.AllowNestedDocks \
97 |QtGui.QMainWindow.AllowTabbedDocks \
98 |QtGui.QMainWindow.VerticalTabs)
99 self.setDockNestingEnabled(True)
100 self.restoreGeometry(self.settings.value('geometry', QtCore.QByteArray()))
102 " add event handlers"
103 self.mpclient.connect_changed.connect(self.__on_connect_changed)
104 self.mpclient.song_changed.connect(self.__on_song_change)
105 self.mpclient.state_changed.connect(self.__update_state_messages)
107 self.__update_state_messages()
108 self.show()
110 def on_quit(self):
111 self.settings.setValue('geometry', self.saveGeometry())
113 def __update_layout_menu(self):
114 self.__layout_menu.clear()
115 self.__layout_menu.addAction('Save layout', self.save_layout)
116 self.__layout_menu.addAction('Restore layout', self.restore_layout)
117 self.__layout_menu.addSeparator()
118 # create checkable menu
119 a = QtGui.QAction('Show titlebars', self)
120 a.setCheckable(True)
121 a.setChecked(int(self.settings.value('show_titlebars', 1)))
122 self.__toggle_titlebars(a.isChecked())
123 a.toggled.connect(self.__toggle_titlebars)
124 self.__layout_menu.addAction(a)
125 self.__layout_menu.addSeparator()
127 m = self.createPopupMenu()
128 if m:
129 for action in m.actions():
130 self.__layout_menu.addAction(action)
132 def __toggle_titlebars(self, val):
133 if val:
134 self.settings.setValue('show_titlebars', 1)
135 else:
136 self.settings.setValue('show_titlebars', 0)
137 for dock in self.__docks:
138 if val:
139 dock.setTitleBarWidget(None)
140 else:
141 dock.setTitleBarWidget(QtGui.QWidget())
142 def add_dock(self, dock):
143 if dock:
144 self.__docks.append(dock)
145 self.addDockWidget(QtCore.Qt.TopDockWidgetArea, dock)
146 self.__update_layout_menu()
147 def remove_dock(self, dock):
148 if dock:
149 self.removeDockWidget(dock)
150 if dock in self.__docks:
151 self.__docks.remove(dock)
152 self.__update_layout_menu()
154 def save_layout(self):
155 self.settings.setValue('layout', self.saveState())
156 def restore_layout(self):
157 layout = self.settings.value('layout')
158 if not layout:
159 l_file = QtCore.QFile(':default_layout')
160 l_file.open(QtCore.QIODevice.ReadOnly)
161 layout = l_file.readAll()
162 self.restoreState(layout)
165 def __on_connect_changed(self, val):
166 if val:
167 self.mDisconnect.setEnabled(True)
168 self.mConnect.setEnabled(False)
169 else:
170 self.mDisconnect.setEnabled(False)
171 self.mConnect.setEnabled(True)
173 def __update_state_messages(self):
174 """Update window title and statusbar"""
175 song = self.mpclient.cur_song
176 state = self.mpclient.status['state']
177 state = 'playing' if state == 'play' else 'paused' if state == 'pause' else 'stopped'
178 if song:
179 self.setWindowTitle('%s by %s - %s [%s]'%(song['?title'], song['?artist'], APPNAME, state))
180 self.__statuslabel.setText('%s by %s on %s [%s]'%(song['?title'], song['?artist'],song['?album'], state))
181 else:
182 self.setWindowTitle(APPNAME)
183 self.__statuslabel.setText('')
185 def __on___time_slider_change(self):
186 self.mpclient.seek(self.__time_slider.value())
188 def __on_song_change(self):
189 status = self.mpclient.status
190 self.__time_slider.setMaximum(status['time'][1])
191 self.__time_slider.setEnabled(True)
192 self.__update_state_messages()
194 def __on_time_change(self, new_time):
195 if not self.__time_slider.isSliderDown():
196 self.__time_slider.setValue(new_time)
198 class TimeLabel(QtGui.QLabel):
200 _mpclient = None
202 def __init__(self, parent, mpclient):
203 QtGui.QLabel.__init__(self, parent)
205 self._mpclient = mpclient
207 self._mpclient.time_changed.connect(self._update_text)
208 self._update_text(self._mpclient.status['time'][0])
210 @Slot(int)
211 def _update_text(self, time):
212 self.setText('%s/%s'%(sec2min(time), sec2min(self._mpclient.status['time'][1])))