##// END OF EJS Templates
allow splitting and merging of heading cells...
allow splitting and merging of heading cells I consider it a bug that you couldn't merge with heading cells, and that you couldn't split them, either. (So much so that I thought it was a bug in ipython-vimception when I ran into it). This change removes that limitation, so heading cells are on par with the other cells in terms of the kinds of manipulations one can carry out with them.

File last commit:

r16532:40354894
r17417:811c7332
Show More
magic_helper.py
213 lines | 7.5 KiB | text/x-python | PythonLexer
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 """MagicHelper - dockable widget showing magic commands for the MainWindow
Dimitry Kloper
Move Maigic Helper into separate class/module/file
r16483 """
Dimitry Kloper
Updated file headers according to IPython Copyright Policy
r16519 # Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
Dimitry Kloper
Move Maigic Helper into separate class/module/file
r16483 #-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
# stdlib imports
import json
import re
import sys
# System library imports
from IPython.external.qt import QtGui,QtCore
from IPython.core.magic import magic_escapes
class MagicHelper(QtGui.QDockWidget):
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 """MagicHelper - dockable widget for convenient search and running of
magic command for IPython QtConsole.
"""
#---------------------------------------------------------------------------
# signals
#---------------------------------------------------------------------------
Dimitry Kloper
Move Maigic Helper into separate class/module/file
r16483
Dimitry Kloper
Rename pyqtSignal to Signal....
r16532 pasteRequested = QtCore.Signal(str, name = 'pasteRequested')
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 """This signal is emitted when user wants to paste selected magic
command into the command line.
"""
Dimitry Kloper
Rename pyqtSignal to Signal....
r16532 runRequested = QtCore.Signal(str, name = 'runRequested')
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 """This signal is emitted when user wants to execute selected magic command
"""
Dimitry Kloper
Rename pyqtSignal to Signal....
r16532 readyForUpdate = QtCore.Signal(name = 'readyForUpdate')
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 """This signal is emitted when MagicHelper is ready to be populated.
Since kernel querying mechanisms are out of scope of this class,
it expects its owner to invoke MagicHelper.populate_magic_helper()
as a reaction on this event.
"""
Dimitry Kloper
Move Maigic Helper into separate class/module/file
r16483
#---------------------------------------------------------------------------
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 # constructor
Dimitry Kloper
Move Maigic Helper into separate class/module/file
r16483 #---------------------------------------------------------------------------
def __init__(self, name, parent):
super(MagicHelper, self).__init__(name, parent)
self.data = None
class MinListWidget(QtGui.QListWidget):
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 """Temp class to overide the default QListWidget size hint
in order to make MagicHelper narrow
"""
Dimitry Kloper
Move Maigic Helper into separate class/module/file
r16483 def sizeHint(self):
s = QtCore.QSize()
s.setHeight(super(MinListWidget,self).sizeHint().height())
s.setWidth(self.sizeHintForColumn(0))
return s
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 # construct content
Dimitry Kloper
Move Maigic Helper into separate class/module/file
r16483 self.frame = QtGui.QFrame()
self.search_label = QtGui.QLabel("Search:")
self.search_line = QtGui.QLineEdit()
self.search_class = QtGui.QComboBox()
self.search_list = MinListWidget()
self.paste_button = QtGui.QPushButton("Paste")
self.run_button = QtGui.QPushButton("Run")
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 # layout all the widgets
Dimitry Kloper
Move Maigic Helper into separate class/module/file
r16483 main_layout = QtGui.QVBoxLayout()
search_layout = QtGui.QHBoxLayout()
search_layout.addWidget(self.search_label)
search_layout.addWidget(self.search_line, 10)
main_layout.addLayout(search_layout)
main_layout.addWidget(self.search_class)
main_layout.addWidget(self.search_list, 10)
action_layout = QtGui.QHBoxLayout()
action_layout.addWidget(self.paste_button)
action_layout.addWidget(self.run_button)
main_layout.addLayout(action_layout)
self.frame.setLayout(main_layout)
self.setWidget(self.frame)
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 # connect all the relevant signals to handlers
self.visibilityChanged[bool].connect( self._update_magic_helper )
Dimitry Kloper
Move Maigic Helper into separate class/module/file
r16483 self.search_class.activated[int].connect(
self.class_selected
)
self.search_line.textChanged[str].connect(
self.search_changed
)
self.search_list.itemDoubleClicked[QtGui.QListWidgetItem].connect(
self.paste_requested
)
self.paste_button.clicked[bool].connect(
self.paste_requested
)
self.run_button.clicked[bool].connect(
self.run_requested
)
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 #---------------------------------------------------------------------------
# implementation
#---------------------------------------------------------------------------
def _update_magic_helper(self, visible):
"""Start update sequence.
This method is called when MagicHelper becomes visible. It clears
the content and emits readyForUpdate signal. The owner of the
instance is expected to invoke populate_magic_helper() when magic
info is available.
"""
Dimitry Kloper
Move Maigic Helper into separate class/module/file
r16483 if not visible or self.data != None:
return
self.data = {}
self.search_class.clear()
self.search_class.addItem("Populating...")
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 self.search_list.clear()
Dimitry Kloper
Eliminate main window logic from MagicHelper....
r16484 self.readyForUpdate.emit()
Dimitry Kloper
Move Maigic Helper into separate class/module/file
r16483
def populate_magic_helper(self, data):
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 """Expects data returned by lsmagics query from kernel.
Populates the search_class and search_list with relevant items.
"""
Dimitry Kloper
Move Maigic Helper into separate class/module/file
r16483 self.search_class.clear()
self.search_list.clear()
self.data = json.loads(
data['data'].get('application/json', {})
)
self.search_class.addItem('All Magics', 'any')
classes = set()
for mtype in sorted(self.data):
subdict = self.data[mtype]
for name in sorted(subdict):
classes.add(subdict[name])
for cls in sorted(classes):
label = re.sub("([a-zA-Z]+)([A-Z][a-z])","\g<1> \g<2>", cls)
self.search_class.addItem(label, cls)
self.filter_magic_helper('.', 'any')
def class_selected(self, index):
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 """Handle search_class selection changes
"""
Dimitry Kloper
Move Maigic Helper into separate class/module/file
r16483 item = self.search_class.itemData(index)
regex = self.search_line.text()
self.filter_magic_helper(regex = regex, cls = item)
def search_changed(self, search_string):
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 """Handle search_line text changes.
The text is interpreted as a regular expression
"""
Dimitry Kloper
Move Maigic Helper into separate class/module/file
r16483 item = self.search_class.itemData(
self.search_class.currentIndex()
)
self.filter_magic_helper(regex = search_string, cls = item)
def _get_current_search_item(self, item = None):
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 """Retrieve magic command currently selected in the search_list
"""
Dimitry Kloper
Move Maigic Helper into separate class/module/file
r16483 text = None
if not isinstance(item, QtGui.QListWidgetItem):
item = self.search_list.currentItem()
text = item.text()
return text
def paste_requested(self, item = None):
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 """Emit pasteRequested signal with currently selected item text
"""
Dimitry Kloper
Move Maigic Helper into separate class/module/file
r16483 text = self._get_current_search_item(item)
if text != None:
self.pasteRequested.emit(text)
def run_requested(self, item = None):
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 """Emit runRequested signal with currently selected item text
"""
Dimitry Kloper
Move Maigic Helper into separate class/module/file
r16483 text = self._get_current_search_item(item)
if text != None:
self.runRequested.emit(text)
def filter_magic_helper(self, regex, cls):
Dimitry Kloper
Added more documentation for MagicHelper.
r16491 """Update search_list with magic commands whose text match
regex and class match cls.
If cls equals 'any' - any class matches.
"""
Dimitry Kloper
Move Maigic Helper into separate class/module/file
r16483 if regex == "" or regex == None:
regex = '.'
if cls == None:
cls = 'any'
self.search_list.clear()
for mtype in sorted(self.data):
subdict = self.data[mtype]
prefix = magic_escapes[mtype]
for name in sorted(subdict):
mclass = subdict[name]
pmagic = prefix + name
if (re.match(regex, name) or re.match(regex, pmagic)) and \
(cls == 'any' or cls == mclass):
self.search_list.addItem(pmagic)