Initial import from the monolithic Qt.
[profile/ivi/qtdeclarative.git] / src / declarative / util / qdeclarativestate.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "private/qdeclarativestate_p_p.h"
43 #include "private/qdeclarativestate_p.h"
44
45 #include "private/qdeclarativetransition_p.h"
46 #include "private/qdeclarativestategroup_p.h"
47 #include "private/qdeclarativestateoperations_p.h"
48 #include "private/qdeclarativeanimation_p.h"
49 #include "private/qdeclarativeanimation_p_p.h"
50
51 #include <qdeclarativebinding_p.h>
52 #include <qdeclarativeglobal_p.h>
53
54 #include <QtCore/qdebug.h>
55
56 QT_BEGIN_NAMESPACE
57
58 DEFINE_BOOL_CONFIG_OPTION(stateChangeDebug, STATECHANGE_DEBUG);
59
60 QDeclarativeAction::QDeclarativeAction()
61 : restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false), fromBinding(0), event(0),
62   specifiedObject(0)
63 {
64 }
65
66 QDeclarativeAction::QDeclarativeAction(QObject *target, const QString &propertyName,
67                const QVariant &value)
68 : restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false), 
69   property(target, propertyName, qmlEngine(target)), toValue(value),
70   fromBinding(0), event(0),
71   specifiedObject(target), specifiedProperty(propertyName)
72 {
73     if (property.isValid())
74         fromValue = property.read();
75 }
76
77 QDeclarativeAction::QDeclarativeAction(QObject *target, const QString &propertyName,
78                QDeclarativeContext *context, const QVariant &value)
79 : restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false),
80   property(target, propertyName, context), toValue(value),
81   fromBinding(0), event(0),
82   specifiedObject(target), specifiedProperty(propertyName)
83 {
84     if (property.isValid())
85         fromValue = property.read();
86 }
87
88
89 QDeclarativeActionEvent::~QDeclarativeActionEvent()
90 {
91 }
92
93 QString QDeclarativeActionEvent::typeName() const
94 {
95     return QString();
96 }
97
98 void QDeclarativeActionEvent::execute(Reason)
99 {
100 }
101
102 bool QDeclarativeActionEvent::isReversable()
103 {
104     return false;
105 }
106
107 void QDeclarativeActionEvent::reverse(Reason)
108 {
109 }
110
111 bool QDeclarativeActionEvent::changesBindings()
112 {
113     return false;
114 }
115
116 void QDeclarativeActionEvent::clearBindings()
117 {
118 }
119
120 bool QDeclarativeActionEvent::override(QDeclarativeActionEvent *other)
121 {
122     Q_UNUSED(other);
123     return false;
124 }
125
126 QDeclarativeStateOperation::QDeclarativeStateOperation(QObjectPrivate &dd, QObject *parent)
127     : QObject(dd, parent)
128 {
129 }
130
131 /*!
132     \qmlclass State QDeclarativeState
133     \ingroup qml-state-elements
134     \since 4.7
135     \brief The State element defines configurations of objects and properties.
136
137     A \e state is a set of batched changes from the default configuration.
138
139     All items have a default state that defines the default configuration of objects
140     and property values. New states can be defined by adding State items to the \l {Item::states}{states} property to
141     allow items to switch between different configurations. These configurations
142     can, for example, be used to apply different sets of property values or execute
143     different scripts.
144
145     The following example displays a single \l Rectangle. In the default state, the rectangle
146     is colored black. In the "clicked" state, a PropertyChanges element changes the
147     rectangle's color to red. Clicking within the MouseArea toggles the rectangle's state
148     between the default state and the "clicked" state, thus toggling the color of the
149     rectangle between black and red.
150
151     \snippet doc/src/snippets/declarative/state.qml 0
152
153     Notice the default state is referred to using an empty string ("").
154
155     States are commonly used together with \l{QML Animation and Transitions}{Transitions} to provide
156     animations when state changes occur.
157
158     \note Setting the state of an object from within another state of the same object is
159     not allowed.
160
161     \sa {declarative/animation/states}{states example}, {qmlstates}{States},
162     {QML Animation and Transitions}{Transitions}, QtDeclarative
163 */
164 QDeclarativeState::QDeclarativeState(QObject *parent)
165 : QObject(*(new QDeclarativeStatePrivate), parent)
166 {
167     Q_D(QDeclarativeState);
168     d->transitionManager.setState(this);
169 }
170
171 QDeclarativeState::~QDeclarativeState()
172 {
173     Q_D(QDeclarativeState);
174     if (d->group)
175         d->group->removeState(this);
176 }
177
178 /*!
179     \qmlproperty string State::name
180     This property holds the name of the state.
181
182     Each state should have a unique name within its item.
183 */
184 QString QDeclarativeState::name() const
185 {
186     Q_D(const QDeclarativeState);
187     return d->name;
188 }
189
190 void QDeclarativeState::setName(const QString &n)
191 {
192     Q_D(QDeclarativeState);
193     d->name = n;
194     d->named = true;
195 }
196
197 bool QDeclarativeState::isNamed() const
198 {
199     Q_D(const QDeclarativeState);
200     return d->named;
201 }
202
203 bool QDeclarativeState::isWhenKnown() const
204 {
205     Q_D(const QDeclarativeState);
206     return d->when != 0;
207 }
208
209 /*!
210     \qmlproperty bool State::when
211     This property holds when the state should be applied.
212
213     This should be set to an expression that evaluates to \c true when you want the state to
214     be applied. For example, the following \l Rectangle changes in and out of the "hidden"
215     state when the \l MouseArea is pressed:
216
217     \snippet doc/src/snippets/declarative/state-when.qml 0
218
219     If multiple states in a group have \c when clauses that evaluate to \c true
220     at the same time, the first matching state will be applied. For example, in
221     the following snippet \c state1 will always be selected rather than
222     \c state2 when sharedCondition becomes \c true.
223     \qml
224     Item {
225         states: [
226             State { name: "state1"; when: sharedCondition },
227             State { name: "state2"; when: sharedCondition }
228         ]
229         // ...
230     }
231     \endqml
232 */
233 QDeclarativeBinding *QDeclarativeState::when() const
234 {
235     Q_D(const QDeclarativeState);
236     return d->when;
237 }
238
239 void QDeclarativeState::setWhen(QDeclarativeBinding *when)
240 {
241     Q_D(QDeclarativeState);
242     d->when = when;
243     if (d->group)
244         d->group->updateAutoState();
245 }
246
247 /*!
248     \qmlproperty string State::extend
249     This property holds the state that this state extends.
250
251     When a state extends another state, it inherits all the changes of that state.
252
253     The state being extended is treated as the base state in regards to
254     the changes specified by the extending state.
255 */
256 QString QDeclarativeState::extends() const
257 {
258     Q_D(const QDeclarativeState);
259     return d->extends;
260 }
261
262 void QDeclarativeState::setExtends(const QString &extends)
263 {
264     Q_D(QDeclarativeState);
265     d->extends = extends;
266 }
267
268 /*!
269     \qmlproperty list<Change> State::changes
270     This property holds the changes to apply for this state
271     \default
272
273     By default these changes are applied against the default state. If the state
274     extends another state, then the changes are applied against the state being
275     extended.
276 */
277 QDeclarativeListProperty<QDeclarativeStateOperation> QDeclarativeState::changes()
278 {
279     Q_D(QDeclarativeState);
280     return QDeclarativeListProperty<QDeclarativeStateOperation>(this, &d->operations, QDeclarativeStatePrivate::operations_append,
281                                               QDeclarativeStatePrivate::operations_count, QDeclarativeStatePrivate::operations_at,
282                                               QDeclarativeStatePrivate::operations_clear);
283 }
284
285 int QDeclarativeState::operationCount() const
286 {
287     Q_D(const QDeclarativeState);
288     return d->operations.count();
289 }
290
291 QDeclarativeStateOperation *QDeclarativeState::operationAt(int index) const
292 {
293     Q_D(const QDeclarativeState);
294     return d->operations.at(index);
295 }
296
297 QDeclarativeState &QDeclarativeState::operator<<(QDeclarativeStateOperation *op)
298 {
299     Q_D(QDeclarativeState);
300     d->operations.append(QDeclarativeStatePrivate::OperationGuard(op, &d->operations));
301     return *this;
302 }
303
304 void QDeclarativeStatePrivate::complete()
305 {
306     Q_Q(QDeclarativeState);
307
308     for (int ii = 0; ii < reverting.count(); ++ii) {
309         for (int jj = 0; jj < revertList.count(); ++jj) {
310             if (revertList.at(jj).property() == reverting.at(ii)) {
311                 revertList.removeAt(jj);
312                 break;
313             }
314         }
315     }
316     reverting.clear();
317
318     emit q->completed();
319 }
320
321 // Generate a list of actions for this state.  This includes coelescing state
322 // actions that this state "extends"
323 QDeclarativeStateOperation::ActionList
324 QDeclarativeStatePrivate::generateActionList(QDeclarativeStateGroup *group) const
325 {
326     QDeclarativeStateOperation::ActionList applyList;
327     if (inState)
328         return applyList;
329
330     // Prevent "extends" recursion
331     inState = true;
332
333     if (!extends.isEmpty()) {
334         QList<QDeclarativeState *> states = group->states();
335         for (int ii = 0; ii < states.count(); ++ii)
336             if (states.at(ii)->name() == extends) {
337                 qmlExecuteDeferred(states.at(ii));
338                 applyList = static_cast<QDeclarativeStatePrivate*>(states.at(ii)->d_func())->generateActionList(group);
339             }
340     }
341
342     foreach(QDeclarativeStateOperation *op, operations)
343         applyList << op->actions();
344
345     inState = false;
346     return applyList;
347 }
348
349 QDeclarativeStateGroup *QDeclarativeState::stateGroup() const
350 {
351     Q_D(const QDeclarativeState);
352     return d->group;
353 }
354
355 void QDeclarativeState::setStateGroup(QDeclarativeStateGroup *group)
356 {
357     Q_D(QDeclarativeState);
358     d->group = group;
359 }
360
361 void QDeclarativeState::cancel()
362 {
363     Q_D(QDeclarativeState);
364     d->transitionManager.cancel();
365 }
366
367 void QDeclarativeAction::deleteFromBinding()
368 {
369     if (fromBinding) {
370         QDeclarativePropertyPrivate::setBinding(property, 0);
371         fromBinding->destroy();
372         fromBinding = 0;
373     }
374 }
375
376 bool QDeclarativeState::containsPropertyInRevertList(QObject *target, const QString &name) const
377 {
378     Q_D(const QDeclarativeState);
379
380     if (isStateActive()) {
381         QListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList);
382
383         while (revertListIterator.hasNext()) {
384             const QDeclarativeSimpleAction &simpleAction = revertListIterator.next();
385             if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
386                 return true;
387         }
388     }
389
390     return false;
391 }
392
393 bool QDeclarativeState::changeValueInRevertList(QObject *target, const QString &name, const QVariant &revertValue)
394 {
395     Q_D(QDeclarativeState);
396
397     if (isStateActive()) {
398         QMutableListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList);
399
400         while (revertListIterator.hasNext()) {
401             QDeclarativeSimpleAction &simpleAction = revertListIterator.next();
402             if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) {
403                     simpleAction.setValue(revertValue);
404                     return true;
405             }
406         }
407     }
408
409     return false;
410 }
411
412 bool QDeclarativeState::changeBindingInRevertList(QObject *target, const QString &name, QDeclarativeAbstractBinding *binding)
413 {
414     Q_D(QDeclarativeState);
415
416     if (isStateActive()) {
417         QMutableListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList);
418
419         while (revertListIterator.hasNext()) {
420             QDeclarativeSimpleAction &simpleAction = revertListIterator.next();
421             if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) {
422                 if (simpleAction.binding())
423                     simpleAction.binding()->destroy();
424
425                 simpleAction.setBinding(binding);
426                 return true;
427             }
428         }
429     }
430
431     return false;
432 }
433
434 bool QDeclarativeState::removeEntryFromRevertList(QObject *target, const QString &name)
435 {
436     Q_D(QDeclarativeState);
437
438     if (isStateActive()) {
439         QMutableListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList);
440
441         while (revertListIterator.hasNext()) {
442             QDeclarativeSimpleAction &simpleAction = revertListIterator.next();
443             if (simpleAction.property().object() == target && simpleAction.property().name() == name) {
444                 QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(simpleAction.property());
445                 if (oldBinding) {
446                     QDeclarativePropertyPrivate::setBinding(simpleAction.property(), 0);
447                     oldBinding->destroy();
448                 }
449
450                 simpleAction.property().write(simpleAction.value());
451                 if (simpleAction.binding())
452                     QDeclarativePropertyPrivate::setBinding(simpleAction.property(), simpleAction.binding());
453
454                 revertListIterator.remove();
455                 return true;
456             }
457         }
458     }
459
460     return false;
461 }
462
463 void QDeclarativeState::addEntryToRevertList(const QDeclarativeAction &action)
464 {
465     Q_D(QDeclarativeState);
466
467     QDeclarativeSimpleAction simpleAction(action);
468
469     d->revertList.append(simpleAction);
470 }
471
472 void QDeclarativeState::removeAllEntriesFromRevertList(QObject *target)
473 {
474      Q_D(QDeclarativeState);
475
476      if (isStateActive()) {
477          QMutableListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList);
478
479          while (revertListIterator.hasNext()) {
480              QDeclarativeSimpleAction &simpleAction = revertListIterator.next();
481              if (simpleAction.property().object() == target) {
482                  QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(simpleAction.property());
483                  if (oldBinding) {
484                      QDeclarativePropertyPrivate::setBinding(simpleAction.property(), 0);
485                      oldBinding->destroy();
486                  }
487
488                  simpleAction.property().write(simpleAction.value());
489                  if (simpleAction.binding())
490                      QDeclarativePropertyPrivate::setBinding(simpleAction.property(), simpleAction.binding());
491
492                  revertListIterator.remove();
493              }
494          }
495      }
496 }
497
498 void QDeclarativeState::addEntriesToRevertList(const QList<QDeclarativeAction> &actionList)
499 {
500     Q_D(QDeclarativeState);
501     if (isStateActive()) {
502         QList<QDeclarativeSimpleAction> simpleActionList;
503
504         QListIterator<QDeclarativeAction> actionListIterator(actionList);
505         while(actionListIterator.hasNext()) {
506             const QDeclarativeAction &action = actionListIterator.next();
507             QDeclarativeSimpleAction simpleAction(action);
508             action.property.write(action.toValue);
509             if (!action.toBinding.isNull()) {
510                 QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(simpleAction.property());
511                 if (oldBinding)
512                     QDeclarativePropertyPrivate::setBinding(simpleAction.property(), 0);
513                 QDeclarativePropertyPrivate::setBinding(simpleAction.property(), action.toBinding.data(), QDeclarativePropertyPrivate::DontRemoveBinding);
514             }
515
516             simpleActionList.append(simpleAction);
517         }
518
519         d->revertList.append(simpleActionList);
520     }
521 }
522
523 QVariant QDeclarativeState::valueInRevertList(QObject *target, const QString &name) const
524 {
525     Q_D(const QDeclarativeState);
526
527     if (isStateActive()) {
528         QListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList);
529
530         while (revertListIterator.hasNext()) {
531             const QDeclarativeSimpleAction &simpleAction = revertListIterator.next();
532             if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
533                 return simpleAction.value();
534         }
535     }
536
537     return QVariant();
538 }
539
540 QDeclarativeAbstractBinding *QDeclarativeState::bindingInRevertList(QObject *target, const QString &name) const
541 {
542     Q_D(const QDeclarativeState);
543
544     if (isStateActive()) {
545         QListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList);
546
547         while (revertListIterator.hasNext()) {
548             const QDeclarativeSimpleAction &simpleAction = revertListIterator.next();
549             if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name)
550                 return simpleAction.binding();
551         }
552     }
553
554     return 0;
555 }
556
557 bool QDeclarativeState::isStateActive() const
558 {
559     return stateGroup() && stateGroup()->state() == name();
560 }
561
562 void QDeclarativeState::apply(QDeclarativeStateGroup *group, QDeclarativeTransition *trans, QDeclarativeState *revert)
563 {
564     Q_D(QDeclarativeState);
565
566     qmlExecuteDeferred(this);
567
568     cancel();
569     if (revert)
570         revert->cancel();
571     d->revertList.clear();
572     d->reverting.clear();
573
574     if (revert) {
575         QDeclarativeStatePrivate *revertPrivate =
576             static_cast<QDeclarativeStatePrivate*>(revert->d_func());
577         d->revertList = revertPrivate->revertList;
578         revertPrivate->revertList.clear();
579     }
580
581     // List of actions caused by this state
582     QDeclarativeStateOperation::ActionList applyList = d->generateActionList(group);
583
584     // List of actions that need to be reverted to roll back (just) this state
585     QDeclarativeStatePrivate::SimpleActionList additionalReverts;
586     // First add the reverse of all the applyList actions
587     for (int ii = 0; ii < applyList.count(); ++ii) {
588         QDeclarativeAction &action = applyList[ii];
589
590         if (action.event) {
591             if (!action.event->isReversable())
592                 continue;
593             bool found = false;
594             for (int jj = 0; jj < d->revertList.count(); ++jj) {
595                 QDeclarativeActionEvent *event = d->revertList.at(jj).event();
596                 if (event && event->typeName() == action.event->typeName()) {
597                     if (action.event->override(event)) {
598                         found = true;
599
600                         if (action.event != d->revertList.at(jj).event() && action.event->needsCopy()) {
601                             action.event->copyOriginals(d->revertList.at(jj).event());
602
603                             QDeclarativeSimpleAction r(action);
604                             additionalReverts << r;
605                             d->revertList.removeAt(jj);
606                             --jj;
607                         } else if (action.event->isRewindable())    //###why needed?
608                             action.event->saveCurrentValues();
609
610                         break;
611                     }
612                 }
613             }
614             if (!found) {
615                 action.event->saveOriginals();
616                 // Only need to revert the applyList action if the previous
617                 // state doesn't have a higher priority revert already
618                 QDeclarativeSimpleAction r(action);
619                 additionalReverts << r;
620             }
621         } else {
622             bool found = false;
623             action.fromBinding = QDeclarativePropertyPrivate::binding(action.property);
624
625             for (int jj = 0; jj < d->revertList.count(); ++jj) {
626                 if (d->revertList.at(jj).property() == action.property) {
627                     found = true;
628                     if (d->revertList.at(jj).binding() != action.fromBinding) {
629                         action.deleteFromBinding();
630                     }
631                     break;
632                 }
633             }
634
635             if (!found) {
636                 if (!action.restore) {
637                     action.deleteFromBinding();;
638                 } else {
639                     // Only need to revert the applyList action if the previous
640                     // state doesn't have a higher priority revert already
641                     QDeclarativeSimpleAction r(action);
642                     additionalReverts << r;
643                 }
644             }
645         }
646     }
647
648     // Any reverts from a previous state that aren't carried forth
649     // into this state need to be translated into apply actions
650     for (int ii = 0; ii < d->revertList.count(); ++ii) {
651         bool found = false;
652         if (d->revertList.at(ii).event()) {
653             QDeclarativeActionEvent *event = d->revertList.at(ii).event();
654             if (!event->isReversable())
655                 continue;
656             for (int jj = 0; !found && jj < applyList.count(); ++jj) {
657                 const QDeclarativeAction &action = applyList.at(jj);
658                 if (action.event && action.event->typeName() == event->typeName()) {
659                     if (action.event->override(event))
660                         found = true;
661                 }
662             }
663         } else {
664             for (int jj = 0; !found && jj < applyList.count(); ++jj) {
665                 const QDeclarativeAction &action = applyList.at(jj);
666                 if (action.property == d->revertList.at(ii).property())
667                     found = true;
668             }
669         }
670         if (!found) {
671             QVariant cur = d->revertList.at(ii).property().read();
672             QDeclarativeAbstractBinding *delBinding = 
673                 QDeclarativePropertyPrivate::setBinding(d->revertList.at(ii).property(), 0);
674             if (delBinding)
675                 delBinding->destroy();
676
677             QDeclarativeAction a;
678             a.property = d->revertList.at(ii).property();
679             a.fromValue = cur;
680             a.toValue = d->revertList.at(ii).value();
681             a.toBinding = QDeclarativeAbstractBinding::getPointer(d->revertList.at(ii).binding());
682             a.specifiedObject = d->revertList.at(ii).specifiedObject();
683             a.specifiedProperty = d->revertList.at(ii).specifiedProperty();
684             a.event = d->revertList.at(ii).event();
685             a.reverseEvent = d->revertList.at(ii).reverseEvent();
686             if (a.event && a.event->isRewindable())
687                 a.event->saveCurrentValues();
688             applyList << a;
689             // Store these special reverts in the reverting list
690             d->reverting << d->revertList.at(ii).property();
691         }
692     }
693     // All the local reverts now become part of the ongoing revertList
694     d->revertList << additionalReverts;
695
696 #ifndef QT_NO_DEBUG_STREAM
697     // Output for debugging
698     if (stateChangeDebug()) {
699         foreach(const QDeclarativeAction &action, applyList) {
700             if (action.event)
701                 qWarning() << "    QDeclarativeAction event:" << action.event->typeName();
702             else
703                 qWarning() << "    QDeclarativeAction:" << action.property.object()
704                            << action.property.name() << "From:" << action.fromValue 
705                            << "To:" << action.toValue;
706         }
707     }
708 #endif
709
710     d->transitionManager.transition(applyList, trans);
711 }
712
713 QDeclarativeStateOperation::ActionList QDeclarativeStateOperation::actions()
714 {
715     return ActionList();
716 }
717
718 QDeclarativeState *QDeclarativeStateOperation::state() const
719 {
720     Q_D(const QDeclarativeStateOperation);
721     return d->m_state;
722 }
723
724 void QDeclarativeStateOperation::setState(QDeclarativeState *state)
725 {
726     Q_D(QDeclarativeStateOperation);
727     d->m_state = state;
728 }
729
730 QT_END_NAMESPACE