--- a/emailuis/nmailui/src/nmeditorcontent.cpp Wed Sep 15 17:47:19 2010 +0300
+++ b/emailuis/nmailui/src/nmeditorcontent.cpp Thu Sep 30 11:43:07 2010 +0300
@@ -77,6 +77,8 @@
// pointer of the QTextDocument which the smiley engine has is NULL and
// inserting a smiley will lead to an error.
mEditorWidget->setPlainText("");
+
+ QCoreApplication::instance()->installEventFilter(this); // see eventFilter()
}
/*!
@@ -85,6 +87,8 @@
NmEditorContent::~NmEditorContent()
{
NM_FUNCTION;
+
+ QCoreApplication::instance()->removeEventFilter(this); // see eventFilter()
}
/*!
@@ -110,8 +114,8 @@
// Create the "reply" header (also for forward message)
// sets the font color of the reply header and the original body text to black
- if ((editorStartMode==NmUiEditorReply || editorStartMode==NmUiEditorReplyAll ||
- editorStartMode==NmUiEditorForward) && originalMessage) {
+ if ((editorStartMode == NmUiEditorReply || editorStartMode == NmUiEditorReplyAll ||
+ editorStartMode == NmUiEditorForward) && originalMessage) {
bodyContent.append(QString("<style type=\"text/css\">* { color: black; }</style>"));
bodyContent.append(NmUtilities::createReplyHeader(originalMessage->envelope()));
}
@@ -126,17 +130,15 @@
if (htmlPart) {
QString bodyText(htmlPart->textContent());
- if (editorStartMode==NmUiEditorReply || editorStartMode==NmUiEditorReplyAll ||
- editorStartMode==NmUiEditorForward) {
+ if (editorStartMode == NmUiEditorReply || editorStartMode == NmUiEditorReplyAll ||
+ editorStartMode == NmUiEditorForward) {
convertBodyStylesToDivision(bodyText);
}
- if(editorStartMode==NmUiEditorReply || editorStartMode==NmUiEditorReplyAll ) {
+ if(editorStartMode == NmUiEditorReply || editorStartMode == NmUiEditorReplyAll ) {
removeEmbeddedImages(bodyText);
}
-
bodyContent.append(bodyText);
- cursor.insertHtml(bodyContent);
}
else if (plainPart) {
// Plain text part was present, set it to HbTextEdit as HTML
@@ -151,6 +153,8 @@
cursor.clearSelection();
cursor.setPosition(0);
cursor.insertHtml(QString("<html><body></body></html>"));
+ mEditorWidget->moveCursor(QTextCursor::Start, QTextCursor::MoveAnchor);
+ QMetaObject::invokeMethod(this, "ensureCursorVisibility", Qt::QueuedConnection);
}
/*!
@@ -176,18 +180,6 @@
connect(mEditorWidget->document()->documentLayout(), SIGNAL(documentSizeChanged(QSizeF)), this,
SLOT(setEditorContentHeight()), Qt::QueuedConnection);
- // We need to update the scroll position according the editor's cursor position
- connect(mHeader->toEdit(), SIGNAL(cursorPositionChanged(int, int)), this,
- SLOT(ensureCursorVisibility()), Qt::QueuedConnection);
- connect(mHeader->ccEdit(), SIGNAL(cursorPositionChanged(int, int)), this,
- SLOT(ensureCursorVisibility()), Qt::QueuedConnection);
- connect(mHeader->bccEdit(), SIGNAL(cursorPositionChanged(int, int)), this,
- SLOT(ensureCursorVisibility()), Qt::QueuedConnection);
- connect(mHeader->subjectEdit(), SIGNAL(cursorPositionChanged(int, int)), this,
- SLOT(ensureCursorVisibility()), Qt::QueuedConnection);
- connect(mEditorWidget, SIGNAL(cursorPositionChanged(int, int)), this,
- SLOT(ensureCursorVisibility()), Qt::QueuedConnection);
-
// listen to the parent's (NmEditorView) size changes which happen eg. when VKB is opened/closed
connect(parent(), SIGNAL(sizeChanged()), this, SLOT(ensureCursorVisibility()),
Qt::QueuedConnection);
@@ -276,7 +268,8 @@
/*!
This slot is called when the cursor visibility has to be ensured ie. the scroll position is
- adjusted so that the cursor can be seen.
+ adjusted so that the cursor can be seen. For defining exatcly what area is ensured the
+ same algorithm that HbAbstractEditPrivate::ensurePositionVisible() uses is used here.
*/
void NmEditorContent::ensureCursorVisibility()
{
@@ -309,17 +302,8 @@
// ensure that the cursor position is visible
if (focused && !localRect.isEmpty()) {
- QPointF topLeftPos = focused->mapToItem(mScrollAreaContents, localRect.topLeft());
- QPointF bottomRightPos =
- focused->mapToItem(mScrollAreaContents, localRect.bottomRight());
- qreal marginRight = 0;
- if (mScrollArea->style()) {
- mScrollArea->style()->parameter("hb-param-margin-gene-right", marginRight);
- }
- bottomRightPos.rx() += marginRight;
-
- mScrollArea->ensureVisible(topLeftPos);
- mScrollArea->ensureVisible(bottomRightPos);
+ QRectF rect = focused->mapRectToItem(mScrollAreaContents, localRect);
+ mScrollArea->ensureVisible(rect.center(), rect.width(), rect.height() / 2 );
}
}
/*!
@@ -352,7 +336,14 @@
// Create translation object for header position adjustment.
QRectF editorBodyRect = mEditorWidget->geometry();
QTransform tr;
- qreal leftMovementThreshold(editorBodyRect.width() - headerWidth);
+
+ qreal bodyWidth = editorBodyRect.width();
+ if ( bodyWidth < mApplication.screenSize().width() ) {
+ bodyWidth = mApplication.screenSize().width();
+ }
+
+ qreal leftMovementThreshold( bodyWidth - headerWidth);
+
if (scrollPosition.x() < 0) {
// Left side positioning. Allow left side baunch effect.
tr.translate(editorBodyRect.topLeft().x() - margin ,0);
@@ -434,12 +425,12 @@
QString bodyStartReplacement("<body>\n<div");
- if(bodyContent.contains(bodyStyleDefinedRegExp)) {
+ if (bodyContent.contains(bodyStyleDefinedRegExp)) {
QString headPartString = bodyStyleDefinedRegExp.cap(0);
QString headBodyStyleString("body(\\s)*");
QRegExp bodyStyleReplacementRegExp(headBodyStyleString, Qt::CaseInsensitive);
- if(headPartString.contains(bodyStyleReplacementRegExp)) {
+ if (headPartString.contains(bodyStyleReplacementRegExp)) {
headPartString.replace(bodyStyleReplacementRegExp, "div.reply ");
bodyContent.replace(bodyStyleDefinedRegExp, headPartString);
@@ -465,9 +456,6 @@
* This is the body text.
* </div>
* </body>
- *
- * TODO: Tämä tapahtuu toistaiseksi riippumatta siitä onko bodyssa style-määrittelyä.
- * TODO: Entä jos dokumentissa on määritelty useampi <body>?
*/
void NmEditorContent::convertBodyToDiv(QString &bodyContent, const QString &replacementString)
{
@@ -497,10 +485,18 @@
{
NM_FUNCTION;
- QString bgColorInBodyFetchString("<body[^<]+(bgcolor(\\s|)=(\\s|)(\"|)(#|))*>");
+ QString bgColorInBodyFetchString("<body"
+ "[^<]+" // 1...* any character except '<'
+ "(bgcolor"
+ "(\\s|)" // White space or nothing
+ "="
+ "(\\s|)" // White space or nothing
+ "(\"|)" // '"' or nothing
+ "(#|))" // '#' or nothing
+ "*>"); // 0...* Any character + >
QRegExp bgColorInBodyRegExp(bgColorInBodyFetchString, Qt::CaseInsensitive);
- if(bodyContent.contains(bgColorInBodyRegExp)) {
+ if (bodyContent.contains(bgColorInBodyRegExp)) {
// There can be only one meaningful bgcolor, the first one.
QString bgColorString = bgColorInBodyRegExp.cap(0);
@@ -516,6 +512,7 @@
"(\"|)" // '"' or nothing
"(#|)", // '#' or nothing
Qt::CaseInsensitive);
+
colorCode.remove(removeBeginningRegExp);
QRegExp removeEndRegExp(""
@@ -523,9 +520,16 @@
"([^<]*)" // 0...* any characters except '<'
">)" // '>'
"|>"); // ... or nothing before this, just '>'
+
colorCode.remove(removeEndRegExp);
- QString plainBgColorFetchString("bgcolor(\\s|)*=(\\s|)*[^\\s]+(\\s|(?=>))");
+ QString plainBgColorFetchString("bgcolor"
+ "(\\s|)*" // 0...* White space or nothing
+ "="
+ "(\\s|)*" // 0...* White space or nothing
+ "[^\\s]+" // 1...* any character except white space
+ "(\\s|(?=>))"); // White space or follower by '>'
+
QString bgColorReplacement("style=\"background: #"+colorCode+"\" ");
QRegExp plainBgColorFetchRegExp(plainBgColorFetchString, Qt::CaseInsensitive);
@@ -536,3 +540,22 @@
bodyContent.replace(bgColorInBodyRegExp, bgColorString);
}
}
+
+/*!
+ * Listen to the input method events (eg. cursor position changes, preedit text changes etc.) and
+ * invoke ensureCursorVisibility. Qt FW does not automatically ensure the visiblity of a text in a
+ * edit widget in our custom scroll area. Filtering events is the only way to get events of the
+ * preedit text changes.
+ */
+bool NmEditorContent::eventFilter(QObject *obj, QEvent *event)
+{
+ // let the FW handle the event first
+ bool ret = QObject::eventFilter(obj, event);
+
+ if (event && event->type() == QEvent::InputMethod) {
+ QMetaObject::invokeMethod(this, "ensureCursorVisibility", Qt::QueuedConnection);
+ }
+
+ return ret;
+}
+