Remove clSettings. Didn't i do this already?
[nephilim.git] / winMain.py
blobaccf86425f75a182f218d3956050800b41937f29
1 from PyQt4 import QtGui, QtCore
2 from PyQt4.QtCore import QVariant
3 from traceback import print_exc
5 from misc import *
6 from mpclient import MPClient
8 import plugins
10 from winConnect import winConnect
11 from winSettings import winSettings
12 import logging
14 DEFAULT_LAYOUT_FILE = 'default_layout'
16 class winMain(QtGui.QMainWindow):
17 """The winMain class is mpc's main window, showing the playlists and control-interface"""
18 docks=[]
20 " menus"
21 mConnect=None
22 mDisconnect=None
23 mLayout=None
25 " connection window"
26 wConnect=None
27 wSettings=None
29 " MPD object"
30 mpclient = None
32 " Statusbar objects"
33 statuslabel = None
34 time_slider = None
35 time_label = None
37 settings = None
38 def __init__(self, parent=None):
39 QtGui.QWidget.__init__(self, parent)
40 self.settings = QtCore.QSettings(ORGNAME, APPNAME)
41 self.mpclient = MPClient()
43 self.wConnect=winConnect(self)
45 # statusbar
46 self.statusBar()
47 self.statuslabel = QtGui.QLabel()
48 self.time_slider = QtGui.QSlider(QtCore.Qt.Horizontal, self)
49 self.time_slider.setMaximumWidth(self.width()/4)
50 self.connect(self.time_slider, QtCore.SIGNAL('sliderReleased()'), self.on_time_slider_change)
51 self.time_label = QtGui.QLabel()
52 self.time_label.duration = '0:00'
54 self.statusBar().addWidget(self.statuslabel)
55 self.statusBar().addPermanentWidget(self.time_label)
56 self.statusBar().addPermanentWidget(self.time_slider)
58 mBar = QtGui.QMenuBar() # create a menubar
59 # File menu
60 m = mBar.addMenu("File")
61 m.setTearOffEnabled(True)
62 # connect
63 self.mConnect=m.addAction('Connect ...', self.wConnect.monitor)
64 self.mConnect.setIcon(QtGui.QIcon(appIcon))
65 # disconnect
66 self.mDisconnect=m.addAction('Disconnect', self.mpclient.disconnect)
67 self.mDisconnect.setIcon(QtGui.QIcon('gfx/disconnect.png'))
68 # separator
69 m.addSeparator()
70 # quit
71 m.addAction("Quit", self.quit).setIcon(QtGui.QIcon('gfx/gtk-quit.svg'))
73 # menu options
74 m=mBar.addMenu("Options")
75 m.setTearOffEnabled(True)
76 # settings
77 m.addAction("Settings", self.showWinSettings).setIcon(QtGui.QIcon('gfx/gtk-preferences.svg'))
79 # menu layout
80 self.mLayout=mBar.addMenu("Layout")
81 self.mLayout.setTearOffEnabled(True)
83 # create a toolbar for the main menu
84 menu_toolbar = QtGui.QToolBar()
85 menu_toolbar.addWidget(mBar)
86 self.addToolBar(QtCore.Qt.TopToolBarArea, menu_toolbar)
88 showWinSettings = False # are there new plugins?
89 for k, entry in plugins.listPlugins().iteritems():
90 # load the plugin
91 plugin=plugins.loadPlugin(entry[plugins.PLUGIN_CLASS], self)
92 if plugin:
93 if self.settings.value(plugin.getName() + '/load') == None:
94 showWinSettings = True
95 if self.settings.value(plugin.getName() + '/load', QVariant(True)).toBool():
96 # load new plugins by default
97 try:
98 plugin.load()
99 except Exception, e:
100 plugins.setPluginMessage(plugin.getName(), "Exception while loading %s: %s"%(plugin.getName(), str(e)))
101 showWinSettings=True
103 self.updateLayoutMenu()
104 self.setDockOptions(QtGui.QMainWindow.AllowNestedDocks \
105 |QtGui.QMainWindow.AllowTabbedDocks \
106 |QtGui.QMainWindow.VerticalTabs)
107 self.setDockNestingEnabled(True)
108 self.restoreGeometry(self.settings.value('geometry').toByteArray())
109 self.restoreLayout()
111 " add event handlers"
112 self.mpclient.add_listener('onReady', self.onReady)
113 self.mpclient.add_listener('onConnect', self.onConnect)
114 self.mpclient.add_listener('onDisconnect', self.onDisconnect)
115 self.mpclient.add_listener('onUpdateDBStart', self.onUpdateDBStart)
116 self.mpclient.add_listener('onUpdateDBFinish', self.onUpdateDBFinish)
117 self.mpclient.add_listener('onSongChange', self.on_song_change)
118 self.mpclient.add_listener('onStateChange', self.update_state_messages)
119 self.mpclient.add_listener('onTimeChange', self.on_time_change)
121 self.enableAll(True)
122 self.setWindowIcon(QtGui.QIcon(appIcon))
123 # set icon in system tray
124 self.wConnect.monitor()
126 self.update_state_messages()
127 self.show()
128 if showWinSettings:
129 self.showWinSettings()
130 doEvents
132 def quit(self):
133 # unload all plugins
134 for entry in plugins.listPlugins().values():
135 p=entry[plugins.PLUGIN_INSTANCE]
136 if p and p.isLoaded():
137 p.unload()
139 self.settings.setValue('geometry', QVariant(self.saveGeometry()))
140 self.settings.sync()
141 QtCore.QCoreApplication.exit()
144 def updateLayoutMenu(self):
145 self.mLayout.clear()
146 self.mLayout.addAction('Save layout', self.saveLayout)
147 self.mLayout.addAction('Restore layout', self.restoreLayout)
148 self.mLayout.addSeparator()
149 # create checkable menu
150 a=QtGui.QAction('Show titlebars', self)
151 a.setCheckable(True)
152 a.setChecked(self.settings.value('show_titlebars', QVariant(True)).toBool())
153 self.toggleTitleBars(a.isChecked())
154 self.connect(a, QtCore.SIGNAL('toggled(bool)'), self.toggleTitleBars)
155 self.mLayout.addAction(a)
156 self.mLayout.addSeparator()
157 # can not use iterators, as that gives some creepy error 'bout c++
158 actions=self.createPopupMenu().actions()
159 for i in xrange(len(actions)):
160 self.mLayout.addAction(actions[i])
162 def toggleTitleBars(self, val):
163 if val:
164 self.settings.setValue('show_titlebars', QVariant(True))
165 else:
166 self.settings.setValue('show_titlebars', QVariant(False))
167 for dock in self.docks:
168 if val:
169 dock.setTitleBarWidget(None)
170 else:
171 dock.setTitleBarWidget(QtGui.QWidget())
172 def addDock(self, dock):
173 if dock:
174 self.docks.append(dock)
175 self.addDockWidget(QtCore.Qt.TopDockWidgetArea, dock)
176 self.updateLayoutMenu()
177 def removeDock(self, dock):
178 if dock:
179 if dock in self.docks:
180 self.docks.remove(dock)
181 self.removeDockWidget(dock)
182 self.updateLayoutMenu()
184 mMenuVisible=None
185 def createPopupMenu(self):
186 ret=QtGui.QMenu('Test', self)
187 if self.mMenuVisible==None:
188 # create checkable menu
189 a=QtGui.QAction('Menubar', self)
190 a.setCheckable(True)
191 a.setChecked(True)
192 self.connect(a, QtCore.SIGNAL('toggled(bool)'), self.switchMenubar)
194 self.mMenuVisible=a
195 ret.addAction(self.mMenuVisible)
196 ret.addSeparator()
197 menu = QtGui.QMainWindow.createPopupMenu(self)
198 if menu:
199 actions = menu.actions()
200 for i in xrange(len(actions)-1):
201 ret.addAction(actions[i])
202 return ret
203 def switchMenubar(self, val):
204 self.menuBar().setVisible(val)
205 def setStatus(self, status):
206 """Set the text of the statusbar."""
207 self.statusBar().showMessage(status, 5000)
208 logging.info(status)
210 def saveLayout(self):
211 self.settings.setValue('layout', QVariant(self.saveState()))
212 def restoreLayout(self):
213 layout = self.settings.value('layout').toByteArray()
214 if not layout:
215 try:
216 layout = open(DEFAULT_LAYOUT_FILE, 'rb').read()
217 except IOError:
218 logging.error("Error reading default layout.")
219 return
220 self.restoreState(layout)
222 def showWinSettings(self):
223 if not self.wSettings:
224 self.wSettings=winSettings(self)
225 self.wSettings.show()
226 self.wSettings.raise_()
228 def onReady(self, params):
229 self.initialiseData()
231 def onConnect(self, params):
232 logging.info("Connected to MPD")
233 self.setStatus('Restoring library and playlist ...')
234 self.mDisconnect.setEnabled(True)
235 self.mConnect.setEnabled(False)
236 doEvents
238 def enableAll(self, value):
239 for k,entry in plugins.listPlugins().iteritems():
240 try:
241 plugin=entry[plugins.PLUGIN_INSTANCE]
242 plugin.o.setEnabled(value)
243 except:
244 pass
246 def initialiseData(self):
247 self.enableAll(True)
248 self.setStatus("")
249 doEvents
251 def onDisconnect(self, params):
252 logging.info("Disconnected from MPD")
253 self.mDisconnect.setEnabled(False)
254 self.mConnect.setEnabled(True)
255 self.enableAll(False)
256 self.setStatus("You are disconnected. Choose File->Connect to reconnect!")
258 def onUpdateDBFinish(self, params):
259 self.setStatus('')
260 def onUpdateDBStart(self, params):
261 self.setStatus('Updating the database. Please wait ...')
263 def update_state_messages(self, params = None):
264 song = self.mpclient.getCurrentSong()
265 if song and self.mpclient.isPlaying():
266 self.setWindowTitle(song.getTitle() + " by " + song.getArtist())
267 self.statuslabel.setText("Now playing " + song.getTitle() + " by " + song.getArtist() + " on " + song.getAlbum())
268 else:
269 self.setWindowTitle(APPNAME)
270 self.statuslabel.setText("")
272 def on_time_slider_change(self):
273 self.mpclient.seek(self.time_slider.value())
275 def on_song_change(self, params):
276 status = self.mpclient.getStatus()
277 self.time_slider.setMaximum(status['length'])
278 self.time_slider.setEnabled(True)
279 self.time_label.duration = sec2min(status['length'])
280 self.update_state_messages(params)
282 def on_time_change(self, params):
283 if not self.time_slider.isSliderDown():
284 self.time_slider.setValue(params['newTime'])
285 self.time_label.setText(sec2min(params['newTime']) + '/' + self.time_label.duration)