1 """Components for the top level of the QUB Express or Fitness.
2
3 Copyright 2008-2013 Research Foundation State University of New York
4 This file is part of QUB Express.
5
6 QUB Express is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 QUB Express is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License,
17 named LICENSE.txt, in the QUB Express program directory. If not, see
18 <http://www.gnu.org/licenses/>.
19
20
21 """
22
23
24 import os
25 import traceback
26
27 import gtk
28 import gobject
29 import numpy
30 import time
31
32 import qubx.faces
33 import qubx.GTK
34 import qubx.notebook
35 import qubx.notebookGTK
36 import qubx.pyenv
37 import qubx.pyenvGTK
38 import qubx.settings
39 import qubx.settingsGTK
40 import qubx.task
41 import qubx.tree
42 import qubx.treeGTK
43 import qubx.table
44 import qubx.tableGTK
45 import qubx.toolspace
46
47 from itertools import izip, count
48 from math import *
49 from gtk import gdk
50 from qubx.accept import *
51 from qubx.GTK import pack_item, pack_space, pack_hsep, pack_vsep, pack_label, pack_button, pack_check, pack_radio, pack_scrolled, build_menuitem
52 from qubx.settings import Propertied, Property
53 from qubx.tree import node_data_or_def
54 from qubx.util_types import *
55
56
57 SCRIPT_PROXY_CHECK_SEC = 0.3
60 """Panel with "Stop Tasks" button and mean progress bar; monitors L{qubx.task.Tasks}; manages QubX.About.Tasks.
61
62 @ivar all_tasks: L{Face} in QubX.About, with progress and stop button for each L{qubx.task.Task}
63 """
64
65 __explore_featured = ['btnStop', 'barMean', 'script_proxies', 'all_tasks', 'update_progress']
66
127 ntask = len(self.all_tasks)
128 if not ntask:
129 self.barMean.set_text('(idle)')
130 self.barMean.set_fraction(0.0)
131 return
132 fraction = max(0.0, min(1.0, sum(panel.task.progress for panel in self.all_tasks) / (ntask * 100.0)))
133 self.barMean.set_text('%i%% of %i task%s' % (int(round(100.0*fraction)), ntask, ntask and 's' or ''))
134 self.barMean.set_fraction(fraction)
152 self.script_proxies[module.filename].status = 'Paused (line %i)' % module.lineno
154 try:
155 task = self.script_proxies[module.filename]
156 except KeyError:
157 return
158 task.status = 'Running (line %i)' % lineno
159 task.progress = lineno * 100.0 / len(module.lines)
163
165 """Represents a running script, in order to show progress and status and allow user to stop and pause (first click on "Stop" pauses it, next click permanently stops it)."""
167 """@param module: L{qubx.pyenv.ScriptModule}"""
168 self.module = module
169 qubx.task.Task.__init__(self, module.filename)
170 self.__ref_interrupt = self.__onInterrupt
171 self.__ref_resume = self.__onResume
172 self.OnInterrupt += self.__ref_interrupt
173 module.OnResume += self.__ref_resume
174 self.not_done = True
175 self.start()
176 self.stop_count = 0
178 """Called by creator (TaskFace) when script finishes, stops proxy task."""
179 self.not_done = False
180 self.module.OnResume -= self.__ref_resume
185 if self.module.paused or (self.stop_count >= 3):
186 self.module.stop()
187 else:
188 self.module.pause()
189 self.stop_count += 1
190 cancel()
193
195 """Panel with script editor, python prompt, and output.
196
197 @ivar scripts: L{qubx.pyenvGTK.PythonScriptView}
198 """
199
200 __explore_featured = ['scripts']
201
213
214
215
216
217
218
219 -class AltKeysFace(qubx.faces.Face):
225
228 """Panel with welcome message. Should add hyperlinked getting-started ideas."""
231
232
233 @Propertied(Property('font_size', qubx.toolspace.Appearance.font_size, "also influences graphical layout sizes"),
234 Property('font_bold', qubx.toolspace.Appearance.font_bold, "True for fatter letters"),
235 Property('line_width', qubx.toolspace.Appearance.line_width, 'used primarily to draw data'),
236 Property('opengl', qubx.toolspace.Appearance.opengl, 'True to allow OpenGL drawing (faster/less compatible); takes effect on program restart'))
238 """
239 Panel to manage L{qubx.toolspace.Appearance} and other active L{qubx.settings}.
240 Saves and restores Appearance settings.
241 Editing of qubx.settings is advisory -- the changes are passed to SettingsMgr[category_name].setProperties/OnSet which is free to ignore them.
242
243 @ivar catlist: L{qubx.GTK.SimpleList}
244 @ivar treeView: L{qubx.treeGTK.TreeView}
245 """
246
247 __explore_featured = ['treeView', 'tree_colors', 'show_colors_dialog', 'show_cat']
248
250 qubx.faces.Face.__init__(self, 'Settings', global_name=global_name)
251 self.__ref = Reffer()
252
253 appname = qubx.pyenv.env.globals['QubX'].appname
254 screen_w = gdk.screen_width()
255 if screen_w < 900:
256 def_font_size = 9
257 elif screen_w < 1100:
258 def_font_size = 10
259 elif screen_w < 1300:
260 def_font_size = 12
261 elif screen_w < 1700:
262 def_font_size = 14
263 else:
264 def_font_size = 16
265 self.font_size = def_font_size
266
267 self.cat_appearance = qubx.settings.SettingsMgr['Appearance']
268 props = self.cat_appearance.active
269 if not props['version'].data:
270 props['version'].data = 2
271 props.remove(props['Colors'])
272 self.propertied_connect_settings('Appearance')
273 self.font_size = self.font_size
274 qubx.toolspace.Appearance.font_bold = self.font_bold
275 qubx.toolspace.Appearance.line_width = self.line_width
276 qubx.toolspace.Appearance.opengl = self.opengl
277 qubx.toolspace.Appearance.hide_hidden_signals = bool(node_data_or_def(props['hide_hidden_signals'], False))
278 qubx.toolspace.Appearance.OnSetHideHiddenSignals += self.__ref(self.__onSetHideHiddenSignals)
279 qubx.toolspace.Appearance.multi_line_data = bool(node_data_or_def(props['multi_line_data'], True))
280 qubx.toolspace.Appearance.OnSetMultiLineData += self.__ref(self.__onSetMultiLineData)
281 qubx.toolspace.Appearance.auto_scale_data = bool(node_data_or_def(props['auto_scale_data'], False))
282 qubx.toolspace.Appearance.OnSetAutoScaleData += self.__ref(self.__onSetAutoScaleData)
283 qubx.toolspace.Appearance.color_idealized = bool(node_data_or_def(props['color_idealized'], False))
284 qubx.toolspace.Appearance.OnSetColorIdealized += self.__ref(self.__onSetColorIdealized)
285 qubx.toolspace.Appearance.gauss_intensity = bool(node_data_or_def(props['gauss_intensity'], True))
286 qubx.toolspace.Appearance.OnSetGaussIntensity += self.__ref(self.__onSetGaussIntensity)
287
288 h = pack_item(gtk.HBox(), self)
289 self.btnColors = pack_button('Colors...', h, on_click=self.__onClickColors)
290 pack_space(h, expand=True)
291 pack_label('Font size: ', h)
292 self.txtFontSize = pack_item(qubx.GTK.NumEntry(def_font_size, acceptIntGreaterThan(0), width_chars=4), h)
293 self.propertied_connect_NumEntry('font_size', self.txtFontSize)
294 self.chkBold = pack_check('bold', h)
295 self.propertied_connect_check('font_bold', self.chkBold)
296 pack_space(h, expand=True)
297 pack_label('Line width:', h)
298 self.txtLineWidth = pack_item(qubx.GTK.NumEntry(qubx.toolspace.Appearance.line_width, width_chars=4), h)
299 self.propertied_connect_NumEntry('line_width', self.txtLineWidth)
300 pack_space(h, expand=True)
301 self.chkOpenGL = pack_check('Allow OpenGL', h, show=False)
302 self.chkOpenGL.set_tooltip_text("Usually draws faster. Takes effect next run.\nTry un-checking if you can't see the data.")
303 self.propertied_connect_check('opengl', self.chkOpenGL)
304 pack_space(h, expand=True)
305 self.mnuPresets = pack_item(qubx.settingsGTK.PresetsMenu('Appearance', appname), h)
306 pack_space(h, expand=True)
307 self.btnSaveAll = pack_button('Save all settings', h, on_click=self.__onClickSaveAll, at_end=True)
308 self.btnSaveAll.set_tooltip_text('Settings are ordinarily saved when closing %s'%appname)
309
310 lr = pack_item(gtk.HPaned(), self, expand=True)
311 self.catlist = qubx.GTK.SimpleList(sortable=False)
312 self.catlist.OnSelect += self.__ref(self._onSelect), 'SettingsFace.onSelect'
313 scr = pack_scrolled(self.catlist, None, size_request=(150, 70))
314 lr.pack1(scr, False, True)
315
316 self.treeView = qubx.treeGTK.TreeView()
317 self.treeView.OnChange += self.__ref(self._onTreeEdit), 'SettingsFace.onTreeEdit'
318 scr = pack_scrolled(self.treeView, None, size_request=(200, 70))
319 lr.pack2(scr, True, True)
320
321 self._lastName = None
322 self._names = []
323
324 self.tree_colors = qubx.settings.SettingsMgr['Appearance'].active['Colors']
325 for child in qubx.tree.children(self.tree_colors):
326 if child.data:
327 qubx.toolspace.Appearance.color_preset(child.name, tuple(child.data[:]))
328 qubx.toolspace.Appearance.OnAddColor += self.__ref(self.__onAddColor)
329 for color in qubx.toolspace.Appearance.colors.values():
330 self.__onAddColor(color.name, color.value)
331
338 self.cat_appearance.active['hide_hidden_signals'].data = x
340 self.cat_appearance.active['multi_line_data'].data = x
342 self.cat_appearance.active['auto_scale_data'].data = x
344 self.cat_appearance.active['color_idealized'].data = x
346 self.cat_appearance.active['gauss_intensity'].data = x
374 def on_apply():
375 backup[0] = self.cat_appearance.active.clone()
376 dlg = qubx.toolspace.TS_ColorsDialog(qubx.pyenv.env.globals['QubX'].appname, qubx.toolspace.Appearance)
377 dlg.show(on_cancel, on_apply)
392
404
408
411 """Face to manage qubx.pyenv.Plugins, the L{qubx.pyenv.PluginManager}."""
412 __explore_featured = ['path', 'open_plugin']
414 qubx.faces.Face.__init__(self, 'Plugins', global_name=global_name)
415 self.__ref = Reffer()
416 self.path = None
417 h = pack_item(gtk.HBox(), self, expand=True)
418 self.lstPlugs = qubx.GTK.SimpleList(sortable=False)
419 self.lstPlugs.OnSelect += self.__ref(self.__onSelect)
420 pack_scrolled(self.lstPlugs, h, size_request=(200, -1))
421 hv = pack_item(gtk.VBox(), h, expand=True)
422 hvh = pack_item(gtk.HBox(), hv)
423 self.btnAdd = pack_button('Add...', hvh, on_click=self.__onClickAdd)
424 self.btnRemove = pack_button('Remove', hvh, on_click=self.__onClickRemove, sensitive=False)
425 self.btnReload = pack_button('Reload', hvh, on_click=self.__onClickReload, sensitive=False)
426 self.txtAbout = gtk.TextView()
427 self.txtAbout.set_wrap_mode(gtk.WRAP_WORD)
428 pack_scrolled(self.txtAbout, hv, expand=True)
429 self.outAbout = qubx.GTK.TextViewAppender(self.txtAbout)
430 qubx.pyenv.Plugins.OnUpdate += self.__ref(self.__onUpdate)
431 qubx.pyenv.Plugins.OnRemoving += self.__ref(self.__onRemoving)
432 for i in xrange(len(qubx.pyenv.Plugins.names)):
433 self.__onUpdate(qubx.pyenv.Plugins, i)
435 have = ix >= 0
436 self.btnRemove.set_sensitive(have)
437 self.btnReload.set_sensitive(have)
438 self.txtAbout.get_buffer().set_text('')
439 if have:
440 self.outAbout.write( qubx.pyenv.Plugins.abouts[ix] )
448 if gtk.RESPONSE_ACCEPT == qubx.pyenvGTK.prompt_choices("Really delete the plugin? This can't be undone."):
449 qubx.pyenv.Plugins.remove( self.lstPlugs.index )
460