Move expand_tags for musicdir from winMain to nephilim_app.
[nephilim.git] / nephilim / winMain.py
blob67a684db7e1a5c121081d66c606b70454bbc506e
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
24 from connect_wg import ConnectWidget
26 DEFAULT_LAYOUT_FILE = 'default_layout'
28 class winMain(QtGui.QMainWindow):
29 """The winMain class is mpc's main window, showing the playlists and control-interface"""
30 docks = []
32 " menus"
33 mConnect = None
34 mDisconnect = None
35 mLayout = None
37 wConnect = None
39 mpclient = None
40 settings = None
42 # Statusbar objects
43 statuslabel = None
44 time_slider = None
45 time_label = None
47 def __init__(self):
48 QtGui.QWidget.__init__(self)
49 self.settings = QtCore.QSettings()
50 self.mpclient = QtGui.QApplication.instance().mpclient
52 self.wConnect = ConnectWidget(self)
54 # statusbar
55 self.statusBar()
56 self.statuslabel = QtGui.QLabel()
57 self.time_slider = QtGui.QSlider(QtCore.Qt.Horizontal, self)
58 self.time_slider.setMaximumWidth(self.width()/4)
59 self.connect(self.time_slider, QtCore.SIGNAL('sliderReleased()'), self.on_time_slider_change)
60 self.time_label = QtGui.QLabel()
61 self.time_label.duration = '0:00'
63 self.statusBar().addWidget(self.statuslabel)
64 self.statusBar().addPermanentWidget(self.time_label)
65 self.statusBar().addPermanentWidget(self.time_slider)
67 mBar = QtGui.QMenuBar() # create a menubar
68 # File menu
69 m = mBar.addMenu("File")
70 m.setTearOffEnabled(True)
71 # connect
72 self.mConnect=m.addAction('Connect ...', self.wConnect.monitor)
73 self.mConnect.setIcon(QtGui.QIcon(appIcon))
74 # disconnect
75 self.mDisconnect=m.addAction('Disconnect', self.mpclient.disconnect_mpd)
76 self.mDisconnect.setIcon(QtGui.QIcon('gfx/disconnect.png'))
77 # separator
78 m.addSeparator()
79 # quit
80 m.addAction("Quit", QtGui.QApplication.instance().quit).setIcon(QtGui.QIcon('gfx/gtk-quit.svg'))
82 # menu options
83 m=mBar.addMenu("Options")
84 m.setTearOffEnabled(True)
85 # settings
86 m.addAction("Settings", QtGui.QApplication.instance().show_settings_win).setIcon(QtGui.QIcon('gfx/gtk-preferences.svg'))
88 # menu layout
89 self.mLayout=mBar.addMenu("Layout")
90 self.mLayout.setTearOffEnabled(True)
92 # create a toolbar for the main menu
93 menu_toolbar = QtGui.QToolBar('Main menu', self)
94 menu_toolbar.addWidget(mBar)
95 self.addToolBar(QtCore.Qt.TopToolBarArea, menu_toolbar)
97 self.updateLayoutMenu()
98 self.setDockOptions(QtGui.QMainWindow.AllowNestedDocks \
99 |QtGui.QMainWindow.AllowTabbedDocks \
100 |QtGui.QMainWindow.VerticalTabs)
101 self.setDockNestingEnabled(True)
102 self.restoreGeometry(self.settings.value('geometry').toByteArray())
104 " add event handlers"
105 self.connect(self.mpclient, QtCore.SIGNAL('connected'), self.onConnected)
106 self.connect(self.mpclient, QtCore.SIGNAL('disconnected'), self.onDisconnect)
107 self.connect(self.mpclient, QtCore.SIGNAL('song_changed'), self.on_song_change)
108 self.connect(self.mpclient, QtCore.SIGNAL('state_changed'), self.update_state_messages)
109 self.connect(self.mpclient, QtCore.SIGNAL('time_changed'), self.on_time_change)
111 self.wConnect.monitor()
113 self.update_state_messages()
114 self.show()
116 def on_quit(self):
117 self.settings.setValue('geometry', QVariant(self.saveGeometry()))
119 def updateLayoutMenu(self):
120 self.mLayout.clear()
121 self.mLayout.addAction('Save layout', self.saveLayout)
122 self.mLayout.addAction('Restore layout', self.restore_layout)
123 self.mLayout.addSeparator()
124 # create checkable menu
125 a=QtGui.QAction('Show titlebars', self)
126 a.setCheckable(True)
127 a.setChecked(self.settings.value('show_titlebars', QVariant(True)).toBool())
128 self.toggleTitleBars(a.isChecked())
129 self.connect(a, QtCore.SIGNAL('toggled(bool)'), self.toggleTitleBars)
130 self.mLayout.addAction(a)
131 self.mLayout.addSeparator()
132 # can not use iterators, as that gives some creepy error 'bout c++
133 actions=self.createPopupMenu().actions()
134 for i in xrange(len(actions)):
135 self.mLayout.addAction(actions[i])
137 def toggleTitleBars(self, val):
138 if val:
139 self.settings.setValue('show_titlebars', QVariant(True))
140 else:
141 self.settings.setValue('show_titlebars', QVariant(False))
142 for dock in self.docks:
143 if val:
144 dock.setTitleBarWidget(None)
145 else:
146 dock.setTitleBarWidget(QtGui.QWidget())
147 def addDock(self, dock):
148 if dock:
149 self.docks.append(dock)
150 self.addDockWidget(QtCore.Qt.TopDockWidgetArea, dock)
151 self.updateLayoutMenu()
152 def removeDock(self, dock):
153 if dock:
154 if dock in self.docks:
155 self.docks.remove(dock)
156 self.removeDockWidget(dock)
157 self.updateLayoutMenu()
159 mMenuVisible=None
160 def createPopupMenu(self):
161 ret=QtGui.QMenu('Test', self)
162 if self.mMenuVisible==None:
163 # create checkable menu
164 a=QtGui.QAction('Menubar', self)
165 a.setCheckable(True)
166 a.setChecked(True)
167 self.connect(a, QtCore.SIGNAL('toggled(bool)'), self.switchMenubar)
169 self.mMenuVisible=a
170 ret.addAction(self.mMenuVisible)
171 ret.addSeparator()
172 menu = QtGui.QMainWindow.createPopupMenu(self)
173 if menu:
174 actions = menu.actions()
175 for i in xrange(len(actions)-1):
176 ret.addAction(actions[i])
177 return ret
178 def switchMenubar(self, val):
179 self.menuBar().setVisible(val)
180 def setStatus(self, status):
181 """Set the text of the statusbar."""
182 self.statusBar().showMessage(status, 5000)
183 logging.info(status)
185 def saveLayout(self):
186 self.settings.setValue('layout', QVariant(self.saveState()))
187 def restore_layout(self):
188 layout = self.settings.value('layout').toByteArray()
189 if not layout:
190 try:
191 layout = open(DEFAULT_LAYOUT_FILE, 'rb').read()
192 except IOError:
193 logging.error("Error reading default layout.")
194 return
195 self.restoreState(layout)
198 def onConnected(self):
199 self.mDisconnect.setEnabled(True)
200 self.mConnect.setEnabled(False)
202 def onDisconnect(self):
203 logging.info("Disconnected from MPD")
204 self.mDisconnect.setEnabled(False)
205 self.mConnect.setEnabled(True)
206 self.setStatus("You are disconnected. Choose File->Connect to reconnect!")
208 def update_state_messages(self):
209 song = self.mpclient.current_song()
210 state = self.mpclient.status()['state']
211 state = 'playing' if state == 'play' else 'paused' if state == 'pause' else 'stopped'
212 if song:
213 self.setWindowTitle('%s by %s - %s [%s]'%(song.title(), song.artist(), APPNAME, state))
214 self.statuslabel.setText('%s by %s on %s [%s]'%(song.title(), song.artist(),song.album(), state))
215 else:
216 self.setWindowTitle(APPNAME)
217 self.statuslabel.setText('')
219 def on_time_slider_change(self):
220 self.mpclient.seek(self.time_slider.value())
222 def on_song_change(self):
223 status = self.mpclient.status()
224 self.time_slider.setMaximum(status['length'])
225 self.time_slider.setEnabled(True)
226 self.time_label.duration = sec2min(status['length'])
227 self.update_state_messages()
229 def on_time_change(self, new_time):
230 if not self.time_slider.isSliderDown():
231 self.time_slider.setValue(new_time)
232 self.time_label.setText(sec2min(new_time) + '/' + self.time_label.duration)