Code Monkey home page Code Monkey logo

enaml's Introduction

Welcome to Enaml

Appveyor Build Status Code Coverage Status Documentation Status PyPI version

Enaml is a programming language and framework for creating professional-quality user interfaces with minimal effort.

What you get

  • A declarative programming language, with a Pythonic flavour.
  • Dozens of widgets, ready to go out-of-the-box (built on Qt).
  • A constraints-based layout engine (built on Kiwi).
  • Integration with a data model tool (built on Atom).
  • An (optional) editor to allow you to see what the results will look like, as you type your code.
  • A well-documented and easy-to-follow code base, plus documentation with plenty of worked examples.
  • Language definitions for a number of popular editors.

What it can do for you

  • Build native GUI applications for a range of platforms
    • Quick and simple or complex and specialised.
    • See the structure of your GUI at a glance.
  • Let you rapidly prototype new GUIs interfaces.
    • Intelligently layout your GUI, using symbolic constraints.
    • It automatically adapts for different platforms, different window sizes.
    • Tell the layout engine what your priorities are for layout, without having to count pixels.
  • Encourages easy-to-maintain code:
    • The GUI can detect updates in the model, and refresh its widgets automatically, without low-level code.
    • Clean separation between your model and view, while keeping your controller code simple.
      • You can incorporate Python code directly in the view layer.
      • As your GUI design evolves, the constraints engine can adapt the layout.
      • Object-Oriented design allows you to reuse parts of your GUI in other parts of your projects.
  • Let you customise a GUI for your particular needs.
    • Integrates with your Python code.
    • Include style-sheets to change the appearance across all, or part, of your application quickly.
    • Extend the available widgets or build your own.

Supported Versions

Enaml applications can be run on any platform which supports Python (3.6+). The Qt backend requires Qt (5.9+, see https://doc.qt.io/qt-5/supported-platforms.html).

This includes Linux, Windows, MacOSX, Android and iOS. (Automated testing of Enaml runs on Linux, Windows and MacOSX.)

Enaml is licensed under the Modified BSD License.

Learn More

The Getting Started chapter is a good first step to learn more. It includes installation instructions.

Watch some introductory talks about Enaml and what it can do:

https://img.youtube.com/vi/ycFEwz_hAxk/2.jpg

S. Chris Colbert (@sccolbert) presents at Enthought 2012.

https://img.youtube.com/vi/G5ZYUGL7uTo/1.jpg

Tom Stordy-Allison (@tstordyallison) presents at Pycon UK 2016.

The Enaml documentation includes all the details, including useful examples.

You can ask questions on the Enaml Google Group or with the Enaml tag on StackOverflow.

For version information, see the release notes.

Examples

The Enaml documentation includes many fully-functioning code samples of how to use Enaml. They range from simple demonstrations of how a widget is used, to advanced explorations of the customisability of Enaml GUIs.

Employee Tutorial

The Employee Tutorial shows how constraints and validators can be used to create easy-to-use and professional-looking applications:

http://enaml.readthedocs.io/en/latest/_images/tut_employee_layout.png

Button Ring

The Button Ring Example goes the other way. The result is neither professional-looking nor easy-to-use, but it shows the power and flexibility of constraints-based layout - it might be silly, but this could not be achieved with typical layout systems.

http://enaml.readthedocs.io/en/latest/_images/ex_button_ring.png

Dock Item Alerts

The Dock Item Alerts Example shows some of the customisability of the appearances of an Enaml application. This application's appearance is based on Visual Studio 2010 style, with dockable items, but has some customisations based on the importance of the alerts being shown.

http://enaml.readthedocs.io/en/latest/_images/ex_dock_item_alerts.png

Check out the documentation for more examples.

enaml's People

Contributors

andiecker avatar bburan avatar blink1073 avatar bmwiedemann avatar brett-patterson avatar corranwebster avatar davirenno avatar dependabot[bot] avatar djmattyg007 avatar dwillmer avatar e-calder avatar ericdill avatar frmdstryr avatar gabrielcnr avatar jf--- avatar jminardi avatar julian-o avatar jwiggins avatar matthieudartiailh avatar mikkkee avatar nasefbasdf avatar nmichaud avatar nweston avatar pbehnke avatar rkern avatar rogererens avatar sccolbert avatar tillsten avatar timgates42 avatar warrenweckesser avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

enaml's Issues

include a mechanism to allow windows to intercept closing

In some applications it is important to intercept a window before it is closed. (Canonical example: put up a message box saying "You have unsaved data. Are you sure you want to quit?", if the answer is yes, then continue; if the answer is no then don't close the window.

Pressing a window's close box appears to do this sequence:

  • hide window
  • emit closed event
  • destroy the window's resources

Something should go ahead of this sequence to allow a window to intercept a closing event and prevent further actions if appropriate.

https://github.com/nucleic/enaml/blob/master/enaml/widgets/window.py

def _handle_close(self):
      """ Handle the close event from the proxy widget.

      """
      self.visible = False
      self.closed()
      if self.destroy_on_close:
          deferred_call(self.destroy)

File dialog problem with PySide: QFileDialog has no attribute 'getOpenFileNameAndFilter'.

In PySide, QFileDialog does not have the method getOpenFileNameAndFilter.

To see the problem, run the 'file_dialog.enaml' example (in examples/widgets), and click on the Browse button. Here's the traceback that I get:

$ enaml-run file_dialog.enaml 
Traceback (most recent call last):
  File "/home/warren/local_anaconda_enaml/lib/python2.7/site-packages/enaml-0.8.0-py2.7-linux-x86_64.egg/enaml/qt/q_deferred_caller.py", line 38, in _onPosted
    callback()
  File "/home/warren/local_anaconda_enaml/lib/python2.7/site-packages/enaml-0.8.0-py2.7-linux-x86_64.egg/enaml/qt/q_deferred_caller.py", line 56, in <lambda>
    f = lambda: callback(*args, **kwargs)
  File "/home/warren/local_anaconda_enaml/lib/python2.7/site-packages/enaml-0.8.0-py2.7-linux-x86_64.egg/enaml/qt/qt_file_dialog.py", line 30, in exec_dialog
    path, selected_filter = QFileDialog.getOpenFileNameAndFilter(
AttributeError: type object 'PySide.QtGui.QFileDialog' has no attribute 'getOpenFileNameAndFilter'

Note: I built enaml using the changes in #53 and #54. Without them, other errors will occur before this one.

table view/model support?

Are there plans in the works to support table view/model objects?

I've got more of a Java background than Python; the JTable class worked very nicely for me with its ability to act as a view for a separate table model, using the GlazedLists library. At this point I'm not sure what I should use to put a table together using enaml.

enaml subscription operator appears to be missing an event

platform: Anaconda 1.8.0, enaml 0.8.9 on Windows 7, 64-bit

As discussed in the google group, I have a simple example where the order of events is as follows:

  1. Push button sets P1 equal to !P2. (event is fired)
  2. Observer of P1 does these steps on changes to P1:
    1. some task (which may take zero time; here in my example it is the pathological case of zero time)
    2. then sets P2 = P1. (event is fired)

Separately: Enaml view observes P1 and P2 sets push button enable state to P1 == P2. (So it should be disabled for a very short time during step 2i, then re-enabled.)

I have added a generic observer on both P1 and P2 which prints out the entire change event in each case. The bug appears to be that the enamldef subscription operator only sees one event, even though there are two events.

Test files here: https://gist.github.com/jason-s/a66731b44cf042c8e6ca revision 2

When I run it one way, I get these results (my comments in [[ ]] ), which gives the external result I expect. (Testcase "A")

>python buttontest2.py
Event occurred: {'object': <__main__.P1P2Model object at 0x0000000004751888>, 'type': 'create', 'name': 'p1', 'value': False}
Event occurred: {'object': <__main__.P1P2Model object at 0x0000000004751888>, 'type': 'create', 'name': 'p2', 'value': False}
P1Observer sees p1 = False, sets p2 from False -> False
enamlview Main sees a change: p1=False p2=False
[[jms: click "go" button]]
Event occurred: {'value': True, 'object': <__main__.P1P2Model object at 0x0000000004751888>, 'type': 'update', 'name': 'p1', 'oldvalue': False}
P1Observer sees p1 = True, sets p2 from False -> True
Event occurred: {'value': True, 'object': <__main__.P1P2Model object at 0x0000000004751888>, 'type': 'update', 'name': 'p2', 'oldvalue': False}
enamlview Main sees a change: p1=True p2=True
[[jms: click "stop" button]]
Event occurred: {'value': False, 'object': <__main__.P1P2Model object at 0x0000000004751888>, 'type': 'update', 'name': 'p1', 'oldvalue': True}
P1Observer sees p1 = False, sets p2 from True -> False
Event occurred: {'value': False, 'object': <__main__.P1P2Model object at 0x0000000004751888>, 'type': 'update', 'name': 'p2', 'oldvalue': True}
enamlview Main sees a change: p1=False p2=False

But when I change the order of adding observers (this happens at the start of program), I get this: (Testcase "B")

>python buttontest2.py viewfirst
Event occurred: {'object': <__main__.P1P2Model object at 0x000000000485C508>, 'type': 'create', 'name': 'p1', 'value': False}
Event occurred: {'object': <__main__.P1P2Model object at 0x000000000485C508>, 'type': 'create', 'name': 'p2', 'value': False}
enamlview Main sees a change: p1=False p2=False
[[jms: click "go" button]]
Event occurred: {'value': True, 'object': <__main__.P1P2Model object at 0x000000000485C508>, 'type': 'update', 'name': 'p1', 'oldvalue': False}
enamlview Main sees a change: p1=True p2=False
P1Observer sees p1 = True, sets p2 from False -> True
Event occurred: {'value': True, 'object': <__main__.P1P2Model object at 0x000000000485C508>, 'type': 'update', 'name': 'p2', 'oldvalue': False}
[[jms: go button stays disabled]]

The general observer always shows 2 events (the first event for the change in p1, the second event for the change in p2), but the subscription operator calls bequal() only once, whether in test case A or test case B. I expect it to be called twice, once per event.

What's going on here? Is there an implicit thread issue that I don't know about? I'm not explicitly creating any threads.

Allow out of order declaration of aliases

Code pasted inline breaks currently.

from enaml.widgets.api import Window, Container, PushButton

enamldef Content(Container):
""" The primary application content.

This 'button_foreground' alias provides access to the internal
push button's foreground color.

"""
alias button_bar: button.bar
PushButton: button:
    attr bar = 1

enamldef Main(Window):
""" The main application window.

This window uses the 'button_foreground' alias of the central
content to bind to its internal push button's foreground color.

"""
title = 'Simple Attribute Alias'
Content: pass

Feature requests for size hints

Make Stacks and Notebooks return size hints based on their currently visible item and not the maximum of all the items contained within them.

description of how to handle enaml.widgets.api.Window close events

I'm not sure if this is an enaml question or a PySide question, but I want to handle close events on my main window, so I can either trigger a cleanup action, and/or prevent the window from being closed (e.g. the "You have unsaved data -- are you sure you want to quit?" kind of situation)

How can I do this? I'm using enaml.qt.qt_application.QtApplication along with a main window that is enamldef'd from enaml.widgets.api.Window.

Enaml in Spyder IDE

I am in the process of adding native support for editing enaml files in the Spyder IDE. It is working great so far, I have syntax highlighting and support for introspection. Jedi is used to pick up python-like completions, goto definition, and docs. A regex-based method is used for completions and goto when Jedi fails (for more enaml-specific things). Note that pressing Tab will also trigger a completion (not yet a feature in the mainline Spyder).

Two questions:

  • Do you have any suggests for improvement or any other features you'd like to see?
  • What should I use as an icon when editing enaml files?

Spyder uses Mercurial and Google Code, so you can find my repo as follows:

hg clone https://[email protected]/p/spyderlib-jedi/ 
hg bookmark extras
cd <spyderlib>
./bootstrap.py

The enaml-specific changes I made were:

  • augmented: spyderlib.spyderlib.widgets.sourcecode.codeeditor.CodeEditor
  • added: spyderlib.spyderlib.widgets.sourcecode.syntaxhighlighter.EnamlSH

You will need jedi >= 0.7.0 for the Jedi features. (pip install jedi).

Yield from click handler?

When a button triggers a long running task no UI updates happen until the handler runs its course. What is the correct way to accomplish the following behavior?

        PushButton: step:
            text = 'Step'
            clicked ::
                step.enabled = False
                worker.step()
                step.enabled = True

Tried wrapping in various combinations of Application.deferred_call()/schedule() to no avail.

Some documentation missing, including links to examples

The documentation at http://nucleic.github.io/enaml/docs/index.html starts out extremely well in the "Getting Started" section, but then suddenly stops. For example, the following sections are missing from the docs pages:

  • Data Models
  • Constraints Layout
  • Architecture Reference
  • FAQ
  • Examples (critical!)

This is disconcerting for new users approaching the framework and it's not obvious that the in-repo examples are complete and functional. For example, the Examples page could simply link to the source view of the Examples directory: https://github.com/nucleic/enaml/tree/master/examples

Creating documentation can be an arduous process, but it's very important to the long-term viability of any framework. Please consider adding the missing documentation, or at the very least link to 0.6.x documentation with appropriate notes explaining key differences in newer versions, perhaps by linking to the changelog: https://github.com/nucleic/enaml/blob/master/releasenotes.rst

Repeatable segfault in ToolBar example on OS X/PySide

You can get a segfault reliably by running examples/widgets/tool_bar.enaml, selecting one of the exclusive toolbar buttons and then closing the window.

Looking at the stack trace, it would appear that the toolbar destructor is attempting to reference a Python object which has already been garbage collected.

This may be a PySide issue.

error in popup_view.enaml?

http://nucleic.github.io/enaml/docs/examples/ex_popup_view.html

I just tried it -- really slick-looking UI, but it crashes if I click on the main window when any of the popups are open.

Here's the traceback. I'm using Anaconda Python 1.8.0 (ignore the "1.6.0" directory path) which includes enaml 0.8.3, pyside 1.2.1. PC platform = Windows 7, 64-bit.

If this has been fixed since then, let me know + I'll ping the Anaconda people.

Traceback (most recent call last):
  File "c:\app\python\anaconda\1.6.0\lib\site-packages\enaml\qt\qt_popup_view.py", line 113, in on_closed
    d._popup_closed()
  File "c:\app\python\anaconda\1.6.0\lib\site-packages\enaml\widgets\popup_view.py", line 253, in _popup_closed
    deferred_call(self.destroy)
  File "c:\app\python\anaconda\1.6.0\lib\site-packages\enaml\application.py", line 462, in deferred_call
    app.deferred_call(callback, *args, **kwargs)
  File "c:\app\python\anaconda\1.6.0\lib\site-packages\enaml\qt\qt_application.py", line 72, in deferred_call
    deferredCall(callback, *args, **kwargs)
  File "c:\app\python\anaconda\1.6.0\lib\site-packages\enaml\qt\q_deferred_caller.py", line 61, in deferredCall
    event = DeferredCallEvent(callback, args, kwargs)
  File "c:\app\python\anaconda\1.6.0\lib\site-packages\enaml\qt\q_deferred_caller.py", line 21, in __init__
    super(DeferredCallEvent, self).__init__(self.Type)
TypeError: 'PySide.QtCore.QEvent' called with wrong argument types:
  PySide.QtCore.QEvent(int)
Supported signatures:
  PySide.QtCore.QEvent(PySide.QtCore.QEvent.Type)

Python 3

any plans to make it Python 3 compatible?

Forum / mailing list

I guess opening an issue for this kind of underscores the point - has nucleic enaml got a mailing list / forum? Traditionally, enthought's devel list was the place to consult the enaml developers, but this situation has become somewhat confusing. Given that enthought is often fwd'ing to enaml on the mailing list, perhaps it time to consider this?

Looking fwd not having to polute this namespace no more ;)

Text Eliding when changing styles in the DockArea

When changing between styles on the DockArea the labels on the dock item title bars elide their text if the font size incurs a large increase. This is likely caused by QTextLabel caching it's size hint and not invalidating that cache on a style change. An appropriate fix would be to catch the QEvent::StyleChange and invalidate the cached hint.

RuntimeError: Failed to disconnect signal lostFocus().

With enaml 0.8.0 (2b2dfd6) and atom 0.3.3 (6dcf3e411bfc7ebb2ee8faffa7c1a0d5ab85b99b), and using the version of PySide in the latest anaconda, many of the examples raise a RuntimeError. E.g.

$ enaml-run form.enaml 
Traceback (most recent call last):
  File "/home/warren/local_enaml/bin/enaml-run", line 9, in <module>
    load_entry_point('enaml==0.8.0', 'console_scripts', 'enaml-run')()
  File "/home/warren/local_enaml/lib/python2.7/site-packages/enaml-0.8.0-py2.7-linux-x86_64.egg/enaml/runner.py", line 64, in main
    window.show()
  File "/home/warren/local_enaml/lib/python2.7/site-packages/enaml-0.8.0-py2.7-linux-x86_64.egg/enaml/widgets/window.py", line 331, in show
    self.activate_proxy()
  File "/home/warren/local_enaml/lib/python2.7/site-packages/enaml-0.8.0-py2.7-linux-x86_64.egg/enaml/widgets/toolkit_object.py", line 206, in activate_proxy
    child.activate_proxy()
  File "/home/warren/local_enaml/lib/python2.7/site-packages/enaml-0.8.0-py2.7-linux-x86_64.egg/enaml/widgets/toolkit_object.py", line 206, in activate_proxy
    child.activate_proxy()
  File "/home/warren/local_enaml/lib/python2.7/site-packages/enaml-0.8.0-py2.7-linux-x86_64.egg/enaml/widgets/toolkit_object.py", line 203, in activate_proxy
    self.activate_top_down()
  File "/home/warren/local_enaml/lib/python2.7/site-packages/enaml-0.8.0-py2.7-linux-x86_64.egg/enaml/widgets/toolkit_object.py", line 219, in activate_top_down
    self.proxy.activate_top_down()
  File "/home/warren/local_enaml/lib/python2.7/site-packages/enaml-0.8.0-py2.7-linux-x86_64.egg/enaml/qt/qt_toolkit_object.py", line 68, in activate_top_down
    self.init_widget()
  File "/home/warren/local_enaml/lib/python2.7/site-packages/enaml-0.8.0-py2.7-linux-x86_64.egg/enaml/qt/qt_field.py", line 78, in init_widget
    self.set_submit_triggers(d.submit_triggers)
  File "/home/warren/local_enaml/lib/python2.7/site-packages/enaml-0.8.0-py2.7-linux-x86_64.egg/enaml/qt/qt_field.py", line 168, in set_submit_triggers
    widget.lostFocus.disconnect(handler)
RuntimeError: Failed to disconnect signal lostFocus().

programmatic access to a widget's descendants?

is there any way you could put a quick doc about the object model / Widget API? I've looked at the source but I can't figure out where it gets various parts of its functionality.

I need to figure out how to add PySide GUI components that are not currently covered by enaml; it appears as though the widgets added in the .enaml file have to be descended from the Declarative class. So I wanted to try to add additional widgets outside of the .enaml file. All I can figure out so far is that the .children attribute allows accessing child elements from a parent.

Is there an equivalent to the DOM getElementById()? I want to create a dummy container in the .enaml file and then manually add a child element into it from my .py file.

FlowArea, GroupBox, MainWindow and other examples fail

Running the examples/widgets/flow_area.enaml file gives this traceback.

Traceback (most recent call last):
  File "/Users/cwebster/Library/Enthought/Canopy_64bit/User/bin/enaml-run", line 9, in <module>
    load_entry_point('enaml==0.7.16', 'console_scripts', 'enaml-run')()
  File "/Users/cwebster/src/enaml/enaml/runner.py", line 57, in main
    exec code in ns
  File "flow_area.enaml", line 89, in 
    enamldef Item(FlowItem):
  File "/Users/cwebster/src/enaml/enaml/core/compiler_helpers.py", line 36, in __make_enamldef_helper
    Resolver.resolve(node, f_globals)
  File "/Users/cwebster/src/enaml/enaml/core/resolver.py", line 55, in resolve
    resolver._call_operators()
  File "/Users/cwebster/src/enaml/enaml/core/resolver.py", line 233, in _call_operators
    binding.operator_func(klass, binding)
  File "/Users/cwebster/src/enaml/enaml/core/operators.py", line 489, in op_simple
    bind_write_operator(klass, binding, OpSimple(binding))
  File "/Users/cwebster/src/enaml/enaml/core/operators.py", line 463, in bind_write_operator
    clone = member.clone()
  File "/Users/cwebster/src/atom/atom/list.py", line 76, in clone
    clone.set_validate_mode(mode, item_clone)
TypeError: Expected object of type `Validate`. Got object of type `int` instead.

You get similar errors with group_box.enaml, main_window.enaml, mpl_canvas.enaml, and popup_view.enaml.

Also happens in examples/stdlib/mapped_view.enaml, examples/dynamic/fields.enaml and examples/layout/advances/button_ring.enaml.

This is running under PySide, so it could be a difference between PyQt and PySide validation systems.

Enaml parser allows incorrect Python

This compiles and runs but shouldn't: can't have keyword arg after non-keyword arg.

enamldef Main(Window):
    Container:
        constraints = [vbox(spacer=12, hbox(foo, bar), spacer=12)]
        PushButton: foo: pass
        PushButton: bar: pass

Bug in template instantiation scoping code

The compiler generates bad code for this:

from enaml.widgets.api import *


template Foo():
    Field:
        placeholder = 'foo'

enamldef Main(Window):
    Container:
        Foo(): f:
            f.text = f.placeholder

The scope key for the outer closure scope is not correctly passed to compiler helper which binds the expression for f.placeholder.

Error running examples from master branch

When I run the tutorial example "hello_world.py" using enaml 0.7.19 packaged with anaconda, it works fine. When I install enaml from the master branch (e.g. 2b2dfd6) at nucleic/enaml, I get this:

$ python hello_world.py 
Traceback (most recent call last):
  File "hello_world.py", line 25, in <module>
    main()
  File "hello_world.py", line 14, in main
    from hello_world_view import Main
  File "/home/warren/local_enaml/lib/python2.7/site-packages/enaml-0.8.0-py2.7-linux-x86_64.egg/enaml/core/import_hooks.py", line 143, in load_module
    exec code in mod.__dict__
  File "/home/warren/gitwork/nucleic_enaml/examples/tutorial/hello_world/hello_world_view.enaml", line 1, in 
    #------------------------------------------------------------------------------
  File "/home/warren/local_enaml/lib/python2.7/site-packages/enaml-0.8.0-py2.7-linux-x86_64.egg/enaml/core/compiler_helpers.py", line 15, in <module>
    from .declarative import Declarative, d_
  File "/home/warren/local_enaml/lib/python2.7/site-packages/enaml-0.8.0-py2.7-linux-x86_64.egg/enaml/core/declarative.py", line 54, in <module>
    class Declarative(Object):
  File "/home/warren/local_enaml/lib/python2.7/site-packages/enaml-0.8.0-py2.7-linux-x86_64.egg/enaml/core/declarative_meta.py", line 123, in __new__
    patch_d_member(value)
  File "/home/warren/local_enaml/lib/python2.7/site-packages/enaml-0.8.0-py2.7-linux-x86_64.egg/enaml/core/declarative_meta.py", line 90, in patch_d_member
    member.add_static_observer(declarative_change_handler)
TypeError: Error when calling the metaclass bases
    Expected object of type `str`. Got object of type `function` instead.

I get the same error when running the widgets examples.

Significant documentation missing, including examples

The documentation at http://nucleic.github.io/enaml/docs/index.html starts out extremely well in the "Getting Started" section, but then suddenly stops. For example, the following sections are missing entirely:

  • Data Models
  • Constraints Layout
  • Architecture Reference
  • FAQ
  • Examples (critical!)

Creating documentation can be an arduous process, but it's very important to the long-term viability of any framework. Please consider adding the missing documentation, or at the very least link to 0.6.x documentation with appropriate notes explaining key differences in newer versions.

Erroneous error message

The following enaml file:

from atom.api import Atom, Float, Typed

from enaml.widgets.api import MainWindow, Container, Form
from enaml.stdlib.fields import FloatField

class Quote(Atom):
    price = Float()

class Model(Atom):
    quote = Typed(Quote)

enamldef Main(MainWindow):
    attr model = Model()

    Container:
        Form:
            FloatField:
                value := model.quote.price

causes a NameError: name 'value' is not defined exception. The issue is that the quote attribute defaults to None
and the price attribute can't be bound.

dependency on SIP?

Is the dependency on SIP creating a dependency on PyQT (and messing up support of PySide?) I'm getting ImportErrors from not having sip installed when testing the hello_world example.

PS - this is with version 0.7.6, as distributed with Anaconda 1.6.1 for Windows, x64

how to get custom widgets to play nicely with enaml's size constraints?

OK, I've figured out how to make custom widgets (without using RawWidget as in #70 ), but I cannot figure out how to get them to play nicely with enaml's size constraints, or how the enaml widgets do it.

Here's what I'm using. The TableView gets instantiated properly, but never changes its size even if I resize my main enaml window. If I include the TableView in horizontal and vertical constraints, it still stays at fixed size and prevents all the other widgets with layout constraints from being automatically resized when my main window is resized. (If I don't include the TableView in horizontal constraints, the other widgets get resized properly.)

I've tried adding setSizePolicy, I've tried the RawWidget approach, and my table just sits there stubbornly with a fixed size. What can I do?

in my main Python script:

        ... other python stuff ...
        import tableview   
        app = QtApplication()
        app.resolver.factories['TableView'] = tableview.table_view_factory
        ... other python stuff ...

tableview.py:

from atom.api import (Typed, ForwardTyped, observe)
from enaml.core.declarative import d_
from enaml.widgets.control import Control, ProxyControl
from enaml.qt.qt_control import QtControl
from PySide.QtCore import (QAbstractTableModel)
from PySide.QtGui import QTableView, QSizePolicy

class ProxyTableView(ProxyControl):
    declaration = ForwardTyped(lambda: TableView)
    def set_model(self, model):
        raise NotImplementedError

class TableView(Control):
    proxy = Typed(ProxyTableView)
    tableModel = d_(Typed(QAbstractTableModel))
    @observe('tableModel')
    def _update_proxy(self, change):
        """ An observer which sends state change to the proxy.
        """
        # The superclass handler implementation is sufficient.
        super(TableView, self)._update_proxy(change)    

class QtTableView(QtControl, ProxyTableView):
    widget = Typed(QTableView)
    def create_widget(self):
        self.widget = QTableView(self.parent_widget())

    def init_widget(self):
        super(QtTableView, self).init_widget()
        self.widget.setSortingEnabled(False)
        self.widget.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)
        d = self.declaration
        self.set_model(d.tableModel)

    def set_model(self, model):
        self.widget.setModel(model)

def table_view_factory():
    return QtTableView 

Employee example validator

Because Validator has been changed, there also needs to be a change in https://github.com/nucleic/enaml/blob/master/examples/tutorial/employee/phone_validator.py . The function:

def validate(self, text, component):

should be:

def validate(self, text):

And the return value should be only just a boolean, so lines 31 and 37 should be return True and line 38 should be return False

This of course makes it so that the phone number formatting won't work, and would need to be implemented in some other way.

DockArea tool bars segfault on OSX

The dock area tool bars segfault on OSX with this error:

(enaml)Ss-MacBook-Pro:enaml Chris$ enaml-run examples/widgets/dock_area.enaml
2013-07-05 14:14:15.655 python[28759:707] *** WARNING: Method userSpaceScaleFactor in class NSView is deprecated on 10.7 and later. It should not be used in new applications. Use convertRectToBacking: instead.
QPainter::begin: Widget painting can only begin as a result of a paintEvent
QPainter::translate: Painter not active
Segmentation fault: 11

GDB indicates a problem with QGraphicsDropShadowEffect:
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000000
0x0000000111ad68e9 in QGraphicsDropShadowEffect::draw ()
(gdb) backtrace
#0 0x0000000111ad68e9 in QGraphicsDropShadowEffect::draw ()
#1 0x0000000110e15c32 in sipQGraphicsDropShadowEffect::draw ()
#2 0x000000011156f19d in QWidgetPrivate::drawWidget ()
#3 0x00000001115700f2 in QWidgetPrivate::paintSiblingsRecursive ()
#4 0x000000011156faf7 in QWidgetPrivate::drawWidget ()
#5 0x00000001115700f2 in QWidgetPrivate::paintSiblingsRecursive ()
#6 0x000000011156ff1e in QWidgetPrivate::paintSiblingsRecursive ()
#7 0x000000011156faf7 in QWidgetPrivate::drawWidget ()
#8 0x00000001115700f2 in QWidgetPrivate::paintSiblingsRecursive ()
#9 0x000000011156faf7 in QWidgetPrivate::drawWidget ()
#10 0x00000001115700f2 in QWidgetPrivate::paintSiblingsRecursive ()
#11 0x000000011156faf7 in QWidgetPrivate::drawWidget ()
#12 0x00000001115700f2 in QWidgetPrivate::paintSiblingsRecursive ()
#13 0x000000011156faf7 in QWidgetPrivate::drawWidget ()
#14 0x00000001114cf397 in -QCocoaView drawRect:

Disabling the drop shadow eliminates the segfault.

FileDialog doesn't work under PySide

The examples/widgets/FileDialog.enaml file fails because of incompatibility between PySide and PyQt:

File "/Users/cwebster/src/enaml/enaml/qt/qt_file_dialog.py", line 30, in exec_dialog
    path, selected_filter = QFileDialog.getOpenFileNameAndFilter(
AttributeError: type object 'PySide.QtGui.QFileDialog' has no attribute 'getOpenFileNameAndFilter'

PySide only supplies getOpenFileName and related functions, without the option to return the filter as well.

feature request: moving "subscription" expressions from the view into the model

The << operator is great for putting expressions into the view. For instance if the model contains a property that is a floating point number, the view can decide how to format it and will automatically be updated.

But I would like to have the auto-update feature of subscription expressions in the model as well; there are derived calculations which depend on the raw model properties that should be managed by the model, not by the view.

Is there a way to do this?

example class:

class ItemWithQuantityDiscount(Atom):
  quantity = Int()
  basePrice = Float()
  def getQuantityDiscount(self):
      # some complicated formula goes here, depends on quantity
  def getUnitPrice(self):
     return self.basePrice * self.getQuantityDiscount()

and in the view I would like to have:

 Label:
    text << '${0:2f} each'.format(model.getUnitPrice())

From http://docs.enthought.com/enaml/instructional/tut_hello_world.html (yeah, i know, that's the old enaml, but I couldn't find the new docs)

Subscription. RHS can be any expression. The expression will be parsed for dependencies, and any dependency which is a trait attribute on a HasTraits class will have a listener attached. When the listener fires, the expression will be re-evaluated and the value of the view property will be updated.

Enaml's parser fails on XOR operator

This fails but is valid python:

1 ^ 2
Traceback (most recent call last):
  File "C:\Anaconda\Scripts\enaml-run-script.py", line 9, in <module>
    load_entry_point('enaml==0.7.17', 'console_scripts', 'enaml-run')()
  File "c:\users\chris\development\enaml\enaml\runner.py", line 43, in main
    code = EnamlCompiler.compile(ast, enaml_file)
  File "c:\users\chris\development\enaml\enaml\core\enaml_compiler.py", line 518, in compile
    compiler.visit(module_ast)
  File "c:\users\chris\development\enaml\enaml\core\enaml_compiler.py", line 357, in visit
    method(node)
  File "c:\users\chris\development\enaml\enaml\core\enaml_compiler.py", line 546, in visit_Module
    self.visit(item)
  File "c:\users\chris\development\enaml\enaml\core\enaml_compiler.py", line 357, in visit
    method(node)
  File "c:\users\chris\development\enaml\enaml\core\enaml_compiler.py", line 549, in visit_Python
    py_code = compile(node.ast, self.filename, mode='exec')
TypeError: required field "lineno" missing from expr

DockArea tool bar buttons overlap on OSX retina

There is severe overlap of the dock area tool buttons on OSX with a retina display. This might be a "won't fix" if it's due to a bug in Qt's hi-dpi scaling. Haven't yet tested on a non-retina display with OSX.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.