Customize TinyMCE for an Dexterity RichWidget - plone

I'm creating some custom content types using dexterity. I would like to "customize" the aspect of a RichText Field allowing only basic buttons of TinyMce on this field.
In Archetypes I could use
TextField('text',
allowable_content_types=('text/html',),
default_output_type='text/x-html-safe',
required=1,
widget=RichWidget
(label='Content',
allow_buttons=(
'bold',
'italic',
'justifyleft',
'justifyright',
),
),),
How would I do this with Dexerity based contenttypes?

There doesn't appear to be a "nice" way to do this right now. Even the Plone docs are currently at a loss. http://docs.plone.org/develop/plone/forms/wysiwyg.html#id9
The problem lies with Products.TinyMCE trying to get the WYSIWYG configuration from the widget attribute of the Field.
https://github.com/plone/Products.TinyMCE/blob/1.3.6/Products/TinyMCE/utility.py#L711-L713
# Get widget attributes
widget = getattr(field, 'widget', None)
filter_buttons = getattr(widget, 'filter_buttons', None)
allow_buttons = getattr(widget, 'allow_buttons', None)
But, as I understand, with Dexterity we instead map fields to widgets on the form object.
from plone.autoform import directives as form
from plone.app.z3cform.wysiwyg import WysiwygFieldWidget
class IExample(model.schema):
form.widget('body', WysiwygFieldWidget)
body = schema.Text(title=u"Body")
So, our body field possesses no widget attribute from which Products.TinyMCE can extract configurations.
At any rate, if you need it to work right now, I was able to hack it by doing the following:
In your ZMI, customize portal_skins/tinymce/tinymce_wysiwyg_support to change the line field field|nothing to field field|view/field|nothing.
Define your content type in a schema-driven fashion, and for your WYSIWYG field do the following:
class mywidg(object):
allow_buttons = ('bold',
'italic',
'justifyright',
'justifyleft',)
class IExample(model.schema):
form.widget('body', WysiwygFieldWidget)
body = schema.Text(title=u"Body")
body.widget = mywidg()

Related

Django/BooleanField: how to add space between case and label?

I have a django project
I have an models with a booleanField -> checkbox in the form
But I don't know why the checkbox is sticked to the label.
I try to select the html element to add specific css but the 2 elements move together...
current result: [ ]I have read... (the 2 elements are sticked)
expected result: [ ]......I have read...
models.py
class Aveugle(models.Model):
unb_ide = models.AutoField(primary_key=True)
unb_val = models.BooleanField("I have read ITBM procedure and want to unblind treatment", null=True, blank=True)
forms.py
unb_val = forms.BooleanField(label = _("I have read ITBM procedure and want to unblind treatment"))
Try:
This is a temporary solution, but it's just a patch, you need to handle css and html better to make it more solid.

Specify a background image via CSS in Vaadin 14 programmatically with Java

In Vaadin 14, we can set some CSS values programmatically in our Java code.
We can call getElement, then getStyle, and set the name of the CSS property along with a value.
For example, here we set the background color to green.
public class MainView extends VerticalLayout
{
public MainView ( )
{
this.getElement().getStyle().set( "background-color" , "Green" );
How do we do this for a CSS property like background-image that takes an argument of the CSS function named url?
Hard-coding the CSS path does not work.
public class MainView extends VerticalLayout
{
public MainView ( )
{
this.getElement().getStyle().set( "background-image" , "cat.jpg" );
➥ In Vaadin Flow, how to do we use Java to get CSS to find an image such as "cat.jpg"?
Furthermore, what should be the relative or absolute path to that image file be? I understand that the usual place for static images in Vaadin web app is in the src/main/resources folder.
In case of a "Plain Java Servlet" (non-Spring, non-CDI) Vaadin project, the file should go under /src/main/webapp
In case of Spring: /src/main/resources/META-INF/resources/img
Taken from official docs here: Resource Cheat Sheet
And, as #symlink has noticed in the comments, you should use a url('filename') syntax to reference an image in css : CSS background-image Property
For example, if I have a file named cat.jpg inside a /src/main/webapp/images, then this sets it getElement().getStyle().set("background-image","url('images/cat.jpg')");
Here is another example, with the picture file cat.jpg in src/main/webapp without nesting in an images folder. This is a Vaadin 14.0.10 web app, using the Plain Java Servlet technology stack option on the Start a new project with Vaadin page.
Below is the source code for an entire view using this image as a background.
Notice the first line of the constructor, where we pass "url('cat.jpg')" as an argument. See how we used single-quote marks around the file name to embed in a Java string without escaping. Fortunately the CSS specification allows for either single quotes (') or double quotes (") — quite convenient for Vaadin programmers embedding CSS within Java code.
package work.basil.example;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.PWA;
/**
* The main view contains a button and a click listener.
*/
#Route ( "" )
#PWA ( name = "Project Base for Vaadin", shortName = "Project Base" )
public class MainView extends VerticalLayout
{
public MainView ( )
{
this.getElement().getStyle().set( "background-image" , "url('cat.jpg')" );
Button button = new Button( "Click me" , event -> Notification.show( "Clicked!" ) );
add( button );
}
}
And a screenshot of this web app in action. The image is cropped because of the short height of the VerticalLayout. The layout is short because it contains only a button, whose label Click me can be seen faintly in blue text on the left edge. The cropped cat’s face is repeated across the page as is the default with CSS.

Can I suppress particular tiny mce buttons for one field of a content type (dexterity)?

Can I suppress particular tiny mce buttons for one field of a content type (dexterity model)?
That is, I'd like people to be able to format text but not insert images.
for archetypes you can use this snippet.
you can use either allow_buttons or filter_buttons.
(see the documentation for more details)
let me know if the WysiwygFieldWidget uses the same options:
atapi.TextField('text',
storage=atapi.AnnotationStorage(),
schemata=u'details',
required=False,
searchable=True,
validators=(('isTidyHtmlWithCleanup', V_REQUIRED),
),
default_output_type='text/x-html-safe',
widget=atapi.RichWidget(
label=_(u"Descriptive Text"),
description=_(u"Text describing the object in detail"),
redefine_parastyles=True,
parastyles=(
'Heading 1|h2',
'Heading 2|h3'),
allow_buttons=('pasteword', 'style', 'bold', 'italic', 'bullist',),
#filter_buttons = ('save-button', 'bg-justify', 'definitionlist',
# 'tabledrawer-button', 'bg-remove', 'olstyles', 'zoom'),
rows=20, #xxx no effect: https://dev.plone.org/ticket/13113
allow_file_upload=False,
),
),

Image Field Validator for Specific Width/Height

I have a dexterity type, with image field definition looks like this:
image = NamedBlobImage(
title=_(u'Lead Image'),
description=_(u"Upload a Image of Size 230x230."),
required=True,
)
How can I add a validator to check the uploaded image file? For example, if an image is over 500px in width, warn the user to upload another file. Hints or sample codes are appreciated.
You want to set a constraint function:
from zope.interface import Invalid
from foo.bar import MessageFactory as _
def imageSizeConstraint(value):
# value implements the plone.namedfile.interfaces.INamedBlobImageField interface
width, height = value.getImageSize()
if width > 500 or height > 500:
raise Invalid(_(u"Your image is too large"))
then set that function as the constraint of your NamedBlobImage field:
image = NamedBlobImage(
title=_(u'Lead Image'),
description=_(u"Upload a Image of Size 230x230."),
constraint=imageSizeConstraint,
required=True,
)
See the Dexterity manual on validation for more information, as well as the plone.namedfile interface definitions.

Resetting Qt Style Sheet

I've managed to style my QLineEdit to something like this:
alt text http://www.kimag.es/share/54278758.png
void Utilities::setFormErrorStyle(QLineEdit *lineEdit)
{
lineEdit->setStyleSheet(
"background-color: #FF8A8A;"
"background-image: url(:/resources/warning.png);"
"background-position: right center;"
"background-repeat: no-repeat;"
"");
}
I called the function using
Utilities *util = new Utilities;
util->setFormErrorStyle(lineNoStaf);
The flow should be something like this:
User open form
User fill data
User submit data
Got error
Use setFormErrorStyle()
User edit the text in the QLineEdit and the style disappear
This function should be reusable over and over again, but how can I connect QLineEdit signal such as textChanged() to a function in other class that will reset the Style Sheet and then disconnect the signal so that it won't be running continuously every time the text changed ?
Qt also allows dynamic properties in its stylesheet, that means you don't need to code your own class for every widget type in your form.
From http://qt-project.org/doc/qt-4.8/stylesheet-examples.html
Customizing Using Dynamic Properties
There are many situations where we need to present a form that has mandatory fields. To indicate to the user that the field is mandatory, one effective (albeit esthetically dubious) solution is to use yellow as the background color for those fields. It turns out this is very easy to implement using Qt Style Sheets. First, we would use the following application-wide style sheet:
*[mandatoryField="true"] { background-color: yellow }
This means that every widget whose mandatoryField Qt property is set to true would have a yellow background.
Then, for each mandatory field widget, we would simply create a mandatoryField property on the fly and set it to true. For example:
QLineEdit *nameEdit = new QLineEdit(this);
nameEdit->setProperty("mandatoryField", true);
QLineEdit *emailEdit = new QLineEdit(this);
emailEdit->setProperty("mandatoryField", true);
QSpinBox *ageSpinBox = new QSpinBox(this);
ageSpinBox->setProperty("mandatoryField", true);
Works also in Qt 4.3!
Allright, this is not compile but should work in principle, you should be able to change the look by calling editWidget->setProperty('isError',true) or editWidget->setError(false)
class ErrorTextEdit : QLineEdit
{
Q_OBJECT
QPROPERTY(bool isError, READ isError, WRITE setError);
public:
ErrorTextEdit(QWidget* parent) : QLineEdit(parent), m_isError(false)
{
m_styleSheet = "" // see below
setStyleSheet(m_styleSheet);
}
void setError(bool val)
{
if (val != m_isError)
{
m_isError = val;
setStyleSheet(m_styleSheet);
}
}
bool isError() {return m_isError;}
private:
QString m_styleSheet;
bool m_isError;
}
for the stylesheet
ErrorTextEdit[isError="false"]
{
optional ...
Style for textedit that is NOT an error
}
ErrorTextEdit[isError="true"]
{
background-color: #FF8A8A;
background-image: url(:/resources/warning.png);
background-position: right center;
background-repeat: no-repeat;
}
the term
[<property>="<value>"]
restricts the application of the stylesheet to instances of the class whose <property> has the appropriate <value> the only caveat is that the style is not changed when the property changes its' value, so the stylesheet has to be reapplied for the look of the widget to actually change, see Stylesheet Documentation -> Property Selector
This construction moves the stylesheet into the widget that uses it and makes switch internal to the widget, the widget changes in accordance to its state.
In general you have a couple of ways to handle invalid inputs in your form
a) observe every change and update the style appropriately, you should be able to use QValidator for that too, but that is a separate topic, using QValidator you will probably be able to completely internalize the state of a single QTextEdit and not have to deal with its validity from the outside
b) Do it in the submit loop that you have described above, whenever the user clicks on submit change the state of the correct and incorrect fields
it all depends the structure of your app and the view
See, the other idea is you need to override the paint evet of line edit and then set the background image and color.
here the implimentation is presetn here button, follow up the same to your line edit

Resources