-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Basic DataView Implementation #543
Merged
Merged
Changes from 22 commits
Commits
Show all changes
52 commits
Select commit
Hold shift + click to select a range
6fca300
First cut a data_view that can display successfully.
corranwebster 70ba5f0
Add a column-based data model and corresponding example.
corranwebster fa3c892
Add missing file.
corranwebster 3bfaaaa
Target code for basic data view implementation.
corranwebster 02c7af7
Update abstract data model docstrings.
corranwebster 5f1de11
Lots more docstrings, some additional clean-up and API clarification.
corranwebster 5b4b43a
More and better tests.
corranwebster 15554b2
Fix up wx widget scaffolding.
corranwebster f06bd98
Add documentation for the DataModel with an example.
corranwebster bc36909
Fix references.
corranwebster cce14b1
Move the column data model to the examples, clean up example.
corranwebster a561645
Add copyright headers.
corranwebster 45fd7ed
Add tests for remaining value type classes.
corranwebster 9208713
Apply suggestions from code review
corranwebster 597f869
Updates and fixes from PR review.
corranwebster 23b852d
Add some more tests, improve a comment.
corranwebster 8a9f49e
Get a smoke test working for the DataViewWidget class.
corranwebster 8e70092
More clean-up of the toolkit implementations.
corranwebster d50d7ef
Apply suggestions from code review
corranwebster 4792f66
Fixes based in PR suggestions.
corranwebster 6f2d37f
Fix flake8 issue.
corranwebster eabf7f5
Convert from lists for indices to tuples.
corranwebster 483db31
Fix bug in set method.
corranwebster 7e8ba1e
Make column count constant, plus some small fixes.
corranwebster a96ac32
Release model when destroying widgets.
corranwebster 1cc2caf
Fix docstrings.
corranwebster 3defcee
Rename "editable" -> "editor_value".
corranwebster e9d680d
And "editable" -> "editro_value" in other files.
corranwebster 9be4d98
Improve TextValue and NumericValues.
corranwebster 8341a2d
Fix spelling.
corranwebster 277a966
Instantiate exceptions.
corranwebster a02a48b
Move to using exceptions to handle failure to set values.
corranwebster 4929afe
Fix iteration over columns.
corranwebster 4b0efee
Use more descriptive metadata for updating value types.
corranwebster 7d12b2a
Don't try to guess value type for array model, ensure 2d arrays.
corranwebster 262bc5b
Add a test for setting 1d data.
corranwebster fde28c2
And test default data is 2d.
corranwebster 62a38c7
Improve tests of empty data.
corranwebster 2aa4c11
Assorted fixes from PR review.
corranwebster 25009ef
Dispatch model changes on the ui thread.
corranwebster e3d625f
Cleanup of confusing parentheses.
corranwebster bb5c380
Improve documentation for data view.
corranwebster aab3854
Minro fixes and improvements to documentation.
corranwebster b4ccec7
Remove ui dispatch from pure data models.
corranwebster f382d71
Docstring fixes.
corranwebster 65a1ebe
More fixes from PR review.
corranwebster 4b0f75a
Change the way that we handle low-dimension arrays.
corranwebster 89748c7
Handle unusual life-cycle issues.
corranwebster b559ac5
Remove extraneous file commited.
corranwebster b92e062
Apply suggestions from code review
corranwebster 83a80ca
various fixes and improvements from review.
corranwebster 516cc22
Add missing import.
corranwebster File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
Pyface DataViews | ||
================= | ||
|
||
The Pyface DataView API allows visualization of heirarchical and | ||
non-heirarchical tabular data. | ||
|
||
Data Models | ||
----------- | ||
|
||
Data to be viewed needs to be exposed to the DataView infrastructure by | ||
creating a data model for it. This is a class that implements the | ||
interface of |AbstractDataModel|. | ||
|
||
A data model for a dictionary could be implemented like this:: | ||
|
||
class DictDataModel(AbstractDataModel): | ||
|
||
data = Dict | ||
|
||
index_manager = Instance(IntIndexManager, ()) | ||
|
||
The index manager is an ``IntIndexManager`` because the data is | ||
non-heirarchical and this is more memory-efficient than the alternative | ||
``TupleIndexManager``. | ||
|
||
Data Structure | ||
~~~~~~~~~~~~~~ | ||
|
||
The keys are displayed in the row headers, so each row has one column | ||
displaying the value:: | ||
|
||
def get_column_count(self, row): | ||
return 1 | ||
|
||
The data is non-heirarchical, so the root has children and no other | ||
rows have children:: | ||
|
||
def can_have_children(self, row): | ||
if len(row) == 0: | ||
return True | ||
return False | ||
|
||
The number of child rows of the root is the length of the dictionary:: | ||
|
||
def get_row_count(self, row): | ||
if len(row) == 0: | ||
return len(self.data) | ||
return 0 | ||
kitchoi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Data Values | ||
~~~~~~~~~~~ | ||
|
||
To get the values of the data model, we need to find the apprpriate value | ||
from the dictionary:: | ||
|
||
keys_header = Str("Keys") | ||
values_header = Str("Values") | ||
|
||
def get_value(self, row, column): | ||
if len(row) == 0: | ||
# this is a column header | ||
if len(column) == 0: | ||
# title of the row headers | ||
return self.keys_header | ||
else: | ||
return self.values_header | ||
else: | ||
row_index = row[0] | ||
key, value = list(self.data.items())[row_index] | ||
if len(column) == 0: | ||
# the is a row header, so get the key | ||
return key | ||
else: | ||
return value | ||
|
||
In this case, all of the values are text, and read-only, so we can have a | ||
trait holding the value type, and return that for every item:: | ||
|
||
header_value_type = Instance(AbstractValueType) | ||
key_value_type = Instance(AbstractValueType) | ||
value_type = Instance(AbstractValueType) | ||
|
||
def _default_header_value_type(self): | ||
return TextValue(is_editable=False) | ||
|
||
def _default_key_value_type(self): | ||
return TextValue(is_editable=False) | ||
|
||
def _default_value_type(self): | ||
return TextValue(is_editable=False) | ||
|
||
def get_value_type(self, row, column): | ||
if len(row) == 0: | ||
return self.header_value_type | ||
elif len(column) == 0: | ||
return self.key_value_type | ||
else: | ||
return self.value_type | ||
|
||
The default assumes that values representable as text, but if the values were | ||
ints, for example then the class could be instantiated with:: | ||
|
||
model = DictDataModel(value_type=IntValue(is_editable=False)) | ||
|
||
The ``is_editable`` arguments are not strictly needed, as the default | ||
implementation of |can_set_value| returns False, but if we wanted to make the | ||
data model read-write we would need to write an implementation of | ||
|can_set_value| which returns True for editable items, and an implementation | ||
of |set_value| that updates the data in-place. This would look something like:: | ||
|
||
def can_set_value(self, row, column): | ||
return len(row) != 0 and len(column) != 0: | ||
|
||
def set_value(self, row, column, value): | ||
if self.can_set_value(row, column): | ||
row_index = row[0] | ||
key = list(self.data)[row_index] | ||
self.data[key] = value | ||
return True | ||
return False | ||
|
||
Update Events | ||
------------- | ||
|
||
Finally, when the underlying data changes, the DataView infrastructure expects | ||
certain event traits to be fired. If a value is changed, or the value type is | ||
updated, but the number of rows and columns is unaffected, then the | ||
``values_changed`` trait should be fired with a tuple of ``(start_row_index, | ||
start_column_index, end_row_index, end_column_index)``. If a major change has | ||
occurred, or if the size, shape or layout of the data has changed, then | ||
the ``structure_changed`` event should be fired with a simple ``True`` value. | ||
|
||
So for example, if the value types change, only the displayed values need to be | ||
updated:: | ||
|
||
@observe('header_value_type.updated') | ||
def header_values_updated(self, event): | ||
self.values_changed = ([], [], [], [0]) | ||
|
||
@observe('key_value_type.updated') | ||
def key_values_updated(self, event): | ||
self.values_changed = ([0], [], [len(self.data) - 1], []) | ||
|
||
@observe('value_type.updated') | ||
def values_updated(self, event): | ||
self.values_changed = ([0], [0], [len(self.data) - 1], [0]) | ||
|
||
On the other hand, if the dictionary or its items change, then it is simplest | ||
to just indicate that the entire view needs updating:: | ||
|
||
@observe('data.items') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Related to another comment as for whether |
||
def data_updated(self, event): | ||
self.structure_changed = True | ||
|
||
|
||
|
||
.. |AbstractDataModel| replace:: :py:class:`~pyface.data_view.abstract_data_model.AbstractDataModel` | ||
.. |can_set_value| replace:: :py:class:`~pyface.data_view.abstract_data_model.AbstractDataModel.can_set_value` | ||
.. |set_value| replace:: :py:class:`~pyface.data_view.abstract_data_model.AbstractDataModel.set_value` |
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,51 @@ | ||
# (C) Copyright 2005-2020 Enthought, Inc., Austin, TX | ||
# All rights reserved. | ||
# | ||
# This software is provided without warranty under the terms of the BSD | ||
# license included in LICENSE.txt and may be redistributed only under | ||
# the conditions described in the aforementioned license. The license | ||
# is also available online at http://www.enthought.com/licenses/BSD.txt | ||
# | ||
# Thanks for using Enthought open source! | ||
|
||
from traits.api import Array, Instance | ||
|
||
from pyface.api import ApplicationWindow, GUI | ||
from pyface.data_view.data_models.array_data_model import ArrayDataModel | ||
from pyface.data_view.i_data_view_widget import IDataViewWidget | ||
from pyface.data_view.data_view_widget import DataViewWidget | ||
|
||
|
||
class MainWindow(ApplicationWindow): | ||
""" The main application window. """ | ||
|
||
data = Array | ||
|
||
data_view = Instance(IDataViewWidget) | ||
|
||
def _create_contents(self, parent): | ||
""" Creates the left hand side or top depending on the style. """ | ||
|
||
self.data_view = DataViewWidget( | ||
parent=parent, | ||
data_model=ArrayDataModel(data=self.data), | ||
) | ||
self.data_view._create() | ||
return self.data_view.control | ||
|
||
def _data_default(self): | ||
import numpy | ||
return numpy.random.uniform(size=(10000, 10, 10))*1000000 | ||
|
||
|
||
# Application entry point. | ||
if __name__ == "__main__": | ||
# Create the GUI (this does NOT start the GUI event loop). | ||
gui = GUI() | ||
|
||
# Create and open the main window. | ||
window = MainWindow() | ||
window.open() | ||
|
||
# Start the GUI event loop! | ||
gui.start_event_loop() |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Styling / nit: There are a few more occurrences of the same misspelling which can be fixed by doing a find-and-replace-all from
"heirarch"
to"hierarch"
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I alwys get it wrong :(