This repository has been archived by the owner on May 24, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #259 from nmichaud/feature-multiline-edit
Feature multiline edit
- Loading branch information
Showing
7 changed files
with
429 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
#------------------------------------------------------------------------------ | ||
# Copyright (c) 2013, Enthought, Inc. | ||
# All rights reserved. | ||
#------------------------------------------------------------------------------ | ||
from .qt.QtGui import QTextEdit | ||
from .qt.QtCore import Signal, QTimer | ||
from .qt_control import QtControl | ||
|
||
|
||
class QFocusMultiLineEdit(QTextEdit): | ||
""" A QTextEdit subclass which converts a lost focus event into | ||
a lost focus signal. | ||
""" | ||
lostFocus = Signal() | ||
|
||
delayedTextChanged = Signal() | ||
|
||
def __init__(self, parent=None): | ||
super(QFocusMultiLineEdit, self).__init__(parent) | ||
|
||
# Set up a collapsing timer to fire 200 milliseconds | ||
# after the text is changed | ||
self._changed_timer = timer = QTimer() | ||
timer.setInterval(200) | ||
timer.setSingleShot(True) | ||
timer.timeout.connect(self.delayedTextChanged) | ||
|
||
# Connect the timer to the text changed signal | ||
self.textChanged.connect(timer.start) | ||
|
||
def focusOutEvent(self, event): | ||
self.lostFocus.emit() | ||
return super(QFocusMultiLineEdit, self).focusOutEvent(event) | ||
|
||
|
||
class QtMultiLineField(QtControl): | ||
""" A Qt4 implementation of an Enaml Field. | ||
""" | ||
#: The list of submit triggers for when to submit a text change. | ||
_submit_triggers = [] | ||
|
||
#-------------------------------------------------------------------------- | ||
# Setup Methods | ||
#-------------------------------------------------------------------------- | ||
def create_widget(self, parent, tree): | ||
""" Creates the underlying QFocusMultiLineEdit widget. | ||
""" | ||
return QFocusMultiLineEdit(parent) | ||
|
||
def create(self, tree): | ||
""" Create and initialize the underlying widget. | ||
""" | ||
super(QtMultiLineField, self).create(tree) | ||
self.set_text(tree['text']) | ||
self.set_submit_triggers(tree['submit_triggers']) | ||
self.set_read_only(tree['read_only']) | ||
widget = self.widget() | ||
widget.lostFocus.connect(self.on_lost_focus) | ||
widget.delayedTextChanged.connect(self.on_text_changed) | ||
|
||
#-------------------------------------------------------------------------- | ||
# Private API | ||
#-------------------------------------------------------------------------- | ||
def _submit_text(self): | ||
""" Submit the given text as an update to the server widget. | ||
""" | ||
text = self.widget().toPlainText() | ||
content = {'text': text} | ||
self.send_action('submit_text', content) | ||
|
||
#-------------------------------------------------------------------------- | ||
# Signal Handlers | ||
#-------------------------------------------------------------------------- | ||
def on_lost_focus(self): | ||
""" The signal handler for 'lostFocus' signal. | ||
""" | ||
if 'lost_focus' in self._submit_triggers: | ||
self._submit_text() | ||
|
||
def on_text_changed(self): | ||
""" The signal handler for 'delayedTextChanged' signal. | ||
""" | ||
if 'text_changed' in self._submit_triggers: | ||
self._submit_text() | ||
|
||
#-------------------------------------------------------------------------- | ||
# Message Handlers | ||
#-------------------------------------------------------------------------- | ||
def on_action_set_text(self, content): | ||
""" Handle the 'set_text' action from the Enaml widget. | ||
""" | ||
self.set_text(content['text']) | ||
|
||
def on_action_set_submit_triggers(self, content): | ||
""" Handle the 'set_submit_triggers' action from the Enaml | ||
widget. | ||
""" | ||
self.set_submit_triggers(content['submit_triggers']) | ||
|
||
def on_action_set_read_only(self, content): | ||
""" Handle the 'set_read_only' action from the Enaml widget. | ||
""" | ||
self.set_read_only(content['read_only']) | ||
|
||
#-------------------------------------------------------------------------- | ||
# Widget Update Methods | ||
#-------------------------------------------------------------------------- | ||
def set_text(self, text): | ||
""" Set the text in the underlying widget. | ||
""" | ||
with self.loopback_guard('text'): | ||
self.widget().setText(text) | ||
|
||
def set_submit_triggers(self, triggers): | ||
""" Set the submit triggers for the underlying widget. | ||
""" | ||
self._submit_triggers = triggers | ||
|
||
def set_read_only(self, read_only): | ||
""" Set whether or not the widget is read only. | ||
""" | ||
self.widget().setEnabled(not read_only) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
#------------------------------------------------------------------------------ | ||
# Copyright (c) 2013, Enthought, Inc. | ||
# All rights reserved. | ||
#------------------------------------------------------------------------------ | ||
from traits.api import Bool, Unicode, Enum, List | ||
|
||
from enaml.validation.validator import Validator | ||
|
||
from .control import Control | ||
|
||
|
||
class MultiLineField(Control): | ||
""" A multi line editable text widget. | ||
""" | ||
#: The unicode text to display in the field. | ||
text = Unicode | ||
|
||
#: The list of actions which should cause the client to submit its | ||
#: text to the server for validation and update. The currently | ||
#: supported values are 'lost_focus' and 'return_pressed'. | ||
submit_triggers = List( | ||
Enum('lost_focus', 'text_changed'), ['lost_focus', 'text_changed'] | ||
) | ||
|
||
#: Whether or not the field is read only. Defaults to False. | ||
read_only = Bool(False) | ||
|
||
#: How strongly a component hugs it's contents' width. Text boxes ignore | ||
#: both the width and height hugs by default, so they expand freely in both | ||
#: directions | ||
hug_width = 'ignore' | ||
hug_height = 'ignore' | ||
|
||
#-------------------------------------------------------------------------- | ||
# Initialization | ||
#-------------------------------------------------------------------------- | ||
def snapshot(self): | ||
""" Returns the snapshot dict for the textedit | ||
""" | ||
snap = super(MultiLineField, self).snapshot() | ||
snap['text'] = self.text | ||
snap['submit_triggers'] = self.submit_triggers | ||
snap['read_only'] = self.read_only | ||
return snap | ||
|
||
def bind(self): | ||
""" A method called after initialization which allows the widget | ||
to bind any event handlers necessary. | ||
""" | ||
super(MultiLineField, self).bind() | ||
attrs = ( | ||
'text', 'read_only', | ||
) | ||
self.publish_attributes(*attrs) | ||
self.on_trait_change(self._send_submit_triggers, 'submit_triggers[]') | ||
|
||
#-------------------------------------------------------------------------- | ||
# Private API | ||
#-------------------------------------------------------------------------- | ||
def _send_submit_triggers(self): | ||
""" Send the new submit triggers to the client widget. | ||
""" | ||
content = {'submit_triggers': self.submit_triggers} | ||
self.send_action('set_submit_triggers', content) | ||
|
||
#-------------------------------------------------------------------------- | ||
# Message Handling | ||
#-------------------------------------------------------------------------- | ||
def on_action_submit_text(self, content): | ||
""" Handle the 'submit_text' action from the client widget. | ||
""" | ||
text = content['text'] | ||
self.set_guarded(text=text) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.