Skip to content

For document editing apps: classes for styling docs e.g. StyleSheet, Styleable, StyleProperty, Formation. Emphasis on object design. Uses Python PySide Qt QGraphicsItems. Demo app.

bootchk/documentStyle

Repository files navigation

Copyright 2012 Lloyd Konneker

This is free software, covered by the GNU General Public License.


About
=====

This is a subsystem of classes for styling document elements of a document.

The subsystem includes GUI, for editing stylesheets and editing the style of document elements.
GUI alternatives: QWidget or QML

One emphasis is on understandable object design (not performance.)  
Certain of the classes (e.g. StyleSheet, Selector) are familiar.
Other classes (abstractions) might be new to you.

See the test app: testStyling.py.  It uses this subsystem to style a document of QGraphicsItems.
The app lets you experience cascading style.

The subsystem uses the Qt framework.  It should be adaptable to other frameworks.


API
===

This discusses the interface between an app and the DocumentStyle subsystem.

See testStyling.py as an example.

DocumentElements should multiply inherit Styleable.
DocumentElements at initialization should call Styleable.setStylingDocumentElementType() 
with one of DocumentElementStylingTypes ...  This creates a Styler for the DocumentElement.

Application should:
- create StyleSheetCascadion initialization time (built-in certain names: 
  docStyleSheet, userStyleSheet, appStyleSheet
- call StyleSheet.edit() when user requests.
- connect styleSheetCascadion signal to app's polish() method
- have a polish method, which should call Styleable.polish() method of all DocumentElements
(the app knows the set of DocumentElements.)

Document elements should:
- have a polish method (redraw with changed style)
- have a scalePen() method (for frameworks where line widths transform, and a transform is used to size DocumentElement)
- when persisted, also persist serializable form of style

Application should also:
- persist the DocumentStyleSheet with the Document (getSerializable() method)
Note that the AppStyleSheet actually comes from the framework's defaults, not the application.
The DocumentElement attributes that contain the style should also be persisted.
but DocumentStyle subsystem doesn't know those attributes except via a Styler.


App requirements on a styling subsystem
=======================================

Persist style of document elements with the document.
Persist document stylesheet with the document.
Persist user stylesheet as settings.
Persist app stylesheet.


Styling subsystem requirements
==============================
Styling systems can support:
- named styles
- cascading stylesheets OR templating stylesheets

The styling system discussed in Wirfs-Brock supports named styles but not cascading.
This subsystem supports cascading stylesheets.
It is designed to also support named styles (but they are FUTURE.)
Templating stylesheets is supported but broken.


Object models for style
=======================

I don't know of any really good discussion of object models for styling documents.

See Wirfs-Brock "Designing Object Oriented Software" for a basic discussion of named styling of documents.

The W3C Cascading Stylesheet (CSS) specification is mostly about serialization and browsers.
But the W3C specs are poor as object models, especially about behavior.
This subsystem implements the behavior of some of the W3C CSS classes.
For example, Selector class.
For another example, our StylingAct class is roughly a W3C Descriptor.

The Qt framework has stylesheets that cascade, but they are specific to style of application widgets, for platform independence. 
This subsystem is not based on that object model (just uses them to style a few widgets so they reflect a user-chosen style.)

Older Qt versions apparently had a QStyleSheet class for styling text documents, but this subsystem does not borrow that class.


Persistence and Undo
====================

Persists using python pickle.

StyleSheets pickle.  Since they use QSignal, they can't be pickled nievely;
they implement a __reduce__ method to pickle the pertinent attributes.
The pertinent attribute is the StylingActSetCollection (the in-line style); most style cascades.

Except the AppStyleSheet does NOT pickle.  It is the root of cascading, and its style essentially comes from the framework.

UserStyleSheet pickles and saves itself in QSetting (persists between app sessions, a preference of a user, not part of a document.)

A Styler pickles to serialize style of a DocumentElement.
Essentially that pickles the DocumentElementStyleSheet of a Styleable.
Note that you must call Styler.resetAfterDeserialization() after deserializing a Styler.

Pickled Styler is also useful to save the style of a DocumentElement for undo/redo.


Configuration of style
======================

To change what a user can style...
Search the code for "configuration".
To change set of instruments for the app, change AppStyleSheet.
To change set of instruments for a morph, change MorphFormation.
To change set of properties for an instrument, change a subclass of InstrumentFormation.

E.G. to eliminate the "Indent" style property for a Text morph, edit BlockFormation.__init__().


QML vs QWidget implementation
=============================

Originally this project used QWidgets but now uses QML.
The reason is: QML should be portable to mobile devices with better look and feel.

Implementations are in separate subdirectories ui/widgetUI and ui/qmlUI.
A switch in config.py named 'useQML' selects the implementation.
Switch is done using dynamic imports (not at the top of .py files.)

The API has changed to support QML: a parameter 'resourceRoot' must be passed to StyleSheetCascadion().
That is the root directory of resources owned by the calling app (of which documentStyle is a subsystem.)
The documentStyle subsystem will look in the subdirectory <resourceRoot>/resources/qml/style for .qml files.
That directory of this project must be copied to the calling app's resources
(and packaged with the calling app, using some process such as pyrcc, rcc, or pyqtdeploy.)
See testStyling.py for an example.

If you use the QML implementation, you don't need ui/widgetUI subpackage.


Status
======

Nov. 2014  Undergoing major changes to support QML or QWidget GUI.
This entails cleanly separating the view and the model.

The file TODO.txt is a list of minor things probably will never get done.

TODO A button on StyleSheetDialogs to reset all values to cascaded values (erase in-lining.)

TODO OK button enabled only if user touches a style property

TODO non-modal stylesheet dialog (style document as user touches properties.)


About

For document editing apps: classes for styling docs e.g. StyleSheet, Styleable, StyleProperty, Formation. Emphasis on object design. Uses Python PySide Qt QGraphicsItems. Demo app.

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages