|
|
|
#!/usr/bin/env python
|
|
|
|
""" The PyTDE application sampler
|
|
|
|
|
|
|
|
This module defines the top-level widgets for displaying the sampler
|
|
|
|
application.
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
import inspect
|
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
|
|
|
|
from PyTQt.tqt import SIGNAL, SLOT, PYSIGNAL, TQt
|
|
|
|
from PyTQt.tqt import TQVBoxLayout, TQLabel, TQPixmap, TQSplitter, TQFrame, TQDialog
|
|
|
|
from PyTQt.tqt import TQSizePolicy, TQHBoxLayout, TQSpacerItem, TQPushButton
|
|
|
|
|
|
|
|
from tdecore import i18n, TDEAboutData, TDEApplication, TDECmdLineArgs, TDEGlobal
|
|
|
|
from tdecore import TDEGlobalSettings, KWin, KWinModule, KURL, TDEIcon
|
|
|
|
|
|
|
|
from tdeui import KComboBox, TDEListView, TDEListViewItem, KTabWidget, KTextEdit
|
|
|
|
from tdeui import TDEMainWindow, KPushButton, KSplashScreen, KStdAction
|
|
|
|
from tdeui import KKeyDialog, KEditToolbar
|
|
|
|
|
|
|
|
from tdeio import TDETrader
|
|
|
|
from tdeparts import createReadOnlyPart, createReadWritePart
|
|
|
|
from tdehtml import TDEHTMLPart
|
|
|
|
|
|
|
|
import lib
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
__file__
|
|
|
|
except (NameError, ):
|
|
|
|
__file__ = sys.argv[0]
|
|
|
|
|
|
|
|
|
|
|
|
sigDoubleClicked = SIGNAL('doubleClicked(TQListViewItem *)')
|
|
|
|
sigViewItemSelected = SIGNAL('selectionChanged(TQListViewItem *)')
|
|
|
|
sigSampleSelected = PYSIGNAL('sample selected')
|
|
|
|
|
|
|
|
blank = KURL('about:blank')
|
|
|
|
|
|
|
|
|
|
|
|
def appConfig(group=None):
|
|
|
|
""" appConfig(group=None) -> returns the application TDEConfig
|
|
|
|
|
|
|
|
"""
|
|
|
|
config = TDEGlobal.instance().config()
|
|
|
|
if group is not None:
|
|
|
|
config.setGroup(group)
|
|
|
|
return config
|
|
|
|
|
|
|
|
|
|
|
|
def getIcon(name, group=TDEIcon.NoGroup, size=TDEIcon.SizeSmall):
|
|
|
|
""" returns a kde icon by name
|
|
|
|
|
|
|
|
"""
|
|
|
|
return TDEGlobal.instance().iconLoader().loadIcon(name, group, size)
|
|
|
|
|
|
|
|
|
|
|
|
def getIconSet(name, group=TDEIcon.NoGroup, size=TDEIcon.SizeSmall):
|
|
|
|
""" returns a kde icon set by name
|
|
|
|
|
|
|
|
"""
|
|
|
|
return TDEGlobal.instance().iconLoader().loadIconSet(name, group, size)
|
|
|
|
|
|
|
|
|
|
|
|
def buildPart(parent, query, constraint, writable=False):
|
|
|
|
""" builds the first available offered part on the parent
|
|
|
|
|
|
|
|
"""
|
|
|
|
offers = TDETrader.self().query(query, constraint)
|
|
|
|
for ptr in offers:
|
|
|
|
if writable:
|
|
|
|
builder = createReadWritePart
|
|
|
|
else:
|
|
|
|
builder = createReadOnlyPart
|
|
|
|
part = builder(ptr.library(), parent, ptr.name())
|
|
|
|
if part:
|
|
|
|
break
|
|
|
|
return part
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CommonFrame(TQFrame):
|
|
|
|
""" provides a modicum of reuse
|
|
|
|
|
|
|
|
"""
|
|
|
|
def __init__(self, parent):
|
|
|
|
TQFrame.__init__(self, parent)
|
|
|
|
layout = TQVBoxLayout(self)
|
|
|
|
layout.setAutoAdd(True)
|
|
|
|
layout.setAlignment(TQt.AlignCenter | TQt.AlignVCenter)
|
|
|
|
|
|
|
|
|
|
|
|
class SamplerFrame(CommonFrame):
|
|
|
|
""" frame type that swaps out old widgets for new when told to do so
|
|
|
|
|
|
|
|
"""
|
|
|
|
def __init__(self, parent):
|
|
|
|
CommonFrame.__init__(self, parent)
|
|
|
|
self.widget = None
|
|
|
|
|
|
|
|
def setWidget(self, widget):
|
|
|
|
self.layout().deleteAllItems()
|
|
|
|
previous = self.widget
|
|
|
|
if previous:
|
|
|
|
previous.close()
|
|
|
|
delattr(self, 'widget')
|
|
|
|
self.widget = widget
|
|
|
|
|
|
|
|
def showSample(self, item, module):
|
|
|
|
try:
|
|
|
|
frameType = module.builder()
|
|
|
|
except (AttributeError, ):
|
|
|
|
print('No sample callable defined in %s' % (module.name(), ))
|
|
|
|
else:
|
|
|
|
frame = frameType(self)
|
|
|
|
self.setWidget(frame)
|
|
|
|
frame.show()
|
|
|
|
|
|
|
|
|
|
|
|
class SourceFrame(CommonFrame):
|
|
|
|
""" frame with part for displaying python source
|
|
|
|
|
|
|
|
"""
|
|
|
|
def __init__(self, parent):
|
|
|
|
CommonFrame.__init__(self, parent)
|
|
|
|
query = ''
|
|
|
|
self.part = buildPart(self, 'application/x-python', query, False)
|
|
|
|
|
|
|
|
def showModuleSource(self, item, module):
|
|
|
|
if not self.part:
|
|
|
|
print('No part available for displaying python source.')
|
|
|
|
return
|
|
|
|
try:
|
|
|
|
modulefile = inspect.getabsfile(module.module)
|
|
|
|
except:
|
|
|
|
return
|
|
|
|
self.part.openURL(blank)
|
|
|
|
if os.path.splitext(modulefile)[-1] == '.py':
|
|
|
|
self.part.openURL(KURL('file://%s' % modulefile))
|
|
|
|
|
|
|
|
|
|
|
|
class WebFrame(CommonFrame):
|
|
|
|
""" frame with part for viewing web pages
|
|
|
|
|
|
|
|
"""
|
|
|
|
docBase = 'http://www.riverbankcomputing.com/Docs/PyTDE3/classref/'
|
|
|
|
|
|
|
|
def __init__(self, parent):
|
|
|
|
CommonFrame.__init__(self, parent)
|
|
|
|
self.part = part = buildPart(self, 'text/html', "Type == 'Service'")
|
|
|
|
#part.connect(part, SIGNAL('tdehtmlMousePressEvent(a)'), self.onURL)
|
|
|
|
|
|
|
|
def onURL(self, a):
|
|
|
|
print('****', a)
|
|
|
|
|
|
|
|
def showDocs(self, item, module):
|
|
|
|
try:
|
|
|
|
mod, cls = module.module.docParts
|
|
|
|
except (AttributeError, ):
|
|
|
|
url = blank
|
|
|
|
else:
|
|
|
|
url = KURL(self.docUrl(mod, cls))
|
|
|
|
self.part.openURL(url)
|
|
|
|
|
|
|
|
|
|
|
|
def docUrl(self, module, klass):
|
|
|
|
""" docUrl(name) -> return a doc url given a name from the kde libs
|
|
|
|
|
|
|
|
"""
|
|
|
|
return '%s/%s/%s.html' % (self.docBase, module, klass, )
|
|
|
|
|
|
|
|
|
|
|
|
class OutputFrame(KTextEdit):
|
|
|
|
""" text widget that acts (just enough) like a file
|
|
|
|
|
|
|
|
"""
|
|
|
|
def __init__(self, parent, filehandle):
|
|
|
|
KTextEdit.__init__(self, parent)
|
|
|
|
self.filehandle = filehandle
|
|
|
|
self.setReadOnly(True)
|
|
|
|
self.setFont(TDEGlobalSettings.fixedFont())
|
|
|
|
|
|
|
|
|
|
|
|
def write(self, text):
|
|
|
|
self.insert(text)
|
|
|
|
|
|
|
|
|
|
|
|
def clear(self):
|
|
|
|
self.setText('')
|
|
|
|
|
|
|
|
|
|
|
|
def __getattr__(self, name):
|
|
|
|
return getattr(self.filehandle, name)
|
|
|
|
|
|
|
|
|
|
|
|
class SamplerListView(TDEListView):
|
|
|
|
""" the main list view of samples
|
|
|
|
|
|
|
|
"""
|
|
|
|
def __init__(self, parent):
|
|
|
|
TDEListView.__init__(self, parent)
|
|
|
|
self.addColumn(i18n('Sample'))
|
|
|
|
self.setRootIsDecorated(True)
|
|
|
|
|
|
|
|
modules = lib.listmodules()
|
|
|
|
modules.sort(key=lambda a: a[0])
|
|
|
|
|
|
|
|
modmap = dict(modules)
|
|
|
|
modules = [(name.split('.'), name, mod) for name, mod in modules]
|
|
|
|
roots, cache = {}, {}
|
|
|
|
|
|
|
|
for names, modname, module in modules:
|
|
|
|
topname, subnames = names[0], names[1:]
|
|
|
|
item = roots.get(topname, None)
|
|
|
|
if item is None:
|
|
|
|
roots[topname] = item = TDEListViewItem(self, module.labelText())
|
|
|
|
item.module = module
|
|
|
|
item.setPixmap(0, getIcon(module.icon()))
|
|
|
|
|
|
|
|
bname = ''
|
|
|
|
subitem = item
|
|
|
|
for subname in subnames:
|
|
|
|
bname = '%s.%s' % (bname, subname, )
|
|
|
|
item = cache.get(bname, None)
|
|
|
|
if item is None:
|
|
|
|
subitem = cache[bname] = \
|
|
|
|
TDEListViewItem(subitem, module.labelText())
|
|
|
|
subitem.module = module
|
|
|
|
subitem.setPixmap(0, getIcon(module.icon()))
|
|
|
|
subitem = item
|
|
|
|
|
|
|
|
for root in list(roots.values()):
|
|
|
|
self.setOpen(root, True)
|
|
|
|
|
|
|
|
|
|
|
|
class SamplerMainWindow(TDEMainWindow):
|
|
|
|
""" the main window
|
|
|
|
|
|
|
|
"""
|
|
|
|
def __init__(self, *args):
|
|
|
|
TDEMainWindow.__init__(self, *args)
|
|
|
|
self.hSplitter = hSplit = TQSplitter(TQt.Horizontal, self)
|
|
|
|
self.samplesList = samplesList = SamplerListView(hSplit)
|
|
|
|
self.vSplitter = vSplit = TQSplitter(TQt.Vertical, hSplit)
|
|
|
|
self.setCentralWidget(hSplit)
|
|
|
|
self.setIcon(getIcon('kmail'))
|
|
|
|
|
|
|
|
hSplit.setOpaqueResize(True)
|
|
|
|
vSplit.setOpaqueResize(True)
|
|
|
|
|
|
|
|
self.contentTabs = cTabs = KTabWidget(vSplit)
|
|
|
|
self.outputTabs = oTabs = KTabWidget(vSplit)
|
|
|
|
|
|
|
|
self.sampleFrame = SamplerFrame(cTabs)
|
|
|
|
self.sourceFrame = SourceFrame(cTabs)
|
|
|
|
self.webFrame = WebFrame(cTabs)
|
|
|
|
|
|
|
|
cTabs.insertTab(self.sampleFrame, getIconSet('exec'), i18n('Sample'))
|
|
|
|
cTabs.insertTab(self.sourceFrame, getIconSet('source'), i18n('Source'))
|
|
|
|
cTabs.insertTab(self.webFrame, getIconSet('help'), i18n('Docs'))
|
|
|
|
|
|
|
|
sys.stdout = self.stdoutFrame = OutputFrame(oTabs, sys.stdout)
|
|
|
|
sys.stderr = self.stderrFrame = OutputFrame(oTabs, sys.stderr)
|
|
|
|
|
|
|
|
termIcons = getIconSet('terminal')
|
|
|
|
oTabs.insertTab(self.stdoutFrame, termIcons, i18n('stdout'))
|
|
|
|
oTabs.insertTab(self.stderrFrame, termIcons, i18n('stderr'))
|
|
|
|
|
|
|
|
self.resize(640, 480)
|
|
|
|
height, width = self.height(), self.width()
|
|
|
|
hSplit.setSizes([int(width * 0.35), int(width * 0.65)])
|
|
|
|
vSplit.setSizes([int(height * 0.80), int(height * 0.20)])
|
|
|
|
|
|
|
|
self.xmlRcFileName = os.path.abspath(os.path.join(os.path.dirname(__file__), 'sampler.rc'))
|
|
|
|
self.setXMLFile(self.xmlRcFileName)
|
|
|
|
config = appConfig()
|
|
|
|
actions = self.actionCollection()
|
|
|
|
actions.readShortcutSettings("", config)
|
|
|
|
self.quitAction = KStdAction.quit(self.close, actions)
|
|
|
|
|
|
|
|
self.toggleMenubarAction = \
|
|
|
|
KStdAction.showMenubar(self.showMenubar, actions)
|
|
|
|
self.toggleToolbarAction = \
|
|
|
|
KStdAction.showToolbar(self.showToolbar, actions)
|
|
|
|
self.toggleStatusbarAction = \
|
|
|
|
KStdAction.showStatusbar(self.showStatusbar, actions)
|
|
|
|
self.configureKeysAction = \
|
|
|
|
KStdAction.keyBindings(self.showConfigureKeys, actions)
|
|
|
|
self.configureToolbarAction = \
|
|
|
|
KStdAction.configureToolbars(self.showConfigureToolbars, actions)
|
|
|
|
self.configureAppAction = \
|
|
|
|
KStdAction.preferences(self.showConfiguration, actions)
|
|
|
|
|
|
|
|
connect = self.connect
|
|
|
|
connect(samplesList, sigViewItemSelected, self.sampleSelected)
|
|
|
|
connect(self, sigSampleSelected, self.reloadModule)
|
|
|
|
connect(self, sigSampleSelected, self.sourceFrame.showModuleSource)
|
|
|
|
connect(self, sigSampleSelected, self.sampleFrame.showSample)
|
|
|
|
connect(self, sigSampleSelected, self.webFrame.showDocs)
|
|
|
|
|
|
|
|
self.restoreWindowSize(config)
|
|
|
|
self.createGUI(self.xmlRcFileName, 0)
|
|
|
|
self.sourceFrame.part.openURL(KURL('file://%s' % os.path.abspath(__file__)))
|
|
|
|
|
|
|
|
|
|
|
|
def showConfiguration(self):
|
|
|
|
""" showConfiguration() -> display the config dialog
|
|
|
|
|
|
|
|
"""
|
|
|
|
return
|
|
|
|
## not yet implemented
|
|
|
|
dlg = configdialog.ConfigurationDialog(self)
|
|
|
|
for obj in (self.stderrFrame, self.stdoutFrame, self.pythonShell):
|
|
|
|
call = getattr(obj, 'configChanged', None)
|
|
|
|
if call:
|
|
|
|
self.connect(dlg, util.sigConfigChanged, call)
|
|
|
|
dlg.show()
|
|
|
|
|
|
|
|
|
|
|
|
def senderCheckShow(self, widget):
|
|
|
|
""" senderCheckShow(widget) -> show or hide widget if sender is checked
|
|
|
|
|
|
|
|
"""
|
|
|
|
if self.sender().isChecked():
|
|
|
|
widget.show()
|
|
|
|
else:
|
|
|
|
widget.hide()
|
|
|
|
|
|
|
|
|
|
|
|
def showMenubar(self):
|
|
|
|
""" showMenuBar() -> toggle the menu bar
|
|
|
|
|
|
|
|
"""
|
|
|
|
self.senderCheckShow(self.menuBar())
|
|
|
|
|
|
|
|
|
|
|
|
def showToolbar(self):
|
|
|
|
""" showToolbar() -> toggle the tool bar
|
|
|
|
|
|
|
|
"""
|
|
|
|
self.senderCheckShow(self.toolBar())
|
|
|
|
|
|
|
|
|
|
|
|
def showStatusbar(self):
|
|
|
|
""" showStatusbar() -> toggle the status bar
|
|
|
|
|
|
|
|
"""
|
|
|
|
self.senderCheckShow(self.statusBar())
|
|
|
|
|
|
|
|
|
|
|
|
def showConfigureKeys(self):
|
|
|
|
""" showConfigureKeys() -> show the shortcut keys dialog
|
|
|
|
|
|
|
|
"""
|
|
|
|
ret = KKeyDialog.configure(self.actionCollection(), self)
|
|
|
|
print(ret)
|
|
|
|
if ret == TQDialog.Accepted:
|
|
|
|
actions = self.actionCollection()
|
|
|
|
actions.writeShortcutSettings(None, appConfig())
|
|
|
|
|
|
|
|
|
|
|
|
def showConfigureToolbars(self):
|
|
|
|
""" showConfigureToolbars() -> broken
|
|
|
|
|
|
|
|
"""
|
|
|
|
dlg = KEditToolbar(self.actionCollection(), self.xmlRcFileName)
|
|
|
|
self.connect(dlg, SIGNAL('newToolbarConfig()'), self.rebuildGui)
|
|
|
|
#connect(self, sigSampleSelected, self.sourceFrame.showModuleSource)
|
|
|
|
|
|
|
|
dlg.exec_loop()
|
|
|
|
|
|
|
|
|
|
|
|
def rebuildGui(self):
|
|
|
|
""" rebuildGui() -> recreate the gui and refresh the palette
|
|
|
|
|
|
|
|
"""
|
|
|
|
self.createGUI(self.xmlRcFileName, 0)
|
|
|
|
for widget in (self.toolBar(), self.menuBar(), ):
|
|
|
|
widget.setPalette(self.palette())
|
|
|
|
|
|
|
|
|
|
|
|
def sampleSelected(self):
|
|
|
|
""" sampleSelected() -> emit the current item and its module
|
|
|
|
|
|
|
|
"""
|
|
|
|
self.stdoutFrame.clear()
|
|
|
|
self.stderrFrame.clear()
|
|
|
|
item = self.sender().currentItem()
|
|
|
|
self.emit(sigSampleSelected, (item, item.module))
|
|
|
|
|
|
|
|
|
|
|
|
def setSplashPixmap(self, pixmap):
|
|
|
|
""" setSplashPixmap(pixmap) -> assimilate the splash screen pixmap
|
|
|
|
|
|
|
|
"""
|
|
|
|
target = self.sampleFrame
|
|
|
|
label = TQLabel(target)
|
|
|
|
label.setPixmap(pixmap)
|
|
|
|
target.setWidget(label)
|
|
|
|
|
|
|
|
|
|
|
|
def reloadModule(self, item, module):
|
|
|
|
print('reload: ', importlib.reload(module.module), file=sys.__stdout__)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
description = b"A sampler application"
|
|
|
|
version = b"1.0"
|
|
|
|
aboutData = TDEAboutData (b"", b"",\
|
|
|
|
version, description, TDEAboutData.License_GPL,\
|
|
|
|
b"(C) 2003 whoever the author is")
|
|
|
|
|
|
|
|
options = [(b'+item', b'An item in the sys.path')]
|
|
|
|
TDECmdLineArgs.init(sys.argv, aboutData)
|
|
|
|
app = TDEApplication()
|
|
|
|
|
|
|
|
splashpix = TQPixmap(os.path.join(lib.samplerpath, 'aboutkde.png'))
|
|
|
|
splash = KSplashScreen(splashpix)
|
|
|
|
splash.resize(splashpix.size())
|
|
|
|
splash.show()
|
|
|
|
mainWindow = SamplerMainWindow()
|
|
|
|
mainWindow.setSplashPixmap(splashpix)
|
|
|
|
mainWindow.show()
|
|
|
|
splash.finish(mainWindow)
|
|
|
|
app.exec_loop()
|