emailuis/nmailui/src/nmeditorcontent.cpp
changeset 48 10eaf342f539
parent 47 f83bd4ae1fe3
child 49 00c7ae862740
equal deleted inserted replaced
47:f83bd4ae1fe3 48:10eaf342f539
    22 static const char *NMUI_EDITOR_SCROLL_AREA = "scrollArea";
    22 static const char *NMUI_EDITOR_SCROLL_AREA = "scrollArea";
    23 static const char *NMUI_EDITOR_SCROLL_AREA_CONTENTS = "scrollAreaContents";
    23 static const char *NMUI_EDITOR_SCROLL_AREA_CONTENTS = "scrollAreaContents";
    24 
    24 
    25 // Regular expression for selecting img tags with "cid" in the mail.
    25 // Regular expression for selecting img tags with "cid" in the mail.
    26 static const char *NMUI_EDITOR_REMOVE_EMBD_IMAGES_REG = 
    26 static const char *NMUI_EDITOR_REMOVE_EMBD_IMAGES_REG = 
    27     "(<img (src\\s*=\\s*)(.{0,1}cid)([^<]+)(>\\s*|/>\\s*|></img>\\s*))";
    27     "(<img[^<]+(src\\s*=\\s*)(.{0,1}cid)([^<]+)(>\\s*|/>\\s*|></img>\\s*))";
    28 	
    28 	
    29 /*!
    29 /*!
    30     Constructor
    30     Constructor
    31 */
    31 */
    32 NmEditorContent::NmEditorContent(QObject *parent,
    32 NmEditorContent::NmEditorContent(QObject *parent,
    33                                  HbDocumentLoader *documentLoader,
    33                                  HbDocumentLoader *documentLoader,
    34                                  QNetworkAccessManager &manager,
    34                                  QNetworkAccessManager &manager,
    35                                  NmApplication &application) :
    35                                  NmApplication &application) :
    36     QObject(parent),
    36     QObject(parent),
    37     mHeaderWidget(NULL),
    37     mHeader(NULL),
    38     mMessageBodyType(NmPlainText),
    38     mMessageBodyType(NmPlainText),
    39     mEditorWidget(NULL),
    39     mEditorWidget(NULL),
    40     mScrollArea(NULL),
    40     mScrollArea(NULL),
    41     mScrollAreaContents(NULL),
    41     mScrollAreaContents(NULL),
    42     mApplication(application)
    42     mApplication(application)
    43 {
    43 {
    44     NM_FUNCTION;
    44     NM_FUNCTION;
    45 
    45 
    46     // Construct container for the header widgets
    46     // Construct container for the header widgets
    47     mHeaderWidget = new NmEditorHeader(this, documentLoader);
    47     mHeader = new NmEditorHeader(this, documentLoader);
    48 
    48 
    49     // Get pointer to body text area handling widget
    49     // Get pointer to body text area handling widget
    50     mEditorWidget = qobject_cast<NmEditorTextEdit *>(documentLoader->findWidget(NMUI_EDITOR_BODY));
    50     mEditorWidget = qobject_cast<NmEditorTextEdit *>(documentLoader->findWidget(NMUI_EDITOR_BODY));
    51     
    51     
    52     // Set body editor to use NmEditorTextDocument
    52     // Set body editor to use NmEditorTextDocument
    54     mEditorWidget->setDocument(textDocument); 
    54     mEditorWidget->setDocument(textDocument); 
    55     textDocument->setParent(mEditorWidget); // ownership changes
    55     textDocument->setParent(mEditorWidget); // ownership changes
    56 
    56 
    57     mScrollArea = qobject_cast<NmBaseViewScrollArea *>
    57     mScrollArea = qobject_cast<NmBaseViewScrollArea *>
    58         (documentLoader->findObject(NMUI_EDITOR_SCROLL_AREA));
    58         (documentLoader->findObject(NMUI_EDITOR_SCROLL_AREA));
    59 
    59     mScrollArea->setScrollDirections(Qt::Vertical | Qt::Horizontal);
       
    60     
    60     // Enable style picker menu item.
    61     // Enable style picker menu item.
    61     mEditorWidget->setFormatDialog(new HbFormatDialog());
    62     mEditorWidget->setFormatDialog(new HbFormatDialog());
    62 
    63 
    63     mScrollAreaContents =
    64     mScrollAreaContents =
    64         qobject_cast<HbWidget *>(documentLoader->findWidget(NMUI_EDITOR_SCROLL_AREA_CONTENTS));
    65         qobject_cast<HbWidget *>(documentLoader->findWidget(NMUI_EDITOR_SCROLL_AREA_CONTENTS));
   127     // Signal for setting HbTextEdit widgets plain text content
   128     // Signal for setting HbTextEdit widgets plain text content
   128     connect(this, SIGNAL(setPlainText(QString)),
   129     connect(this, SIGNAL(setPlainText(QString)),
   129             mEditorWidget, SLOT(setPlainText(QString)), Qt::QueuedConnection);
   130             mEditorWidget, SLOT(setPlainText(QString)), Qt::QueuedConnection);
   130 
   131 
   131     // Inform text edit widget that header height has been changed
   132     // Inform text edit widget that header height has been changed
   132     connect(mHeaderWidget, SIGNAL(headerHeightChanged(int)), this, SLOT(setEditorContentHeight()),
   133     connect(mHeader, SIGNAL(headerHeightChanged(int)), this, SLOT(setEditorContentHeight()),
   133         Qt::QueuedConnection);
   134         Qt::QueuedConnection);
   134 
   135 
   135     // we are interested in the document's height changes
   136     // we are interested in the document's height changes
   136     connect(mEditorWidget->document()->documentLayout(), SIGNAL(documentSizeChanged(QSizeF)), this,
   137     connect(mEditorWidget->document()->documentLayout(), SIGNAL(documentSizeChanged(QSizeF)), this,
   137         SLOT(setEditorContentHeight()), Qt::QueuedConnection);
   138         SLOT(setEditorContentHeight()), Qt::QueuedConnection);
   138 
   139 
   139     // We need to update the scroll position according the editor cursor position
   140     // We need to update the scroll position according the editor's cursor position
       
   141     connect(mHeader->toEdit(), SIGNAL(cursorPositionChanged(int, int)), this, 
       
   142         SLOT(ensureCursorVisibility()), Qt::QueuedConnection);
       
   143     connect(mHeader->ccEdit(), SIGNAL(cursorPositionChanged(int, int)), this, 
       
   144         SLOT(ensureCursorVisibility()), Qt::QueuedConnection);
       
   145     connect(mHeader->bccEdit(), SIGNAL(cursorPositionChanged(int, int)), this, 
       
   146         SLOT(ensureCursorVisibility()), Qt::QueuedConnection);
       
   147     connect(mHeader->subjectEdit(), SIGNAL(cursorPositionChanged(int, int)), this, 
       
   148         SLOT(ensureCursorVisibility()), Qt::QueuedConnection);
   140     connect(mEditorWidget, SIGNAL(cursorPositionChanged(int, int)), this, 
   149     connect(mEditorWidget, SIGNAL(cursorPositionChanged(int, int)), this, 
   141         SLOT(setScrollPosition(int, int)), Qt::QueuedConnection);
   150         SLOT(ensureCursorVisibility()), Qt::QueuedConnection);
   142     
   151 
   143     // We need to know the scroll area's current position for calculating the new position in
   152     // listen to the parent's (NmEditorView) size changes which happen eg. when VKB is opened/closed
   144 	// setScrollPosition
   153     connect(parent(), SIGNAL(sizeChanged()), this, SLOT(ensureCursorVisibility()),
   145     connect(mScrollArea, SIGNAL(scrollPositionChanged(QPointF)), this, 
   154         Qt::QueuedConnection);
   146         SLOT(updateScrollPosition(QPointF)), Qt::QueuedConnection);
       
   147 }
   155 }
   148 
   156 
   149 /*!
   157 /*!
   150     Return pointer to the email body text edit widget
   158     Return pointer to the email body text edit widget
   151  */
   159  */
   161  */
   169  */
   162 NmEditorHeader *NmEditorContent::header() const
   170 NmEditorHeader *NmEditorContent::header() const
   163 {
   171 {
   164     NM_FUNCTION;
   172     NM_FUNCTION;
   165     
   173     
   166     return mHeaderWidget;
   174     return mHeader;
   167 }
   175 }
   168 
   176 
   169 /*!
   177 /*!
   170     This slot is called when header widget height has been changed. Function performs
   178     This slot is called when header widget height has been changed. Function performs
   171     the repositioning of the body field and resizing of the editor and content area.
   179     the repositioning of the body field and resizing of the editor and content area.
   172  */
   180  */
   173 void NmEditorContent::setEditorContentHeight()
   181 void NmEditorContent::setEditorContentHeight()
   174 {
   182 {
   175     NM_FUNCTION;
   183     NM_FUNCTION;
   176     
   184     
       
   185     // the height of the margin between the title bar and the header
   177     qreal topMargin = 0;
   186     qreal topMargin = 0;
   178     HbStyle().parameter("hb-param-margin-gene-top", topMargin);
   187     HbStyle().parameter("hb-param-margin-gene-top", topMargin);
   179     
   188     
   180     // header height
   189     // header height
   181     qreal headerHeight = mHeaderWidget->headerHeight();
   190     qreal headerHeight = mHeader->headerHeight();
   182 
   191 
   183     // body area editor's document height with margins added
   192     // body area editor's document height with margins added
   184     qreal documentHeightAndMargins = mEditorWidget->document()->size().height() +
   193     qreal documentHeightAndMargins = mEditorWidget->document()->size().height() +
   185         (mEditorWidget->document()->documentMargin() * 2);
   194         (mEditorWidget->document()->documentMargin() * 2);
   186 
   195 
   187     // get the chrome height
   196     // chrome height
   188     qreal chromeHeight = 0;
   197     qreal chromeHeight = 0;
   189     HbStyle().parameter("hb-param-widget-chrome-height", chromeHeight);
   198     HbStyle().parameter("hb-param-widget-chrome-height", chromeHeight);
   190     
   199     
   191     qreal toolbarHeight = 0;
       
   192     HbStyle().parameter("hb-param-widget-toolbar-height", toolbarHeight);
       
   193 
       
   194     // screen height
   200     // screen height
   195     qreal screenHeight = mApplication.screenSize().height();
   201     qreal screenHeight = mApplication.screenSize().height();
   196 
   202 
   197     // set min size for the body area so that at least the screen area is always filled
   203     // set min size for the body area so that at least the screen area is always filled
   198     qreal bodyAreaMinSize = screenHeight - chromeHeight - topMargin - headerHeight;
   204     qreal bodyAreaMinSize = screenHeight - chromeHeight - topMargin - headerHeight;
   201 
   207 
   202     mScrollAreaContents->setPreferredHeight(topMargin + headerHeight + bodyAreaSize);
   208     mScrollAreaContents->setPreferredHeight(topMargin + headerHeight + bodyAreaSize);
   203 }
   209 }
   204 
   210 
   205 /*!
   211 /*!
   206     This slot is called when cursor position is changed in body area using
   212     This slot is called when the cursor visibility has to be ensured ie. the scroll position is 
   207     'pointing stick' or keyboard. Function will update the scroll position
   213     adjusted so that the cursor can be seen.
   208     of the content so that cursor does not go outside of the screen or
   214 */
   209     behind the virtual keyboard.
   215 void NmEditorContent::ensureCursorVisibility()
   210  */
   216 {
   211 void NmEditorContent::setScrollPosition(int oldPos, int newPos)
   217     NM_FUNCTION;
   212 {
   218 
   213     NM_FUNCTION;
   219     // check which of the editors has the focus and get the x/y coordinates for the cursor position
   214     
   220     QGraphicsWidget *focused = mScrollAreaContents->focusWidget();
   215     Q_UNUSED(oldPos);
   221     
   216 
   222     if (focused) {
   217     qreal chromeHeight = 0;
   223         QRectF localRect(0, 0, 0, 0);
   218     HbStyle().parameter("hb-param-widget-chrome-height", chromeHeight);
   224         bool notFound = false;
   219     
   225         
   220     const QSizeF screenReso = mApplication.screenSize();
   226         if (focused == mHeader->toEdit()) {
   221     qreal maxHeight = screenReso.height() - chromeHeight;
   227             localRect = mHeader->toEdit()->rectForCursorPosition();
   222 
   228         }
   223     // Get cursor position coordinates
   229         else if (focused == mHeader->ccEdit()) {
   224     QRectF cursorPosPix = mEditorWidget->rectForPosition(newPos);
   230             localRect = mHeader->ccEdit()->rectForCursorPosition();
   225     
   231         }
   226     // Calculate the screen top and bottom boundaries, this means the part of the
   232         else if (focused == mHeader->bccEdit()) {
   227     // background scroll area which is currently visible.
   233             localRect = mHeader->bccEdit()->rectForCursorPosition();
   228     qreal visibleRectTopBoundary;
   234         }
   229     qreal visibleRectBottomBoundary;
   235         else if (focused == mHeader->subjectEdit()) {
   230     
   236             localRect = mHeader->subjectEdit()->rectForCursorPosition();
   231     qreal headerHeight = mHeaderWidget->headerHeight();
   237         }
   232 
   238         else if (focused == mEditorWidget) {
   233     if (mScrollPosition.y() < headerHeight) {
   239             localRect = mEditorWidget->rectForCursorPosition();
   234         // Header is completely or partially visible
   240         }
   235         visibleRectTopBoundary = headerHeight - mScrollPosition.y();
   241         else {
   236         visibleRectBottomBoundary = maxHeight - visibleRectTopBoundary;
   242             notFound = true;
   237     }
   243         }
   238     else {
   244 
   239         // Header is not visible
   245         if (!notFound) {
   240         visibleRectTopBoundary = mScrollPosition.y() - headerHeight;
   246             QPointF topLeftPos = focused->mapToItem(mScrollAreaContents, localRect.topLeft());
   241         visibleRectBottomBoundary = visibleRectTopBoundary + maxHeight;
   247             QPointF bottomRightPos =
   242     }
   248                 focused->mapToItem(mScrollAreaContents, localRect.bottomRight());
   243 
   249             qreal marginRight = 0;
   244     // Do scrolling if cursor is out of the screen boundaries
   250             HbStyle().parameter("hb-param-margin-gene-right", marginRight);
   245     if (cursorPosPix.y() > visibleRectBottomBoundary) {
   251             bottomRightPos.rx() += marginRight;
   246         // Do scroll forward
   252             mScrollArea->ensureVisible(topLeftPos);
   247         mScrollArea->scrollContentsTo(QPointF(0, cursorPosPix.y() - maxHeight + headerHeight));
   253             mScrollArea->ensureVisible(bottomRightPos);
   248     }
   254         }
   249     else if (cursorPosPix.y() + headerHeight < mScrollPosition.y()) {
   255     }
   250         // Do scroll backward
   256 }
   251         mScrollArea->scrollContentsTo(QPointF(0, cursorPosPix.y() + headerHeight));
       
   252     }
       
   253 }
       
   254 
       
   255 /*!
       
   256     This slot is called when background scroll areas scroll position has been shanged.
       
   257 */
       
   258 void NmEditorContent::updateScrollPosition(const QPointF &newPosition)
       
   259 {
       
   260     NM_FUNCTION;
       
   261     
       
   262     mScrollPosition = newPosition;
       
   263 }
       
   264 
       
   265 /*!
   257 /*!
   266     Removes embedded images from the message body
   258     Removes embedded images from the message body
   267  */
   259  */
   268 void NmEditorContent::removeEmbeddedImages(QString &bodyContent)
   260 void NmEditorContent::removeEmbeddedImages(QString &bodyContent)
   269 {
   261 {