Subversion Repositories Scribus

Compare Revisions

Ignore whitespace Rev 19604 → Rev 19605

/trunk/Scribus/scribus/canvasmode_framelinks.cpp
1,493 → 1,493
/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
 
 
#include "canvasmode_framelinks.h"
 
#include <QApplication>
#include <QButtonGroup>
#include <QCheckBox>
#include <QCursor>
#include <QEvent>
#include <QMessageBox>
#include <QMouseEvent>
#include <QPainterPath>
#include <QPoint>
#include <QRect>
#include <QTimer>
#include <QWidgetAction>
#include <QDebug>
 
#include "appmodes.h"
#include "canvas.h"
#include "fpoint.h"
#include "fpointarray.h"
#include "pageitem_textframe.h"
#include "prefscontext.h"
#include "prefsfile.h"
#include "prefsmanager.h"
#include "scribus.h"
#include "scribusdoc.h"
#include "scribusview.h"
#include "selection.h"
#include "ui/contextmenu.h"
#include "ui/pageselector.h"
#include "ui/propertiespalette.h"
#include "undomanager.h"
#include "units.h"
#include "util.h"
#include "util_icon.h"
#include "util_math.h"
 
 
 
CanvasMode_FrameLinks::CanvasMode_FrameLinks(ScribusView* view) : CanvasMode(view), m_ScMW(view->m_ScMW)
{
Mxp = Myp = -1;
Dxp = Dyp = -1;
frameResizeHandle = -1;
}
 
inline bool CanvasMode_FrameLinks::GetItem(PageItem** pi)
{
*pi = m_doc->m_Selection->itemAt(0);
return (*pi) != NULL;
}
 
void CanvasMode_FrameLinks::drawControls(QPainter* p)
{
commonDrawControls(p, false);
}
 
void CanvasMode_FrameLinks::enterEvent(QEvent *)
{
if (!m_canvas->m_viewMode.m_MouseButtonPressed)
{
setModeCursor();
}
}
 
void CanvasMode_FrameLinks::leaveEvent(QEvent *e)
{
}
 
 
void CanvasMode_FrameLinks::activate(bool fromGesture)
{
// qDebug() << "CanvasMode_FrameLinks::activate" << fromGesture;
m_canvas->m_viewMode.m_MouseButtonPressed = false;
m_canvas->resetRenderMode();
m_doc->DragP = false;
m_doc->leaveDrag = false;
m_canvas->m_viewMode.operItemMoving = false;
m_canvas->m_viewMode.operItemResizing = false;
m_view->MidButt = false;
Mxp = Myp = -1;
Dxp = Dyp = -1;
frameResizeHandle = -1;
setModeCursor();
if (fromGesture)
{
m_view->update();
}
}
 
void CanvasMode_FrameLinks::deactivate(bool forGesture)
{
// qDebug() << "CanvasMode_FrameLinks::deactivate" << forGesture;
m_view->setRedrawMarkerShown(false);
}
 
void CanvasMode_FrameLinks::mouseDoubleClickEvent(QMouseEvent *m)
{
m->accept();
m_canvas->m_viewMode.m_MouseButtonPressed = false;
m_canvas->resetRenderMode();
// m_view->stopDragTimer();
}
 
void CanvasMode_FrameLinks::mouseMoveEvent(QMouseEvent *m)
{
const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
m->accept();
 
if (commonMouseMove(m))
return;
if ((m_canvas->m_viewMode.m_MouseButtonPressed) && (m->buttons() & Qt::LeftButton))
{
SeRx = qRound(mousePointDoc.x()); //m_view->translateToDoc(m->x(), m->y()).x());
SeRy = qRound(mousePointDoc.y()); //m_view->translateToDoc(m->x(), m->y()).y());
QPoint startP = m_canvas->canvasToGlobal(m_doc->appMode == modeDrawTable2 ? QPointF(Dxp, Dyp) : QPointF(Mxp, Myp));
m_view->redrawMarker->setGeometry(QRect(m_view->mapFromGlobal(startP), m_view->mapFromGlobal(m->globalPos())).normalized());
m_view->setRedrawMarkerShown(true);
m_view->HaveSelRect = true;
return;
}
}
 
void CanvasMode_FrameLinks::mousePressEvent(QMouseEvent *m)
{
const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
 
double Rxp = 0;
double Ryp = 0;
PageItem *currItem, *bb;
m_canvas->PaintSizeRect(QRect());
m_canvas->m_viewMode.m_MouseButtonPressed = true;
m_canvas->m_viewMode.operItemMoving = false;
m_view->HaveSelRect = false;
m_doc->DragP = false;
m_doc->leaveDrag = false;
// oldClip = 0;
m->accept();
m_view->registerMousePress(m->globalPos());
Mxp = mousePointDoc.x(); //qRound(m->x()/m_canvas->scale() + 0*m_doc->minCanvasCoordinate.x());
Myp = mousePointDoc.y(); //qRound(m->y()/m_canvas->scale() + 0*m_doc->minCanvasCoordinate.y());
Rxp = m_doc->ApplyGridF(FPoint(Mxp, Myp)).x();
Mxp = qRound(Rxp);
Ryp = m_doc->ApplyGridF(FPoint(Mxp, Myp)).y();
Myp = qRound(Ryp);
SeRx = Mxp;
SeRy = Myp;
if (m->button() == Qt::MidButton)
{
m_view->MidButt = true;
if (m->modifiers() & Qt::ControlModifier)
m_view->DrawNew();
return;
}
switch (m_doc->appMode)
{
case modeLinkFrames:
if (m->button() != Qt::LeftButton)
break;
currItem = m_doc->ElemToLink;
if (currItem==NULL)
break;
SeleItem(m);
if (GetItem(&bb) && (bb->asTextFrame()))
{
PageItem* bblast = bb;
while (bblast->nextInChain())
bblast = bblast->nextInChain();
if (currItem->nextInChain() == NULL && currItem != bblast) //possibility to insert empty frames into chain
{
if (bb->prevInChain() != NULL)
{
QMessageBox msgBox(QMessageBox::Question, tr("Linking Text Frames"),
"<qt>" + ScribusView::tr("You are trying to insert a frame into an existing text chain, where would you like to insert it?") + "<qt>");
//QMessageBox msgBox;
QPushButton *cancelButton = msgBox.addButton(CommonStrings::tr_Cancel, QMessageBox::RejectRole);
QPushButton *beforeButton = msgBox.addButton(tr("Before"), QMessageBox::AcceptRole);
QPushButton *afterButton = msgBox.addButton(tr("After"), QMessageBox::AcceptRole);
msgBox.exec();
if ((QPushButton *) msgBox.clickedButton() == cancelButton)
break;
if ((QPushButton *) msgBox.clickedButton() == beforeButton)
{
if (currItem->prevInChain())
currItem->prevInChain()->unlink();
PageItem *prev = bb->prevInChain();
prev->unlink();
prev->link(currItem);
}
else if ((QPushButton *) msgBox.clickedButton() == afterButton)
{
if (bb->nextInChain() != NULL)
{
if (currItem->prevInChain())
currItem->prevInChain()->unlink();
PageItem *next = bb->nextInChain();
bb->unlink();
bb->link(currItem);
bb = next;
}
else
{ // link at end of last frame in chain - switch currItem <-> bb
PageItem* tmp = currItem;
currItem = bb;
bb = tmp;
}
}
}
if (bb->prevInChain())
bb->prevInChain()->unlink();
currItem->link(bb);
int cid = m_doc->Items->indexOf(currItem);
int bid = m_doc->Items->indexOf(bb);
// CB We need to do this because we draw in the order of the item list
// Which is also item number list.. but #3488: we must also renumber the items
if (bid < cid)
{
m_doc->Items->insert(cid+1, bb);
bb = m_doc->Items->takeAt(bid);
}
// m_view->updateContents();
// link calls PageItem::update
//ECE no, link() not force update
currItem->update();
m_view->DrawNew();
//emit DocChanged();
m_doc->ElemToLink = bb;
}
else if (currItem == bblast)
{
//CB Mouse is released when this messagebox takes focus
m_canvas->m_viewMode.m_MouseButtonPressed = false;
QMessageBox::warning(m_view, ScribusView::tr("Linking Text Frames"),
"<qt>" + ScribusView::tr("You are trying to link a frame to itself.") + "</qt>");
}
else
{
//CB Mouse is released when this messagebox takes focus
m_canvas->m_viewMode.m_MouseButtonPressed = false;
QMessageBox::warning(m_view, ScribusView::tr("Linking Text Frames"),
"<qt>" + ScribusView::tr("You are trying to link a non-empty frame to frame which is already linked.") + "</qt>");
}
}
else
m_doc->ElemToLink = NULL;
break;
case modeUnlinkFrames:
if (m->button() != Qt::LeftButton)
break;
SeleItem(m);
if (GetItem(&currItem) && (currItem->asTextFrame()))
{
if (currItem->prevInChain() != 0)
{
currItem->prevInChain()->unlink();
}
// unlink calls PageItem::update emit DocChanged();
// m_view->updateContents();
}
break;
}
}
 
void CanvasMode_FrameLinks::mouseReleaseEvent(QMouseEvent *m)
{
#ifdef GESTURE_FRAME_PREVIEW
clearPixmapCache();
#endif // GESTURE_FRAME_PREVIEW
const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
PageItem *currItem;
m_canvas->m_viewMode.m_MouseButtonPressed = false;
m_canvas->resetRenderMode();
m->accept();
// m_view->stopDragTimer();
//m_canvas->update(); //ugly in a mouseReleaseEvent!!!!!!!
if ((GetItem(&currItem)) && (m->button() == Qt::RightButton) && (!m_doc->DragP))
{
createContextMenu(currItem, mousePointDoc.x(), mousePointDoc.y());
return;
}
if ((m_doc->appMode == modeLinkFrames) || (m_doc->appMode == modeUnlinkFrames))
{
m_view->updateContents();
if (!PrefsManager::instance()->appPrefs.uiPrefs.stickyTools || m_doc->ElemToLink == 0)
m_view->requestMode(submodePaintingDone);
return;
}
m_canvas->setRenderModeUseBuffer(false);
m_doc->DragP = false;
m_doc->leaveDrag = false;
m_canvas->m_viewMode.operItemMoving = false;
m_canvas->m_viewMode.operItemResizing = false;
m_view->MidButt = false;
for (int i = 0; i < m_doc->m_Selection->count(); ++i)
m_doc->m_Selection->itemAt(i)->checkChanges(true);
//Make sure the Zoom spinbox and page selector dont have focus if we click on the canvas
m_view->m_ScMW->zoomSpinBox->clearFocus();
m_view->m_ScMW->pageSelector->clearFocus();
}
 
void CanvasMode_FrameLinks::selectPage(QMouseEvent *m)
{
m_canvas->m_viewMode.m_MouseButtonPressed = true;
FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
Mxp = mousePointDoc.x(); //static_cast<int>(m->x()/m_canvas->scale());
Myp = mousePointDoc.y(); //static_cast<int>(m->y()/m_canvas->scale());
m_doc->nodeEdit.deselect();
m_view->Deselect(false);
if (!m_doc->masterPageMode())
{
int i = m_doc->OnPage(Mxp, Myp);
if (i!=-1)
{
uint docCurrPageNo=m_doc->currentPageNumber();
uint j=static_cast<uint>(i);
if (docCurrPageNo != j)
{
m_doc->setCurrentPage(m_doc->Pages->at(j));
m_view->m_ScMW->slotSetCurrentPage(j);
m_view->DrawNew();
}
}
m_view->setRulerPos(m_view->contentsX(), m_view->contentsY());
}
}
 
//CB-->Doc/Fix
bool CanvasMode_FrameLinks::SeleItem(QMouseEvent *m)
{
const unsigned SELECT_IN_GROUP = Qt::AltModifier;
const unsigned SELECT_MULTIPLE = Qt::ShiftModifier;
const unsigned SELECT_BENEATH = Qt::ControlModifier;
QTransform p;
PageItem *currItem;
m_canvas->m_viewMode.m_MouseButtonPressed = true;
FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
Mxp = mousePointDoc.x(); //m->x()/m_canvas->scale());
Myp = mousePointDoc.y(); //m->y()/m_canvas->scale());
int MxpS = static_cast<int>(mousePointDoc.x()); //m->x()/m_canvas->scale() + 0*m_doc->minCanvasCoordinate.x());
int MypS = static_cast<int>(mousePointDoc.y()); //m->y()/m_canvas->scale() + 0*m_doc->minCanvasCoordinate.y());
m_doc->nodeEdit.deselect();
if (!m_doc->masterPageMode())
{
int pgNum = -1;
int docPageCount = static_cast<int>(m_doc->Pages->count() - 1);
MarginStruct pageBleeds;
bool drawBleed = false;
if (m_doc->bleeds()->hasNonZeroValue() && m_doc->guidesPrefs().showBleed)
drawBleed = true;
for (int a = docPageCount; a > -1; a--)
{
if (drawBleed)
m_doc->getBleeds(a, pageBleeds);
int x = static_cast<int>(m_doc->Pages->at(a)->xOffset() - pageBleeds.Left);
int y = static_cast<int>(m_doc->Pages->at(a)->yOffset() - pageBleeds.Top);
int w = static_cast<int>(m_doc->Pages->at(a)->width() + pageBleeds.Left + pageBleeds.Right);
int h = static_cast<int>(m_doc->Pages->at(a)->height() + pageBleeds.Bottom + pageBleeds.Top);
if (QRect(x, y, w, h).contains(MxpS, MypS))
{
pgNum = static_cast<int>(a);
if (drawBleed) // check again if its really on the correct page
{
for (int a2 = docPageCount; a2 > -1; a2--)
{
int xn = static_cast<int>(m_doc->Pages->at(a2)->xOffset());
int yn = static_cast<int>(m_doc->Pages->at(a2)->yOffset());
int wn = static_cast<int>(m_doc->Pages->at(a2)->width());
int hn = static_cast<int>(m_doc->Pages->at(a2)->height());
if (QRect(xn, yn, wn, hn).contains(MxpS, MypS))
{
pgNum = static_cast<int>(a2);
break;
}
}
}
break;
}
}
if (pgNum >= 0)
{
if (m_doc->currentPageNumber() != pgNum)
{
m_doc->setCurrentPage(m_doc->Pages->at(unsigned(pgNum)));
m_view->m_ScMW->slotSetCurrentPage(unsigned(pgNum));
m_view->DrawNew();
}
}
m_view->setRulerPos(m_view->contentsX(), m_view->contentsY());
}
currItem = NULL;
if ((m->modifiers() & SELECT_BENEATH) != 0)
{
for (int i=0; i < m_doc->m_Selection->count(); ++i)
{
if (m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), m_doc->m_Selection->itemAt(i)) >= 0)
{
currItem = m_doc->m_Selection->itemAt(i);
m_doc->m_Selection->removeItem(currItem);
break;
}
}
}
else if ( (m->modifiers() & SELECT_MULTIPLE) == Qt::NoModifier || (m_doc->appMode == modeLinkFrames) || (m_doc->appMode == modeUnlinkFrames) )
{
m_view->Deselect(false);
}
currItem = m_canvas->itemUnderCursor(m->globalPos(), currItem, (m->modifiers() & SELECT_IN_GROUP));
if (currItem)
{
m_doc->m_Selection->delaySignalsOn();
if (m_doc->m_Selection->containsItem(currItem))
{
m_doc->m_Selection->removeItem(currItem);
}
else
{
//CB: If we have a selection but the user clicks with control on another item that is not below the current
//then clear and select the new item
if ((m->modifiers() == SELECT_BENEATH) && m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), currItem) >= 0)
m_doc->m_Selection->clear();
//CB: #7186: This was prependItem, does not seem to need to be anymore with current select code
m_doc->m_Selection->addItem(currItem);
if ( (m->modifiers() & SELECT_IN_GROUP) && (!currItem->isGroup()))
{
currItem->isSingleSel = true;
}
}
currItem->update();
m_doc->m_Selection->delaySignalsOff();
if (m_doc->m_Selection->count() > 1)
{
for (int aa = 0; aa < m_doc->m_Selection->count(); ++aa)
{
PageItem *bb = m_doc->m_Selection->itemAt(aa);
bb->update();
}
m_doc->m_Selection->setGroupRect();
double x, y, w, h;
m_doc->m_Selection->getGroupRect(&x, &y, &w, &h);
m_view->getGroupRectScreen(&x, &y, &w, &h);
}
if (m_doc->m_Selection->count() == 1)
{
frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), currItem);
if ((frameResizeHandle == Canvas::INSIDE) && (!currItem->locked()))
m_view->setCursor(QCursor(Qt::SizeAllCursor));
}
else
{
m_view->setCursor(QCursor(Qt::SizeAllCursor));
m_canvas->m_viewMode.operItemResizing = false;
}
return true;
}
m_doc->m_Selection->connectItemToGUI();
if ( !(m->modifiers() & SELECT_MULTIPLE) || (m_doc->appMode == modeLinkFrames) || (m_doc->appMode == modeUnlinkFrames))
m_view->Deselect(true);
return false;
}
 
void CanvasMode_FrameLinks::createContextMenu(PageItem* currItem, double mx, double my)
{
ContextMenu* cmen=NULL;
m_view->setObjectUndoMode();
Mxp = mx;
Myp = my;
if(currItem!=NULL)
{
cmen = new ContextMenu(*(m_doc->m_Selection), m_ScMW, m_doc);
cmen->exec(QCursor::pos());
m_view->setGlobalUndoMode();
delete cmen;
}
}
/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
 
 
#include "canvasmode_framelinks.h"
 
#include <QApplication>
#include <QButtonGroup>
#include <QCheckBox>
#include <QCursor>
#include <QEvent>
#include <QMessageBox>
#include <QMouseEvent>
#include <QPainterPath>
#include <QPoint>
#include <QRect>
#include <QTimer>
#include <QWidgetAction>
#include <QDebug>
 
#include "appmodes.h"
#include "canvas.h"
#include "fpoint.h"
#include "fpointarray.h"
#include "pageitem_textframe.h"
#include "prefscontext.h"
#include "prefsfile.h"
#include "prefsmanager.h"
#include "scribus.h"
#include "scribusdoc.h"
#include "scribusview.h"
#include "selection.h"
#include "ui/contextmenu.h"
#include "ui/pageselector.h"
#include "ui/propertiespalette.h"
#include "undomanager.h"
#include "units.h"
#include "util.h"
#include "util_icon.h"
#include "util_math.h"
 
 
 
CanvasMode_FrameLinks::CanvasMode_FrameLinks(ScribusView* view) : CanvasMode(view), m_ScMW(view->m_ScMW)
{
Mxp = Myp = -1;
Dxp = Dyp = -1;
frameResizeHandle = -1;
}
 
inline bool CanvasMode_FrameLinks::GetItem(PageItem** pi)
{
*pi = m_doc->m_Selection->itemAt(0);
return (*pi) != NULL;
}
 
void CanvasMode_FrameLinks::drawControls(QPainter* p)
{
commonDrawControls(p, false);
}
 
void CanvasMode_FrameLinks::enterEvent(QEvent *)
{
if (!m_canvas->m_viewMode.m_MouseButtonPressed)
{
setModeCursor();
}
}
 
void CanvasMode_FrameLinks::leaveEvent(QEvent *e)
{
}
 
 
void CanvasMode_FrameLinks::activate(bool fromGesture)
{
// qDebug() << "CanvasMode_FrameLinks::activate" << fromGesture;
m_canvas->m_viewMode.m_MouseButtonPressed = false;
m_canvas->resetRenderMode();
m_doc->DragP = false;
m_doc->leaveDrag = false;
m_canvas->m_viewMode.operItemMoving = false;
m_canvas->m_viewMode.operItemResizing = false;
m_view->MidButt = false;
Mxp = Myp = -1;
Dxp = Dyp = -1;
frameResizeHandle = -1;
setModeCursor();
if (fromGesture)
{
m_view->update();
}
}
 
void CanvasMode_FrameLinks::deactivate(bool forGesture)
{
// qDebug() << "CanvasMode_FrameLinks::deactivate" << forGesture;
m_view->setRedrawMarkerShown(false);
}
 
void CanvasMode_FrameLinks::mouseDoubleClickEvent(QMouseEvent *m)
{
m->accept();
m_canvas->m_viewMode.m_MouseButtonPressed = false;
m_canvas->resetRenderMode();
// m_view->stopDragTimer();
}
 
void CanvasMode_FrameLinks::mouseMoveEvent(QMouseEvent *m)
{
const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
m->accept();
 
if (commonMouseMove(m))
return;
if ((m_canvas->m_viewMode.m_MouseButtonPressed) && (m->buttons() & Qt::LeftButton))
{
SeRx = qRound(mousePointDoc.x()); //m_view->translateToDoc(m->x(), m->y()).x());
SeRy = qRound(mousePointDoc.y()); //m_view->translateToDoc(m->x(), m->y()).y());
QPoint startP = m_canvas->canvasToGlobal(m_doc->appMode == modeDrawTable2 ? QPointF(Dxp, Dyp) : QPointF(Mxp, Myp));
m_view->redrawMarker->setGeometry(QRect(m_view->mapFromGlobal(startP), m_view->mapFromGlobal(m->globalPos())).normalized());
m_view->setRedrawMarkerShown(true);
m_view->HaveSelRect = true;
return;
}
}
 
void CanvasMode_FrameLinks::mousePressEvent(QMouseEvent *m)
{
const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
 
double Rxp = 0;
double Ryp = 0;
PageItem *currItem, *bb;
m_canvas->PaintSizeRect(QRect());
m_canvas->m_viewMode.m_MouseButtonPressed = true;
m_canvas->m_viewMode.operItemMoving = false;
m_view->HaveSelRect = false;
m_doc->DragP = false;
m_doc->leaveDrag = false;
// oldClip = 0;
m->accept();
m_view->registerMousePress(m->globalPos());
Mxp = mousePointDoc.x(); //qRound(m->x()/m_canvas->scale() + 0*m_doc->minCanvasCoordinate.x());
Myp = mousePointDoc.y(); //qRound(m->y()/m_canvas->scale() + 0*m_doc->minCanvasCoordinate.y());
Rxp = m_doc->ApplyGridF(FPoint(Mxp, Myp)).x();
Mxp = qRound(Rxp);
Ryp = m_doc->ApplyGridF(FPoint(Mxp, Myp)).y();
Myp = qRound(Ryp);
SeRx = Mxp;
SeRy = Myp;
if (m->button() == Qt::MidButton)
{
m_view->MidButt = true;
if (m->modifiers() & Qt::ControlModifier)
m_view->DrawNew();
return;
}
switch (m_doc->appMode)
{
case modeLinkFrames:
if (m->button() != Qt::LeftButton)
break;
currItem = m_doc->ElemToLink;
if (currItem==NULL)
break;
SeleItem(m);
if (GetItem(&bb) && (bb->asTextFrame()))
{
PageItem* bblast = bb;
while (bblast->nextInChain())
bblast = bblast->nextInChain();
if (currItem->nextInChain() == NULL && currItem != bblast) //possibility to insert empty frames into chain
{
if (bb->prevInChain() != NULL)
{
ScMessageBox msgBox(QMessageBox::Question, tr("Linking Text Frames"),
"<qt>" + ScribusView::tr("You are trying to insert a frame into an existing text chain, where would you like to insert it?") + "<qt>");
QPushButton *cancelButton = msgBox.addButton(CommonStrings::tr_Cancel, QMessageBox::RejectRole);
QPushButton *beforeButton = msgBox.addButton(tr("Before"), QMessageBox::AcceptRole);
QPushButton *afterButton = msgBox.addButton(tr("After"), QMessageBox::AcceptRole);
msgBox.setDefaultBatchButton(afterButton);
msgBox.exec();
if ((QPushButton *) msgBox.clickedButton() == cancelButton)
break;
if ((QPushButton *) msgBox.clickedButton() == beforeButton)
{
if (currItem->prevInChain())
currItem->prevInChain()->unlink();
PageItem *prev = bb->prevInChain();
prev->unlink();
prev->link(currItem);
}
else if ((QPushButton *) msgBox.clickedButton() == afterButton)
{
if (bb->nextInChain() != NULL)
{
if (currItem->prevInChain())
currItem->prevInChain()->unlink();
PageItem *next = bb->nextInChain();
bb->unlink();
bb->link(currItem);
bb = next;
}
else
{ // link at end of last frame in chain - switch currItem <-> bb
PageItem* tmp = currItem;
currItem = bb;
bb = tmp;
}
}
}
if (bb->prevInChain())
bb->prevInChain()->unlink();
currItem->link(bb);
int cid = m_doc->Items->indexOf(currItem);
int bid = m_doc->Items->indexOf(bb);
// CB We need to do this because we draw in the order of the item list
// Which is also item number list.. but #3488: we must also renumber the items
if (bid < cid)
{
m_doc->Items->insert(cid+1, bb);
bb = m_doc->Items->takeAt(bid);
}
// m_view->updateContents();
// link calls PageItem::update
//ECE no, link() not force update
currItem->update();
m_view->DrawNew();
//emit DocChanged();
m_doc->ElemToLink = bb;
}
else if (currItem == bblast)
{
//CB Mouse is released when this messagebox takes focus
m_canvas->m_viewMode.m_MouseButtonPressed = false;
ScMessageBox::warning(m_view, ScribusView::tr("Linking Text Frames"),
"<qt>" + ScribusView::tr("You are trying to link a frame to itself.") + "</qt>");
}
else
{
//CB Mouse is released when this messagebox takes focus
m_canvas->m_viewMode.m_MouseButtonPressed = false;
ScMessageBox::warning(m_view, ScribusView::tr("Linking Text Frames"),
"<qt>" + ScribusView::tr("You are trying to link a non-empty frame to frame which is already linked.") + "</qt>");
}
}
else
m_doc->ElemToLink = NULL;
break;
case modeUnlinkFrames:
if (m->button() != Qt::LeftButton)
break;
SeleItem(m);
if (GetItem(&currItem) && (currItem->asTextFrame()))
{
if (currItem->prevInChain() != 0)
{
currItem->prevInChain()->unlink();
}
// unlink calls PageItem::update emit DocChanged();
// m_view->updateContents();
}
break;
}
}
 
void CanvasMode_FrameLinks::mouseReleaseEvent(QMouseEvent *m)
{
#ifdef GESTURE_FRAME_PREVIEW
clearPixmapCache();
#endif // GESTURE_FRAME_PREVIEW
const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
PageItem *currItem;
m_canvas->m_viewMode.m_MouseButtonPressed = false;
m_canvas->resetRenderMode();
m->accept();
// m_view->stopDragTimer();
//m_canvas->update(); //ugly in a mouseReleaseEvent!!!!!!!
if ((GetItem(&currItem)) && (m->button() == Qt::RightButton) && (!m_doc->DragP))
{
createContextMenu(currItem, mousePointDoc.x(), mousePointDoc.y());
return;
}
if ((m_doc->appMode == modeLinkFrames) || (m_doc->appMode == modeUnlinkFrames))
{
m_view->updateContents();
if (!PrefsManager::instance()->appPrefs.uiPrefs.stickyTools || m_doc->ElemToLink == 0)
m_view->requestMode(submodePaintingDone);
return;
}
m_canvas->setRenderModeUseBuffer(false);
m_doc->DragP = false;
m_doc->leaveDrag = false;
m_canvas->m_viewMode.operItemMoving = false;
m_canvas->m_viewMode.operItemResizing = false;
m_view->MidButt = false;
for (int i = 0; i < m_doc->m_Selection->count(); ++i)
m_doc->m_Selection->itemAt(i)->checkChanges(true);
//Make sure the Zoom spinbox and page selector dont have focus if we click on the canvas
m_view->m_ScMW->zoomSpinBox->clearFocus();
m_view->m_ScMW->pageSelector->clearFocus();
}
 
void CanvasMode_FrameLinks::selectPage(QMouseEvent *m)
{
m_canvas->m_viewMode.m_MouseButtonPressed = true;
FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
Mxp = mousePointDoc.x(); //static_cast<int>(m->x()/m_canvas->scale());
Myp = mousePointDoc.y(); //static_cast<int>(m->y()/m_canvas->scale());
m_doc->nodeEdit.deselect();
m_view->Deselect(false);
if (!m_doc->masterPageMode())
{
int i = m_doc->OnPage(Mxp, Myp);
if (i!=-1)
{
uint docCurrPageNo=m_doc->currentPageNumber();
uint j=static_cast<uint>(i);
if (docCurrPageNo != j)
{
m_doc->setCurrentPage(m_doc->Pages->at(j));
m_view->m_ScMW->slotSetCurrentPage(j);
m_view->DrawNew();
}
}
m_view->setRulerPos(m_view->contentsX(), m_view->contentsY());
}
}
 
//CB-->Doc/Fix
bool CanvasMode_FrameLinks::SeleItem(QMouseEvent *m)
{
const unsigned SELECT_IN_GROUP = Qt::AltModifier;
const unsigned SELECT_MULTIPLE = Qt::ShiftModifier;
const unsigned SELECT_BENEATH = Qt::ControlModifier;
QTransform p;
PageItem *currItem;
m_canvas->m_viewMode.m_MouseButtonPressed = true;
FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
Mxp = mousePointDoc.x(); //m->x()/m_canvas->scale());
Myp = mousePointDoc.y(); //m->y()/m_canvas->scale());
int MxpS = static_cast<int>(mousePointDoc.x()); //m->x()/m_canvas->scale() + 0*m_doc->minCanvasCoordinate.x());
int MypS = static_cast<int>(mousePointDoc.y()); //m->y()/m_canvas->scale() + 0*m_doc->minCanvasCoordinate.y());
m_doc->nodeEdit.deselect();
if (!m_doc->masterPageMode())
{
int pgNum = -1;
int docPageCount = static_cast<int>(m_doc->Pages->count() - 1);
MarginStruct pageBleeds;
bool drawBleed = false;
if (m_doc->bleeds()->hasNonZeroValue() && m_doc->guidesPrefs().showBleed)
drawBleed = true;
for (int a = docPageCount; a > -1; a--)
{
if (drawBleed)
m_doc->getBleeds(a, pageBleeds);
int x = static_cast<int>(m_doc->Pages->at(a)->xOffset() - pageBleeds.Left);
int y = static_cast<int>(m_doc->Pages->at(a)->yOffset() - pageBleeds.Top);
int w = static_cast<int>(m_doc->Pages->at(a)->width() + pageBleeds.Left + pageBleeds.Right);
int h = static_cast<int>(m_doc->Pages->at(a)->height() + pageBleeds.Bottom + pageBleeds.Top);
if (QRect(x, y, w, h).contains(MxpS, MypS))
{
pgNum = static_cast<int>(a);
if (drawBleed) // check again if its really on the correct page
{
for (int a2 = docPageCount; a2 > -1; a2--)
{
int xn = static_cast<int>(m_doc->Pages->at(a2)->xOffset());
int yn = static_cast<int>(m_doc->Pages->at(a2)->yOffset());
int wn = static_cast<int>(m_doc->Pages->at(a2)->width());
int hn = static_cast<int>(m_doc->Pages->at(a2)->height());
if (QRect(xn, yn, wn, hn).contains(MxpS, MypS))
{
pgNum = static_cast<int>(a2);
break;
}
}
}
break;
}
}
if (pgNum >= 0)
{
if (m_doc->currentPageNumber() != pgNum)
{
m_doc->setCurrentPage(m_doc->Pages->at(unsigned(pgNum)));
m_view->m_ScMW->slotSetCurrentPage(unsigned(pgNum));
m_view->DrawNew();
}
}
m_view->setRulerPos(m_view->contentsX(), m_view->contentsY());
}
currItem = NULL;
if ((m->modifiers() & SELECT_BENEATH) != 0)
{
for (int i=0; i < m_doc->m_Selection->count(); ++i)
{
if (m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), m_doc->m_Selection->itemAt(i)) >= 0)
{
currItem = m_doc->m_Selection->itemAt(i);
m_doc->m_Selection->removeItem(currItem);
break;
}
}
}
else if ( (m->modifiers() & SELECT_MULTIPLE) == Qt::NoModifier || (m_doc->appMode == modeLinkFrames) || (m_doc->appMode == modeUnlinkFrames) )
{
m_view->Deselect(false);
}
currItem = m_canvas->itemUnderCursor(m->globalPos(), currItem, (m->modifiers() & SELECT_IN_GROUP));
if (currItem)
{
m_doc->m_Selection->delaySignalsOn();
if (m_doc->m_Selection->containsItem(currItem))
{
m_doc->m_Selection->removeItem(currItem);
}
else
{
//CB: If we have a selection but the user clicks with control on another item that is not below the current
//then clear and select the new item
if ((m->modifiers() == SELECT_BENEATH) && m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), currItem) >= 0)
m_doc->m_Selection->clear();
//CB: #7186: This was prependItem, does not seem to need to be anymore with current select code
m_doc->m_Selection->addItem(currItem);
if ( (m->modifiers() & SELECT_IN_GROUP) && (!currItem->isGroup()))
{
currItem->isSingleSel = true;
}
}
currItem->update();
m_doc->m_Selection->delaySignalsOff();
if (m_doc->m_Selection->count() > 1)
{
for (int aa = 0; aa < m_doc->m_Selection->count(); ++aa)
{
PageItem *bb = m_doc->m_Selection->itemAt(aa);
bb->update();
}
m_doc->m_Selection->setGroupRect();
double x, y, w, h;
m_doc->m_Selection->getGroupRect(&x, &y, &w, &h);
m_view->getGroupRectScreen(&x, &y, &w, &h);
}
if (m_doc->m_Selection->count() == 1)
{
frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), currItem);
if ((frameResizeHandle == Canvas::INSIDE) && (!currItem->locked()))
m_view->setCursor(QCursor(Qt::SizeAllCursor));
}
else
{
m_view->setCursor(QCursor(Qt::SizeAllCursor));
m_canvas->m_viewMode.operItemResizing = false;
}
return true;
}
m_doc->m_Selection->connectItemToGUI();
if ( !(m->modifiers() & SELECT_MULTIPLE) || (m_doc->appMode == modeLinkFrames) || (m_doc->appMode == modeUnlinkFrames))
m_view->Deselect(true);
return false;
}
 
void CanvasMode_FrameLinks::createContextMenu(PageItem* currItem, double mx, double my)
{
ContextMenu* cmen=NULL;
m_view->setObjectUndoMode();
Mxp = mx;
Myp = my;
if(currItem!=NULL)
{
cmen = new ContextMenu(*(m_doc->m_Selection), m_ScMW, m_doc);
cmen->exec(QCursor::pos());
m_view->setGlobalUndoMode();
delete cmen;
}
}
/trunk/Scribus/scribus/canvasmode_normal.cpp
1,1934 → 1,1934
/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
 
 
#include "canvasmode_normal.h"
 
#include <QApplication>
#include <QButtonGroup>
#include <QCheckBox>
#include <QCursor>
#include <QEvent>
#include <QMessageBox>
#include <QMouseEvent>
#include <QPainterPath>
#include <QPoint>
#include <QRect>
#include <QTimer>
#include <QToolTip>
#include <QWidgetAction>
#include <QDrag>
#include <QDebug>
 
#include "appmodes.h"
#include "canvas.h"
#include "canvasgesture_linemove.h"
#include "canvasgesture_resize.h"
#include "canvasgesture_rulermove.h"
#include "fileloader.h"
#include "fpoint.h"
#include "fpointarray.h"
#include "hyphenator.h"
#include "loadsaveplugin.h"
#include "pageitem_arc.h"
#include "pageitem_line.h"
#include "pageitem_regularpolygon.h"
#include "pageitem_textframe.h"
#include "plugins/formatidlist.h"
#include "prefscontext.h"
#include "prefsfile.h"
#include "prefsmanager.h"
#include "scmimedata.h"
#include "scraction.h"
#include "scribus.h"
#include "scribusXml.h"
#include "scribusdoc.h"
#include "scribusview.h"
#include "selection.h"
#include "ui/aligndistribute.h"
#include "ui/contextmenu.h"
#include "ui/customfdialog.h"
#include "ui/insertTable.h"
#include "ui/pageselector.h"
#include "ui/polyprops.h"
#include "ui/propertiespalette.h"
#include "ui/propertiespalette_line.h"
#include "ui/propertiespalette_text.h"
#include "ui/propertiespalette_xyz.h"
#include "undomanager.h"
#include "util.h"
#include "util_icon.h"
#include "util_math.h"
 
 
 
 
 
CanvasMode_Normal::CanvasMode_Normal(ScribusView* view) : CanvasMode(view), m_ScMW(view->m_ScMW)
{
frameResizeHandle = -1;
shiftSelItems = false;
resizeGesture = NULL;
lineMoveGesture = NULL;
guideMoveGesture = NULL;
m_mousePressPoint.setXY(0, 0);
m_mouseCurrentPoint.setXY(0, 0);
m_mouseSavedPoint.setXY(0, 0);
m_objectDeltaPos.setXY(0,0 );
ySnap = 0;
xSnap = 0;
m_hoveredItem = NULL;
}
 
inline bool CanvasMode_Normal::GetItem(PageItem** pi)
{
*pi = m_doc->m_Selection->itemAt(0);
return (*pi) != NULL;
}
 
void CanvasMode_Normal::drawControls(QPainter* p)
{
// qDebug() << "CanvasMode_Normal::drawControls";
if (m_canvas->m_viewMode.operItemMoving)
drawOutline(p, 1.0, 1.0, m_objectDeltaPos.x(), m_objectDeltaPos.y());
else
drawSelection(p, !m_doc->drawAsPreview);
}
 
void CanvasMode_Normal::enterEvent(QEvent *)
{
if (!m_canvas->m_viewMode.m_MouseButtonPressed)
{
setModeCursor();
}
}
 
void CanvasMode_Normal::leaveEvent(QEvent *e)
{
}
 
 
void CanvasMode_Normal::activate(bool fromGesture)
{
// qDebug() << "CanvasMode_Normal::activate" << fromGesture;
m_canvas->m_viewMode.m_MouseButtonPressed = false;
m_canvas->resetRenderMode();
m_doc->DragP = false;
m_doc->leaveDrag = false;
m_canvas->m_viewMode.operItemMoving = false;
m_canvas->m_viewMode.operItemResizing = false;
m_view->MidButt = false;
m_mousePressPoint.setXY(0, 0);
m_mouseCurrentPoint.setXY(0, 0);
m_mouseSavedPoint.setXY(0, 0);
m_objectDeltaPos.setXY(0,0 );
frameResizeHandle = -1;
shiftSelItems = false;
m_hoveredItem = NULL;
setModeCursor();
if (fromGesture)
{
m_view->update();
}
}
 
void CanvasMode_Normal::deactivate(bool forGesture)
{
// qDebug() << "CanvasMode_Normal::deactivate" << forGesture;
m_view->setRedrawMarkerShown(false);
}
 
void CanvasMode_Normal::mouseDoubleClickEvent(QMouseEvent *m)
{
PageItem *currItem = 0;
m->accept();
m_canvas->m_viewMode.m_MouseButtonPressed = false;
if (m_doc->drawAsPreview)
{
if (GetItem(&currItem))
{
if (currItem->isAnnotation())
{
if (currItem->annotation().Type() == Annotation::Text)
{
currItem->annotation().setOpen(!currItem->annotation().IsOpen());
currItem->asTextFrame()->setTextAnnotationOpen(currItem->annotation().IsOpen());
currItem->update();
m_view->updateContents();
}
}
}
return;
}
m_canvas->resetRenderMode();
// m_view->stopDragTimer();
if (m_doc->m_Selection->isMultipleSelection())
{
if (GetItem(&currItem))
{
/* CB: old code, removing this as shift-alt select on an unselected table selects a cell now.
//#6789 is closed by sorting this.
if (currItem->isTableItem)
{
m_view->Deselect(false);
m_doc->m_Selection->addItem(currItem);
currItem->isSingleSel = true;
//CB FIXME dont call this if the added item is item 0
if (!m_doc->m_Selection->primarySelectionIs(currItem))
currItem->emitAllToGUI();
m_view->updateContents(currItem->getRedrawBounding(m_canvas->scale()));
}*/
}
return;
}
if (GetItem(&currItem))
{
if (currItem->asLatexFrame())
{
if (currItem->locked()) // || (!currItem->ScaleType))
{
return;
}
if (currItem->imageShown())
m_view->requestMode(modeEdit);
}
#ifdef HAVE_OSG
else if (currItem->asOSGFrame())
{
m_view->requestMode(submodeEditExternal);
}
#endif
else if ((currItem->itemType() == PageItem::Polygon) || (currItem->itemType() == PageItem::PolyLine) || (currItem->itemType() == PageItem::Group) || (currItem->itemType() == PageItem::ImageFrame) || (currItem->itemType() == PageItem::PathText))
{
if (currItem->locked()) //|| (!currItem->ScaleType))
{
//mousePressEvent(m);
return;
}
//If we double click on an image frame and theres no image assigned, open the
//load picture dialog, else put it into edit mode if the frame is set to show the image
if (currItem->itemType() == PageItem::ImageFrame)
{
if (currItem->Pfile.isEmpty())
m_view->requestMode(submodeLoadPic);
else if (!currItem->PictureIsAvailable)
m_view->requestMode(submodeStatusPic);
else if (currItem->imageShown())
m_view->requestMode(modeEdit);
}
else if (currItem->itemType() == PageItem::TextFrame)
{
m_view->requestMode(modeEdit);
}
else
{
m_view->requestMode(modeEditClip);
m_ScMW->scrActions["itemUngroup"]->setEnabled(false);
}
}
else if (currItem->itemType() == PageItem::TextFrame)
{
// See if double click was on a frame handle
FPoint p = m_canvas->globalToCanvas(m->globalPos());
Canvas::FrameHandle fh = m_canvas->frameHitTest(QPointF(p.x(),p.y()), currItem);
//CB old code
//emit currItem->isAnnotation() ? AnnotProps() : Amode(modeEdit);
//mousePressEvent(m);
//CB if annotation, open the annotation dialog
if (currItem->isAnnotation())
{
m_view->requestMode(submodeAnnotProps);
//mousePressEvent(m);
}
else if (fh == Canvas::SOUTH)
currItem->asTextFrame()->setTextFrameHeight();
//else if not in mode edit, set mode edit
else if (m_doc->appMode != modeEdit)
{
m_view->requestMode(modeEdit);
m_view->slotSetCurs(m->globalPos().x(), m->globalPos().y());
//used for updating Notes Styles Editor and menu actions for marks
//if cursor is in mark`s place
m_ScMW->setTBvals(currItem);
//CB ignore the double click and go with a single one
//if we werent in mode edit before.
//unsure if this is correct, but its ok given we had no
//double click select until now.
// mousePressEvent(m);
}
}
else if (currItem->asSymbolFrame())
{
if (!m_doc->symbolEditMode())
m_view->requestMode(submodeEditSymbol);
}
else if (currItem->asArc())
{
m_view->requestMode(modeEditArc);
}
else if (currItem->asRegularPolygon())
{
m_view->requestMode(modeEditPolygon);
}
else if (currItem->asSpiral())
{
m_view->requestMode(modeEditSpiral);
}
else if (currItem->asTable())
{
m_view->requestMode(modeEditTable);
m_view->slotSetCurs(m->globalPos().x(), m->globalPos().y());
}
}
}
 
 
void CanvasMode_Normal::mouseMoveEvent(QMouseEvent *m)
{
// qDebug()<<"CanvasMode_Normal::mouseMoveEvent";
// const double mouseX = m->globalX();
// const double mouseY = m->globalY();
const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
m_lastPosWasOverGuide = false;
double newX, newY;
PageItem *currItem=NULL;
bool erf = false;
m->accept();
// qDebug() << "legacy mode move:" << m->x() << m->y() << m_canvas->globalToCanvas(m->globalPos()).x() << m_canvas->globalToCanvas(m->globalPos()).y();
// emit MousePos(m->x()/m_canvas->scale(),// + m_doc->minCanvasCoordinate.x(),
// m->y()/m_canvas->scale()); // + m_doc->minCanvasCoordinate.y());
 
if (commonMouseMove(m))
return;
// m_mouseCurrentPoint = mousePointDoc;
bool movingOrResizing = (m_canvas->m_viewMode.operItemMoving || m_canvas->m_viewMode.operItemResizing);
bool mouseIsOnPage = (m_doc->OnPage(mousePointDoc.x(), mousePointDoc.y()) != -1);
if ((m_doc->guidesPrefs().guidesShown) && (!m_doc->GuideLock) && (!movingOrResizing) && (mouseIsOnPage) )
{
// #9002: Resize points undraggable when object is aligned to a guide
// Allow item resize when guides are aligned to item while preserving
// ability to drag guide when guis is in foreground and inside selection
bool enableGuideGesture(false);
Canvas::FrameHandle frameResizeHandle(Canvas::OUTSIDE);
if (m_doc->m_Selection->count() > 0)
{
double gx(0.0), gy(0.0), gw(0.0), gh(0.0);
m_doc->m_Selection->setGroupRect();
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), QRectF(gx, gy, gw, gh));
}
enableGuideGesture |= (frameResizeHandle == Canvas::OUTSIDE);
enableGuideGesture |= ((m_doc->guidesPrefs().renderStackOrder.indexOf(3) > m_doc->guidesPrefs().renderStackOrder.indexOf(4)) && (frameResizeHandle == Canvas::INSIDE));
if (enableGuideGesture)
{
if (!guideMoveGesture)
{
guideMoveGesture = new RulerGesture(m_view, RulerGesture::HORIZONTAL);
connect(guideMoveGesture,SIGNAL(guideInfo(int, qreal)), m_ScMW->alignDistributePalette,SLOT(setGuide(int, qreal)));
}
if (guideMoveGesture->mouseHitsGuide(mousePointDoc))
{
m_lastPosWasOverGuide = true;
switch (guideMoveGesture->getMode())
{
case RulerGesture::HORIZONTAL:
m_view->setCursor(QCursor(Qt::SplitVCursor));
break;
case RulerGesture::VERTICAL:
m_view->setCursor(QCursor(Qt::SplitHCursor));
break;
default:
m_view->setCursor(QCursor(Qt::ArrowCursor));
}
return;
}
// Here removed a bunch of comments which made reading code difficult,
// there is svn for tracking changes after all. pm
m_view->setCursor(QCursor(Qt::ArrowCursor));
}
}
else if (!mouseIsOnPage)
{
if ((m_view->cursor().shape() == Qt::SplitHCursor) || (m_view->cursor().shape() == Qt::SplitVCursor))
m_view->setCursor(QCursor(Qt::ArrowCursor));
}
//<<#10116 Show overflow counter HUD
if (!movingOrResizing && mouseIsOnPage)
{
PageItem* hoveredItem = NULL;
hoveredItem = m_canvas->itemUnderCursor(m->globalPos(), hoveredItem, m->modifiers());
if (hoveredItem)
{
if (m_doc->drawAsPreview)
{
if (hoveredItem->isAnnotation())
{
QString toolT = "";
if (!hoveredItem->annotation().ToolTip().isEmpty())
toolT = hoveredItem->annotation().ToolTip();
if (hoveredItem->annotation().Type() == Annotation::Button)
{
if (!hoveredItem->annotation().RollOver().isEmpty())
toolT = hoveredItem->annotation().RollOver();
else if (!hoveredItem->annotation().Down().isEmpty())
toolT = hoveredItem->annotation().Down();
}
else if (hoveredItem->annotation().Type() == Annotation::Link)
{
if (hoveredItem->annotation().ActionType() == Annotation::Action_GoTo)
toolT = QString( tr("Go to Page %1").arg(hoveredItem->annotation().Ziel() + 1));
else if (hoveredItem->annotation().ActionType() == Annotation::Action_URI)
toolT = QString( tr("Go to URL %1").arg(hoveredItem->annotation().Extern()));
else if ((hoveredItem->annotation().ActionType() == Annotation::Action_GoToR_FileAbs) || (hoveredItem->annotation().ActionType() == Annotation::Action_GoToR_FileRel))
toolT = QString( tr("Go to Page %1 in File %2").arg(hoveredItem->annotation().Ziel() + 1).arg(hoveredItem->annotation().Extern()));
m_view->setCursor(QCursor(Qt::PointingHandCursor));
}
if (toolT.isEmpty())
toolT = hoveredItem->itemText.plainText();
if (!toolT.isEmpty())
QToolTip::showText(m->globalPos() + QPoint(5, 5), toolT, m_canvas);
if (hoveredItem != m_hoveredItem)
{
if (m_hoveredItem)
handleMouseLeave(m_hoveredItem);
handleMouseEnter(hoveredItem);
}
m_hoveredItem = hoveredItem;
if ((hoveredItem->annotation().Type() == Annotation::Text) && (hoveredItem->annotation().IsOpen()))
{
if (m_view->moveTimerElapsed() && m_canvas->m_viewMode.m_MouseButtonPressed && (m->buttons() & Qt::LeftButton) && (!hoveredItem->locked()))
{
double dx = mousePointDoc.x() - m_mouseCurrentPoint.x();
double dy = mousePointDoc.y() - m_mouseCurrentPoint.y();
hoveredItem->setXYPos(hoveredItem->xPos() + dx, hoveredItem->yPos() + dy, true);
m_mouseCurrentPoint = mousePointDoc;
m_canvas->resetRenderMode();
m_canvas->setRenderModeUseBuffer(false);
m_canvas->repaint();
}
}
}
else
{
if (QToolTip::isVisible())
QToolTip::hideText();
m_hoveredItem = NULL;
}
}
else
{
if (hoveredItem->asTextFrame() && hoveredItem->frameOverflows())
{
if (m_canvas->cursorOverTextFrameControl(m->globalPos(), hoveredItem))
{
QToolTip::showText(m->globalPos() + QPoint(5, 5), tr("Overflow Characters: %1 (%2 White Spaces)").arg(hoveredItem->frameOverflowCount()).arg(hoveredItem->frameOverflowBlankCount()), m_canvas);
}
}
else
if (QToolTip::isVisible())
QToolTip::hideText();
}
}
else
{
if (QToolTip::isVisible())
QToolTip::hideText();
if (m_doc->drawAsPreview)
{
if (m_hoveredItem)
handleMouseLeave(m_hoveredItem);
m_hoveredItem = NULL;
}
}
}
//>>#10116
if (m_doc->drawAsPreview)
return;
m_mouseCurrentPoint = mousePointDoc;
if ((GetItem(&currItem)) && (!shiftSelItems))
{
newX = qRound(mousePointDoc.x()); //m_view->translateToDoc(m->x(), m->y()).x());
newY = qRound(mousePointDoc.y()); //m_view->translateToDoc(m->x(), m->y()).y());
// #0007865
if (/*(((m_view->dragTimerElapsed()) && (m->buttons() & Qt::LeftButton)) ||*/
(m_view->moveTimerElapsed())
&& (m->buttons() & Qt::RightButton)
&& (m_canvas->m_viewMode.m_MouseButtonPressed)
&& (!m_doc->DragP)
&& (!(currItem->isSingleSel)))
{
// start drag
// m_view->stopDragTimer();
if ((fabs(m_mousePressPoint.x() - newX) > 10) || (fabs(m_mousePressPoint.y() - newY) > 10))
{
m_canvas->setRenderMode(Canvas::RENDER_NORMAL);
// m_view->resetDragTimer();
m_doc->DragP = true;
m_doc->leaveDrag = false;
m_doc->DraggedElem = currItem;
m_doc->DragElements.clear();
for (int dre=0; dre<m_doc->m_Selection->count(); ++dre)
m_doc->DragElements.append(m_doc->m_Selection->itemAt(dre));
ScElemMimeData* md = ScriXmlDoc::WriteToMimeData(m_doc, m_doc->m_Selection);
QDrag* dr = new QDrag(m_view);
dr->setMimeData(md);
const QPixmap& pm = loadIcon("DragPix.xpm");
dr->setPixmap(pm);
// dr->setDragCursor(pm, Qt::CopyAction);
// dr->setDragCursor(pm, Qt::MoveAction);
// dr->setDragCursor(pm, Qt::LinkAction);
dr->exec();
m_doc->DragP = false;
m_doc->leaveDrag = false;
m_canvas->m_viewMode.m_MouseButtonPressed = false;
m_doc->DraggedElem = 0;
m_doc->DragElements.clear();
m_view->setCursor(QCursor(Qt::ArrowCursor));
m_view->updateContents();
}
return;
}
if (m_doc->DragP)
return;
//Operations run here:
//Item resize, esp after creating a new one
if (m_view->moveTimerElapsed() && m_canvas->m_viewMode.m_MouseButtonPressed && (m->buttons() & Qt::LeftButton) &&
((m_doc->appMode == modeNormal)) && (!currItem->locked()))
{
// m_view->stopDragTimer();
if (!m_canvas->m_viewMode.operItemResizing)
{
//Dragging an item (plus more?)
newX = mousePointDoc.x(); //static_cast<int>(m->x()/sc);
newY = mousePointDoc.y(); //static_cast<int>(m->y()/sc);
m_canvas->m_viewMode.operItemMoving = true;
if (!(m_doc->drawAsPreview && !m_doc->editOnPreview))
m_view->setCursor(Qt::ClosedHandCursor);
else
m_view->setCursor(QCursor(Qt::ArrowCursor));
erf = false;
int dX = qRound(newX - m_mousePressPoint.x()), dY = qRound(newY - m_mousePressPoint.y());
if (!m_doc->m_Selection->isMultipleSelection())
{
erf=true;
currItem = m_doc->m_Selection->itemAt(0);
//Control Alt drag image in frame without being in edit mode
if ((currItem->asImageFrame()) && (m->modifiers() & Qt::ControlModifier) && (m->modifiers() & Qt::AltModifier))
{
currItem->moveImageInFrame(dX/currItem->imageXScale(),dY/currItem->imageYScale());
m_view->updateContents(currItem->getRedrawBounding(m_canvas->scale()));
}
else
{
//Dragging orthogonally - Ctrl Drag
if ((m->modifiers() & Qt::ControlModifier) && !(m->modifiers() & Qt::ShiftModifier) && !(m->modifiers() & Qt::AltModifier))
{
if (abs(dX) > abs(dY))
dY=0;
else
if (abs(dY) > abs(dX))
dX=0;
erf=false;
dX+=qRound(dragConstrainInitPtX-currItem->xPos());
dY+=qRound(dragConstrainInitPtY-currItem->yPos());
}
double gx, gy, gh, gw;
m_objectDeltaPos.setXY(dX, dY);
// m_doc->m_Selection->getGroupRect(&gx, &gy, &gw, &gh);
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
// #10677 : temporary hack : we need to introduce the
// concept of item snapping points to handle better
// the various types of items
if (currItem->isLine())
{
QPointF startPoint = currItem->asLine()->startPoint();
QPointF endPoint = currItem->asLine()->endPoint();
gx = qMin(startPoint.x(), endPoint.x());
gy = qMin(startPoint.y(), endPoint.y());
gw = fabs(startPoint.x() - endPoint.x());
gh = fabs(startPoint.y() - endPoint.y());
}
if (m_doc->SnapGuides)
{
double nx = gx + m_objectDeltaPos.x();
double ny = gy + m_objectDeltaPos.y();
double nxo = nx, nyo = ny;
m_doc->ApplyGuides(&nx, &ny);
m_objectDeltaPos += FPoint(nx - nxo, ny - nyo);
nx = nxo = gx + gw + m_objectDeltaPos.x();
ny = nyo = gy + gh + m_objectDeltaPos.y();
m_doc->ApplyGuides(&nx, &ny);
m_objectDeltaPos += FPoint(nx-nxo, ny-nyo);
if(false)
{
nx = nxo = gx + gw/2 + m_objectDeltaPos.x();
ny = nyo = gy + gh/2 + m_objectDeltaPos.y();
m_doc->ApplyGuides(&nx, &ny);
m_objectDeltaPos += FPoint(nx-nxo, ny-nyo);
}
}
if (m_doc->SnapElement)
{
xSnap = 0;
ySnap = 0;
double snapWidth[] = {0,gw,gw/2};
double snapHeight[] = {0,gh,gh/2};
if(m_objectDeltaPos.x()<0)
std::swap(snapWidth[0],snapWidth[2]);
if(m_objectDeltaPos.y()<0)
std::swap(snapHeight[0],snapHeight[2]);
double nx,ny,nyo,nxo;
for(int i = 0;i<3;i++)
{
nx = gx + snapWidth[i] + m_objectDeltaPos.x();
ny = gy + snapHeight[i] + m_objectDeltaPos.y();
nxo = nx, nyo = ny;
m_doc->ApplyGuides(&nx, &ny,true);
m_objectDeltaPos += FPoint(nx - nxo, ny - nyo);
if(ny != nyo)
ySnap = ny;
if(nx != nxo)
xSnap = nx;
}
}
if (m_doc->SnapGrid)
{
m_doc->m_Selection->setGroupRect();
double gx, gy, gh, gw, gxo, gyo;
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
gx += m_objectDeltaPos.x();
gy += m_objectDeltaPos.y();
gxo = gx;
gyo = gy;
FPoint npx = m_doc->ApplyGridF(FPoint(gx, gy));
FPoint npw = m_doc->ApplyGridF(FPoint(gx+gw, gy+gh));
if ((fabs(gx-npx.x())) > (fabs((gx+gw)-npw.x())))
gx = npw.x() - gw;
else
gx = npx.x();
if ((fabs(gy-npx.y())) > (fabs((gy+gh)-npw.y())))
gy = npw.y() - gh;
else
gy = npx.y();
if ((fabs(gx - gxo) < (m_doc->guidesPrefs().guideRad) / m_canvas->scale()) && (fabs(gy - gyo) < (m_doc->guidesPrefs().guideRad) / m_canvas->scale()))
m_objectDeltaPos += FPoint(gx-gxo, gy-gyo);
}
}
}
else
{
double gx, gy, gh, gw;
m_doc->m_Selection->setGroupRect();
// m_doc->m_Selection->getGroupRect(&gx, &gy, &gw, &gh);
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
int dX=qRound(newX - m_mousePressPoint.x()), dY=qRound(newY - m_mousePressPoint.y());
erf = true;
if (m->modifiers() & Qt::ControlModifier)
{
if (abs(dX)>abs(dY))
dY=0;
else
if (abs(dY)>abs(dX))
dX=0;
erf=false;
dX+=dragConstrainInitPtX-qRound(gx);
dY+=dragConstrainInitPtY-qRound(gy);
}
m_objectDeltaPos.setXY(dX, dY);
if (m_doc->SnapGuides)
{
double nx = gx + m_objectDeltaPos.x();
double ny = gy + m_objectDeltaPos.y();
double nxo = nx, nyo = ny;
m_doc->ApplyGuides(&nx, &ny);
m_objectDeltaPos += FPoint(nx - nxo, ny - nyo);
nx = nxo = gx + gw + m_objectDeltaPos.x();
ny = nyo = gy + gh + m_objectDeltaPos.y();
m_doc->ApplyGuides(&nx, &ny);
m_objectDeltaPos += FPoint(nx-nxo, ny-nyo);
if(false)
{
nx = nxo = gx + gw/2 + m_objectDeltaPos.x();
ny = nyo = gy + gh/2 + m_objectDeltaPos.y();
m_doc->ApplyGuides(&nx, &ny);
m_objectDeltaPos += FPoint(nx-nxo, ny-nyo);
}
}
if (m_doc->SnapElement)
{
xSnap = 0;
ySnap = 0;
double snapWidth[] = {0,gw,gw/2};
double snapHeight[] = {0,gh,gh/2};
if(m_objectDeltaPos.x()<0)
std::swap(snapWidth[0],snapWidth[2]);
if(m_objectDeltaPos.y()<0)
std::swap(snapHeight[0],snapHeight[2]);
double nx,ny,nyo,nxo;
for(int i = 0;i<3;i++)
{
nx = gx + snapWidth[i] + m_objectDeltaPos.x();
ny = gy + snapHeight[i] + m_objectDeltaPos.y();
nxo = nx, nyo = ny;
m_doc->ApplyGuides(&nx, &ny,true);
m_objectDeltaPos += FPoint(nx - nxo, ny - nyo);
if(ny != nyo)
ySnap = ny;
if(nx != nxo)
xSnap = nx;
}
}
if (m_doc->SnapGrid)
{
double gx, gy, gh, gw, gxo, gyo;
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
gx += m_objectDeltaPos.x();
gy += m_objectDeltaPos.y();
gxo = gx;
gyo = gy;
FPoint npx = m_doc->ApplyGridF(FPoint(gx, gy));
FPoint npw = m_doc->ApplyGridF(FPoint(gx+gw, gy+gh));
if ((fabs(gx-npx.x())) > (fabs((gx+gw)-npw.x())))
gx = npw.x() - gw;
else
gx = npx.x();
if ((fabs(gy-npx.y())) > (fabs((gy+gh)-npw.y())))
gy = npw.y() - gh;
else
gy = npx.y();
if ((fabs(gx - gxo) < (m_doc->guidesPrefs().guideRad) / m_canvas->scale()) && (fabs(gy - gyo) < (m_doc->guidesPrefs().guideRad) / m_canvas->scale()))
m_objectDeltaPos += FPoint(gx-gxo, gy-gyo);
}
}
if (erf)
{
m_mouseCurrentPoint.setXY(newX, newY);
}
{
double gx, gy, gh, gw;
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
m_doc->adjustCanvas(FPoint(gx,gy), FPoint(gx+gw, gy+gh));
QPoint selectionCenter = m_canvas->canvasToLocal(QPointF(gx+gw/2, gy+gh/2));
QPoint localMousePos = m_canvas->canvasToLocal(mousePointDoc);
int localwidth = static_cast<int>(gw * m_canvas->scale());
int localheight = static_cast<int>(gh * m_canvas->scale());
if (localwidth > 200)
{
localwidth = 0;
selectionCenter.setX(localMousePos.x());
}
if (localheight > 200)
{
localheight = 0;
selectionCenter.setY(localMousePos.y());
}
m_view->ensureVisible(selectionCenter.x(), selectionCenter.y(), localwidth/2 + 20, localheight/2 + 20);
m_canvas->repaint();
m_doc->m_Selection->getGroupRect(&gx, &gy, &gw, &gh);
m_canvas->displayCorrectedXYHUD(m->globalPos(), gx + m_objectDeltaPos.x(), gy + m_objectDeltaPos.y());
}
}
}
if ((!m_canvas->m_viewMode.m_MouseButtonPressed) && (m_doc->appMode != modeDrawBezierLine))
{
if (m_doc->m_Selection->isMultipleSelection())
{
// QRect mpo = QRect(qRound(m->x()/m_canvas->scale())-m_doc->guidesPrefs().grabRad, qRound(m->y()/m_canvas->scale())-m_doc->guidesPrefs().grabRad, m_doc->guidesPrefs().grabRad*2, m_doc->guidesPrefs().grabRad*2);
// mpo.moveBy(qRound(m_doc->minCanvasCoordinate.x()), qRound(m_doc->minCanvasCoordinate.y()));
double gx, gy, gh, gw;
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
int how = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), QRectF(gx, gy, gw, gh));
// if ((QRect(static_cast<int>(gx), static_cast<int>(gy), static_cast<int>(gw), static_cast<int>(gh)).intersects(mpo))
if (how >= 0)
{
if (how > 0)
{
setResizeCursor(how);
}
else
{
m_view->setCursor(QCursor(Qt::OpenHandCursor));
}
}
else
{
setModeCursor();
}
return;
}
for (int a = 0; a < m_doc->m_Selection->count(); ++a)
{
currItem = m_doc->m_Selection->itemAt(a);
if (currItem->locked())
break;
QTransform p;
m_canvas->Transform(currItem, p);
QRect mpo = QRect(m->x()-m_doc->guidesPrefs().grabRadius, m->y()-m_doc->guidesPrefs().grabRadius, m_doc->guidesPrefs().grabRadius*2, m_doc->guidesPrefs().grabRadius*2);
// mpo.moveBy(qRound(m_doc->minCanvasCoordinate.x() * m_canvas->scale()), qRound(m_doc->minCanvasCoordinate.y() * m_canvas->scale()));
if ((QRegion(p.map(QPolygon(QRect(-3, -3, static_cast<int>(currItem->width()+6), static_cast<int>(currItem->height()+6))))).contains(mpo)))
{
QRect tx = p.mapRect(QRect(0, 0, static_cast<int>(currItem->width()), static_cast<int>(currItem->height())));
if ((tx.intersects(mpo)) && (!currItem->locked()))
{
m_view->setCursor(QCursor(Qt::OpenHandCursor));
if (!currItem->sizeLocked())
m_view->HandleCurs(currItem, mpo);
}
}
else
{
// setModeCursor();
}
}
if (GetItem(&currItem) && (m_doc->appMode == modeNormal))
{
int how = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), currItem);
if (how > 0)
{
if(currItem->asLine())
m_view->setCursor(QCursor(Qt::SizeAllCursor));
else if(!currItem->locked() && !currItem->sizeLocked())
{
if ((!currItem->sizeHLocked() && !currItem->sizeVLocked()) || (currItem->sizeHLocked() && (how == 5 || how == 8))
|| (currItem->sizeVLocked() && (how == 6 || how == 7)))
setResizeCursor(how, currItem->rotation());
}
}
else if (how == 0)
{
if (!(m_doc->drawAsPreview && !m_doc->editOnPreview))
m_view->setCursor(QCursor(Qt::OpenHandCursor));
else
m_view->setCursor(QCursor(Qt::ArrowCursor));
}
else
{
m_view->setCursor(QCursor(Qt::ArrowCursor));
}
}
}
}
else
{
if ((m_canvas->m_viewMode.m_MouseButtonPressed) && (m->buttons() & Qt::LeftButton))
{
newX = qRound(mousePointDoc.x()); //m_view->translateToDoc(m->x(), m->y()).x());
newY = qRound(mousePointDoc.y()); //m_view->translateToDoc(m->x(), m->y()).y());
m_mouseSavedPoint.setXY(newX, newY);
QPoint startP = m_canvas->canvasToGlobal(m_mousePressPoint);
m_view->redrawMarker->setGeometry(QRect(m_view->mapFromGlobal(startP), m_view->mapFromGlobal(m->globalPos())).normalized());
m_view->setRedrawMarkerShown(true);
m_view->HaveSelRect = true;
return;
}
}
}
 
void CanvasMode_Normal::mousePressEvent(QMouseEvent *m)
{
const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
PageItem *currItem;
 
m_objectDeltaPos = FPoint(0, 0);
m_mousePressPoint = m_mouseCurrentPoint = mousePointDoc;
m_mouseSavedPoint = mousePointDoc;
m_canvas->m_viewMode.m_MouseButtonPressed = true;
m_canvas->m_viewMode.operItemMoving = false;
m_view->HaveSelRect = false;
m_doc->DragP = false;
m_doc->leaveDrag = false;
m->accept();
m_view->registerMousePress(m->globalPos());
QRect mpo(m->x()-m_doc->guidesPrefs().grabRadius, m->y()-m_doc->guidesPrefs().grabRadius, m_doc->guidesPrefs().grabRadius*2, m_doc->guidesPrefs().grabRadius*2);
// mpo.moveBy(qRound(m_doc->minCanvasCoordinate.x() * m_canvas->scale()), qRound(m_doc->minCanvasCoordinate.y() * m_canvas->scale()));
 
if (m->button() == Qt::MidButton)
{
m_view->MidButt = true;
if (m->modifiers() & Qt::ControlModifier)
m_view->DrawNew();
return;
}
 
if ((GetItem(&currItem)) && (!m_lastPosWasOverGuide))
{
if ((currItem->asLine()) && (!m_doc->m_Selection->isMultipleSelection()) && (!m_doc->drawAsPreview))
{
if (!lineMoveGesture)
lineMoveGesture = new LineMove(this);
lineMoveGesture->mousePressEvent(m);
if (lineMoveGesture->haveLineItem())
{
m_view->startGesture(lineMoveGesture);
return;
}
}
else
{
bool isMS=m_doc->m_Selection->isMultipleSelection();
if ((isMS || (!isMS && (!currItem->locked() && !currItem->sizeLocked()))) && (!m_doc->drawAsPreview))
{
if (!resizeGesture)
resizeGesture = new ResizeGesture(this);
 
resizeGesture->mousePressEvent(m);
if (resizeGesture->frameHandle() > 0)
{
m_view->startGesture(resizeGesture);
return;
}
}
//#7928 else
//#7928 return;
}
if (!(m_doc->drawAsPreview && !m_doc->editOnPreview))
m_view->setCursor(Qt::ClosedHandCursor);
else
m_view->setCursor(QCursor(Qt::ArrowCursor));
#if 1
if (m_doc->m_Selection->isMultipleSelection() && (!m_doc->drawAsPreview))
{
m_canvas->PaintSizeRect(QRect());
double gx, gy, gh, gw;
bool shiftSel = true;
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
dragConstrainInitPtX = qRound(gx);
dragConstrainInitPtY = qRound(gy);
frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), QRectF(gx, gy, gw, gh));
if (frameResizeHandle == Canvas::OUTSIDE ||
(frameResizeHandle == Canvas::INSIDE && m->modifiers() != Qt::NoModifier))
{
frameResizeHandle = 0;
m_doc->m_Selection->delaySignalsOn();
m_view->updatesOn(false);
shiftSel = SeleItem(m);
m_view->updatesOn(true);
m_doc->m_Selection->delaySignalsOff();
}
if (((m_doc->m_Selection->count() == 0) || (!shiftSel)) && (m->modifiers() == Qt::ShiftModifier))
{
shiftSelItems = true;
m_mouseCurrentPoint = m_mousePressPoint = m_mouseSavedPoint = mousePointDoc;
}
else
shiftSelItems = false;
m_canvas->setRenderModeFillBuffer();
}
else // not multiple selection
{
dragConstrainInitPtX = qRound(currItem->xPos());
dragConstrainInitPtY = qRound(currItem->yPos());
// dont call SeleItem() without need here:
frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), currItem);
//#6797
if (frameResizeHandle <= 0 || m->modifiers() != Qt::NoModifier)
{
m_doc->m_Selection->delaySignalsOn();
m_view->updatesOn(false);
SeleItem(m); //Where we send the mouse press event to select an item
if (GetItem(&currItem) && (!m_doc->drawAsPreview))
frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), currItem);
else
frameResizeHandle = 0;
m_view->updatesOn(true);
m_doc->m_Selection->delaySignalsOff();
}
if ((currItem && !currItem->locked() && frameResizeHandle > 0) == false && (!m_doc->drawAsPreview))
{
m_mouseCurrentPoint = m_mousePressPoint = m_mouseSavedPoint = mousePointDoc;
}
}
m_canvas->setRenderModeFillBuffer();
#endif
}
else // !GetItem()
{
SeleItem(m);
if (m_doc->m_Selection->count() == 0)
{
m_mouseCurrentPoint = m_mousePressPoint = m_mouseSavedPoint = mousePointDoc;
m_view->redrawMarker->setGeometry(m->globalPos().x(), m->globalPos().y(), 1, 1);
m_view->setRedrawMarkerShown(true);
}
else
{
if (!(m_doc->drawAsPreview && !m_doc->editOnPreview))
m_canvas->setRenderModeFillBuffer();
}
}
/* if (m->button() == MidButton)
{
MidButt = true;
if (m_doc->m_Selection->count() != 0)
m_view->Deselect(true);
DrawNew();
} */
if ((m_doc->m_Selection->count() != 0) && (m->button() == Qt::RightButton))
{
m_canvas->m_viewMode.m_MouseButtonPressed = true;
m_mousePressPoint = m_mouseCurrentPoint;
}
if (m_doc->drawAsPreview && !m_doc->editOnPreview)
{
m_canvas->setRenderModeUseBuffer(false);
if (m_doc->m_Selection->count() == 1)
{
currItem = m_doc->m_Selection->itemAt(0);
if (currItem->isAnnotation())
{
if (currItem->annotation().Type() == Annotation::Checkbox)
handleCheckBoxPress(currItem);
else if (currItem->annotation().Type() == Annotation::RadioButton)
handleRadioButtonPress(currItem);
else if (currItem->annotation().Type() == Annotation::Button)
handlePushButtonPress(currItem);
}
}
}
// Commented out to fix bug #7865
// if ((m_doc->m_Selection->count() != 0) && (m->button() == Qt::LeftButton) && (frameResizeHandle == 0))
// {
// m_view->startDragTimer();
// }
m_canvas->PaintSizeRect(QRect());
}
 
 
 
void CanvasMode_Normal::mouseReleaseEvent(QMouseEvent *m)
{
// qDebug("CanvasMode_Normal::mouseReleaseEvent");
#ifdef GESTURE_FRAME_PREVIEW
clearPixmapCache();
#endif // GESTURE_FRAME_PREVIEW
const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
PageItem *currItem;
m_canvas->m_viewMode.m_MouseButtonPressed = false;
m_canvas->resetRenderMode();
m->accept();
m_view->setRedrawMarkerShown(false);
// m_view->stopDragTimer();
//m_canvas->update(); //ugly in a mouseReleaseEvent!!!!!!!
if ((!GetItem(&currItem)) && (m->button() == Qt::RightButton) && (!m_doc->DragP) && (!m_doc->drawAsPreview))
{
createContextMenu(NULL, mousePointDoc.x(), mousePointDoc.y());
return;
}
if ((GetItem(&currItem)) && (m->button() == Qt::RightButton) && (!m_doc->DragP) && (!(m_doc->drawAsPreview && !m_doc->editOnPreview)))
{
createContextMenu(currItem, mousePointDoc.x(), mousePointDoc.y());
return;
}
//<<#10116: Click on overflow icon to get into link frame mode
PageItem* clickedItem=NULL;
clickedItem = m_canvas->itemUnderCursor(m->globalPos(), clickedItem, m->modifiers());
if (clickedItem && clickedItem->asTextFrame() && (!clickedItem->isAnnotation()) && (!m_doc->drawAsPreview))
{
if (clickedItem->frameOverflows())
{
if (m_canvas->cursorOverTextFrameControl(m->globalPos(), clickedItem))
{
m_view->requestMode(modeLinkFrames);
return;
}
}
}
//>>#10116
if (m_view->moveTimerElapsed() && (GetItem(&currItem)))
{
// m_view->stopDragTimer();
m_canvas->setRenderModeUseBuffer(false);
if (!m_doc->m_Selection->isMultipleSelection())
{
m_doc->setRedrawBounding(currItem);
currItem->OwnPage = m_doc->OnPage(currItem);
m_canvas->m_viewMode.operItemResizing = false;
if (currItem->asLine())
m_view->updateContents();
}
if (m_canvas->m_viewMode.operItemMoving)
{
// we want to invalidate all frames under the moved frame
// hm, I will try to be more explicit :) - pm
int itemIndex = m_doc->Items->count();
PageItem* underItem( m_canvas->itemUnderItem(currItem, itemIndex) );
while(underItem)
{
if(underItem->asTextFrame())
underItem->asTextFrame()->invalidateLayout(false);
else
underItem->invalidateLayout();
underItem = m_canvas->itemUnderItem(currItem, itemIndex);
}
m_view->updatesOn(false);
if (!m_view->groupTransactionStarted())
{
m_view->startGroupTransaction(Um::Move, "", Um::IMove);
}
if (m_doc->m_Selection->isMultipleSelection())
{
m_doc->moveGroup(m_objectDeltaPos.x(), m_objectDeltaPos.y());
m_doc->m_Selection->setGroupRect();
double gx, gy, gh, gw;
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
double nx = gx;
double ny = gy;
if (!m_doc->ApplyGuides(&nx, &ny) && !m_doc->ApplyGuides(&nx, &ny,true))
{
FPoint npx = m_doc->ApplyGridF(FPoint(gx, gy));
FPoint npw = m_doc->ApplyGridF(FPoint(gx+gw, gy+gh));
if ((fabs(gx-npx.x())) > (fabs((gx+gw)-npw.x())))
nx = npw.x() - gw;
else
nx = npx.x();
if ((fabs(gy-npx.y())) > (fabs((gy+gh)-npw.y())))
ny = npw.y() - gh;
else
ny = npx.y();
}
m_doc->moveGroup(nx-gx, ny-gy);
m_doc->m_Selection->setGroupRect();
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
nx = gx+gw;
ny = gy+gh;
if (m_doc->ApplyGuides(&nx, &ny) && !m_doc->ApplyGuides(&nx, &ny,true))
m_doc->moveGroup(nx-(gx+gw), ny-(gy+gh));
m_doc->m_Selection->setGroupRect();
}
else
{
currItem = m_doc->m_Selection->itemAt(0);
m_doc->MoveItem(m_objectDeltaPos.x(), m_objectDeltaPos.y(), currItem);
if (m_doc->SnapGrid)
{
double nx = currItem->xPos();
double ny = currItem->yPos();
if (!m_doc->ApplyGuides(&nx, &ny) && !m_doc->ApplyGuides(&nx, &ny,true))
{
m_doc->m_Selection->setGroupRect();
double gx, gy, gh, gw, gxo, gyo;
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
gxo = gx;
gyo = gy;
FPoint npx = m_doc->ApplyGridF(FPoint(gx, gy));
FPoint npw = m_doc->ApplyGridF(FPoint(gx+gw, gy+gh));
if ((fabs(gx-npx.x())) > (fabs((gx+gw)-npw.x())))
gx = npw.x() - gw;
else
gx = npx.x();
if ((fabs(gy-npx.y())) > (fabs((gy+gh)-npw.y())))
gy = npw.y() - gh;
else
gy = npx.y();
if ((fabs(gx - gxo) < (m_doc->guidesPrefs().guideRad) / m_canvas->scale()) && (fabs(gy - gyo) < (m_doc->guidesPrefs().guideRad) / m_canvas->scale()))
{
nx += (gx - gxo);
ny += (gy - gyo);
}
}
m_doc->MoveItem(nx-currItem->xPos(), ny-currItem->yPos(), currItem);
}
}
m_canvas->m_viewMode.operItemMoving = false;
if (m_doc->m_Selection->isMultipleSelection())
{
double gx, gy, gh, gw;
m_doc->m_Selection->getGroupRect(&gx, &gy, &gw, &gh);
FPoint maxSize(gx+gw+m_doc->scratch()->Right, gy+gh+m_doc->scratch()->Bottom);
FPoint minSize(gx-m_doc->scratch()->Left, gy-m_doc->scratch()->Top);
m_doc->adjustCanvas(minSize, maxSize);
}
m_doc->setRedrawBounding(currItem);
currItem->OwnPage = m_doc->OnPage(currItem);
if (currItem->OwnPage != -1)
{
m_doc->setCurrentPage(m_doc->Pages->at(currItem->OwnPage));
m_view->m_ScMW->slotSetCurrentPage(currItem->OwnPage);
}
//CB done with emitAllToGUI
//emit HaveSel();
//EmitValues(currItem);
//CB need this for? a moved item will send its new data with the new xpos/ypos emits
//CB TODO And what if we have dragged to a new page. Items X&Y are not updated anyway now
//currItem->emitAllToGUI();
m_view->updatesOn(true);
m_view->updateContents();
m_doc->changed();
}
}
//CB Drag selection performed here
if (((m_doc->m_Selection->count() == 0) && (m_view->HaveSelRect) && (!m_view->MidButt)) || ((shiftSelItems) && (m_view->HaveSelRect) && (!m_view->MidButt)))
{
double dx = m_mouseSavedPoint.x() - m_mousePressPoint.x();
double dy = m_mouseSavedPoint.y() - m_mousePressPoint.y();
QRectF canvasSele = QRectF(m_mousePressPoint.x(), m_mousePressPoint.y(), dx, dy).normalized();
QRectF localSele = m_canvas->canvasToLocal(canvasSele).normalized();
if (!m_doc->masterPageMode())
{
uint docPagesCount=m_doc->Pages->count();
uint docCurrPageNo=m_doc->currentPageNumber();
for (uint i = 0; i < docPagesCount; ++i)
{
ScPage* page = m_doc->Pages->at(i);
QRectF pageRect(page->xOffset(), page->yOffset(), page->width(), page->height());
if (pageRect.intersects(canvasSele))
{
if (docCurrPageNo != i)
{
m_doc->setCurrentPage(m_doc->Pages->at(i));
m_view->m_ScMW->slotSetCurrentPage(i);
}
break;
}
}
m_view->setRulerPos(m_view->contentsX(), m_view->contentsY());
}
int docItemCount=m_doc->Items->count();
if (docItemCount != 0)
{
m_doc->m_Selection->delaySignalsOn();
for (int a = 0; a < docItemCount; ++a)
{
PageItem* docItem = m_doc->Items->at(a);
if ((m_doc->masterPageMode()) && (docItem->OnMasterPage != m_doc->currentPage()->pageName()))
continue;
QRect apr2 = m_canvas->canvasToLocal( docItem->getCurrentBoundingRect(docItem->lineWidth()) );
if ((localSele.contains(apr2)) && ((docItem->LayerID == m_doc->activeLayer()) || (m_doc->layerSelectable(docItem->LayerID))) && (!m_doc->layerLocked(docItem->LayerID)))
{
bool redrawSelection=false;
m_view->SelectItemNr(a, redrawSelection);
}
}
m_doc->m_Selection->delaySignalsOff();
if (m_doc->m_Selection->count() > 1)
{
m_doc->m_Selection->setGroupRect();
double x, y, w, h;
m_doc->m_Selection->getGroupRect(&x, &y, &w, &h);
m_view->getGroupRectScreen(&x, &y, &w, &h);
}
}
m_view->HaveSelRect = false;
shiftSelItems = false;
// m_view->redrawMarker->hide();
m_view->updateContents();
}
if (m_doc->appMode != modeEdit)
{
if (!PrefsManager::instance()->appPrefs.uiPrefs.stickyTools)
m_view->requestMode(modeNormal);
else
{
int appMode = m_doc->appMode;
m_view->requestMode(appMode);
}
}
if (GetItem(&currItem))
{
// qApp->changeOverrideCursor(QCursor(Qt::OpenHandCursor));
if (m_doc->m_Selection->count() > 1)
{
m_doc->m_Selection->setGroupRect();
double x, y, w, h;
m_doc->m_Selection->getGroupRect(&x, &y, &w, &h);
m_canvas->m_viewMode.operItemMoving = false;
m_canvas->m_viewMode.operItemResizing = false;
m_view->updateContents(QRect(static_cast<int>(x-5), static_cast<int>(y-5), static_cast<int>(w+10), static_cast<int>(h+10)));
//Now unuseful as PropertiesPalette_XYZ::setCurrentItem() handles multiple selection
//m_ScMW->propertiesPalette->setXY(x,y);
//m_ScMW->propertiesPalette->setBH(w,h);
}
/*else
currItem->emitAllToGUI();*/
}
else
m_view->Deselect(true);
xSnap = ySnap = 0;
m_canvas->setRenderModeUseBuffer(false);
m_doc->DragP = false;
m_doc->leaveDrag = false;
m_canvas->m_viewMode.operItemMoving = false;
m_canvas->m_viewMode.operItemResizing = false;
m_view->MidButt = false;
shiftSelItems = false;
if (m_view->groupTransactionStarted())
{
for (int i = 0; i < m_doc->m_Selection->count(); ++i)
m_doc->m_Selection->itemAt(i)->checkChanges(true);
m_view->endGroupTransaction();
}
for (int i = 0; i < m_doc->m_Selection->count(); ++i)
m_doc->m_Selection->itemAt(i)->checkChanges(true);
//Commit drag created items to undo manager.
if (m_doc->m_Selection->count() > 0)
{
if (m_doc->m_Selection->itemAt(0)!=NULL)
{
m_doc->itemAddCommit(m_doc->m_Selection->itemAt(0));
}
}
//Make sure the Zoom spinbox and page selector dont have focus if we click on the canvas
m_view->m_ScMW->zoomSpinBox->clearFocus();
m_view->m_ScMW->pageSelector->clearFocus();
if (m_doc->m_Selection->count() > 0)
{
if (m_doc->m_Selection->itemAt(0) != 0) // is there the old clip stored for the undo action
{
currItem = m_doc->m_Selection->itemAt(0);
m_doc->nodeEdit.finishTransaction(currItem);
}
}
if (m_doc->drawAsPreview && !m_doc->editOnPreview)
{
if (m_doc->m_Selection->count() == 1)
{
currItem = m_doc->m_Selection->itemAt(0);
if (currItem->isAnnotation())
{
if (currItem->annotation().Type() == Annotation::Text)
{
if (currItem->annotation().IsOpen())
{
if (m_canvas->cursorOverFrameControl(m->globalPos(), QRectF(245, 20, 11, 11), currItem))
{
currItem->annotation().setOpen(false);
currItem->asTextFrame()->setTextAnnotationOpen(false);
currItem->update();
m_view->updateContents();
}
}
}
if (currItem->annotation().Type() == Annotation::Link)
handleLinkAnnotation(currItem);
else if (currItem->annotation().Type() == Annotation::Checkbox)
handleCheckBoxRelease(currItem);
else if (currItem->annotation().Type() == Annotation::RadioButton)
handleRadioButtonRelease(currItem);
else if (currItem->annotation().Type() == Annotation::Button)
handlePushButtonRelease(currItem);
}
}
}
}
 
void CanvasMode_Normal::handleCheckBoxPress(PageItem* currItem)
{
m_view->m_AnnotChanged = true;
currItem->annotation().setOnState(true);
currItem->update();
if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
handleJavaAction(currItem, Annotation::Java_PressButton);
m_doc->regionsChanged()->update(currItem->getVisualBoundingRect());
}
 
void CanvasMode_Normal::handlePushButtonPress(PageItem* currItem)
{
currItem->annotation().setOnState(true);
currItem->update();
if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
handleJavaAction(currItem, Annotation::Java_PressButton);
m_doc->regionsChanged()->update(currItem->getVisualBoundingRect());
}
 
void CanvasMode_Normal::handleRadioButtonPress(PageItem* currItem)
{
m_view->m_AnnotChanged = true;
if (currItem->isGroupChild())
{
PageItem *group = currItem->Parent->asGroupFrame();
for (int a = 0; a < group->groupItemList.count(); a++)
{
PageItem *gItem = group->groupItemList[a];
if ((gItem->isAnnotation()) && (gItem->annotation().Type() == Annotation::RadioButton))
{
gItem->update();
}
}
}
else
{
int op = currItem->OwnPage;
uint docItemCount = m_doc->Items->count();
for (uint i = 0; i < docItemCount; ++i)
{
PageItem *gItem = m_doc->Items->at(i);
if ((gItem->isAnnotation()) && (gItem->annotation().Type() == Annotation::RadioButton) && (gItem->OwnPage == op))
{
gItem->update();
}
}
}
currItem->annotation().setOnState(true);
currItem->update();
if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
handleJavaAction(currItem, Annotation::Java_PressButton);
m_view->updateContents();
}
 
void CanvasMode_Normal::handleCheckBoxRelease(PageItem* currItem)
{
m_view->m_AnnotChanged = true;
currItem->annotation().setOnState(false);
currItem->annotation().setCheckState(!currItem->annotation().IsChecked());
if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
handleJavaAction(currItem, Annotation::Java_ReleaseButton);
currItem->update();
m_doc->regionsChanged()->update(currItem->getVisualBoundingRect());
}
 
void CanvasMode_Normal::handlePushButtonRelease(PageItem* currItem)
{
m_view->m_AnnotChanged = true;
currItem->annotation().setOnState(false);
currItem->update();
switch (currItem->annotation().ActionType())
{
case Annotation::Action_JavaScript:
handleJavaAction(currItem, Annotation::Java_ReleaseButton);
break;
case Annotation::Action_GoTo:
case Annotation::Action_URI:
case Annotation::Action_GoToR_FileAbs:
case Annotation::Action_GoToR_FileRel:
handleLinkAnnotation(currItem);
break;
case Annotation::Action_ResetForm:
m_doc->ResetFormFields();
break;
case Annotation::Action_ImportData:
m_doc->ImportData();
break;
case Annotation::Action_SubmitForm:
m_doc->SubmitForm();
break;
case Annotation::Action_Named:
handleNamedAction(currItem);
default:
break;
}
}
 
void CanvasMode_Normal::handleRadioButtonRelease(PageItem* currItem)
{
m_view->m_AnnotChanged = true;
if (currItem->isGroupChild())
{
PageItem *group = currItem->Parent->asGroupFrame();
for (int a = 0; a < group->groupItemList.count(); a++)
{
PageItem *gItem = group->groupItemList[a];
if ((gItem->isAnnotation()) && (gItem->annotation().Type() == Annotation::RadioButton))
{
gItem->annotation().setCheckState(false);
gItem->update();
}
}
}
else
{
int op = currItem->OwnPage;
uint docItemCount = m_doc->Items->count();
for (uint i = 0; i < docItemCount; ++i)
{
PageItem *gItem = m_doc->Items->at(i);
if ((gItem->isAnnotation()) && (gItem->annotation().Type() == Annotation::RadioButton) && (gItem->OwnPage == op))
{
gItem->annotation().setCheckState(false);
gItem->update();
}
}
}
currItem->annotation().setCheckState(true);
currItem->annotation().setOnState(false);
if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
handleJavaAction(currItem, Annotation::Java_ReleaseButton);
currItem->update();
m_view->updateContents();
}
 
void CanvasMode_Normal::handleJavaAction(PageItem* currItem, int event)
{
QString scriptCode = "";
switch (event)
{
case Annotation::Java_PressButton:
scriptCode = currItem->annotation().D_act();
break;
case Annotation::Java_ReleaseButton:
scriptCode = currItem->annotation().Action();
break;
case Annotation::Java_EnterWidget:
scriptCode = currItem->annotation().E_act();
break;
case Annotation::Java_LeaveWidget:
scriptCode = currItem->annotation().X_act();
break;
case Annotation::Java_FocusIn:
scriptCode = currItem->annotation().Fo_act();
break;
case Annotation::Java_FocusOut:
scriptCode = currItem->annotation().Bl_act();
break;
case Annotation::Java_SelectionChg:
scriptCode = currItem->annotation().K_act();
break;
case Annotation::Java_FieldFormat:
scriptCode = currItem->annotation().F_act();
break;
case Annotation::Java_FieldValidate:
scriptCode = currItem->annotation().V_act();
break;
case Annotation::Java_FieldCalculate:
scriptCode = currItem->annotation().C_act();
break;
default:
break;
}
if (!scriptCode.isEmpty())
{
// Execute the JavasScript Code
// qDebug() << "JavaScript:" << scriptCode;
}
}
 
void CanvasMode_Normal::handleNamedAction(PageItem* currItem)
{
m_view->Deselect(true);
QString name = currItem->annotation().Action();
if (name == "FirstPage")
m_view->GotoPage(0);
else if (name == "PrevPage")
m_view->GotoPage(qMax(0, m_doc->currentPageNumber()-1));
else if (name == "NextPage")
m_view->GotoPage(qMin(m_doc->currentPageNumber()+1, m_doc->Pages->count()-1));
else if (name == "LastPage")
m_view->GotoPage(m_doc->Pages->count()-1);
else if (name == "Print")
m_ScMW->slotFilePrint();
else if (name == "Close")
m_ScMW->slotFileClose();
else if (name == "Quit")
m_ScMW->slotFileQuit();
else if (name == "FitHeight")
m_ScMW->slotZoom(-100);
else if (name == "FitWidth")
m_ScMW->slotZoom(-200);
}
 
void CanvasMode_Normal::handleLinkAnnotation(PageItem* currItem)
{
if (currItem->annotation().ActionType() == Annotation::Action_GoTo)
{
m_view->Deselect(true);
if (currItem->annotation().Ziel() < m_doc->Pages->count())
m_view->GotoPage(currItem->annotation().Ziel());
else
{
QString message = tr("Page %1 does not exist!").arg(currItem->annotation().Ziel() + 1);
QMessageBox::warning(m_view, CommonStrings::trWarning, message, CommonStrings::tr_OK);
}
}
else if (currItem->annotation().ActionType() == Annotation::Action_URI)
{
QString message = tr("Link Target is Web URL.\nURL: %1").arg(currItem->annotation().Extern());
QMessageBox::information(m_view, tr("Information"), message, CommonStrings::tr_OK);
}
else if ((currItem->annotation().ActionType() == Annotation::Action_GoToR_FileAbs) || (currItem->annotation().ActionType() == Annotation::Action_GoToR_FileRel))
{
QString message = tr("Link Target is external File.\nFile: %1\nPage: %2").arg(currItem->annotation().Extern()).arg(currItem->annotation().Ziel() + 1);
QMessageBox::information(m_view, tr("Information"), message, CommonStrings::tr_OK);
}
}
 
void CanvasMode_Normal::handleFocusOut(PageItem* currItem)
{
if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
handleJavaAction(currItem, Annotation::Java_FocusOut);
}
 
void CanvasMode_Normal::handleFocusIn(PageItem* currItem)
{
if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
handleJavaAction(currItem, Annotation::Java_FocusIn);
}
 
void CanvasMode_Normal::handleMouseLeave(PageItem* currItem)
{
if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
handleJavaAction(currItem, Annotation::Java_LeaveWidget);
}
 
void CanvasMode_Normal::handleMouseEnter(PageItem* currItem)
{
if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
handleJavaAction(currItem, Annotation::Java_EnterWidget);
}
 
void CanvasMode_Normal::keyPressEvent(QKeyEvent *e)
{
commonkeyPressEvent_NormalNodeEdit(e);
}
 
void CanvasMode_Normal::keyReleaseEvent(QKeyEvent *e)
{
commonkeyReleaseEvent(e);
}
 
//CB-->Doc/Fix
bool CanvasMode_Normal::SeleItem(QMouseEvent *m)
{
PageItem *previousSelectedItem = NULL;
if (m_doc->m_Selection->count() != 0)
previousSelectedItem = m_doc->m_Selection->itemAt(0);
m_canvas->m_viewMode.operItemSelecting = true;
const unsigned SELECT_IN_GROUP = Qt::AltModifier; // Qt::MetaModifier;
const unsigned SELECT_MULTIPLE = Qt::ShiftModifier;
const unsigned SELECT_BENEATH = Qt::ControlModifier;
QTransform p;
PageItem *currItem;
m_canvas->m_viewMode.m_MouseButtonPressed = true;
FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
m_mouseCurrentPoint = mousePointDoc;
double grabRadius = m_doc->guidesPrefs().grabRadius / m_canvas->scale();
int MxpS = static_cast<int>(mousePointDoc.x()); //m->x()/m_canvas->scale() + 0*m_doc->minCanvasCoordinate.x());
int MypS = static_cast<int>(mousePointDoc.y()); //m->y()/m_canvas->scale() + 0*m_doc->minCanvasCoordinate.y());
QRectF mpo(m_mouseCurrentPoint.x()-grabRadius, m_mouseCurrentPoint.y()-grabRadius, grabRadius*2, grabRadius*2);
m_doc->nodeEdit.deselect();
 
if (m_doc->guidesPrefs().renderStackOrder.indexOf(3) > m_doc->guidesPrefs().renderStackOrder.indexOf(4)) // guides are on foreground and want to be processed first
{
if ((m_doc->guidesPrefs().guidesShown) && (m_doc->OnPage(MxpS, MypS) != -1))
{
// #9002: Resize points undraggable when object is aligned to a guide
// Allow item resize when guides are aligned to item while preserving
// ability to drag guide when guis is in foreground and inside selection
bool enableGuideGesture(true);
if (m_doc->m_Selection->count() > 0)
{
double gx(0.0), gy(0.0), gw(0.0), gh(0.0);
m_doc->m_Selection->setGroupRect();
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
Canvas::FrameHandle frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), QRectF(gx, gy, gw, gh));
enableGuideGesture = (frameResizeHandle == Canvas::INSIDE);
}
if (enableGuideGesture)
{
if (!guideMoveGesture)
{
guideMoveGesture = new RulerGesture(m_view, RulerGesture::HORIZONTAL);
connect(guideMoveGesture,SIGNAL(guideInfo(int, qreal)), m_ScMW->alignDistributePalette,SLOT(setGuide(int, qreal)));
}
if ( (!m_doc->GuideLock) && (guideMoveGesture->mouseHitsGuide(mousePointDoc)) )
{
m_view->startGesture(guideMoveGesture);
guideMoveGesture->mouseMoveEvent(m);
m_doc->m_Selection->connectItemToGUI();
// qDebug()<<"Out Of SeleItem"<<__LINE__;
return true;
}
else
{
// If we call startGesture now, a new guide is created each time.
// ### could be a weakness to avoid calling it tho.
// m_view->startGesture(guideMoveGesture);
guideMoveGesture->mouseSelectGuide(m);
}
}
}
}
bool pageChanged(false);
if (!m_doc->masterPageMode())
{
int pgNum = -1;
int docPageCount = static_cast<int>(m_doc->Pages->count() - 1);
MarginStruct pageBleeds;
bool drawBleed = false;
if (m_doc->bleeds()->hasNonZeroValue() && m_doc->guidesPrefs().showBleed)
drawBleed = true;
for (int a = docPageCount; a > -1; a--)
{
if (drawBleed)
m_doc->getBleeds(a, pageBleeds);
int x = static_cast<int>(m_doc->Pages->at(a)->xOffset() - pageBleeds.Left);
int y = static_cast<int>(m_doc->Pages->at(a)->yOffset() - pageBleeds.Top);
int w = static_cast<int>(m_doc->Pages->at(a)->width() + pageBleeds.Left + pageBleeds.Right);
int h = static_cast<int>(m_doc->Pages->at(a)->height() + pageBleeds.Bottom + pageBleeds.Top);
if (QRect(x, y, w, h).contains(MxpS, MypS))
{
pgNum = static_cast<int>(a);
if (drawBleed) // check again if its really on the correct page
{
for (int a2 = docPageCount; a2 > -1; a2--)
{
int xn = static_cast<int>(m_doc->Pages->at(a2)->xOffset());
int yn = static_cast<int>(m_doc->Pages->at(a2)->yOffset());
int wn = static_cast<int>(m_doc->Pages->at(a2)->width());
int hn = static_cast<int>(m_doc->Pages->at(a2)->height());
if (QRect(xn, yn, wn, hn).contains(MxpS, MypS))
{
pgNum = static_cast<int>(a2);
break;
}
}
}
break;
}
}
if (pgNum >= 0)
{
if (m_doc->currentPageNumber() != pgNum)
{
m_doc->setCurrentPage(m_doc->Pages->at(unsigned(pgNum)));
m_view->m_ScMW->slotSetCurrentPage(unsigned(pgNum));
pageChanged = true;
}
}
m_view->setRulerPos(m_view->contentsX(), m_view->contentsY());
}
currItem = NULL;
if ((m->modifiers() & SELECT_BENEATH) != 0)
{
for (int i=0; i < m_doc->m_Selection->count(); ++i)
{
if (m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), m_doc->m_Selection->itemAt(i)) >= 0)
{
currItem = m_doc->m_Selection->itemAt(i);
m_doc->m_Selection->removeItem(currItem);
break;
}
}
}
else if ( (m->modifiers() & SELECT_MULTIPLE) == Qt::NoModifier)
{
m_view->Deselect(false);
}
currItem = m_canvas->itemUnderCursor(m->globalPos(), currItem, ((m->modifiers() & SELECT_IN_GROUP) || (m_doc->drawAsPreview && !m_doc->editOnPreview)));
if (currItem)
{
m_doc->m_Selection->delaySignalsOn();
if (m_doc->m_Selection->containsItem(currItem))
{
m_doc->m_Selection->removeItem(currItem);
}
else
{
//CB: If we have a selection but the user clicks with control on another item that is not below the current
//then clear and select the new item
if ((m->modifiers() == SELECT_BENEATH) && m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), currItem) >= 0)
m_doc->m_Selection->clear();
//CB: #7186: This was prependItem, does not seem to need to be anymore with current select code
if (m_doc->drawAsPreview && !m_doc->editOnPreview)
m_doc->m_Selection->clear();
m_doc->m_Selection->addItem(currItem);
if (((m->modifiers() & SELECT_IN_GROUP) || (m_doc->drawAsPreview && !m_doc->editOnPreview)) && (!currItem->isGroup()))
{
currItem->isSingleSel = true;
}
}
if(pageChanged)
{
m_canvas->setForcedRedraw(true);
m_canvas->update();
}
else
m_canvas->update();
m_doc->m_Selection->delaySignalsOff();
if (m_doc->m_Selection->count() > 1)
{
m_doc->beginUpdate();
for (int aa = 0; aa < m_doc->m_Selection->count(); ++aa)
{
PageItem *bb = m_doc->m_Selection->itemAt(aa);
bb->update();
}
m_doc->endUpdate();
m_doc->m_Selection->setGroupRect();
double x, y, w, h;
m_doc->m_Selection->getGroupRect(&x, &y, &w, &h);
m_view->getGroupRectScreen(&x, &y, &w, &h);
}
if (previousSelectedItem != NULL)
{
if (currItem != previousSelectedItem)
{
handleFocusOut(previousSelectedItem);
handleFocusIn(currItem);
}
}
else
handleFocusIn(currItem);
return true;
}
if ((m_doc->guidesPrefs().guidesShown) /*&& (!m_doc->GuideLock)*/ && (m_doc->OnPage(MxpS, MypS) != -1))
{
if (!guideMoveGesture)
{
guideMoveGesture = new RulerGesture(m_view, RulerGesture::HORIZONTAL);
connect(guideMoveGesture,SIGNAL(guideInfo(int, qreal)), m_ScMW->alignDistributePalette,SLOT(setGuide(int, qreal)));
}
if ( (!m_doc->GuideLock) && (guideMoveGesture->mouseHitsGuide(mousePointDoc)) )
{
m_view->startGesture(guideMoveGesture);
guideMoveGesture->mouseMoveEvent(m);
m_doc->m_Selection->connectItemToGUI();
return true;
}
else
{
// If we call startGesture now, a new guide is created each time.
// ### could be a weakness to avoid calling it tho.
// m_view->startGesture(guideMoveGesture);
guideMoveGesture->mouseSelectGuide(m);
}
}
m_doc->m_Selection->connectItemToGUI();
if ( !(m->modifiers() & SELECT_MULTIPLE))
{
if(m_doc->m_Selection->isEmpty())
{
m_canvas->setForcedRedraw(true);
m_canvas->update();
}
else
m_view->Deselect(true);
}
if (previousSelectedItem != NULL)
handleFocusOut(previousSelectedItem);
return false;
}
 
void CanvasMode_Normal::importToPage()
{
QString fileName;
QString allFormats = tr("All Supported Formats")+" (";
QStringList formats;
int fmtCode = FORMATID_FIRSTUSER;
const FileFormat *fmt = LoadSavePlugin::getFormatById(fmtCode);
while (fmt != 0)
{
if (fmt->load)
{
formats.append(fmt->filter);
int an = fmt->filter.indexOf("(");
int en = fmt->filter.indexOf(")");
while (an != -1)
{
allFormats += fmt->filter.mid(an+1, en-an-1)+" ";
an = fmt->filter.indexOf("(", en);
en = fmt->filter.indexOf(")", an);
}
}
fmtCode++;
fmt = LoadSavePlugin::getFormatById(fmtCode);
}
allFormats += "*.sce *.SCE);;";
formats.append("Scribus Objects (*.sce *.SCE)");
qSort(formats);
allFormats += formats.join(";;");
PrefsContext* dirs = PrefsManager::instance()->prefsFile->getContext("dirs");
QString wdir = dirs->get("pastefile", ".");
FPoint pastePoint = m_mouseCurrentPoint;
CustomFDialog dia(m_view, wdir, tr("Open"), allFormats, fdExistingFiles | fdShowImportOptions);
if (dia.exec() == QDialog::Accepted)
fileName = dia.selectedFile();
else
return;
if (!fileName.isEmpty())
{
PrefsManager::instance()->prefsFile->getContext("dirs")->set("pastefile", fileName.left(fileName.lastIndexOf("/")));
m_doc->setLoading(true);
QFileInfo fi(fileName);
bool savedAlignGrid = m_doc->SnapGrid;
bool savedAlignGuides = m_doc->SnapGuides;
bool savedAlignElement = m_doc->SnapElement;
m_doc->SnapElement = false;
m_doc->SnapGrid = false;
m_doc->SnapGuides = false;
if (fi.suffix().toLower() == "sce")
m_ScMW->slotElemRead(fileName, pastePoint.x(), pastePoint.y(), true, false, m_doc, m_doc->view());
else
{
m_doc->dontResize = true;
FileLoader *fileLoader = new FileLoader(fileName);
int testResult = fileLoader->testFile();
delete fileLoader;
if ((testResult != -1) && (testResult >= FORMATID_FIRSTUSER))
{
const FileFormat * fmt = LoadSavePlugin::getFormatById(testResult);
if( fmt )
{
fmt->loadFile(fileName, LoadSavePlugin::lfUseCurrentPage|LoadSavePlugin::lfInteractive|LoadSavePlugin::lfScripted);
}
}
m_doc->dontResize = false;
}
for (int a = 0; a < m_doc->m_Selection->count(); ++a)
{
PageItem *currItem = m_doc->m_Selection->itemAt(a);
currItem->LayerID = m_doc->activeLayer();
}
if (m_doc->m_Selection->count() > 0)
{
PageItem *newItem = m_doc->m_Selection->itemAt(0);
if (dia.TxCodeM->currentIndex() == 1)
{
if ((newItem->width() > m_doc->currentPage()->width()) || (newItem->height() > m_doc->currentPage()->height()))
m_doc->rescaleGroup(newItem, qMin(qMin(m_doc->currentPage()->width() / newItem->width(), m_doc->currentPage()->height() / newItem->height()), 1.0));
}
else if (dia.TxCodeM->currentIndex() == 2)
{
m_doc->rescaleGroup(newItem, qMax(qMin(m_doc->currentPage()->width() / newItem->width(), m_doc->currentPage()->height() / newItem->height()), 1.0));
}
double x2, y2, w, h;
m_doc->m_Selection->getGroupRect(&x2, &y2, &w, &h);
m_doc->moveGroup(pastePoint.x() - x2, pastePoint.y() - y2);
m_ScMW->requestUpdate(reqColorsUpdate | reqSymbolsUpdate | reqLineStylesUpdate | reqTextStylesUpdate);
}
m_doc->SnapGrid = savedAlignGrid;
m_doc->SnapGuides = savedAlignGuides;
m_doc->SnapElement = savedAlignElement;
m_doc->setLoading(false);
m_doc->view()->DrawNew();
if (m_doc->m_Selection->count() > 0)
{
m_doc->m_Selection->connectItemToGUI();
m_ScMW->HaveNewSel();
}
}
}
 
void CanvasMode_Normal::createContextMenu(PageItem* currItem, double mx, double my)
{
ContextMenu* cmen=NULL;
// qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
m_view->setObjectUndoMode();
m_mouseCurrentPoint.setXY(mx, my);
if(currItem!=NULL)
cmen = new ContextMenu(*(m_doc->m_Selection), m_ScMW, m_doc);
else
cmen = new ContextMenu(m_ScMW, m_doc, mx, my);
if (cmen)
cmen->exec(QCursor::pos());
m_view->setGlobalUndoMode();
delete cmen;
}
/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
 
 
#include "canvasmode_normal.h"
 
#include <QApplication>
#include <QButtonGroup>
#include <QCheckBox>
#include <QCursor>
#include <QEvent>
#include <QMessageBox>
#include <QMouseEvent>
#include <QPainterPath>
#include <QPoint>
#include <QRect>
#include <QTimer>
#include <QToolTip>
#include <QWidgetAction>
#include <QDrag>
#include <QDebug>
 
#include "appmodes.h"
#include "canvas.h"
#include "canvasgesture_linemove.h"
#include "canvasgesture_resize.h"
#include "canvasgesture_rulermove.h"
#include "fileloader.h"
#include "fpoint.h"
#include "fpointarray.h"
#include "hyphenator.h"
#include "loadsaveplugin.h"
#include "pageitem_arc.h"
#include "pageitem_line.h"
#include "pageitem_regularpolygon.h"
#include "pageitem_textframe.h"
#include "plugins/formatidlist.h"
#include "prefscontext.h"
#include "prefsfile.h"
#include "prefsmanager.h"
#include "scmimedata.h"
#include "scraction.h"
#include "scribus.h"
#include "scribusXml.h"
#include "scribusdoc.h"
#include "scribusview.h"
#include "selection.h"
#include "ui/aligndistribute.h"
#include "ui/contextmenu.h"
#include "ui/customfdialog.h"
#include "ui/insertTable.h"
#include "ui/pageselector.h"
#include "ui/polyprops.h"
#include "ui/propertiespalette.h"
#include "ui/propertiespalette_line.h"
#include "ui/propertiespalette_text.h"
#include "ui/propertiespalette_xyz.h"
#include "undomanager.h"
#include "util.h"
#include "util_icon.h"
#include "util_math.h"
 
 
 
 
 
CanvasMode_Normal::CanvasMode_Normal(ScribusView* view) : CanvasMode(view), m_ScMW(view->m_ScMW)
{
frameResizeHandle = -1;
shiftSelItems = false;
resizeGesture = NULL;
lineMoveGesture = NULL;
guideMoveGesture = NULL;
m_mousePressPoint.setXY(0, 0);
m_mouseCurrentPoint.setXY(0, 0);
m_mouseSavedPoint.setXY(0, 0);
m_objectDeltaPos.setXY(0,0 );
ySnap = 0;
xSnap = 0;
m_hoveredItem = NULL;
}
 
inline bool CanvasMode_Normal::GetItem(PageItem** pi)
{
*pi = m_doc->m_Selection->itemAt(0);
return (*pi) != NULL;
}
 
void CanvasMode_Normal::drawControls(QPainter* p)
{
// qDebug() << "CanvasMode_Normal::drawControls";
if (m_canvas->m_viewMode.operItemMoving)
drawOutline(p, 1.0, 1.0, m_objectDeltaPos.x(), m_objectDeltaPos.y());
else
drawSelection(p, !m_doc->drawAsPreview);
}
 
void CanvasMode_Normal::enterEvent(QEvent *)
{
if (!m_canvas->m_viewMode.m_MouseButtonPressed)
{
setModeCursor();
}
}
 
void CanvasMode_Normal::leaveEvent(QEvent *e)
{
}
 
 
void CanvasMode_Normal::activate(bool fromGesture)
{
// qDebug() << "CanvasMode_Normal::activate" << fromGesture;
m_canvas->m_viewMode.m_MouseButtonPressed = false;
m_canvas->resetRenderMode();
m_doc->DragP = false;
m_doc->leaveDrag = false;
m_canvas->m_viewMode.operItemMoving = false;
m_canvas->m_viewMode.operItemResizing = false;
m_view->MidButt = false;
m_mousePressPoint.setXY(0, 0);
m_mouseCurrentPoint.setXY(0, 0);
m_mouseSavedPoint.setXY(0, 0);
m_objectDeltaPos.setXY(0,0 );
frameResizeHandle = -1;
shiftSelItems = false;
m_hoveredItem = NULL;
setModeCursor();
if (fromGesture)
{
m_view->update();
}
}
 
void CanvasMode_Normal::deactivate(bool forGesture)
{
// qDebug() << "CanvasMode_Normal::deactivate" << forGesture;
m_view->setRedrawMarkerShown(false);
}
 
void CanvasMode_Normal::mouseDoubleClickEvent(QMouseEvent *m)
{
PageItem *currItem = 0;
m->accept();
m_canvas->m_viewMode.m_MouseButtonPressed = false;
if (m_doc->drawAsPreview)
{
if (GetItem(&currItem))
{
if (currItem->isAnnotation())
{
if (currItem->annotation().Type() == Annotation::Text)
{
currItem->annotation().setOpen(!currItem->annotation().IsOpen());
currItem->asTextFrame()->setTextAnnotationOpen(currItem->annotation().IsOpen());
currItem->update();
m_view->updateContents();
}
}
}
return;
}
m_canvas->resetRenderMode();
// m_view->stopDragTimer();
if (m_doc->m_Selection->isMultipleSelection())
{
if (GetItem(&currItem))
{
/* CB: old code, removing this as shift-alt select on an unselected table selects a cell now.
//#6789 is closed by sorting this.
if (currItem->isTableItem)
{
m_view->Deselect(false);
m_doc->m_Selection->addItem(currItem);
currItem->isSingleSel = true;
//CB FIXME dont call this if the added item is item 0
if (!m_doc->m_Selection->primarySelectionIs(currItem))
currItem->emitAllToGUI();
m_view->updateContents(currItem->getRedrawBounding(m_canvas->scale()));
}*/
}
return;
}
if (GetItem(&currItem))
{
if (currItem->asLatexFrame())
{
if (currItem->locked()) // || (!currItem->ScaleType))
{
return;
}
if (currItem->imageShown())
m_view->requestMode(modeEdit);
}
#ifdef HAVE_OSG
else if (currItem->asOSGFrame())
{
m_view->requestMode(submodeEditExternal);
}
#endif
else if ((currItem->itemType() == PageItem::Polygon) || (currItem->itemType() == PageItem::PolyLine) || (currItem->itemType() == PageItem::Group) || (currItem->itemType() == PageItem::ImageFrame) || (currItem->itemType() == PageItem::PathText))
{
if (currItem->locked()) //|| (!currItem->ScaleType))
{
//mousePressEvent(m);
return;
}
//If we double click on an image frame and theres no image assigned, open the
//load picture dialog, else put it into edit mode if the frame is set to show the image
if (currItem->itemType() == PageItem::ImageFrame)
{
if (currItem->Pfile.isEmpty())
m_view->requestMode(submodeLoadPic);
else if (!currItem->PictureIsAvailable)
m_view->requestMode(submodeStatusPic);
else if (currItem->imageShown())
m_view->requestMode(modeEdit);
}
else if (currItem->itemType() == PageItem::TextFrame)
{
m_view->requestMode(modeEdit);
}
else
{
m_view->requestMode(modeEditClip);
m_ScMW->scrActions["itemUngroup"]->setEnabled(false);
}
}
else if (currItem->itemType() == PageItem::TextFrame)
{
// See if double click was on a frame handle
FPoint p = m_canvas->globalToCanvas(m->globalPos());
Canvas::FrameHandle fh = m_canvas->frameHitTest(QPointF(p.x(),p.y()), currItem);
//CB old code
//emit currItem->isAnnotation() ? AnnotProps() : Amode(modeEdit);
//mousePressEvent(m);
//CB if annotation, open the annotation dialog
if (currItem->isAnnotation())
{
m_view->requestMode(submodeAnnotProps);
//mousePressEvent(m);
}
else if (fh == Canvas::SOUTH)
currItem->asTextFrame()->setTextFrameHeight();
//else if not in mode edit, set mode edit
else if (m_doc->appMode != modeEdit)
{
m_view->requestMode(modeEdit);
m_view->slotSetCurs(m->globalPos().x(), m->globalPos().y());
//used for updating Notes Styles Editor and menu actions for marks
//if cursor is in mark`s place
m_ScMW->setTBvals(currItem);
//CB ignore the double click and go with a single one
//if we werent in mode edit before.
//unsure if this is correct, but its ok given we had no
//double click select until now.
// mousePressEvent(m);
}
}
else if (currItem->asSymbolFrame())
{
if (!m_doc->symbolEditMode())
m_view->requestMode(submodeEditSymbol);
}
else if (currItem->asArc())
{
m_view->requestMode(modeEditArc);
}
else if (currItem->asRegularPolygon())
{
m_view->requestMode(modeEditPolygon);
}
else if (currItem->asSpiral())
{
m_view->requestMode(modeEditSpiral);
}
else if (currItem->asTable())
{
m_view->requestMode(modeEditTable);
m_view->slotSetCurs(m->globalPos().x(), m->globalPos().y());
}
}
}
 
 
void CanvasMode_Normal::mouseMoveEvent(QMouseEvent *m)
{
// qDebug()<<"CanvasMode_Normal::mouseMoveEvent";
// const double mouseX = m->globalX();
// const double mouseY = m->globalY();
const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
m_lastPosWasOverGuide = false;
double newX, newY;
PageItem *currItem=NULL;
bool erf = false;
m->accept();
// qDebug() << "legacy mode move:" << m->x() << m->y() << m_canvas->globalToCanvas(m->globalPos()).x() << m_canvas->globalToCanvas(m->globalPos()).y();
// emit MousePos(m->x()/m_canvas->scale(),// + m_doc->minCanvasCoordinate.x(),
// m->y()/m_canvas->scale()); // + m_doc->minCanvasCoordinate.y());
 
if (commonMouseMove(m))
return;
// m_mouseCurrentPoint = mousePointDoc;
bool movingOrResizing = (m_canvas->m_viewMode.operItemMoving || m_canvas->m_viewMode.operItemResizing);
bool mouseIsOnPage = (m_doc->OnPage(mousePointDoc.x(), mousePointDoc.y()) != -1);
if ((m_doc->guidesPrefs().guidesShown) && (!m_doc->GuideLock) && (!movingOrResizing) && (mouseIsOnPage) )
{
// #9002: Resize points undraggable when object is aligned to a guide
// Allow item resize when guides are aligned to item while preserving
// ability to drag guide when guis is in foreground and inside selection
bool enableGuideGesture(false);
Canvas::FrameHandle frameResizeHandle(Canvas::OUTSIDE);
if (m_doc->m_Selection->count() > 0)
{
double gx(0.0), gy(0.0), gw(0.0), gh(0.0);
m_doc->m_Selection->setGroupRect();
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), QRectF(gx, gy, gw, gh));
}
enableGuideGesture |= (frameResizeHandle == Canvas::OUTSIDE);
enableGuideGesture |= ((m_doc->guidesPrefs().renderStackOrder.indexOf(3) > m_doc->guidesPrefs().renderStackOrder.indexOf(4)) && (frameResizeHandle == Canvas::INSIDE));
if (enableGuideGesture)
{
if (!guideMoveGesture)
{
guideMoveGesture = new RulerGesture(m_view, RulerGesture::HORIZONTAL);
connect(guideMoveGesture,SIGNAL(guideInfo(int, qreal)), m_ScMW->alignDistributePalette,SLOT(setGuide(int, qreal)));
}
if (guideMoveGesture->mouseHitsGuide(mousePointDoc))
{
m_lastPosWasOverGuide = true;
switch (guideMoveGesture->getMode())
{
case RulerGesture::HORIZONTAL:
m_view->setCursor(QCursor(Qt::SplitVCursor));
break;
case RulerGesture::VERTICAL:
m_view->setCursor(QCursor(Qt::SplitHCursor));
break;
default:
m_view->setCursor(QCursor(Qt::ArrowCursor));
}
return;
}
// Here removed a bunch of comments which made reading code difficult,
// there is svn for tracking changes after all. pm
m_view->setCursor(QCursor(Qt::ArrowCursor));
}
}
else if (!mouseIsOnPage)
{
if ((m_view->cursor().shape() == Qt::SplitHCursor) || (m_view->cursor().shape() == Qt::SplitVCursor))
m_view->setCursor(QCursor(Qt::ArrowCursor));
}
//<<#10116 Show overflow counter HUD
if (!movingOrResizing && mouseIsOnPage)
{
PageItem* hoveredItem = NULL;
hoveredItem = m_canvas->itemUnderCursor(m->globalPos(), hoveredItem, m->modifiers());
if (hoveredItem)
{
if (m_doc->drawAsPreview)
{
if (hoveredItem->isAnnotation())
{
QString toolT = "";
if (!hoveredItem->annotation().ToolTip().isEmpty())
toolT = hoveredItem->annotation().ToolTip();
if (hoveredItem->annotation().Type() == Annotation::Button)
{
if (!hoveredItem->annotation().RollOver().isEmpty())
toolT = hoveredItem->annotation().RollOver();
else if (!hoveredItem->annotation().Down().isEmpty())
toolT = hoveredItem->annotation().Down();
}
else if (hoveredItem->annotation().Type() == Annotation::Link)
{
if (hoveredItem->annotation().ActionType() == Annotation::Action_GoTo)
toolT = QString( tr("Go to Page %1").arg(hoveredItem->annotation().Ziel() + 1));
else if (hoveredItem->annotation().ActionType() == Annotation::Action_URI)
toolT = QString( tr("Go to URL %1").arg(hoveredItem->annotation().Extern()));
else if ((hoveredItem->annotation().ActionType() == Annotation::Action_GoToR_FileAbs) || (hoveredItem->annotation().ActionType() == Annotation::Action_GoToR_FileRel))
toolT = QString( tr("Go to Page %1 in File %2").arg(hoveredItem->annotation().Ziel() + 1).arg(hoveredItem->annotation().Extern()));
m_view->setCursor(QCursor(Qt::PointingHandCursor));
}
if (toolT.isEmpty())
toolT = hoveredItem->itemText.plainText();
if (!toolT.isEmpty())
QToolTip::showText(m->globalPos() + QPoint(5, 5), toolT, m_canvas);
if (hoveredItem != m_hoveredItem)
{
if (m_hoveredItem)
handleMouseLeave(m_hoveredItem);
handleMouseEnter(hoveredItem);
}
m_hoveredItem = hoveredItem;
if ((hoveredItem->annotation().Type() == Annotation::Text) && (hoveredItem->annotation().IsOpen()))
{
if (m_view->moveTimerElapsed() && m_canvas->m_viewMode.m_MouseButtonPressed && (m->buttons() & Qt::LeftButton) && (!hoveredItem->locked()))
{
double dx = mousePointDoc.x() - m_mouseCurrentPoint.x();
double dy = mousePointDoc.y() - m_mouseCurrentPoint.y();
hoveredItem->setXYPos(hoveredItem->xPos() + dx, hoveredItem->yPos() + dy, true);
m_mouseCurrentPoint = mousePointDoc;
m_canvas->resetRenderMode();
m_canvas->setRenderModeUseBuffer(false);
m_canvas->repaint();
}
}
}
else
{
if (QToolTip::isVisible())
QToolTip::hideText();
m_hoveredItem = NULL;
}
}
else
{
if (hoveredItem->asTextFrame() && hoveredItem->frameOverflows())
{
if (m_canvas->cursorOverTextFrameControl(m->globalPos(), hoveredItem))
{
QToolTip::showText(m->globalPos() + QPoint(5, 5), tr("Overflow Characters: %1 (%2 White Spaces)").arg(hoveredItem->frameOverflowCount()).arg(hoveredItem->frameOverflowBlankCount()), m_canvas);
}
}
else
if (QToolTip::isVisible())
QToolTip::hideText();
}
}
else
{
if (QToolTip::isVisible())
QToolTip::hideText();
if (m_doc->drawAsPreview)
{
if (m_hoveredItem)
handleMouseLeave(m_hoveredItem);
m_hoveredItem = NULL;
}
}
}
//>>#10116
if (m_doc->drawAsPreview)
return;
m_mouseCurrentPoint = mousePointDoc;
if ((GetItem(&currItem)) && (!shiftSelItems))
{
newX = qRound(mousePointDoc.x()); //m_view->translateToDoc(m->x(), m->y()).x());
newY = qRound(mousePointDoc.y()); //m_view->translateToDoc(m->x(), m->y()).y());
// #0007865
if (/*(((m_view->dragTimerElapsed()) && (m->buttons() & Qt::LeftButton)) ||*/
(m_view->moveTimerElapsed())
&& (m->buttons() & Qt::RightButton)
&& (m_canvas->m_viewMode.m_MouseButtonPressed)
&& (!m_doc->DragP)
&& (!(currItem->isSingleSel)))
{
// start drag
// m_view->stopDragTimer();
if ((fabs(m_mousePressPoint.x() - newX) > 10) || (fabs(m_mousePressPoint.y() - newY) > 10))
{
m_canvas->setRenderMode(Canvas::RENDER_NORMAL);
// m_view->resetDragTimer();
m_doc->DragP = true;
m_doc->leaveDrag = false;
m_doc->DraggedElem = currItem;
m_doc->DragElements.clear();
for (int dre=0; dre<m_doc->m_Selection->count(); ++dre)
m_doc->DragElements.append(m_doc->m_Selection->itemAt(dre));
ScElemMimeData* md = ScriXmlDoc::WriteToMimeData(m_doc, m_doc->m_Selection);
QDrag* dr = new QDrag(m_view);
dr->setMimeData(md);
const QPixmap& pm = loadIcon("DragPix.xpm");
dr->setPixmap(pm);
// dr->setDragCursor(pm, Qt::CopyAction);
// dr->setDragCursor(pm, Qt::MoveAction);
// dr->setDragCursor(pm, Qt::LinkAction);
dr->exec();
m_doc->DragP = false;
m_doc->leaveDrag = false;
m_canvas->m_viewMode.m_MouseButtonPressed = false;
m_doc->DraggedElem = 0;
m_doc->DragElements.clear();
m_view->setCursor(QCursor(Qt::ArrowCursor));
m_view->updateContents();
}
return;
}
if (m_doc->DragP)
return;
//Operations run here:
//Item resize, esp after creating a new one
if (m_view->moveTimerElapsed() && m_canvas->m_viewMode.m_MouseButtonPressed && (m->buttons() & Qt::LeftButton) &&
((m_doc->appMode == modeNormal)) && (!currItem->locked()))
{
// m_view->stopDragTimer();
if (!m_canvas->m_viewMode.operItemResizing)
{
//Dragging an item (plus more?)
newX = mousePointDoc.x(); //static_cast<int>(m->x()/sc);
newY = mousePointDoc.y(); //static_cast<int>(m->y()/sc);
m_canvas->m_viewMode.operItemMoving = true;
if (!(m_doc->drawAsPreview && !m_doc->editOnPreview))
m_view->setCursor(Qt::ClosedHandCursor);
else
m_view->setCursor(QCursor(Qt::ArrowCursor));
erf = false;
int dX = qRound(newX - m_mousePressPoint.x()), dY = qRound(newY - m_mousePressPoint.y());
if (!m_doc->m_Selection->isMultipleSelection())
{
erf=true;
currItem = m_doc->m_Selection->itemAt(0);
//Control Alt drag image in frame without being in edit mode
if ((currItem->asImageFrame()) && (m->modifiers() & Qt::ControlModifier) && (m->modifiers() & Qt::AltModifier))
{
currItem->moveImageInFrame(dX/currItem->imageXScale(),dY/currItem->imageYScale());
m_view->updateContents(currItem->getRedrawBounding(m_canvas->scale()));
}
else
{
//Dragging orthogonally - Ctrl Drag
if ((m->modifiers() & Qt::ControlModifier) && !(m->modifiers() & Qt::ShiftModifier) && !(m->modifiers() & Qt::AltModifier))
{
if (abs(dX) > abs(dY))
dY=0;
else
if (abs(dY) > abs(dX))
dX=0;
erf=false;
dX+=qRound(dragConstrainInitPtX-currItem->xPos());
dY+=qRound(dragConstrainInitPtY-currItem->yPos());
}
double gx, gy, gh, gw;
m_objectDeltaPos.setXY(dX, dY);
// m_doc->m_Selection->getGroupRect(&gx, &gy, &gw, &gh);
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
// #10677 : temporary hack : we need to introduce the
// concept of item snapping points to handle better
// the various types of items
if (currItem->isLine())
{
QPointF startPoint = currItem->asLine()->startPoint();
QPointF endPoint = currItem->asLine()->endPoint();
gx = qMin(startPoint.x(), endPoint.x());
gy = qMin(startPoint.y(), endPoint.y());
gw = fabs(startPoint.x() - endPoint.x());
gh = fabs(startPoint.y() - endPoint.y());
}
if (m_doc->SnapGuides)
{
double nx = gx + m_objectDeltaPos.x();
double ny = gy + m_objectDeltaPos.y();
double nxo = nx, nyo = ny;
m_doc->ApplyGuides(&nx, &ny);
m_objectDeltaPos += FPoint(nx - nxo, ny - nyo);
nx = nxo = gx + gw + m_objectDeltaPos.x();
ny = nyo = gy + gh + m_objectDeltaPos.y();
m_doc->ApplyGuides(&nx, &ny);
m_objectDeltaPos += FPoint(nx-nxo, ny-nyo);
if(false)
{
nx = nxo = gx + gw/2 + m_objectDeltaPos.x();
ny = nyo = gy + gh/2 + m_objectDeltaPos.y();
m_doc->ApplyGuides(&nx, &ny);
m_objectDeltaPos += FPoint(nx-nxo, ny-nyo);
}
}
if (m_doc->SnapElement)
{
xSnap = 0;
ySnap = 0;
double snapWidth[] = {0,gw,gw/2};
double snapHeight[] = {0,gh,gh/2};
if(m_objectDeltaPos.x()<0)
std::swap(snapWidth[0],snapWidth[2]);
if(m_objectDeltaPos.y()<0)
std::swap(snapHeight[0],snapHeight[2]);
double nx,ny,nyo,nxo;
for(int i = 0;i<3;i++)
{
nx = gx + snapWidth[i] + m_objectDeltaPos.x();
ny = gy + snapHeight[i] + m_objectDeltaPos.y();
nxo = nx, nyo = ny;
m_doc->ApplyGuides(&nx, &ny,true);
m_objectDeltaPos += FPoint(nx - nxo, ny - nyo);
if(ny != nyo)
ySnap = ny;
if(nx != nxo)
xSnap = nx;
}
}
if (m_doc->SnapGrid)
{
m_doc->m_Selection->setGroupRect();
double gx, gy, gh, gw, gxo, gyo;
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
gx += m_objectDeltaPos.x();
gy += m_objectDeltaPos.y();
gxo = gx;
gyo = gy;
FPoint npx = m_doc->ApplyGridF(FPoint(gx, gy));
FPoint npw = m_doc->ApplyGridF(FPoint(gx+gw, gy+gh));
if ((fabs(gx-npx.x())) > (fabs((gx+gw)-npw.x())))
gx = npw.x() - gw;
else
gx = npx.x();
if ((fabs(gy-npx.y())) > (fabs((gy+gh)-npw.y())))
gy = npw.y() - gh;
else
gy = npx.y();
if ((fabs(gx - gxo) < (m_doc->guidesPrefs().guideRad) / m_canvas->scale()) && (fabs(gy - gyo) < (m_doc->guidesPrefs().guideRad) / m_canvas->scale()))
m_objectDeltaPos += FPoint(gx-gxo, gy-gyo);
}
}
}
else
{
double gx, gy, gh, gw;
m_doc->m_Selection->setGroupRect();
// m_doc->m_Selection->getGroupRect(&gx, &gy, &gw, &gh);
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
int dX=qRound(newX - m_mousePressPoint.x()), dY=qRound(newY - m_mousePressPoint.y());
erf = true;
if (m->modifiers() & Qt::ControlModifier)
{
if (abs(dX)>abs(dY))
dY=0;
else
if (abs(dY)>abs(dX))
dX=0;
erf=false;
dX+=dragConstrainInitPtX-qRound(gx);
dY+=dragConstrainInitPtY-qRound(gy);
}
m_objectDeltaPos.setXY(dX, dY);
if (m_doc->SnapGuides)
{
double nx = gx + m_objectDeltaPos.x();
double ny = gy + m_objectDeltaPos.y();
double nxo = nx, nyo = ny;
m_doc->ApplyGuides(&nx, &ny);
m_objectDeltaPos += FPoint(nx - nxo, ny - nyo);
nx = nxo = gx + gw + m_objectDeltaPos.x();
ny = nyo = gy + gh + m_objectDeltaPos.y();
m_doc->ApplyGuides(&nx, &ny);
m_objectDeltaPos += FPoint(nx-nxo, ny-nyo);
if(false)
{
nx = nxo = gx + gw/2 + m_objectDeltaPos.x();
ny = nyo = gy + gh/2 + m_objectDeltaPos.y();
m_doc->ApplyGuides(&nx, &ny);
m_objectDeltaPos += FPoint(nx-nxo, ny-nyo);
}
}
if (m_doc->SnapElement)
{
xSnap = 0;
ySnap = 0;
double snapWidth[] = {0,gw,gw/2};
double snapHeight[] = {0,gh,gh/2};
if(m_objectDeltaPos.x()<0)
std::swap(snapWidth[0],snapWidth[2]);
if(m_objectDeltaPos.y()<0)
std::swap(snapHeight[0],snapHeight[2]);
double nx,ny,nyo,nxo;
for(int i = 0;i<3;i++)
{
nx = gx + snapWidth[i] + m_objectDeltaPos.x();
ny = gy + snapHeight[i] + m_objectDeltaPos.y();
nxo = nx, nyo = ny;
m_doc->ApplyGuides(&nx, &ny,true);
m_objectDeltaPos += FPoint(nx - nxo, ny - nyo);
if(ny != nyo)
ySnap = ny;
if(nx != nxo)
xSnap = nx;
}
}
if (m_doc->SnapGrid)
{
double gx, gy, gh, gw, gxo, gyo;
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
gx += m_objectDeltaPos.x();
gy += m_objectDeltaPos.y();
gxo = gx;
gyo = gy;
FPoint npx = m_doc->ApplyGridF(FPoint(gx, gy));
FPoint npw = m_doc->ApplyGridF(FPoint(gx+gw, gy+gh));
if ((fabs(gx-npx.x())) > (fabs((gx+gw)-npw.x())))
gx = npw.x() - gw;
else
gx = npx.x();
if ((fabs(gy-npx.y())) > (fabs((gy+gh)-npw.y())))
gy = npw.y() - gh;
else
gy = npx.y();
if ((fabs(gx - gxo) < (m_doc->guidesPrefs().guideRad) / m_canvas->scale()) && (fabs(gy - gyo) < (m_doc->guidesPrefs().guideRad) / m_canvas->scale()))
m_objectDeltaPos += FPoint(gx-gxo, gy-gyo);
}
}
if (erf)
{
m_mouseCurrentPoint.setXY(newX, newY);
}
{
double gx, gy, gh, gw;
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
m_doc->adjustCanvas(FPoint(gx,gy), FPoint(gx+gw, gy+gh));
QPoint selectionCenter = m_canvas->canvasToLocal(QPointF(gx+gw/2, gy+gh/2));
QPoint localMousePos = m_canvas->canvasToLocal(mousePointDoc);
int localwidth = static_cast<int>(gw * m_canvas->scale());
int localheight = static_cast<int>(gh * m_canvas->scale());
if (localwidth > 200)
{
localwidth = 0;
selectionCenter.setX(localMousePos.x());
}
if (localheight > 200)
{
localheight = 0;
selectionCenter.setY(localMousePos.y());
}
m_view->ensureVisible(selectionCenter.x(), selectionCenter.y(), localwidth/2 + 20, localheight/2 + 20);
m_canvas->repaint();
m_doc->m_Selection->getGroupRect(&gx, &gy, &gw, &gh);
m_canvas->displayCorrectedXYHUD(m->globalPos(), gx + m_objectDeltaPos.x(), gy + m_objectDeltaPos.y());
}
}
}
if ((!m_canvas->m_viewMode.m_MouseButtonPressed) && (m_doc->appMode != modeDrawBezierLine))
{
if (m_doc->m_Selection->isMultipleSelection())
{
// QRect mpo = QRect(qRound(m->x()/m_canvas->scale())-m_doc->guidesPrefs().grabRad, qRound(m->y()/m_canvas->scale())-m_doc->guidesPrefs().grabRad, m_doc->guidesPrefs().grabRad*2, m_doc->guidesPrefs().grabRad*2);
// mpo.moveBy(qRound(m_doc->minCanvasCoordinate.x()), qRound(m_doc->minCanvasCoordinate.y()));
double gx, gy, gh, gw;
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
int how = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), QRectF(gx, gy, gw, gh));
// if ((QRect(static_cast<int>(gx), static_cast<int>(gy), static_cast<int>(gw), static_cast<int>(gh)).intersects(mpo))
if (how >= 0)
{
if (how > 0)
{
setResizeCursor(how);
}
else
{
m_view->setCursor(QCursor(Qt::OpenHandCursor));
}
}
else
{
setModeCursor();
}
return;
}
for (int a = 0; a < m_doc->m_Selection->count(); ++a)
{
currItem = m_doc->m_Selection->itemAt(a);
if (currItem->locked())
break;
QTransform p;
m_canvas->Transform(currItem, p);
QRect mpo = QRect(m->x()-m_doc->guidesPrefs().grabRadius, m->y()-m_doc->guidesPrefs().grabRadius, m_doc->guidesPrefs().grabRadius*2, m_doc->guidesPrefs().grabRadius*2);
// mpo.moveBy(qRound(m_doc->minCanvasCoordinate.x() * m_canvas->scale()), qRound(m_doc->minCanvasCoordinate.y() * m_canvas->scale()));
if ((QRegion(p.map(QPolygon(QRect(-3, -3, static_cast<int>(currItem->width()+6), static_cast<int>(currItem->height()+6))))).contains(mpo)))
{
QRect tx = p.mapRect(QRect(0, 0, static_cast<int>(currItem->width()), static_cast<int>(currItem->height())));
if ((tx.intersects(mpo)) && (!currItem->locked()))
{
m_view->setCursor(QCursor(Qt::OpenHandCursor));
if (!currItem->sizeLocked())
m_view->HandleCurs(currItem, mpo);
}
}
else
{
// setModeCursor();
}
}
if (GetItem(&currItem) && (m_doc->appMode == modeNormal))
{
int how = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), currItem);
if (how > 0)
{
if(currItem->asLine())
m_view->setCursor(QCursor(Qt::SizeAllCursor));
else if(!currItem->locked() && !currItem->sizeLocked())
{
if ((!currItem->sizeHLocked() && !currItem->sizeVLocked()) || (currItem->sizeHLocked() && (how == 5 || how == 8))
|| (currItem->sizeVLocked() && (how == 6 || how == 7)))
setResizeCursor(how, currItem->rotation());
}
}
else if (how == 0)
{
if (!(m_doc->drawAsPreview && !m_doc->editOnPreview))
m_view->setCursor(QCursor(Qt::OpenHandCursor));
else
m_view->setCursor(QCursor(Qt::ArrowCursor));
}
else
{
m_view->setCursor(QCursor(Qt::ArrowCursor));
}
}
}
}
else
{
if ((m_canvas->m_viewMode.m_MouseButtonPressed) && (m->buttons() & Qt::LeftButton))
{
newX = qRound(mousePointDoc.x()); //m_view->translateToDoc(m->x(), m->y()).x());
newY = qRound(mousePointDoc.y()); //m_view->translateToDoc(m->x(), m->y()).y());
m_mouseSavedPoint.setXY(newX, newY);
QPoint startP = m_canvas->canvasToGlobal(m_mousePressPoint);
m_view->redrawMarker->setGeometry(QRect(m_view->mapFromGlobal(startP), m_view->mapFromGlobal(m->globalPos())).normalized());
m_view->setRedrawMarkerShown(true);
m_view->HaveSelRect = true;
return;
}
}
}
 
void CanvasMode_Normal::mousePressEvent(QMouseEvent *m)
{
const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
PageItem *currItem;
 
m_objectDeltaPos = FPoint(0, 0);
m_mousePressPoint = m_mouseCurrentPoint = mousePointDoc;
m_mouseSavedPoint = mousePointDoc;
m_canvas->m_viewMode.m_MouseButtonPressed = true;
m_canvas->m_viewMode.operItemMoving = false;
m_view->HaveSelRect = false;
m_doc->DragP = false;
m_doc->leaveDrag = false;
m->accept();
m_view->registerMousePress(m->globalPos());
QRect mpo(m->x()-m_doc->guidesPrefs().grabRadius, m->y()-m_doc->guidesPrefs().grabRadius, m_doc->guidesPrefs().grabRadius*2, m_doc->guidesPrefs().grabRadius*2);
// mpo.moveBy(qRound(m_doc->minCanvasCoordinate.x() * m_canvas->scale()), qRound(m_doc->minCanvasCoordinate.y() * m_canvas->scale()));
 
if (m->button() == Qt::MidButton)
{
m_view->MidButt = true;
if (m->modifiers() & Qt::ControlModifier)
m_view->DrawNew();
return;
}
 
if ((GetItem(&currItem)) && (!m_lastPosWasOverGuide))
{
if ((currItem->asLine()) && (!m_doc->m_Selection->isMultipleSelection()) && (!m_doc->drawAsPreview))
{
if (!lineMoveGesture)
lineMoveGesture = new LineMove(this);
lineMoveGesture->mousePressEvent(m);
if (lineMoveGesture->haveLineItem())
{
m_view->startGesture(lineMoveGesture);
return;
}
}
else
{
bool isMS=m_doc->m_Selection->isMultipleSelection();
if ((isMS || (!isMS && (!currItem->locked() && !currItem->sizeLocked()))) && (!m_doc->drawAsPreview))
{
if (!resizeGesture)
resizeGesture = new ResizeGesture(this);
 
resizeGesture->mousePressEvent(m);
if (resizeGesture->frameHandle() > 0)
{
m_view->startGesture(resizeGesture);
return;
}
}
//#7928 else
//#7928 return;
}
if (!(m_doc->drawAsPreview && !m_doc->editOnPreview))
m_view->setCursor(Qt::ClosedHandCursor);
else
m_view->setCursor(QCursor(Qt::ArrowCursor));
#if 1
if (m_doc->m_Selection->isMultipleSelection() && (!m_doc->drawAsPreview))
{
m_canvas->PaintSizeRect(QRect());
double gx, gy, gh, gw;
bool shiftSel = true;
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
dragConstrainInitPtX = qRound(gx);
dragConstrainInitPtY = qRound(gy);
frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), QRectF(gx, gy, gw, gh));
if (frameResizeHandle == Canvas::OUTSIDE ||
(frameResizeHandle == Canvas::INSIDE && m->modifiers() != Qt::NoModifier))
{
frameResizeHandle = 0;
m_doc->m_Selection->delaySignalsOn();
m_view->updatesOn(false);
shiftSel = SeleItem(m);
m_view->updatesOn(true);
m_doc->m_Selection->delaySignalsOff();
}
if (((m_doc->m_Selection->count() == 0) || (!shiftSel)) && (m->modifiers() == Qt::ShiftModifier))
{
shiftSelItems = true;
m_mouseCurrentPoint = m_mousePressPoint = m_mouseSavedPoint = mousePointDoc;
}
else
shiftSelItems = false;
m_canvas->setRenderModeFillBuffer();
}
else // not multiple selection
{
dragConstrainInitPtX = qRound(currItem->xPos());
dragConstrainInitPtY = qRound(currItem->yPos());
// dont call SeleItem() without need here:
frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), currItem);
//#6797
if (frameResizeHandle <= 0 || m->modifiers() != Qt::NoModifier)
{
m_doc->m_Selection->delaySignalsOn();
m_view->updatesOn(false);
SeleItem(m); //Where we send the mouse press event to select an item
if (GetItem(&currItem) && (!m_doc->drawAsPreview))
frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), currItem);
else
frameResizeHandle = 0;
m_view->updatesOn(true);
m_doc->m_Selection->delaySignalsOff();
}
if ((currItem && !currItem->locked() && frameResizeHandle > 0) == false && (!m_doc->drawAsPreview))
{
m_mouseCurrentPoint = m_mousePressPoint = m_mouseSavedPoint = mousePointDoc;
}
}
m_canvas->setRenderModeFillBuffer();
#endif
}
else // !GetItem()
{
SeleItem(m);
if (m_doc->m_Selection->count() == 0)
{
m_mouseCurrentPoint = m_mousePressPoint = m_mouseSavedPoint = mousePointDoc;
m_view->redrawMarker->setGeometry(m->globalPos().x(), m->globalPos().y(), 1, 1);
m_view->setRedrawMarkerShown(true);
}
else
{
if (!(m_doc->drawAsPreview && !m_doc->editOnPreview))
m_canvas->setRenderModeFillBuffer();
}
}
/* if (m->button() == MidButton)
{
MidButt = true;
if (m_doc->m_Selection->count() != 0)
m_view->Deselect(true);
DrawNew();
} */
if ((m_doc->m_Selection->count() != 0) && (m->button() == Qt::RightButton))
{
m_canvas->m_viewMode.m_MouseButtonPressed = true;
m_mousePressPoint = m_mouseCurrentPoint;
}
if (m_doc->drawAsPreview && !m_doc->editOnPreview)
{
m_canvas->setRenderModeUseBuffer(false);
if (m_doc->m_Selection->count() == 1)
{
currItem = m_doc->m_Selection->itemAt(0);
if (currItem->isAnnotation())
{
if (currItem->annotation().Type() == Annotation::Checkbox)
handleCheckBoxPress(currItem);
else if (currItem->annotation().Type() == Annotation::RadioButton)
handleRadioButtonPress(currItem);
else if (currItem->annotation().Type() == Annotation::Button)
handlePushButtonPress(currItem);
}
}
}
// Commented out to fix bug #7865
// if ((m_doc->m_Selection->count() != 0) && (m->button() == Qt::LeftButton) && (frameResizeHandle == 0))
// {
// m_view->startDragTimer();
// }
m_canvas->PaintSizeRect(QRect());
}
 
 
 
void CanvasMode_Normal::mouseReleaseEvent(QMouseEvent *m)
{
// qDebug("CanvasMode_Normal::mouseReleaseEvent");
#ifdef GESTURE_FRAME_PREVIEW
clearPixmapCache();
#endif // GESTURE_FRAME_PREVIEW
const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
PageItem *currItem;
m_canvas->m_viewMode.m_MouseButtonPressed = false;
m_canvas->resetRenderMode();
m->accept();
m_view->setRedrawMarkerShown(false);
// m_view->stopDragTimer();
//m_canvas->update(); //ugly in a mouseReleaseEvent!!!!!!!
if ((!GetItem(&currItem)) && (m->button() == Qt::RightButton) && (!m_doc->DragP) && (!m_doc->drawAsPreview))
{
createContextMenu(NULL, mousePointDoc.x(), mousePointDoc.y());
return;
}
if ((GetItem(&currItem)) && (m->button() == Qt::RightButton) && (!m_doc->DragP) && (!(m_doc->drawAsPreview && !m_doc->editOnPreview)))
{
createContextMenu(currItem, mousePointDoc.x(), mousePointDoc.y());
return;
}
//<<#10116: Click on overflow icon to get into link frame mode
PageItem* clickedItem=NULL;
clickedItem = m_canvas->itemUnderCursor(m->globalPos(), clickedItem, m->modifiers());
if (clickedItem && clickedItem->asTextFrame() && (!clickedItem->isAnnotation()) && (!m_doc->drawAsPreview))
{
if (clickedItem->frameOverflows())
{
if (m_canvas->cursorOverTextFrameControl(m->globalPos(), clickedItem))
{
m_view->requestMode(modeLinkFrames);
return;
}
}
}
//>>#10116
if (m_view->moveTimerElapsed() && (GetItem(&currItem)))
{
// m_view->stopDragTimer();
m_canvas->setRenderModeUseBuffer(false);
if (!m_doc->m_Selection->isMultipleSelection())
{
m_doc->setRedrawBounding(currItem);
currItem->OwnPage = m_doc->OnPage(currItem);
m_canvas->m_viewMode.operItemResizing = false;
if (currItem->asLine())
m_view->updateContents();
}
if (m_canvas->m_viewMode.operItemMoving)
{
// we want to invalidate all frames under the moved frame
// hm, I will try to be more explicit :) - pm
int itemIndex = m_doc->Items->count();
PageItem* underItem( m_canvas->itemUnderItem(currItem, itemIndex) );
while(underItem)
{
if(underItem->asTextFrame())
underItem->asTextFrame()->invalidateLayout(false);
else
underItem->invalidateLayout();
underItem = m_canvas->itemUnderItem(currItem, itemIndex);
}
m_view->updatesOn(false);
if (!m_view->groupTransactionStarted())
{
m_view->startGroupTransaction(Um::Move, "", Um::IMove);
}
if (m_doc->m_Selection->isMultipleSelection())
{
m_doc->moveGroup(m_objectDeltaPos.x(), m_objectDeltaPos.y());
m_doc->m_Selection->setGroupRect();
double gx, gy, gh, gw;
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
double nx = gx;
double ny = gy;
if (!m_doc->ApplyGuides(&nx, &ny) && !m_doc->ApplyGuides(&nx, &ny,true))
{
FPoint npx = m_doc->ApplyGridF(FPoint(gx, gy));
FPoint npw = m_doc->ApplyGridF(FPoint(gx+gw, gy+gh));
if ((fabs(gx-npx.x())) > (fabs((gx+gw)-npw.x())))
nx = npw.x() - gw;
else
nx = npx.x();
if ((fabs(gy-npx.y())) > (fabs((gy+gh)-npw.y())))
ny = npw.y() - gh;
else
ny = npx.y();
}
m_doc->moveGroup(nx-gx, ny-gy);
m_doc->m_Selection->setGroupRect();
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
nx = gx+gw;
ny = gy+gh;
if (m_doc->ApplyGuides(&nx, &ny) && !m_doc->ApplyGuides(&nx, &ny,true))
m_doc->moveGroup(nx-(gx+gw), ny-(gy+gh));
m_doc->m_Selection->setGroupRect();
}
else
{
currItem = m_doc->m_Selection->itemAt(0);
m_doc->MoveItem(m_objectDeltaPos.x(), m_objectDeltaPos.y(), currItem);
if (m_doc->SnapGrid)
{
double nx = currItem->xPos();
double ny = currItem->yPos();
if (!m_doc->ApplyGuides(&nx, &ny) && !m_doc->ApplyGuides(&nx, &ny,true))
{
m_doc->m_Selection->setGroupRect();
double gx, gy, gh, gw, gxo, gyo;
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
gxo = gx;
gyo = gy;
FPoint npx = m_doc->ApplyGridF(FPoint(gx, gy));
FPoint npw = m_doc->ApplyGridF(FPoint(gx+gw, gy+gh));
if ((fabs(gx-npx.x())) > (fabs((gx+gw)-npw.x())))
gx = npw.x() - gw;
else
gx = npx.x();
if ((fabs(gy-npx.y())) > (fabs((gy+gh)-npw.y())))
gy = npw.y() - gh;
else
gy = npx.y();
if ((fabs(gx - gxo) < (m_doc->guidesPrefs().guideRad) / m_canvas->scale()) && (fabs(gy - gyo) < (m_doc->guidesPrefs().guideRad) / m_canvas->scale()))
{
nx += (gx - gxo);
ny += (gy - gyo);
}
}
m_doc->MoveItem(nx-currItem->xPos(), ny-currItem->yPos(), currItem);
}
}
m_canvas->m_viewMode.operItemMoving = false;
if (m_doc->m_Selection->isMultipleSelection())
{
double gx, gy, gh, gw;
m_doc->m_Selection->getGroupRect(&gx, &gy, &gw, &gh);
FPoint maxSize(gx+gw+m_doc->scratch()->Right, gy+gh+m_doc->scratch()->Bottom);
FPoint minSize(gx-m_doc->scratch()->Left, gy-m_doc->scratch()->Top);
m_doc->adjustCanvas(minSize, maxSize);
}
m_doc->setRedrawBounding(currItem);
currItem->OwnPage = m_doc->OnPage(currItem);
if (currItem->OwnPage != -1)
{
m_doc->setCurrentPage(m_doc->Pages->at(currItem->OwnPage));
m_view->m_ScMW->slotSetCurrentPage(currItem->OwnPage);
}
//CB done with emitAllToGUI
//emit HaveSel();
//EmitValues(currItem);
//CB need this for? a moved item will send its new data with the new xpos/ypos emits
//CB TODO And what if we have dragged to a new page. Items X&Y are not updated anyway now
//currItem->emitAllToGUI();
m_view->updatesOn(true);
m_view->updateContents();
m_doc->changed();
}
}
//CB Drag selection performed here
if (((m_doc->m_Selection->count() == 0) && (m_view->HaveSelRect) && (!m_view->MidButt)) || ((shiftSelItems) && (m_view->HaveSelRect) && (!m_view->MidButt)))
{
double dx = m_mouseSavedPoint.x() - m_mousePressPoint.x();
double dy = m_mouseSavedPoint.y() - m_mousePressPoint.y();
QRectF canvasSele = QRectF(m_mousePressPoint.x(), m_mousePressPoint.y(), dx, dy).normalized();
QRectF localSele = m_canvas->canvasToLocal(canvasSele).normalized();
if (!m_doc->masterPageMode())
{
uint docPagesCount=m_doc->Pages->count();
uint docCurrPageNo=m_doc->currentPageNumber();
for (uint i = 0; i < docPagesCount; ++i)
{
ScPage* page = m_doc->Pages->at(i);
QRectF pageRect(page->xOffset(), page->yOffset(), page->width(), page->height());
if (pageRect.intersects(canvasSele))
{
if (docCurrPageNo != i)
{
m_doc->setCurrentPage(m_doc->Pages->at(i));
m_view->m_ScMW->slotSetCurrentPage(i);
}
break;
}
}
m_view->setRulerPos(m_view->contentsX(), m_view->contentsY());
}
int docItemCount=m_doc->Items->count();
if (docItemCount != 0)
{
m_doc->m_Selection->delaySignalsOn();
for (int a = 0; a < docItemCount; ++a)
{
PageItem* docItem = m_doc->Items->at(a);
if ((m_doc->masterPageMode()) && (docItem->OnMasterPage != m_doc->currentPage()->pageName()))
continue;
QRect apr2 = m_canvas->canvasToLocal( docItem->getCurrentBoundingRect(docItem->lineWidth()) );
if ((localSele.contains(apr2)) && ((docItem->LayerID == m_doc->activeLayer()) || (m_doc->layerSelectable(docItem->LayerID))) && (!m_doc->layerLocked(docItem->LayerID)))
{
bool redrawSelection=false;
m_view->SelectItemNr(a, redrawSelection);
}
}
m_doc->m_Selection->delaySignalsOff();
if (m_doc->m_Selection->count() > 1)
{
m_doc->m_Selection->setGroupRect();
double x, y, w, h;
m_doc->m_Selection->getGroupRect(&x, &y, &w, &h);
m_view->getGroupRectScreen(&x, &y, &w, &h);
}
}
m_view->HaveSelRect = false;
shiftSelItems = false;
// m_view->redrawMarker->hide();
m_view->updateContents();
}
if (m_doc->appMode != modeEdit)
{
if (!PrefsManager::instance()->appPrefs.uiPrefs.stickyTools)
m_view->requestMode(modeNormal);
else
{
int appMode = m_doc->appMode;
m_view->requestMode(appMode);
}
}
if (GetItem(&currItem))
{
// qApp->changeOverrideCursor(QCursor(Qt::OpenHandCursor));
if (m_doc->m_Selection->count() > 1)
{
m_doc->m_Selection->setGroupRect();
double x, y, w, h;
m_doc->m_Selection->getGroupRect(&x, &y, &w, &h);
m_canvas->m_viewMode.operItemMoving = false;
m_canvas->m_viewMode.operItemResizing = false;
m_view->updateContents(QRect(static_cast<int>(x-5), static_cast<int>(y-5), static_cast<int>(w+10), static_cast<int>(h+10)));
//Now unuseful as PropertiesPalette_XYZ::setCurrentItem() handles multiple selection
//m_ScMW->propertiesPalette->setXY(x,y);
//m_ScMW->propertiesPalette->setBH(w,h);
}
/*else
currItem->emitAllToGUI();*/
}
else
m_view->Deselect(true);
xSnap = ySnap = 0;
m_canvas->setRenderModeUseBuffer(false);
m_doc->DragP = false;
m_doc->leaveDrag = false;
m_canvas->m_viewMode.operItemMoving = false;
m_canvas->m_viewMode.operItemResizing = false;
m_view->MidButt = false;
shiftSelItems = false;
if (m_view->groupTransactionStarted())
{
for (int i = 0; i < m_doc->m_Selection->count(); ++i)
m_doc->m_Selection->itemAt(i)->checkChanges(true);
m_view->endGroupTransaction();
}
for (int i = 0; i < m_doc->m_Selection->count(); ++i)
m_doc->m_Selection->itemAt(i)->checkChanges(true);
//Commit drag created items to undo manager.
if (m_doc->m_Selection->count() > 0)
{
if (m_doc->m_Selection->itemAt(0)!=NULL)
{
m_doc->itemAddCommit(m_doc->m_Selection->itemAt(0));
}
}
//Make sure the Zoom spinbox and page selector dont have focus if we click on the canvas
m_view->m_ScMW->zoomSpinBox->clearFocus();
m_view->m_ScMW->pageSelector->clearFocus();
if (m_doc->m_Selection->count() > 0)
{
if (m_doc->m_Selection->itemAt(0) != 0) // is there the old clip stored for the undo action
{
currItem = m_doc->m_Selection->itemAt(0);
m_doc->nodeEdit.finishTransaction(currItem);
}
}
if (m_doc->drawAsPreview && !m_doc->editOnPreview)
{
if (m_doc->m_Selection->count() == 1)
{
currItem = m_doc->m_Selection->itemAt(0);
if (currItem->isAnnotation())
{
if (currItem->annotation().Type() == Annotation::Text)
{
if (currItem->annotation().IsOpen())
{
if (m_canvas->cursorOverFrameControl(m->globalPos(), QRectF(245, 20, 11, 11), currItem))
{
currItem->annotation().setOpen(false);
currItem->asTextFrame()->setTextAnnotationOpen(false);
currItem->update();
m_view->updateContents();
}
}
}
if (currItem->annotation().Type() == Annotation::Link)
handleLinkAnnotation(currItem);
else if (currItem->annotation().Type() == Annotation::Checkbox)
handleCheckBoxRelease(currItem);
else if (currItem->annotation().Type() == Annotation::RadioButton)
handleRadioButtonRelease(currItem);
else if (currItem->annotation().Type() == Annotation::Button)
handlePushButtonRelease(currItem);
}
}
}
}
 
void CanvasMode_Normal::handleCheckBoxPress(PageItem* currItem)
{
m_view->m_AnnotChanged = true;
currItem->annotation().setOnState(true);
currItem->update();
if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
handleJavaAction(currItem, Annotation::Java_PressButton);
m_doc->regionsChanged()->update(currItem->getVisualBoundingRect());
}
 
void CanvasMode_Normal::handlePushButtonPress(PageItem* currItem)
{
currItem->annotation().setOnState(true);
currItem->update();
if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
handleJavaAction(currItem, Annotation::Java_PressButton);
m_doc->regionsChanged()->update(currItem->getVisualBoundingRect());
}
 
void CanvasMode_Normal::handleRadioButtonPress(PageItem* currItem)
{
m_view->m_AnnotChanged = true;
if (currItem->isGroupChild())
{
PageItem *group = currItem->Parent->asGroupFrame();
for (int a = 0; a < group->groupItemList.count(); a++)
{
PageItem *gItem = group->groupItemList[a];
if ((gItem->isAnnotation()) && (gItem->annotation().Type() == Annotation::RadioButton))
{
gItem->update();
}
}
}
else
{
int op = currItem->OwnPage;
uint docItemCount = m_doc->Items->count();
for (uint i = 0; i < docItemCount; ++i)
{
PageItem *gItem = m_doc->Items->at(i);
if ((gItem->isAnnotation()) && (gItem->annotation().Type() == Annotation::RadioButton) && (gItem->OwnPage == op))
{
gItem->update();
}
}
}
currItem->annotation().setOnState(true);
currItem->update();
if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
handleJavaAction(currItem, Annotation::Java_PressButton);
m_view->updateContents();
}
 
void CanvasMode_Normal::handleCheckBoxRelease(PageItem* currItem)
{
m_view->m_AnnotChanged = true;
currItem->annotation().setOnState(false);
currItem->annotation().setCheckState(!currItem->annotation().IsChecked());
if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
handleJavaAction(currItem, Annotation::Java_ReleaseButton);
currItem->update();
m_doc->regionsChanged()->update(currItem->getVisualBoundingRect());
}
 
void CanvasMode_Normal::handlePushButtonRelease(PageItem* currItem)
{
m_view->m_AnnotChanged = true;
currItem->annotation().setOnState(false);
currItem->update();
switch (currItem->annotation().ActionType())
{
case Annotation::Action_JavaScript:
handleJavaAction(currItem, Annotation::Java_ReleaseButton);
break;
case Annotation::Action_GoTo:
case Annotation::Action_URI:
case Annotation::Action_GoToR_FileAbs:
case Annotation::Action_GoToR_FileRel:
handleLinkAnnotation(currItem);
break;
case Annotation::Action_ResetForm:
m_doc->ResetFormFields();
break;
case Annotation::Action_ImportData:
m_doc->ImportData();
break;
case Annotation::Action_SubmitForm:
m_doc->SubmitForm();
break;
case Annotation::Action_Named:
handleNamedAction(currItem);
default:
break;
}
}
 
void CanvasMode_Normal::handleRadioButtonRelease(PageItem* currItem)
{
m_view->m_AnnotChanged = true;
if (currItem->isGroupChild())
{
PageItem *group = currItem->Parent->asGroupFrame();
for (int a = 0; a < group->groupItemList.count(); a++)
{
PageItem *gItem = group->groupItemList[a];
if ((gItem->isAnnotation()) && (gItem->annotation().Type() == Annotation::RadioButton))
{
gItem->annotation().setCheckState(false);
gItem->update();
}
}
}
else
{
int op = currItem->OwnPage;
uint docItemCount = m_doc->Items->count();
for (uint i = 0; i < docItemCount; ++i)
{
PageItem *gItem = m_doc->Items->at(i);
if ((gItem->isAnnotation()) && (gItem->annotation().Type() == Annotation::RadioButton) && (gItem->OwnPage == op))
{
gItem->annotation().setCheckState(false);
gItem->update();
}
}
}
currItem->annotation().setCheckState(true);
currItem->annotation().setOnState(false);
if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
handleJavaAction(currItem, Annotation::Java_ReleaseButton);
currItem->update();
m_view->updateContents();
}
 
void CanvasMode_Normal::handleJavaAction(PageItem* currItem, int event)
{
QString scriptCode = "";
switch (event)
{
case Annotation::Java_PressButton:
scriptCode = currItem->annotation().D_act();
break;
case Annotation::Java_ReleaseButton:
scriptCode = currItem->annotation().Action();
break;
case Annotation::Java_EnterWidget:
scriptCode = currItem->annotation().E_act();
break;
case Annotation::Java_LeaveWidget:
scriptCode = currItem->annotation().X_act();
break;
case Annotation::Java_FocusIn:
scriptCode = currItem->annotation().Fo_act();
break;
case Annotation::Java_FocusOut:
scriptCode = currItem->annotation().Bl_act();
break;
case Annotation::Java_SelectionChg:
scriptCode = currItem->annotation().K_act();
break;
case Annotation::Java_FieldFormat:
scriptCode = currItem->annotation().F_act();
break;
case Annotation::Java_FieldValidate:
scriptCode = currItem->annotation().V_act();
break;
case Annotation::Java_FieldCalculate:
scriptCode = currItem->annotation().C_act();
break;
default:
break;
}
if (!scriptCode.isEmpty())
{
// Execute the JavasScript Code
// qDebug() << "JavaScript:" << scriptCode;
}
}
 
void CanvasMode_Normal::handleNamedAction(PageItem* currItem)
{
m_view->Deselect(true);
QString name = currItem->annotation().Action();
if (name == "FirstPage")
m_view->GotoPage(0);
else if (name == "PrevPage")
m_view->GotoPage(qMax(0, m_doc->currentPageNumber()-1));
else if (name == "NextPage")
m_view->GotoPage(qMin(m_doc->currentPageNumber()+1, m_doc->Pages->count()-1));
else if (name == "LastPage")
m_view->GotoPage(m_doc->Pages->count()-1);
else if (name == "Print")
m_ScMW->slotFilePrint();
else if (name == "Close")
m_ScMW->slotFileClose();
else if (name == "Quit")
m_ScMW->slotFileQuit();
else if (name == "FitHeight")
m_ScMW->slotZoom(-100);
else if (name == "FitWidth")
m_ScMW->slotZoom(-200);
}
 
void CanvasMode_Normal::handleLinkAnnotation(PageItem* currItem)
{
if (currItem->annotation().ActionType() == Annotation::Action_GoTo)
{
m_view->Deselect(true);
if (currItem->annotation().Ziel() < m_doc->Pages->count())
m_view->GotoPage(currItem->annotation().Ziel());
else
{
QString message = tr("Page %1 does not exist!").arg(currItem->annotation().Ziel() + 1);
ScMessageBox::warning(m_view, CommonStrings::trWarning, message);
}
}
else if (currItem->annotation().ActionType() == Annotation::Action_URI)
{
QString message = tr("Link Target is Web URL.\nURL: %1").arg(currItem->annotation().Extern());
ScMessageBox::information(m_view, tr("Information"), message);
}
else if ((currItem->annotation().ActionType() == Annotation::Action_GoToR_FileAbs) || (currItem->annotation().ActionType() == Annotation::Action_GoToR_FileRel))
{
QString message = tr("Link Target is external File.\nFile: %1\nPage: %2").arg(currItem->annotation().Extern()).arg(currItem->annotation().Ziel() + 1);
ScMessageBox::information(m_view, tr("Information"), message);
}
}
 
void CanvasMode_Normal::handleFocusOut(PageItem* currItem)
{
if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
handleJavaAction(currItem, Annotation::Java_FocusOut);
}
 
void CanvasMode_Normal::handleFocusIn(PageItem* currItem)
{
if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
handleJavaAction(currItem, Annotation::Java_FocusIn);
}
 
void CanvasMode_Normal::handleMouseLeave(PageItem* currItem)
{
if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
handleJavaAction(currItem, Annotation::Java_LeaveWidget);
}
 
void CanvasMode_Normal::handleMouseEnter(PageItem* currItem)
{
if (currItem->annotation().ActionType() == Annotation::Action_JavaScript)
handleJavaAction(currItem, Annotation::Java_EnterWidget);
}
 
void CanvasMode_Normal::keyPressEvent(QKeyEvent *e)
{
commonkeyPressEvent_NormalNodeEdit(e);
}
 
void CanvasMode_Normal::keyReleaseEvent(QKeyEvent *e)
{
commonkeyReleaseEvent(e);
}
 
//CB-->Doc/Fix
bool CanvasMode_Normal::SeleItem(QMouseEvent *m)
{
PageItem *previousSelectedItem = NULL;
if (m_doc->m_Selection->count() != 0)
previousSelectedItem = m_doc->m_Selection->itemAt(0);
m_canvas->m_viewMode.operItemSelecting = true;
const unsigned SELECT_IN_GROUP = Qt::AltModifier; // Qt::MetaModifier;
const unsigned SELECT_MULTIPLE = Qt::ShiftModifier;
const unsigned SELECT_BENEATH = Qt::ControlModifier;
QTransform p;
PageItem *currItem;
m_canvas->m_viewMode.m_MouseButtonPressed = true;
FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
m_mouseCurrentPoint = mousePointDoc;
double grabRadius = m_doc->guidesPrefs().grabRadius / m_canvas->scale();
int MxpS = static_cast<int>(mousePointDoc.x()); //m->x()/m_canvas->scale() + 0*m_doc->minCanvasCoordinate.x());
int MypS = static_cast<int>(mousePointDoc.y()); //m->y()/m_canvas->scale() + 0*m_doc->minCanvasCoordinate.y());
QRectF mpo(m_mouseCurrentPoint.x()-grabRadius, m_mouseCurrentPoint.y()-grabRadius, grabRadius*2, grabRadius*2);
m_doc->nodeEdit.deselect();
 
if (m_doc->guidesPrefs().renderStackOrder.indexOf(3) > m_doc->guidesPrefs().renderStackOrder.indexOf(4)) // guides are on foreground and want to be processed first
{
if ((m_doc->guidesPrefs().guidesShown) && (m_doc->OnPage(MxpS, MypS) != -1))
{
// #9002: Resize points undraggable when object is aligned to a guide
// Allow item resize when guides are aligned to item while preserving
// ability to drag guide when guis is in foreground and inside selection
bool enableGuideGesture(true);
if (m_doc->m_Selection->count() > 0)
{
double gx(0.0), gy(0.0), gw(0.0), gh(0.0);
m_doc->m_Selection->setGroupRect();
m_doc->m_Selection->getVisualGroupRect(&gx, &gy, &gw, &gh);
Canvas::FrameHandle frameResizeHandle = m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), QRectF(gx, gy, gw, gh));
enableGuideGesture = (frameResizeHandle == Canvas::INSIDE);
}
if (enableGuideGesture)
{
if (!guideMoveGesture)
{
guideMoveGesture = new RulerGesture(m_view, RulerGesture::HORIZONTAL);
connect(guideMoveGesture,SIGNAL(guideInfo(int, qreal)), m_ScMW->alignDistributePalette,SLOT(setGuide(int, qreal)));
}
if ( (!m_doc->GuideLock) && (guideMoveGesture->mouseHitsGuide(mousePointDoc)) )
{
m_view->startGesture(guideMoveGesture);
guideMoveGesture->mouseMoveEvent(m);
m_doc->m_Selection->connectItemToGUI();
// qDebug()<<"Out Of SeleItem"<<__LINE__;
return true;
}
else
{
// If we call startGesture now, a new guide is created each time.
// ### could be a weakness to avoid calling it tho.
// m_view->startGesture(guideMoveGesture);
guideMoveGesture->mouseSelectGuide(m);
}
}
}
}
bool pageChanged(false);
if (!m_doc->masterPageMode())
{
int pgNum = -1;
int docPageCount = static_cast<int>(m_doc->Pages->count() - 1);
MarginStruct pageBleeds;
bool drawBleed = false;
if (m_doc->bleeds()->hasNonZeroValue() && m_doc->guidesPrefs().showBleed)
drawBleed = true;
for (int a = docPageCount; a > -1; a--)
{
if (drawBleed)
m_doc->getBleeds(a, pageBleeds);
int x = static_cast<int>(m_doc->Pages->at(a)->xOffset() - pageBleeds.Left);
int y = static_cast<int>(m_doc->Pages->at(a)->yOffset() - pageBleeds.Top);
int w = static_cast<int>(m_doc->Pages->at(a)->width() + pageBleeds.Left + pageBleeds.Right);
int h = static_cast<int>(m_doc->Pages->at(a)->height() + pageBleeds.Bottom + pageBleeds.Top);
if (QRect(x, y, w, h).contains(MxpS, MypS))
{
pgNum = static_cast<int>(a);
if (drawBleed) // check again if its really on the correct page
{
for (int a2 = docPageCount; a2 > -1; a2--)
{
int xn = static_cast<int>(m_doc->Pages->at(a2)->xOffset());
int yn = static_cast<int>(m_doc->Pages->at(a2)->yOffset());
int wn = static_cast<int>(m_doc->Pages->at(a2)->width());
int hn = static_cast<int>(m_doc->Pages->at(a2)->height());
if (QRect(xn, yn, wn, hn).contains(MxpS, MypS))
{
pgNum = static_cast<int>(a2);
break;
}
}
}
break;
}
}
if (pgNum >= 0)
{
if (m_doc->currentPageNumber() != pgNum)
{
m_doc->setCurrentPage(m_doc->Pages->at(unsigned(pgNum)));
m_view->m_ScMW->slotSetCurrentPage(unsigned(pgNum));
pageChanged = true;
}
}
m_view->setRulerPos(m_view->contentsX(), m_view->contentsY());
}
currItem = NULL;
if ((m->modifiers() & SELECT_BENEATH) != 0)
{
for (int i=0; i < m_doc->m_Selection->count(); ++i)
{
if (m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), m_doc->m_Selection->itemAt(i)) >= 0)
{
currItem = m_doc->m_Selection->itemAt(i);
m_doc->m_Selection->removeItem(currItem);
break;
}
}
}
else if ( (m->modifiers() & SELECT_MULTIPLE) == Qt::NoModifier)
{
m_view->Deselect(false);
}
currItem = m_canvas->itemUnderCursor(m->globalPos(), currItem, ((m->modifiers() & SELECT_IN_GROUP) || (m_doc->drawAsPreview && !m_doc->editOnPreview)));
if (currItem)
{
m_doc->m_Selection->delaySignalsOn();
if (m_doc->m_Selection->containsItem(currItem))
{
m_doc->m_Selection->removeItem(currItem);
}
else
{
//CB: If we have a selection but the user clicks with control on another item that is not below the current
//then clear and select the new item
if ((m->modifiers() == SELECT_BENEATH) && m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), currItem) >= 0)
m_doc->m_Selection->clear();
//CB: #7186: This was prependItem, does not seem to need to be anymore with current select code
if (m_doc->drawAsPreview && !m_doc->editOnPreview)
m_doc->m_Selection->clear();
m_doc->m_Selection->addItem(currItem);
if (((m->modifiers() & SELECT_IN_GROUP) || (m_doc->drawAsPreview && !m_doc->editOnPreview)) && (!currItem->isGroup()))
{
currItem->isSingleSel = true;
}
}
if(pageChanged)
{
m_canvas->setForcedRedraw(true);
m_canvas->update();
}
else
m_canvas->update();
m_doc->m_Selection->delaySignalsOff();
if (m_doc->m_Selection->count() > 1)
{
m_doc->beginUpdate();
for (int aa = 0; aa < m_doc->m_Selection->count(); ++aa)
{
PageItem *bb = m_doc->m_Selection->itemAt(aa);
bb->update();
}
m_doc->endUpdate();
m_doc->m_Selection->setGroupRect();
double x, y, w, h;
m_doc->m_Selection->getGroupRect(&x, &y, &w, &h);
m_view->getGroupRectScreen(&x, &y, &w, &h);
}
if (previousSelectedItem != NULL)
{
if (currItem != previousSelectedItem)
{
handleFocusOut(previousSelectedItem);
handleFocusIn(currItem);
}
}
else
handleFocusIn(currItem);
return true;
}
if ((m_doc->guidesPrefs().guidesShown) /*&& (!m_doc->GuideLock)*/ && (m_doc->OnPage(MxpS, MypS) != -1))
{
if (!guideMoveGesture)
{
guideMoveGesture = new RulerGesture(m_view, RulerGesture::HORIZONTAL);
connect(guideMoveGesture,SIGNAL(guideInfo(int, qreal)), m_ScMW->alignDistributePalette,SLOT(setGuide(int, qreal)));
}
if ( (!m_doc->GuideLock) && (guideMoveGesture->mouseHitsGuide(mousePointDoc)) )
{
m_view->startGesture(guideMoveGesture);
guideMoveGesture->mouseMoveEvent(m);
m_doc->m_Selection->connectItemToGUI();
return true;
}
else
{
// If we call startGesture now, a new guide is created each time.
// ### could be a weakness to avoid calling it tho.
// m_view->startGesture(guideMoveGesture);
guideMoveGesture->mouseSelectGuide(m);
}
}
m_doc->m_Selection->connectItemToGUI();
if ( !(m->modifiers() & SELECT_MULTIPLE))
{
if(m_doc->m_Selection->isEmpty())
{
m_canvas->setForcedRedraw(true);
m_canvas->update();
}
else
m_view->Deselect(true);
}
if (previousSelectedItem != NULL)
handleFocusOut(previousSelectedItem);
return false;
}
 
void CanvasMode_Normal::importToPage()
{
QString fileName;
QString allFormats = tr("All Supported Formats")+" (";
QStringList formats;
int fmtCode = FORMATID_FIRSTUSER;
const FileFormat *fmt = LoadSavePlugin::getFormatById(fmtCode);
while (fmt != 0)
{
if (fmt->load)
{
formats.append(fmt->filter);
int an = fmt->filter.indexOf("(");
int en = fmt->filter.indexOf(")");
while (an != -1)
{
allFormats += fmt->filter.mid(an+1, en-an-1)+" ";
an = fmt->filter.indexOf("(", en);
en = fmt->filter.indexOf(")", an);
}
}
fmtCode++;
fmt = LoadSavePlugin::getFormatById(fmtCode);
}
allFormats += "*.sce *.SCE);;";
formats.append("Scribus Objects (*.sce *.SCE)");
qSort(formats);
allFormats += formats.join(";;");
PrefsContext* dirs = PrefsManager::instance()->prefsFile->getContext("dirs");
QString wdir = dirs->get("pastefile", ".");
FPoint pastePoint = m_mouseCurrentPoint;
CustomFDialog dia(m_view, wdir, tr("Open"), allFormats, fdExistingFiles | fdShowImportOptions);
if (dia.exec() == QDialog::Accepted)
fileName = dia.selectedFile();
else
return;
if (!fileName.isEmpty())
{
PrefsManager::instance()->prefsFile->getContext("dirs")->set("pastefile", fileName.left(fileName.lastIndexOf("/")));
m_doc->setLoading(true);
QFileInfo fi(fileName);
bool savedAlignGrid = m_doc->SnapGrid;
bool savedAlignGuides = m_doc->SnapGuides;
bool savedAlignElement = m_doc->SnapElement;
m_doc->SnapElement = false;
m_doc->SnapGrid = false;
m_doc->SnapGuides = false;
if (fi.suffix().toLower() == "sce")
m_ScMW->slotElemRead(fileName, pastePoint.x(), pastePoint.y(), true, false, m_doc, m_doc->view());
else
{
m_doc->dontResize = true;
FileLoader *fileLoader = new FileLoader(fileName);
int testResult = fileLoader->testFile();
delete fileLoader;
if ((testResult != -1) && (testResult >= FORMATID_FIRSTUSER))
{
const FileFormat * fmt = LoadSavePlugin::getFormatById(testResult);
if( fmt )
{
fmt->loadFile(fileName, LoadSavePlugin::lfUseCurrentPage|LoadSavePlugin::lfInteractive|LoadSavePlugin::lfScripted);
}
}
m_doc->dontResize = false;
}
for (int a = 0; a < m_doc->m_Selection->count(); ++a)
{
PageItem *currItem = m_doc->m_Selection->itemAt(a);
currItem->LayerID = m_doc->activeLayer();
}
if (m_doc->m_Selection->count() > 0)
{
PageItem *newItem = m_doc->m_Selection->itemAt(0);
if (dia.TxCodeM->currentIndex() == 1)
{
if ((newItem->width() > m_doc->currentPage()->width()) || (newItem->height() > m_doc->currentPage()->height()))
m_doc->rescaleGroup(newItem, qMin(qMin(m_doc->currentPage()->width() / newItem->width(), m_doc->currentPage()->height() / newItem->height()), 1.0));
}
else if (dia.TxCodeM->currentIndex() == 2)
{
m_doc->rescaleGroup(newItem, qMax(qMin(m_doc->currentPage()->width() / newItem->width(), m_doc->currentPage()->height() / newItem->height()), 1.0));
}
double x2, y2, w, h;
m_doc->m_Selection->getGroupRect(&x2, &y2, &w, &h);
m_doc->moveGroup(pastePoint.x() - x2, pastePoint.y() - y2);
m_ScMW->requestUpdate(reqColorsUpdate | reqSymbolsUpdate | reqLineStylesUpdate | reqTextStylesUpdate);
}
m_doc->SnapGrid = savedAlignGrid;
m_doc->SnapGuides = savedAlignGuides;
m_doc->SnapElement = savedAlignElement;
m_doc->setLoading(false);
m_doc->view()->DrawNew();
if (m_doc->m_Selection->count() > 0)
{
m_doc->m_Selection->connectItemToGUI();
m_ScMW->HaveNewSel();
}
}
}
 
void CanvasMode_Normal::createContextMenu(PageItem* currItem, double mx, double my)
{
ContextMenu* cmen=NULL;
// qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
m_view->setObjectUndoMode();
m_mouseCurrentPoint.setXY(mx, my);
if(currItem!=NULL)
cmen = new ContextMenu(*(m_doc->m_Selection), m_ScMW, m_doc);
else
cmen = new ContextMenu(m_ScMW, m_doc, mx, my);
if (cmen)
cmen->exec(QCursor::pos());
m_view->setGlobalUndoMode();
delete cmen;
}
/trunk/Scribus/scribus/collect4output.cpp
99,9 → 99,8
bool created = dir.mkpath(directories[i]);
if (!created)
{
QMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning,
"<qt>" + tr("Cannot create directory:\n%1").arg(directories[i]) + "</qt>",
CommonStrings::tr_OK);
ScMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning,
"<qt>" + tr("Cannot create directory:\n%1").arg(directories[i]) + "</qt>");
return false;
}
}
120,9 → 119,8
if (!collectItems())
{
QString errorMsg( tr("Cannot collect all files for output for file:\n%1").arg(newName) );
QMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning,
"<qt>" + errorMsg + "</qt>",
CommonStrings::tr_OK);
ScMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning,
"<qt>" + errorMsg + "</qt>");
return errorMsg;
}
 
135,7 → 133,7
if (!collectDocument())
{
QString errorMsg( tr("Cannot collect the file: \n%1").arg(newName) );
QMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning, "<qt>" + errorMsg + "</qt>", CommonStrings::tr_OK);
ScMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning, "<qt>" + errorMsg + "</qt>");
return errorMsg;
}
 
/trunk/Scribus/scribus/fileloader.cpp
481,7 → 481,7
{
mess += it.key() + tr(" was replaced by: ")+ it.value() +"\n";
}
QMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning, mess, 1, 0, 0);
ScMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning, mess);
}
}
 
/trunk/Scribus/scribus/latexhelpers.cpp
1,474 → 1,474
/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/
/***************************************************************************
latexhelpers.cpp - description
-------------------
copyright : Scribus Team
***************************************************************************/
 
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
 
 
#include "latexhelpers.h"
 
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QMessageBox>
 
#include "prefsmanager.h"
#include "scpaths.h"
 
 
LatexHighlighter::LatexHighlighter(QTextDocument *document)
: QSyntaxHighlighter(document)
{
rules = 0;
}
 
void LatexHighlighter::highlightBlock(const QString &text)
{
//This is required to fix a Qt incompatibility. See error message below for details.
static bool disable_highlighting = false;
if (disable_highlighting) return;
 
if (!rules) return;
foreach (LatexHighlighterRule *rule, *rules)
{
int index = text.indexOf(rule->regex);
while (index >= 0) {
int length;
if (rule->regex.captureCount() == 0)
{
length = rule->regex.matchedLength();
}
else
{
length = rule->regex.cap(1).length();
index = rule->regex.pos(1);
}
if (length == 0)
{
qWarning() << "Highlighter pattern" << rule->regex.pattern() << "matched a zero length string. This would lead to an infinite loop. Aborting. Please fix this pattern!";
break;
}
setFormat(index, length, rule->format);
int oldindex = index;
int offset = index + length;
index = text.indexOf(rule->regex, offset);
if (index >= 0 && (index == oldindex || index <= offset)) {
qWarning() << QObject::tr("Highlighter error: Invalid index returned by Qt's QString.indexOf(). This is a incompatibility between different Qt versions and it can only be fixed by recompiling Scribus with the same Qt version that is running on this system. Syntax highlighting is disabled now, but render frames should continue to work without problems.") << "Additional debugging info: old index:" << oldindex << "new index:"<< index << "offset:" << offset;
disable_highlighting = true;
return;
}
}
}
}
 
QString LatexConfigParser::configBase()
{
return ScPaths::instance().shareDir() + "/editorconfig/";
}
 
QString LatexConfigParser::absoluteFilename(QString fn)
{
QFileInfo fi(fn);
if (!fi.exists())
return configBase() + fn;
else
return fn;
}
 
//TODO: Pass this information to LatexEditor, so the second parser can be removed
bool LatexConfigParser::parseConfigFile(QString fn)
{
fn = absoluteFilename(fn);
m_error = "";
m_filename = fn;
QFile f(fn);
if (!f.open(QIODevice::ReadOnly))
{
QMessageBox::critical(0, QObject::tr("Error"), "<qt>" +
QObject::tr("Opening the configfile %1 failed! %2").arg(
fn, f.errorString())
+ "</qt>", 1, 0, 0);
}
xml.setDevice(&f);
while (!xml.atEnd())
{
xml.readNext();
if (xml.isWhitespace() || xml.isComment() || xml.isStartDocument() || xml.isEndDocument())
continue;
if (xml.isStartElement() && xml.name() == "editorsettings")
{
m_description = xml.attributes().value("description").toString();
m_icon = xml.attributes().value("icon").toString();
if (m_description.isEmpty())
m_description = fn;
parseElements();
}
else
formatError("Unexpected element at root level"+xml.name().toString()+", Token String: "+ xml.tokenString());
}
if (xml.hasError())
formatError(xml.errorString());
f.close();
if (!m_error.isEmpty())
return false;
return true;
}
 
void LatexConfigParser::parseElements()
{
while (!xml.atEnd())
{
xml.readNext();
if (xml.isEndElement() && xml.name() == "editorsettings") break;
if (xml.isWhitespace() || xml.isComment() || xml.isEndElement()) continue;
if (!xml.isStartElement())
{
formatError("Unexpected element in <editorsettings>"+xml.name().toString()+", Token String: "+
xml.tokenString());
continue;
}
if (xml.name() == "executable") {
m_executable = xml.attributes().value("command").toString();
} else if (xml.name() == "imagefile") {
m_imageExtension = xml.attributes().value("extension").toString();
} else if (xml.name() == "highlighter") {
parseHighlighter();
} else if (xml.name() == "empty-frame-text") {
m_emptyFrameText = xml.readI18nText(true);
} else if (xml.name() == "preamble") {
m_preamble = xml.readElementText();
} else if (xml.name() == "postamble") {
m_postamble = xml.readElementText();
} else if (xml.name() == "tab") {
parseTab();
} else {
formatError("Unknown tag in <editorsettings>: "+xml.name().toString());
}
}
}
 
void LatexConfigParser::formatError(QString message)
{
QString new_error = QString::number(xml.lineNumber()) + ":" +
QString::number(xml.columnNumber()) + ":" + message;
qWarning() << m_filename << new_error;
m_error += new_error + "\n";
}
 
bool LatexConfigParser::StrRefToBool(const QStringRef &str) const
{
if (str == "1" || str == "true")
return true;
if (str == "0" || str == "false" || str.isEmpty())
return false;
qWarning() << "Invalid bool string:" << str.toString();
return false;
}
 
void LatexConfigParser::parseHighlighter()
{
foreach (LatexHighlighterRule *rule, highlighterRules)
delete rule;
highlighterRules.clear();
while (!xml.atEnd()) {
xml.readNext();
if (xml.isWhitespace() || xml.isComment())
continue;
if (xml.isEndElement() && xml.name() == "highlighter")
break;
if (xml.isEndElement() && xml.name() == "rule")
continue;
if (!xml.isStartElement() || xml.name() != "rule")
{
formatError("Unexpected element in <highlighter>: "+
xml.name().toString()+", Token String: "+
xml.tokenString());
continue;
}
QString regex = xml.attributes().value("regex").toString();
bool bold = StrRefToBool(xml.attributes().value("bold"));
bool italic = StrRefToBool(xml.attributes().value("italic"));
bool underline = StrRefToBool(xml.attributes().value("underline"));
bool minimal = StrRefToBool(xml.attributes().value("minimal"));
QString colorStr = xml.attributes().value("color").toString();
QColor color(colorStr);
if (!color.isValid())
{
color.fromRgb(0, 0, 0); //Black
if (!colorStr.isEmpty())
qWarning() << "Invalid color:" << colorStr;
}
LatexHighlighterRule *newRule = new LatexHighlighterRule();
newRule->format.setForeground(color);
newRule->format.setFontItalic(italic);
if (bold)
newRule->format.setFontWeight(QFont::Bold);
newRule->format.setFontUnderline(underline);
newRule->regex.setPattern(regex);
newRule->regex.setMinimal(minimal);
highlighterRules.append(newRule);
}
}
 
 
void LatexConfigParser::parseTab()
{
QString type = xml.attributes().value("type").toString();
bool itemstab = (type == "items");
QString title = "";
QString name, text, default_value;
while (!xml.atEnd())
{
xml.readNext();
if (xml.isWhitespace() || xml.isComment()) continue;
if (xml.isEndElement() && xml.name() == "tab") break;
if (!xml.isStartElement())
{
formatError("Unexpected element in <tab>: "+xml.name().toString()+", Token String: "+
xml.tokenString());
continue;
}
if (xml.name() == "title")
{
if (!title.isEmpty())
formatError("Second <title> tag in <tab>");
title = xml.readI18nText();
}
else if (xml.name() == "item")
{
if (!itemstab)
formatError("Found <item> in a 'settings'-tab!");
QString value = xml.attributes().value("value").toString();
QString img = xml.attributes().value("image").toString();
text = xml.readI18nText();
}
else if (xml.name() == "comment" || xml.name() == "font"
|| xml.name() == "spinbox" || xml.name() == "color"
|| xml.name() == "text" || xml.name() == "list")
{
//TODO: Store this + attributes in a list
QString tagname = xml.name().toString();
name = xml.attributes().value("name").toString();
default_value = xml.attributes().value("default").toString();
if (xml.name() != "list")
text = xml.readI18nText();
else
ignoreList();
if (!name.isEmpty())
{
if (properties.contains(name))
formatError("Redeclared setting with name: " + name);
else
properties.insert(name, default_value);
}
//TODO: qDebug() << "For future use:" << tagname << name << text << default_value;
}
else
formatError("Unexpected element in <tab>: " + xml.name().toString());
}
if (title.isEmpty())
formatError("Tab ended here, but no title was found!");
}
 
void LatexConfigParser::ignoreList()
{
//TODO: Quick hack to avoid real parsing
while (!xml.atEnd())
{
xml.readNext();
if (xml.isEndElement() && xml.name() == "list") break;
}
}
 
QString LatexConfigParser::executable() const
{
QFileInfo f(m_filename);
QString fileName=f.fileName();
QString command = PrefsManager::instance()->latexCommands()[fileName];
if (command.isEmpty())
return m_executable;
else
return command;
}
 
QString I18nXmlStreamReader::readI18nText(bool unindent)
{
QString language = PrefsManager::instance()->uiLanguage();
QString result;
int matchquality = 0;
bool i18n = false;
if (!isStartElement()) raiseError("readI18nText called without startelement!");
QString startTag = name().toString();
while (!atEnd()) {
readNext();
if (isWhitespace() || isComment()) continue;
if (isStartElement() && name() == startTag) {
raiseError("Invalid nested elements.");
return "Error";
}
if (isEndElement() && name() == startTag) {
if (!unindent) {
return result.trimmed();
} else {
QStringList splitted = result.split("\n");
int i;
int minspaces = 0xffff;
/* NOTE: First line contains no leading whitespace so we start at 1 */
for (i = 1; i < splitted.size(); i++) {
if (splitted[i].trimmed().isEmpty()) continue;
int spaces;
QString tmp = splitted[i];
for (spaces = 0; spaces < tmp.length(); spaces++) {
if (!tmp[spaces].isSpace()) break;
}
if (spaces < minspaces) minspaces = spaces;
}
for (i = 1; i < splitted.size(); i++) {
splitted[i] = splitted[i].mid(minspaces);
}
return splitted.join("\n").trimmed();
}
}
if (i18n) {
if (isEndElement()) {
if (name() == "i18n") {
i18n = false;
} else {
raiseError("Invalid end element "+ name().toString());
}
continue;
}
if (!isStartElement()) {
raiseError("Unexpected data!");
}
if (name() == language) {
matchquality = 2; //Perfect match
result = readElementText();
} else if (language.startsWith(name().toString()) && matchquality <= 1) {
matchquality = 1; //Only beginning part matches
result = readElementText();
} else if (result.isEmpty()) {
matchquality = 0;
result = readElementText();
} else {
readElementText(); //Ignore the text
}
} else {
if (isStartElement()) {
if (name() == "i18n") {
i18n = true;
continue;
} else {
raiseError("Tag " + name().toString() +
"found, but \"i18n\" or string data expected.");
continue;
}
} else if (isCharacters()) {
result = result + text().toString();
}
}
}
raiseError("Unexpected end of XML file");
return result;
}
 
LatexConfigCache* LatexConfigCache::_instance = 0;
 
LatexConfigCache* LatexConfigCache::instance()
{
if (!_instance)
_instance = new LatexConfigCache();
return _instance;
}
 
LatexConfigParser* LatexConfigCache::parser(QString filename, bool warnOnError)
{
if (parsers.contains(filename))
{
if (warnOnError && error[filename])
{
//Recreate element as error might have been fixed.
delete parsers[filename];
createParser(filename, warnOnError);
}
}
else
createParser(filename, warnOnError);
return parsers[filename];
}
 
 
void LatexConfigCache::createParser(QString filename, bool warnOnError)
{
LatexConfigParser *parser = new LatexConfigParser();
bool hasError = !parser->parseConfigFile(filename);
parsers[filename] = parser;
error[filename] = hasError;
if (hasError)
{
QMessageBox::critical(0, QObject::tr("Error"), "<qt>" +
QObject::tr("Parsing the configfile %1 failed! Depending on the type of the error "
"render frames might not work correctly!\n%2").arg(
filename, parser->error())
+ "</qt>", 1, 0, 0);
}
}
 
bool LatexConfigCache::hasError(QString filename)
{
if (!error.contains(filename))
return true;
return error[filename];
}
 
QStringList LatexConfigCache::defaultConfigs()
{
QDir dir(LatexConfigParser::configBase());
QStringList files;
files = dir.entryList(QStringList("*.xml"));
files.sort();
int i;
for (i = 0; i < files.size(); i++)
{
if (files[i].compare("sample.xml",Qt::CaseInsensitive)==0)
{
files.removeAt(i);
i--;
}
}
return files;
}
 
QMap<QString, QString> LatexConfigCache::defaultCommands()
{
QStringList configFiles = PrefsManager::instance()->latexConfigs();
QMap<QString, QString> configCmds;
foreach (QString configFile, configFiles)
{
LatexConfigParser *config = LatexConfigCache::instance()->parser(configFile);
configCmds.insert(configFile, config->executable());
}
return configCmds;
}
/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/
/***************************************************************************
latexhelpers.cpp - description
-------------------
copyright : Scribus Team
***************************************************************************/
 
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
 
 
#include "latexhelpers.h"
 
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QMessageBox>
 
#include "prefsmanager.h"
#include "scpaths.h"
#include "ui/scmessagebox.h"
 
LatexHighlighter::LatexHighlighter(QTextDocument *document)
: QSyntaxHighlighter(document)
{
rules = 0;
}
 
void LatexHighlighter::highlightBlock(const QString &text)
{
//This is required to fix a Qt incompatibility. See error message below for details.
static bool disable_highlighting = false;
if (disable_highlighting) return;
 
if (!rules) return;
foreach (LatexHighlighterRule *rule, *rules)
{
int index = text.indexOf(rule->regex);
while (index >= 0) {
int length;
if (rule->regex.captureCount() == 0)
{
length = rule->regex.matchedLength();
}
else
{
length = rule->regex.cap(1).length();
index = rule->regex.pos(1);
}
if (length == 0)
{
qWarning() << "Highlighter pattern" << rule->regex.pattern() << "matched a zero length string. This would lead to an infinite loop. Aborting. Please fix this pattern!";
break;
}
setFormat(index, length, rule->format);
int oldindex = index;
int offset = index + length;
index = text.indexOf(rule->regex, offset);
if (index >= 0 && (index == oldindex || index <= offset)) {
qWarning() << QObject::tr("Highlighter error: Invalid index returned by Qt's QString.indexOf(). This is a incompatibility between different Qt versions and it can only be fixed by recompiling Scribus with the same Qt version that is running on this system. Syntax highlighting is disabled now, but render frames should continue to work without problems.") << "Additional debugging info: old index:" << oldindex << "new index:"<< index << "offset:" << offset;
disable_highlighting = true;
return;
}
}
}
}
 
QString LatexConfigParser::configBase()
{
return ScPaths::instance().shareDir() + "/editorconfig/";
}
 
QString LatexConfigParser::absoluteFilename(QString fn)
{
QFileInfo fi(fn);
if (!fi.exists())
return configBase() + fn;
else
return fn;
}
 
//TODO: Pass this information to LatexEditor, so the second parser can be removed
bool LatexConfigParser::parseConfigFile(QString fn)
{
fn = absoluteFilename(fn);
m_error = "";
m_filename = fn;
QFile f(fn);
if (!f.open(QIODevice::ReadOnly))
{
ScMessageBox::critical(0, QObject::tr("Error"), "<qt>" +
QObject::tr("Opening the configfile %1 failed! %2").arg(
fn, f.errorString())
+ "</qt>");
}
xml.setDevice(&f);
while (!xml.atEnd())
{
xml.readNext();
if (xml.isWhitespace() || xml.isComment() || xml.isStartDocument() || xml.isEndDocument())
continue;
if (xml.isStartElement() && xml.name() == "editorsettings")
{
m_description = xml.attributes().value("description").toString();
m_icon = xml.attributes().value("icon").toString();
if (m_description.isEmpty())
m_description = fn;
parseElements();
}
else
formatError("Unexpected element at root level"+xml.name().toString()+", Token String: "+ xml.tokenString());
}
if (xml.hasError())
formatError(xml.errorString());
f.close();
if (!m_error.isEmpty())
return false;
return true;
}
 
void LatexConfigParser::parseElements()
{
while (!xml.atEnd())
{
xml.readNext();
if (xml.isEndElement() && xml.name() == "editorsettings") break;
if (xml.isWhitespace() || xml.isComment() || xml.isEndElement()) continue;
if (!xml.isStartElement())
{
formatError("Unexpected element in <editorsettings>"+xml.name().toString()+", Token String: "+
xml.tokenString());
continue;
}
if (xml.name() == "executable") {
m_executable = xml.attributes().value("command").toString();
} else if (xml.name() == "imagefile") {
m_imageExtension = xml.attributes().value("extension").toString();
} else if (xml.name() == "highlighter") {
parseHighlighter();
} else if (xml.name() == "empty-frame-text") {
m_emptyFrameText = xml.readI18nText(true);
} else if (xml.name() == "preamble") {
m_preamble = xml.readElementText();
} else if (xml.name() == "postamble") {
m_postamble = xml.readElementText();
} else if (xml.name() == "tab") {
parseTab();
} else {
formatError("Unknown tag in <editorsettings>: "+xml.name().toString());
}
}
}
 
void LatexConfigParser::formatError(QString message)
{
QString new_error = QString::number(xml.lineNumber()) + ":" +
QString::number(xml.columnNumber()) + ":" + message;
qWarning() << m_filename << new_error;
m_error += new_error + "\n";
}
 
bool LatexConfigParser::StrRefToBool(const QStringRef &str) const
{
if (str == "1" || str == "true")
return true;
if (str == "0" || str == "false" || str.isEmpty())
return false;
qWarning() << "Invalid bool string:" << str.toString();
return false;
}
 
void LatexConfigParser::parseHighlighter()
{
foreach (LatexHighlighterRule *rule, highlighterRules)
delete rule;
highlighterRules.clear();
while (!xml.atEnd()) {
xml.readNext();
if (xml.isWhitespace() || xml.isComment())
continue;
if (xml.isEndElement() && xml.name() == "highlighter")
break;
if (xml.isEndElement() && xml.name() == "rule")
continue;
if (!xml.isStartElement() || xml.name() != "rule")
{
formatError("Unexpected element in <highlighter>: "+
xml.name().toString()+", Token String: "+
xml.tokenString());
continue;
}
QString regex = xml.attributes().value("regex").toString();
bool bold = StrRefToBool(xml.attributes().value("bold"));
bool italic = StrRefToBool(xml.attributes().value("italic"));
bool underline = StrRefToBool(xml.attributes().value("underline"));
bool minimal = StrRefToBool(xml.attributes().value("minimal"));
QString colorStr = xml.attributes().value("color").toString();
QColor color(colorStr);
if (!color.isValid())
{
color.fromRgb(0, 0, 0); //Black
if (!colorStr.isEmpty())
qWarning() << "Invalid color:" << colorStr;
}
LatexHighlighterRule *newRule = new LatexHighlighterRule();
newRule->format.setForeground(color);
newRule->format.setFontItalic(italic);
if (bold)
newRule->format.setFontWeight(QFont::Bold);
newRule->format.setFontUnderline(underline);
newRule->regex.setPattern(regex);
newRule->regex.setMinimal(minimal);
highlighterRules.append(newRule);
}
}
 
 
void LatexConfigParser::parseTab()
{
QString type = xml.attributes().value("type").toString();
bool itemstab = (type == "items");
QString title = "";
QString name, text, default_value;
while (!xml.atEnd())
{
xml.readNext();
if (xml.isWhitespace() || xml.isComment()) continue;
if (xml.isEndElement() && xml.name() == "tab") break;
if (!xml.isStartElement())
{
formatError("Unexpected element in <tab>: "+xml.name().toString()+", Token String: "+
xml.tokenString());
continue;
}
if (xml.name() == "title")
{
if (!title.isEmpty())
formatError("Second <title> tag in <tab>");
title = xml.readI18nText();
}
else if (xml.name() == "item")
{
if (!itemstab)
formatError("Found <item> in a 'settings'-tab!");
QString value = xml.attributes().value("value").toString();
QString img = xml.attributes().value("image").toString();
text = xml.readI18nText();
}
else if (xml.name() == "comment" || xml.name() == "font"
|| xml.name() == "spinbox" || xml.name() == "color"
|| xml.name() == "text" || xml.name() == "list")
{
//TODO: Store this + attributes in a list
QString tagname = xml.name().toString();
name = xml.attributes().value("name").toString();
default_value = xml.attributes().value("default").toString();
if (xml.name() != "list")
text = xml.readI18nText();
else
ignoreList();
if (!name.isEmpty())
{
if (properties.contains(name))
formatError("Redeclared setting with name: " + name);
else
properties.insert(name, default_value);
}
//TODO: qDebug() << "For future use:" << tagname << name << text << default_value;
}
else
formatError("Unexpected element in <tab>: " + xml.name().toString());
}
if (title.isEmpty())
formatError("Tab ended here, but no title was found!");
}
 
void LatexConfigParser::ignoreList()
{
//TODO: Quick hack to avoid real parsing
while (!xml.atEnd())
{
xml.readNext();
if (xml.isEndElement() && xml.name() == "list") break;
}
}
 
QString LatexConfigParser::executable() const
{
QFileInfo f(m_filename);
QString fileName=f.fileName();
QString command = PrefsManager::instance()->latexCommands()[fileName];
if (command.isEmpty())
return m_executable;
else
return command;
}
 
QString I18nXmlStreamReader::readI18nText(bool unindent)
{
QString language = PrefsManager::instance()->uiLanguage();
QString result;
int matchquality = 0;
bool i18n = false;
if (!isStartElement()) raiseError("readI18nText called without startelement!");
QString startTag = name().toString();
while (!atEnd()) {
readNext();
if (isWhitespace() || isComment()) continue;
if (isStartElement() && name() == startTag) {
raiseError("Invalid nested elements.");
return "Error";
}
if (isEndElement() && name() == startTag) {
if (!unindent) {
return result.trimmed();
} else {
QStringList splitted = result.split("\n");
int i;
int minspaces = 0xffff;
/* NOTE: First line contains no leading whitespace so we start at 1 */
for (i = 1; i < splitted.size(); i++) {
if (splitted[i].trimmed().isEmpty()) continue;
int spaces;
QString tmp = splitted[i];
for (spaces = 0; spaces < tmp.length(); spaces++) {
if (!tmp[spaces].isSpace()) break;
}
if (spaces < minspaces) minspaces = spaces;
}
for (i = 1; i < splitted.size(); i++) {
splitted[i] = splitted[i].mid(minspaces);
}
return splitted.join("\n").trimmed();
}
}
if (i18n) {
if (isEndElement()) {
if (name() == "i18n") {
i18n = false;
} else {
raiseError("Invalid end element "+ name().toString());
}
continue;
}
if (!isStartElement()) {
raiseError("Unexpected data!");
}
if (name() == language) {
matchquality = 2; //Perfect match
result = readElementText();
} else if (language.startsWith(name().toString()) && matchquality <= 1) {
matchquality = 1; //Only beginning part matches
result = readElementText();
} else if (result.isEmpty()) {
matchquality = 0;
result = readElementText();
} else {
readElementText(); //Ignore the text
}
} else {
if (isStartElement()) {
if (name() == "i18n") {
i18n = true;
continue;
} else {
raiseError("Tag " + name().toString() +
"found, but \"i18n\" or string data expected.");
continue;
}
} else if (isCharacters()) {
result = result + text().toString();
}
}
}
raiseError("Unexpected end of XML file");
return result;
}
 
LatexConfigCache* LatexConfigCache::_instance = 0;
 
LatexConfigCache* LatexConfigCache::instance()
{
if (!_instance)
_instance = new LatexConfigCache();
return _instance;
}
 
LatexConfigParser* LatexConfigCache::parser(QString filename, bool warnOnError)
{
if (parsers.contains(filename))
{
if (warnOnError && error[filename])
{
//Recreate element as error might have been fixed.
delete parsers[filename];
createParser(filename, warnOnError);
}
}
else
createParser(filename, warnOnError);
return parsers[filename];
}
 
 
void LatexConfigCache::createParser(QString filename, bool warnOnError)
{
LatexConfigParser *parser = new LatexConfigParser();
bool hasError = !parser->parseConfigFile(filename);
parsers[filename] = parser;
error[filename] = hasError;
if (hasError)
{
ScMessageBox::critical(0, QObject::tr("Error"), "<qt>" +
QObject::tr("Parsing the configfile %1 failed! Depending on the type of the error "
"render frames might not work correctly!\n%2").arg(
filename, parser->error())
+ "</qt>");
}
}
 
bool LatexConfigCache::hasError(QString filename)
{
if (!error.contains(filename))
return true;
return error[filename];
}
 
QStringList LatexConfigCache::defaultConfigs()
{
QDir dir(LatexConfigParser::configBase());
QStringList files;
files = dir.entryList(QStringList("*.xml"));
files.sort();
int i;
for (i = 0; i < files.size(); i++)
{
if (files[i].compare("sample.xml",Qt::CaseInsensitive)==0)
{
files.removeAt(i);
i--;
}
}
return files;
}
 
QMap<QString, QString> LatexConfigCache::defaultCommands()
{
QStringList configFiles = PrefsManager::instance()->latexConfigs();
QMap<QString, QString> configCmds;
foreach (QString configFile, configFiles)
{
LatexConfigParser *config = LatexConfigCache::instance()->parser(configFile);
configCmds.insert(configFile, config->executable());
}
return configCmds;
}
/trunk/Scribus/scribus/loadsaveplugin.cpp
442,8 → 442,7
{
if (ScCore->usingGUI())
{
QMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning,
plug->lastError(), CommonStrings::tr_OK);
ScMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning, plug->lastError());
}
else
{
509,8 → 508,7
{
if (ScCore->usingGUI())
{
QMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning,
plug->lastError(), CommonStrings::tr_OK);
ScMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning, plug->lastError());
}
else
{
/trunk/Scribus/scribus/main_nix.cpp
133,7 → 133,7
if (ScribusQApp::useGUI)
{
ScCore->closeSplash();
QMessageBox::critical(ScMW, sigHdr, sigMsg, QObject::tr("&OK"));
ScMessageBox::critical(ScMW, sigHdr, sigMsg);
ScMW->emergencySave();
ScMW->close();
}
/trunk/Scribus/scribus/main_win32.cpp
287,7 → 287,7
if (ScribusQApp::useGUI)
{
ScCore->closeSplash();
QMessageBox::critical(ScMW, expHdr, expMsg, QObject::tr("&OK"));
ScMessageBox::critical(ScMW, expHdr, expMsg);
ScMW->emergencySave();
ScMW->close();
}
325,7 → 325,7
ScCore->closeSplash();
QString expHdr = QObject::tr("Scribus Crash");
QString expMsg = msg;
QMessageBox::critical(ScMW, expHdr, expMsg, QObject::tr("&OK"));
ScMessageBox::critical(ScMW, expHdr, expMsg);
ScMW->emergencySave();
ScMW->close();
}
/trunk/Scribus/scribus/pageitem_latexframe.cpp
1,588 → 1,588
/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/
/***************************************************************************
pageitem_latexframe.cpp - description
-------------------
begin : Mon May 28 2007
copyright : (C) 2007 by Hermann Kraus
email : hermann@physiklaborant.de
***************************************************************************/
 
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
 
#include "pageitem_latexframe.h"
 
#include <QDebug>
#include <QMessageBox>
#include <QTemporaryFile>
 
#include "prefsmanager.h"
#include "scpainter.h"
#include "scraction.h"
#include "scribus.h"
#include "scribusdoc.h"
#include "undomanager.h"
#include "undostate.h"
#include "ui/latexeditor.h"
#include "latexhelpers.h"
#include "util.h"
 
PageItem_LatexFrame::PageItem_LatexFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, QString fill, QString outline)
: PageItem_ImageFrame(pa, x, y, w, h, w2, fill, outline)
{
setUPixmap(Um::ILatexFrame);
AnName = tr("Render") + QString::number(m_Doc->TotalItems);
setUName(AnName);
imgValid = false;
m_usePreamble = true;
err = 0;
internalEditor = 0;
killed = false;
config = 0;
if (PrefsManager::instance()->latexConfigs().count() > 0)
setConfigFile(PrefsManager::instance()->latexConfigs()[0]);
 
latex = new QProcess();
connect(latex, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(updateImage(int, QProcess::ExitStatus)));
connect(latex, SIGNAL(error(QProcess::ProcessError)), this, SLOT(latexError(QProcess::ProcessError)));
latex->setProcessChannelMode(QProcess::MergedChannels);
QTemporaryFile *tempfile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_render_XXXXXX");
tempfile->open();
tempFileBase = getLongPathName(tempfile->fileName());
tempfile->setAutoRemove(false);
tempfile->close();
delete tempfile;
Q_ASSERT(!tempFileBase.isEmpty());
m_dpi = 0;
}
 
PageItem_LatexFrame::~PageItem_LatexFrame()
{
if (internalEditor) delete internalEditor;
latex->disconnect();
if (latex->state() != QProcess::NotRunning) {
killed = true;
latex->terminate();
latex->waitForFinished(500);
if (latex->state() != QProcess::NotRunning) {
latex->kill();
latex->waitForFinished(500);
}
}
deleteImageFile();
delete latex;
}
 
void PageItem_LatexFrame::clearContents()
{
PageItem_ImageFrame::clearContents();
formulaText = "";
appStdout = "";
err = 0;
imgValid = false;
}
 
void PageItem_LatexFrame::deleteImageFile()
{
QFileInfo fi(tempFileBase);
QDir dir = fi.absoluteDir();
QStringList filter;
filter << fi.fileName() + "*";
Q_ASSERT(!fi.fileName().isEmpty());
Q_ASSERT(!fi.fileName().contains("/"));
Q_ASSERT(!fi.fileName().contains("\\"));
QStringList files;
files = dir.entryList(filter);
foreach (QString file, files) {
Q_ASSERT(file.startsWith("scribus_temp"));
dir.remove(file);
}
imgValid = false;
}
 
void PageItem_LatexFrame::DrawObj_Item(ScPainter *p, QRectF e)
{
layout();
if (!imgValid && !err)
{
//Draw indicator that latex is running
p->setBrush(Qt::white);
p->setPen(Qt::green, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
p->drawLine(FPoint(0, 0), FPoint(m_width, m_height));
p->drawText(QRectF(0.0, 0.0, m_width, m_height), tr("Rendering..."));
}
else if (err)
{
//Draw error indicator
p->setBrush(Qt::white);
p->setPen(Qt::blue, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
p->drawLine(FPoint(0, 0), FPoint(m_width, m_height));
p->drawLine(FPoint(0, m_height), FPoint(m_width, 0));
p->drawText(QRectF(0.0, 0.0, m_width, m_height), tr("Render Error"));
}
else
{
//Just pass it to ImageFrame
PageItem_ImageFrame::DrawObj_Item(p, e);
}
}
 
void PageItem_LatexFrame::updateImage(int exitCode, QProcess::ExitStatus exitStatus)
{
appStdout = latex->readAllStandardOutput();
err = exitCode;
emit latexFinished();
emit stateChanged(latex->state());
static bool firstWarning = true;
if (exitCode) {
imgValid = false;
if (firstWarning && !killed)
{
bool editorRunning = internalEditor && internalEditor->isVisible();
QMessageBox msgBox;
msgBox.setText(tr("Running the external application failed!"));
QString informativeText = tr("This is usually a problem with your input. Please check the program's output.");
if (!editorRunning) {
informativeText += " "+tr("Do you want to open the editor to fix the problem?");
msgBox.setStandardButtons(QMessageBox::Yes|QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::Yes);
} else {
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
}
msgBox.setIcon(QMessageBox::Warning);
msgBox.setInformativeText(informativeText);
msgBox.setDetailedText(output());
if ((msgBox.exec() == QMessageBox::Yes) && !editorRunning) {
runEditor();
}
firstWarning = false;
}
qCritical() << "RENDER FRAME: updateImage():" << tr("Running the external application failed!");
killed = false;
update(); //Show error marker
return;
}
else
{
firstWarning = true;
}
imgValid = true;
 
//Save state and restore afterwards
double xres, yres;
if (PictureIsAvailable)
{
xres = pixm.imgInfo.xres;
yres = pixm.imgInfo.yres;
}
else
{
xres = yres = realDpi();
}
double scaleX = m_imageXScale * xres;
double scaleY = m_imageYScale * yres;
double offX = m_imageXOffset / xres;
double offY = m_imageYOffset / yres;
PageItem_ImageFrame::loadImage(imageFile, true, realDpi());
if (PrefsManager::instance()->latexForceDpi())
{
pixm.imgInfo.xres = pixm.imgInfo.yres = realDpi();
}
//Restore parameters, account for dpi changes
m_imageXScale = scaleX / pixm.imgInfo.xres;
m_imageYScale = scaleY / pixm.imgInfo.yres;
m_imageXOffset = offX * pixm.imgInfo.xres;
m_imageYOffset = offY * pixm.imgInfo.yres;
//emit imageOffsetScale(LocalScX, LocalScY, LocalX, LocalY);
update();
}
 
 
void PageItem_LatexFrame::runApplication()
{
imgValid = false;
err = 0;
killed = false;
static bool firstWarningTmpfile = true;
static bool firstWarningLatexMissing = true;
 
if (!config)
{
qCritical() << "RENDER FRAME:" << tr("No configuration defined to run the application!");
return;
}
QFile tempfile(tempFileBase);
if (!tempfile.open(QIODevice::Truncate|QIODevice::WriteOnly)) {
err = 0xffff;
update(); //Show error marker
if (firstWarningTmpfile)
{
QMessageBox::critical(0, tr("Error"), "<qt>" +
tr("Could not create a temporary file to run the application!")
+ "</qt>", 1, 0, 0);
firstWarningTmpfile = false;
}
qCritical() << "RENDER FRAME:" << tr("Could not create a temporary file to run the application!");
//Don't know how to continue as it's impossible to create tempfile
return;
}
else
{
firstWarningTmpfile = true;
}
QString full_command = config->executable();
if (full_command.isEmpty()) {
err = 0xffff;
update(); //Show error marker
if (firstWarningLatexMissing)
{
QMessageBox::critical(0, tr("Error"),
"<qt>" + tr("The config file didn't specify a executable path!") +
"</qt>",1, 0, 0);
firstWarningLatexMissing = false;
}
qCritical() << "RENDER FRAME:" << tr("The config file didn't specify a executable path!");
return;
}
else
{
firstWarningLatexMissing = true;
}
 
full_command.replace("%dpi", QString::number(realDpi()));
if (full_command.contains("%file")) {
full_command.replace("%file", QString("\"%1\"").arg(QDir::toNativeSeparators(tempFileBase)));
} else {
full_command = full_command + QString(" \"%1\"").arg(QDir::toNativeSeparators(tempFileBase));
}
full_command.replace("%dir", QString("\"%1\"").arg(QDir::toNativeSeparators(QDir::tempPath())));
latex->setWorkingDirectory(QDir::tempPath());
 
double lDpi = realDpi()/72.0;
full_command.replace("$scribus_height_px$", QString::number(qRound(m_height*lDpi)));
full_command.replace("$scribus_width_px$", QString::number(qRound(m_width*lDpi)));
QMapIterator<QString, QString> i(editorProperties);
while (i.hasNext())
{
i.next();
full_command.replace("$scribus_"+i.key()+"$", i.value());
}
imageFile = tempFileBase + config->imageExtension();
 
writeFileContents(&tempfile);
tempfile.close();
latex->start(full_command);
emit stateChanged(QProcess::Starting);
}
 
void PageItem_LatexFrame::runEditor()
{
if (!internalEditor) {
internalEditor = new LatexEditor(this);
internalEditor->startEditor();
} else if (internalEditor->isVisible()) {
internalEditor->activateWindow();
internalEditor->raise();
} else {
internalEditor->startEditor();
}
}
 
void PageItem_LatexFrame::rerunApplication(bool updateDisplay)
{
if (latex->state() != QProcess::NotRunning) {
killed = true;
latex->terminate();
latex->waitForFinished(500);
if (latex->state() != QProcess::NotRunning) {
//Still not terminated?
latex->kill();
latex->waitForFinished(500);
}
}
runApplication();
if (updateDisplay) this->update();
}
 
 
void PageItem_LatexFrame::writeFileContents(QFile *tempfile)
{
QString tmp(formulaText);
double scaleX, scaleY, realW, realH, offsetX, offsetY;
double lDpi = realDpi()/72.0;
scaleX = m_imageXScale*lDpi;
scaleY = m_imageYScale*lDpi;
offsetX = m_imageXOffset*m_imageXScale;
offsetY = m_imageYOffset*m_imageYScale;
realW = m_width/scaleX - m_imageXOffset/lDpi;
realH = m_height/scaleY - m_imageYOffset/lDpi;
if (!tmp.contains("$scribus_noprepost$") && m_usePreamble) {
tmp = config->preamble() + tmp + config->postamble();
}
tmp.replace(QString("$scribus_width$"), QString::number(m_width));
tmp.replace(QString("$scribus_width_px$"), QString::number(qRound(m_width*lDpi)));
tmp.replace(QString("$scribus_width_inch$"), QString::number(m_width/72.0));
tmp.replace(QString("$scribus_height$"), QString::number(m_height));
tmp.replace(QString("$scribus_height_px$"), QString::number(qRound(m_height*lDpi)));
tmp.replace(QString("$scribus_height_inch$"), QString::number(m_height/72.0));
tmp.replace(QString("$scribus_realwidth$"), QString::number(realW));
tmp.replace(QString("$scribus_realwidth_px$"), QString::number(qRound(realW*lDpi)));
tmp.replace(QString("$scribus_realheight$"), QString::number(realH));
tmp.replace(QString("$scribus_realheight_px$"), QString::number(qRound(realH*lDpi)));
tmp.replace(QString("$scribus_offsetX$"), QString::number(offsetX));
tmp.replace(QString("$scribus_offsetX_px$"), QString::number(qRound(offsetX*lDpi)));
tmp.replace(QString("$scribus_offsetY$"), QString::number(offsetY));
tmp.replace(QString("$scribus_offsetY$"), QString::number(qRound(offsetY*lDpi)));
tmp.replace(QString("$scribus_scaleX$"), QString::number(scaleX));
tmp.replace(QString("$scribus_scaleY$"), QString::number(scaleY));
tmp.replace(QString("$scribus_dpi$"), QString::number(realDpi()));
tmp.replace(QString("$scribus_file$"), tempFileBase);
tmp.replace(QString("$scribus_dir$"), QDir::tempPath());
QMapIterator<QString, QString> i(editorProperties);
while (i.hasNext()) {
i.next();
tmp.replace("$scribus_"+i.key()+"$", i.value());
}
tempfile->write(tmp.toUtf8());
}
 
bool PageItem_LatexFrame::setFormula(QString formula, bool undoable)
{
if (formula == formulaText) {
//Nothing changed
return false;
}
imgValid = false;
err = 0;
if (UndoManager::undoEnabled() && undoable)
{
SimpleState *ss = new SimpleState(Um::ChangeFormula, "", Um::IChangeFormula);
ss->set("CHANGE_FORMULA", "change_formula");
ss->set("OLD_FORMULA", formulaText);
ss->set("NEW_FORMULA", formula);
undoManager->action(this, ss);
} else if (!undoable) {
emit formulaAutoUpdate(formulaText, formula);
}
formulaText = formula;
return true;
}
 
void PageItem_LatexFrame::latexError(QProcess::ProcessError error)
{
err = 0xffff;
update(); //Show error marker
static bool firstWarning = true;
if (killed) {
killed = false;
update();
//Don't show errors caused by killing processes
return;
}
if (firstWarning)
{
if (latex->error() == QProcess::FailedToStart) {
QMessageBox::critical(0, tr("Error"), "<qt>" +
tr("The application \"%1\" failed to start! Please check the path: ").
arg(config->executable())
+ "</qt>", 1, 0, 0);
} else {
QMessageBox::critical(0, tr("Error"), "<qt>" +
tr("The application \"%1\" crashed!").arg(config->executable())
+ "</qt>", 1, 0, 0);
}
firstWarning = false;
}
qCritical() << "RENDER FRAME: latexError():" <<
tr("Running the application \"%1\" failed!").arg(config->executable()) << latex->error();
emit stateChanged(QProcess::NotRunning);
}
 
 
QString PageItem_LatexFrame::application() const
{
return config ? config->executable() : tr("No application defined");
}
 
QString PageItem_LatexFrame::configFile() const
{
return configFilename;
}
 
int PageItem_LatexFrame::realDpi() const
{
if (m_dpi) {
return m_dpi;
} else {
return PrefsManager::instance()->latexResolution();
}
}
 
void PageItem_LatexFrame::setDpi(int newDpi)
{
m_dpi = newDpi;
}
 
void PageItem_LatexFrame::setConfigFile(QString newConfig, bool relative)
{
// Try to interpret a config file as a relative path even when it is given with a full path
if (relative)
{
QFileInfo fi;
QStringList configs = PrefsManager::instance()->latexConfigs();
foreach (QString config, configs)
{
fi.setFile(config);
if (newConfig == fi.fileName())
{
newConfig = config;
break;
}
}
}
 
if (configFilename == newConfig) return;
bool unchanged = formulaText.isEmpty();
if (config && (formulaText == config->emptyFrameText())) {
unchanged = true;
}
configFilename = newConfig;
config = LatexConfigCache::instance()->parser(configFilename);
//Initialize with default values
QString key;
QMapIterator<QString, QString> i(config->properties);
while (i.hasNext()) {
i.next();
key = i.key();
if (!editorProperties.contains(key)) {
editorProperties[key] = i.value();
}
}
QString newFormula;
if (unchanged) {
if (PrefsManager::instance()->latexStartWithEmptyFrames()) {
newFormula = "";
} else {
newFormula = config->emptyFrameText();
}
emit formulaAutoUpdate(formulaText, newFormula);
formulaText = newFormula;
}
emit applicationChanged();
}
 
void PageItem_LatexFrame::killProcess()
{
killed = true;
latex->kill();
}
 
void PageItem_LatexFrame::restore(UndoState *state, bool isUndo)
{
SimpleState *ss = dynamic_cast<SimpleState*>(state);
if (!ss) {
PageItem_ImageFrame::restore(state, isUndo);
return;
}
if (ss->contains("CHANGE_FORMULA")) {
if (isUndo)
setFormula(ss->get("OLD_FORMULA"), false);
else
setFormula(ss->get("NEW_FORMULA"), false);
rerunApplication(true);
} else {
PageItem_ImageFrame::restore(state, isUndo);
}
}
 
 
void PageItem_LatexFrame::setUsePreamble(bool useP)
{
m_usePreamble = useP;
}
 
void PageItem_LatexFrame::layout()
{
if (!invalid) return;
invalid = false;
if (m_width == lastWidth && m_height == lastHeight) return;
lastWidth = m_width;
lastHeight = m_height;
rerunApplication(false);
}
 
void PageItem_LatexFrame::applicableActions(QStringList & actionList)
{
actionList << "itemImageIsVisible";
actionList << "itemPreviewFull";
actionList << "itemPreviewLow";
actionList << "itemPreviewNormal";
actionList << "itemUpdateImage";
actionList << "editEditRenderSource";
if (PictureIsAvailable)
{
/*if (!isTableItem)
actionList << "itemAdjustFrameToImage";*/
actionList << "editClearContents";
actionList << "editCopyContents";
}
if (doc()->scMW()->contentsBuffer.sourceType==PageItem::LatexFrame)
{
actionList << "editPasteContents";
actionList << "editPasteContentsAbs";
}
}
 
QString PageItem_LatexFrame::infoDescription()
{
QString htmlText;
htmlText.append("<h2>"+tr("Render Frame") + "</h2><table>");
htmlText.append("<tr><th align=\"right\">" + tr("Application") + ": </th><td>" + application());
htmlText.append("</td></tr><tr><th align=\"right\">" + tr("DPI") + ": </th><td>" +
QString::number(realDpi()));
htmlText.append("</td></tr><tr><th align=\"right\">" + tr("State") + ": </th><td>");
if (latex->state() == QProcess::NotRunning) {
if (error()) {
htmlText.append(tr("Error"));
} else {
htmlText.append(tr("Finished"));
}
} else {
htmlText.append(tr("Running"));
}
htmlText.append("</td></tr></table><hr>");
htmlText.append(PageItem::infoDescription());
return htmlText;
}
 
/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/
/***************************************************************************
pageitem_latexframe.cpp - description
-------------------
begin : Mon May 28 2007
copyright : (C) 2007 by Hermann Kraus
email : hermann@physiklaborant.de
***************************************************************************/
 
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
 
#include "pageitem_latexframe.h"
 
#include <QDebug>
#include <QMessageBox>
#include <QTemporaryFile>
 
#include "prefsmanager.h"
#include "scpainter.h"
#include "scraction.h"
#include "scribus.h"
#include "scribusdoc.h"
#include "undomanager.h"
#include "undostate.h"
#include "ui/latexeditor.h"
#include "latexhelpers.h"
#include "util.h"
 
PageItem_LatexFrame::PageItem_LatexFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, QString fill, QString outline)
: PageItem_ImageFrame(pa, x, y, w, h, w2, fill, outline)
{
setUPixmap(Um::ILatexFrame);
AnName = tr("Render") + QString::number(m_Doc->TotalItems);
setUName(AnName);
imgValid = false;
m_usePreamble = true;
err = 0;
internalEditor = 0;
killed = false;
config = 0;
if (PrefsManager::instance()->latexConfigs().count() > 0)
setConfigFile(PrefsManager::instance()->latexConfigs()[0]);
 
latex = new QProcess();
connect(latex, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(updateImage(int, QProcess::ExitStatus)));
connect(latex, SIGNAL(error(QProcess::ProcessError)), this, SLOT(latexError(QProcess::ProcessError)));
latex->setProcessChannelMode(QProcess::MergedChannels);
QTemporaryFile *tempfile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_render_XXXXXX");
tempfile->open();
tempFileBase = getLongPathName(tempfile->fileName());
tempfile->setAutoRemove(false);
tempfile->close();
delete tempfile;
Q_ASSERT(!tempFileBase.isEmpty());
m_dpi = 0;
}
 
PageItem_LatexFrame::~PageItem_LatexFrame()
{
if (internalEditor) delete internalEditor;
latex->disconnect();
if (latex->state() != QProcess::NotRunning) {
killed = true;
latex->terminate();
latex->waitForFinished(500);
if (latex->state() != QProcess::NotRunning) {
latex->kill();
latex->waitForFinished(500);
}
}
deleteImageFile();
delete latex;
}
 
void PageItem_LatexFrame::clearContents()
{
PageItem_ImageFrame::clearContents();
formulaText = "";
appStdout = "";
err = 0;
imgValid = false;
}
 
void PageItem_LatexFrame::deleteImageFile()
{
QFileInfo fi(tempFileBase);
QDir dir = fi.absoluteDir();
QStringList filter;
filter << fi.fileName() + "*";
Q_ASSERT(!fi.fileName().isEmpty());
Q_ASSERT(!fi.fileName().contains("/"));
Q_ASSERT(!fi.fileName().contains("\\"));
QStringList files;
files = dir.entryList(filter);
foreach (QString file, files) {
Q_ASSERT(file.startsWith("scribus_temp"));
dir.remove(file);
}
imgValid = false;
}
 
void PageItem_LatexFrame::DrawObj_Item(ScPainter *p, QRectF e)
{
layout();
if (!imgValid && !err)
{
//Draw indicator that latex is running
p->setBrush(Qt::white);
p->setPen(Qt::green, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
p->drawLine(FPoint(0, 0), FPoint(m_width, m_height));
p->drawText(QRectF(0.0, 0.0, m_width, m_height), tr("Rendering..."));
}
else if (err)
{
//Draw error indicator
p->setBrush(Qt::white);
p->setPen(Qt::blue, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
p->drawLine(FPoint(0, 0), FPoint(m_width, m_height));
p->drawLine(FPoint(0, m_height), FPoint(m_width, 0));
p->drawText(QRectF(0.0, 0.0, m_width, m_height), tr("Render Error"));
}
else
{
//Just pass it to ImageFrame
PageItem_ImageFrame::DrawObj_Item(p, e);
}
}
 
void PageItem_LatexFrame::updateImage(int exitCode, QProcess::ExitStatus exitStatus)
{
appStdout = latex->readAllStandardOutput();
err = exitCode;
emit latexFinished();
emit stateChanged(latex->state());
static bool firstWarning = true;
if (exitCode) {
imgValid = false;
if (firstWarning && !killed)
{
bool editorRunning = internalEditor && internalEditor->isVisible();
ScMessageBox msgBox;
msgBox.setText(tr("Running the external application failed!"));
QString informativeText = tr("This is usually a problem with your input. Please check the program's output.");
if (!editorRunning) {
informativeText += " "+tr("Do you want to open the editor to fix the problem?");
msgBox.setStandardButtons(QMessageBox::Yes|QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::Yes);
} else {
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
}
msgBox.setIcon(QMessageBox::Warning);
msgBox.setInformativeText(informativeText);
msgBox.setDetailedText(output());
if ((msgBox.exec() == QMessageBox::Yes) && !editorRunning) {
runEditor();
}
firstWarning = false;
}
qCritical() << "RENDER FRAME: updateImage():" << tr("Running the external application failed!");
killed = false;
update(); //Show error marker
return;
}
else
{
firstWarning = true;
}
imgValid = true;
 
//Save state and restore afterwards
double xres, yres;
if (PictureIsAvailable)
{
xres = pixm.imgInfo.xres;
yres = pixm.imgInfo.yres;
}
else
{
xres = yres = realDpi();
}
double scaleX = m_imageXScale * xres;
double scaleY = m_imageYScale * yres;
double offX = m_imageXOffset / xres;
double offY = m_imageYOffset / yres;
PageItem_ImageFrame::loadImage(imageFile, true, realDpi());
if (PrefsManager::instance()->latexForceDpi())
{
pixm.imgInfo.xres = pixm.imgInfo.yres = realDpi();
}
//Restore parameters, account for dpi changes
m_imageXScale = scaleX / pixm.imgInfo.xres;
m_imageYScale = scaleY / pixm.imgInfo.yres;
m_imageXOffset = offX * pixm.imgInfo.xres;
m_imageYOffset = offY * pixm.imgInfo.yres;
//emit imageOffsetScale(LocalScX, LocalScY, LocalX, LocalY);
update();
}
 
 
void PageItem_LatexFrame::runApplication()
{
imgValid = false;
err = 0;
killed = false;
static bool firstWarningTmpfile = true;
static bool firstWarningLatexMissing = true;
 
if (!config)
{
qCritical() << "RENDER FRAME:" << tr("No configuration defined to run the application!");
return;
}
QFile tempfile(tempFileBase);
if (!tempfile.open(QIODevice::Truncate|QIODevice::WriteOnly)) {
err = 0xffff;
update(); //Show error marker
if (firstWarningTmpfile)
{
ScMessageBox::critical(0, tr("Error"), "<qt>" +
tr("Could not create a temporary file to run the application!")
+ "</qt>");
firstWarningTmpfile = false;
}
qCritical() << "RENDER FRAME:" << tr("Could not create a temporary file to run the application!");
//Don't know how to continue as it's impossible to create tempfile
return;
}
else
{
firstWarningTmpfile = true;
}
QString full_command = config->executable();
if (full_command.isEmpty()) {
err = 0xffff;
update(); //Show error marker
if (firstWarningLatexMissing)
{
ScMessageBox::critical(0, tr("Error"),
"<qt>" + tr("The config file didn't specify a executable path!") +
"</qt>");
firstWarningLatexMissing = false;
}
qCritical() << "RENDER FRAME:" << tr("The config file didn't specify a executable path!");
return;
}
else
{
firstWarningLatexMissing = true;
}
 
full_command.replace("%dpi", QString::number(realDpi()));
if (full_command.contains("%file")) {
full_command.replace("%file", QString("\"%1\"").arg(QDir::toNativeSeparators(tempFileBase)));
} else {
full_command = full_command + QString(" \"%1\"").arg(QDir::toNativeSeparators(tempFileBase));
}
full_command.replace("%dir", QString("\"%1\"").arg(QDir::toNativeSeparators(QDir::tempPath())));
latex->setWorkingDirectory(QDir::tempPath());
 
double lDpi = realDpi()/72.0;
full_command.replace("$scribus_height_px$", QString::number(qRound(m_height*lDpi)));
full_command.replace("$scribus_width_px$", QString::number(qRound(m_width*lDpi)));
QMapIterator<QString, QString> i(editorProperties);
while (i.hasNext())
{
i.next();
full_command.replace("$scribus_"+i.key()+"$", i.value());
}
imageFile = tempFileBase + config->imageExtension();
 
writeFileContents(&tempfile);
tempfile.close();
latex->start(full_command);
emit stateChanged(QProcess::Starting);
}
 
void PageItem_LatexFrame::runEditor()
{
if (!internalEditor) {
internalEditor = new LatexEditor(this);
internalEditor->startEditor();
} else if (internalEditor->isVisible()) {
internalEditor->activateWindow();
internalEditor->raise();
} else {
internalEditor->startEditor();
}
}
 
void PageItem_LatexFrame::rerunApplication(bool updateDisplay)
{
if (latex->state() != QProcess::NotRunning) {
killed = true;
latex->terminate();
latex->waitForFinished(500);
if (latex->state() != QProcess::NotRunning) {
//Still not terminated?
latex->kill();
latex->waitForFinished(500);
}
}
runApplication();
if (updateDisplay) this->update();
}
 
 
void PageItem_LatexFrame::writeFileContents(QFile *tempfile)
{
QString tmp(formulaText);
double scaleX, scaleY, realW, realH, offsetX, offsetY;
double lDpi = realDpi()/72.0;
scaleX = m_imageXScale*lDpi;
scaleY = m_imageYScale*lDpi;
offsetX = m_imageXOffset*m_imageXScale;
offsetY = m_imageYOffset*m_imageYScale;
realW = m_width/scaleX - m_imageXOffset/lDpi;
realH = m_height/scaleY - m_imageYOffset/lDpi;
if (!tmp.contains("$scribus_noprepost$") && m_usePreamble) {
tmp = config->preamble() + tmp + config->postamble();
}
tmp.replace(QString("$scribus_width$"), QString::number(m_width));
tmp.replace(QString("$scribus_width_px$"), QString::number(qRound(m_width*lDpi)));
tmp.replace(QString("$scribus_width_inch$"), QString::number(m_width/72.0));
tmp.replace(QString("$scribus_height$"), QString::number(m_height));
tmp.replace(QString("$scribus_height_px$"), QString::number(qRound(m_height*lDpi)));
tmp.replace(QString("$scribus_height_inch$"), QString::number(m_height/72.0));
tmp.replace(QString("$scribus_realwidth$"), QString::number(realW));
tmp.replace(QString("$scribus_realwidth_px$"), QString::number(qRound(realW*lDpi)));
tmp.replace(QString("$scribus_realheight$"), QString::number(realH));
tmp.replace(QString("$scribus_realheight_px$"), QString::number(qRound(realH*lDpi)));
tmp.replace(QString("$scribus_offsetX$"), QString::number(offsetX));
tmp.replace(QString("$scribus_offsetX_px$"), QString::number(qRound(offsetX*lDpi)));
tmp.replace(QString("$scribus_offsetY$"), QString::number(offsetY));
tmp.replace(QString("$scribus_offsetY$"), QString::number(qRound(offsetY*lDpi)));
tmp.replace(QString("$scribus_scaleX$"), QString::number(scaleX));
tmp.replace(QString("$scribus_scaleY$"), QString::number(scaleY));
tmp.replace(QString("$scribus_dpi$"), QString::number(realDpi()));
tmp.replace(QString("$scribus_file$"), tempFileBase);
tmp.replace(QString("$scribus_dir$"), QDir::tempPath());
QMapIterator<QString, QString> i(editorProperties);
while (i.hasNext()) {
i.next();
tmp.replace("$scribus_"+i.key()+"$", i.value());
}
tempfile->write(tmp.toUtf8());
}
 
bool PageItem_LatexFrame::setFormula(QString formula, bool undoable)
{
if (formula == formulaText) {
//Nothing changed
return false;
}
imgValid = false;
err = 0;
if (UndoManager::undoEnabled() && undoable)
{
SimpleState *ss = new SimpleState(Um::ChangeFormula, "", Um::IChangeFormula);
ss->set("CHANGE_FORMULA", "change_formula");
ss->set("OLD_FORMULA", formulaText);
ss->set("NEW_FORMULA", formula);
undoManager->action(this, ss);
} else if (!undoable) {
emit formulaAutoUpdate(formulaText, formula);
}
formulaText = formula;
return true;
}
 
void PageItem_LatexFrame::latexError(QProcess::ProcessError error)
{
err = 0xffff;
update(); //Show error marker
static bool firstWarning = true;
if (killed) {
killed = false;
update();
//Don't show errors caused by killing processes
return;
}
if (firstWarning)
{
if (latex->error() == QProcess::FailedToStart) {
ScMessageBox::critical(0, tr("Error"), "<qt>" +
tr("The application \"%1\" failed to start! Please check the path: ").
arg(config->executable())
+ "</qt>");
} else {
ScMessageBox::critical(0, tr("Error"), "<qt>" +
tr("The application \"%1\" crashed!").arg(config->executable())
+ "</qt>");
}
firstWarning = false;
}
qCritical() << "RENDER FRAME: latexError():" <<
tr("Running the application \"%1\" failed!").arg(config->executable()) << latex->error();
emit stateChanged(QProcess::NotRunning);
}
 
 
QString PageItem_LatexFrame::application() const
{
return config ? config->executable() : tr("No application defined");
}
 
QString PageItem_LatexFrame::configFile() const
{
return configFilename;
}
 
int PageItem_LatexFrame::realDpi() const
{
if (m_dpi) {
return m_dpi;
} else {
return PrefsManager::instance()->latexResolution();
}
}
 
void PageItem_LatexFrame::setDpi(int newDpi)
{
m_dpi = newDpi;
}
 
void PageItem_LatexFrame::setConfigFile(QString newConfig, bool relative)
{
// Try to interpret a config file as a relative path even when it is given with a full path
if (relative)
{
QFileInfo fi;
QStringList configs = PrefsManager::instance()->latexConfigs();
foreach (QString config, configs)
{
fi.setFile(config);
if (newConfig == fi.fileName())
{
newConfig = config;
break;
}
}
}
 
if (configFilename == newConfig) return;
bool unchanged = formulaText.isEmpty();
if (config && (formulaText == config->emptyFrameText())) {
unchanged = true;
}
configFilename = newConfig;
config = LatexConfigCache::instance()->parser(configFilename);
//Initialize with default values
QString key;
QMapIterator<QString, QString> i(config->properties);
while (i.hasNext()) {
i.next();
key = i.key();
if (!editorProperties.contains(key)) {
editorProperties[key] = i.value();
}
}
QString newFormula;
if (unchanged) {
if (PrefsManager::instance()->latexStartWithEmptyFrames()) {
newFormula = "";
} else {
newFormula = config->emptyFrameText();
}
emit formulaAutoUpdate(formulaText, newFormula);
formulaText = newFormula;
}
emit applicationChanged();
}
 
void PageItem_LatexFrame::killProcess()
{
killed = true;
latex->kill();
}
 
void PageItem_LatexFrame::restore(UndoState *state, bool isUndo)
{
SimpleState *ss = dynamic_cast<SimpleState*>(state);
if (!ss) {
PageItem_ImageFrame::restore(state, isUndo);
return;
}
if (ss->contains("CHANGE_FORMULA")) {
if (isUndo)
setFormula(ss->get("OLD_FORMULA"), false);
else
setFormula(ss->get("NEW_FORMULA"), false);
rerunApplication(true);
} else {
PageItem_ImageFrame::restore(state, isUndo);
}
}
 
 
void PageItem_LatexFrame::setUsePreamble(bool useP)
{
m_usePreamble = useP;
}
 
void PageItem_LatexFrame::layout()
{
if (!invalid) return;
invalid = false;
if (m_width == lastWidth && m_height == lastHeight) return;
lastWidth = m_width;
lastHeight = m_height;
rerunApplication(false);
}
 
void PageItem_LatexFrame::applicableActions(QStringList & actionList)
{
actionList << "itemImageIsVisible";
actionList << "itemPreviewFull";
actionList << "itemPreviewLow";
actionList << "itemPreviewNormal";
actionList << "itemUpdateImage";
actionList << "editEditRenderSource";
if (PictureIsAvailable)
{
/*if (!isTableItem)
actionList << "itemAdjustFrameToImage";*/
actionList << "editClearContents";
actionList << "editCopyContents";
}
if (doc()->scMW()->contentsBuffer.sourceType==PageItem::LatexFrame)
{
actionList << "editPasteContents";
actionList << "editPasteContentsAbs";
}
}
 
QString PageItem_LatexFrame::infoDescription()
{
QString htmlText;
htmlText.append("<h2>"+tr("Render Frame") + "</h2><table>");
htmlText.append("<tr><th align=\"right\">" + tr("Application") + ": </th><td>" + application());
htmlText.append("</td></tr><tr><th align=\"right\">" + tr("DPI") + ": </th><td>" +
QString::number(realDpi()));
htmlText.append("</td></tr><tr><th align=\"right\">" + tr("State") + ": </th><td>");
if (latex->state() == QProcess::NotRunning) {
if (error()) {
htmlText.append(tr("Error"));
} else {
htmlText.append(tr("Finished"));
}
} else {
htmlText.append(tr("Running"));
}
htmlText.append("</td></tr></table><hr>");
htmlText.append(PageItem::infoDescription());
return htmlText;
}
 
/trunk/Scribus/scribus/pluginmanager.cpp
228,11 → 228,10
failedStr += "</ul>";
if (splashShown)
ScCore->showSplash(false);
QMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning,
ScMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning,
"<qt>" + tr("There is a problem loading %1 of %2 plugins. %3 This is probably caused by some kind of dependency issue or old plugins existing in your install directory. If you clean out your install directory and reinstall and this still occurs, please report it on bugs.scribus.net."
).arg(allPlugs.count()-loaded).arg(allPlugs.count()).arg(failedStr)
+ "</qt>",
CommonStrings::tr_OK);
+ "</qt>");
if (splashShown)
ScCore->showSplash(true);
}
/trunk/Scribus/scribus/plugins/colorwheel/cwdialog.cpp
338,7 → 338,7
status += "<p>" + tr("Now opening the color manager.") + "</p></qt>";
if (err)
{
QMessageBox::information(this, tr("Color Merging"), status);
ScMessageBox::information(this, tr("Color Merging"), status);
m_Doc->scMW()->managePaints();
return;
}
486,7 → 486,7
else
{
colorList->clear();
QMessageBox::information(this, windowTitle(),
ScMessageBox::information(this, windowTitle(),
"<qt>" + tr("Unable to find the requested color. "
"You have probably selected black, gray or white. "
"There is no way to process this color.") + "</qt>");
/trunk/Scribus/scribus/plugins/export/pixmapexport/export.cpp
120,13 → 120,13
QFileInfo fi(ex->exportDir);
if (!fi.isDir())
{
QMessageBox::warning(doc->scMW(), tr("Save as Image"),
ScMessageBox::warning(doc->scMW(), tr("Save as Image"),
tr("The target location %1 must be an existing directory").arg(ex->exportDir));
return false;
}
if (!fi.isWritable())
{
QMessageBox::warning(doc->scMW(), tr("Save as Image"),
ScMessageBox::warning(doc->scMW(), tr("Save as Image"),
tr("The target location %1 must be writable").arg(ex->exportDir));
return false;
}
191,7 → 191,7
QImage im(doc->view()->PageToPixmap(pageNr, qRound(pixmapSize * enlargement * (pageDPI / 72.0) / 100.0), false, background));
if (im.isNull())
{
QMessageBox::warning(doc->scMW(), tr("Save as Image"), tr("Insufficient memory for this image size."));
ScMessageBox::warning(doc->scMW(), tr("Save as Image"), tr("Insufficient memory for this image size."));
doc->scMW()->setStatusBarInfoText( tr("Insufficient memory for this image size."));
return false;
}
204,10 → 204,12
QString fn = QDir::toNativeSeparators(fileName);
// QApplication::restoreOverrideCursor();
QApplication::changeOverrideCursor(Qt::ArrowCursor);
over = QMessageBox::question(doc->scMW(), tr("File exists. Overwrite?"),
over = ScMessageBox::question(doc->scMW(), tr("File exists. Overwrite?"),
fn +"\n"+ tr("exists already. Overwrite?"),
// hack for multiple overwriting (petr)
(single == true) ? QMessageBox::Yes | QMessageBox::No : QMessageBox::Yes | QMessageBox::No | QMessageBox::YesToAll);
(single == true) ? QMessageBox::Yes | QMessageBox::No : QMessageBox::Yes | QMessageBox::No | QMessageBox::YesToAll,
QMessageBox::NoButton, // GUI default
QMessageBox::YesToAll); // batch default
QApplication::changeOverrideCursor(QCursor(Qt::WaitCursor));
if (over == QMessageBox::Yes || over == QMessageBox::YesToAll)
doFileSave = true;
218,7 → 220,7
saved = im.save(fileName, bitmapType.toLocal8Bit().constData(), quality);
if (!saved && doFileSave)
{
QMessageBox::warning(doc->scMW(), tr("Save as Image"), tr("Error writing the output file(s)."));
ScMessageBox::warning(doc->scMW(), tr("Save as Image"), tr("Error writing the output file(s)."));
doc->scMW()->setStatusBarInfoText( tr("Error writing the output file(s)."));
}
return saved;
/trunk/Scribus/scribus/plugins/export/svgexplugin/svgexplugin.cpp
51,6 → 51,7
#include "util.h"
#include "ui/customfdialog.h"
#include "ui/guidemanager.h"
#include "ui/scmessagebox.h"
#include "sccolorengine.h"
#include "util_formats.h"
#include "util_math.h"
169,9 → 170,11
QFile f(fileName);
if (f.exists())
{
int exit = QMessageBox::warning(doc->scMW(), CommonStrings::trWarning,
int exit = ScMessageBox::warning(doc->scMW(), CommonStrings::trWarning,
QObject::tr("Do you really want to overwrite the file:\n%1 ?").arg(fileName),
QMessageBox::Yes | QMessageBox::No);
QMessageBox::Yes | QMessageBox::No,
QMessageBox::NoButton, // GUI default
QMessageBox::Yes); // batch default
if (exit == QMessageBox::No)
return true;
}
/trunk/Scribus/scribus/plugins/export/xpsexport/xpsexplugin.cpp
1,2954 → 1,2957
/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/
/***************************************************************************
xpsexport.cpp - description
-------------------
begin : Sun Nov 24 08:00:00 CEST 2013
copyright : (C) 2013 by Franz Schmid
email : Franz.Schmid@altmuehlnet.de
***************************************************************************/
 
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
 
#include <QBuffer>
#include <QByteArray>
#include <QComboBox>
#include <QDataStream>
#include <QFile>
#include <QList>
#include <QMessageBox>
#include <QScopedPointer>
#include <QTemporaryDir>
#include <QTextStream>
#include <QUuid>
 
#include "xpsexplugin.h"
 
#include "scconfig.h"
#include "canvas.h"
#include "cmsettings.h"
#include "commonstrings.h"
#include "pageitem_pathtext.h"
#include "pageitem_table.h"
#include "prefsmanager.h"
#include "prefsfile.h"
#include "prefscontext.h"
#include "scpage.h"
#include "scpattern.h"
#include "scribuscore.h"
#include "scribusdoc.h"
#include "scribusview.h"
#include "sctextstruct.h"
#include "tableutils.h"
#include "util.h"
#include "ui/customfdialog.h"
#include "ui/guidemanager.h"
#include "sccolorengine.h"
#include "util_formats.h"
#include "util_math.h"
#include "third_party/zip/scribus_zip.h"
 
int xpsexplugin_getPluginAPIVersion()
{
return PLUGIN_API_VERSION;
}
 
ScPlugin* xpsexplugin_getPlugin()
{
XPSExportPlugin* plug = new XPSExportPlugin();
Q_CHECK_PTR(plug);
return plug;
}
 
void xpsexplugin_freePlugin(ScPlugin* plugin)
{
XPSExportPlugin* plug = dynamic_cast<XPSExportPlugin*>(plugin);
Q_ASSERT(plug);
delete plug;
}
 
using namespace TableUtils;
 
XPSExportPlugin::XPSExportPlugin() : ScActionPlugin()
{
// Set action info in languageChange, so we only have to do
// it in one place.
languageChange();
}
 
XPSExportPlugin::~XPSExportPlugin() {};
 
void XPSExportPlugin::languageChange()
{
// Note that we leave the unused members unset. They'll be initialised
// with their default ctors during construction.
// Action name
m_actionInfo.name = "ExportAsXPS";
// Action text for menu, including accel
m_actionInfo.text = tr("Save as XPS...");
// Menu
m_actionInfo.menu = "FileExport";
m_actionInfo.enabledOnStartup = false;
m_actionInfo.needsNumObjects = -1;
}
 
const QString XPSExportPlugin::fullTrName() const
{
return QObject::tr("XPS Export");
}
 
const ScActionPlugin::AboutData* XPSExportPlugin::getAboutData() const
{
AboutData* about = new AboutData;
about->authors = "Franz Schmid <franz@scribus.info>";
about->shortDescription = tr("Exports XPS Files");
about->description = tr("Exports the current document into an XPS file.");
about->license = "GPL";
Q_CHECK_PTR(about);
return about;
}
 
void XPSExportPlugin::deleteAboutData(const AboutData* about) const
{
Q_ASSERT(about);
delete about;
}
 
bool XPSExportPlugin::run(ScribusDoc* doc, QString filename)
{
Q_ASSERT(filename.isEmpty());
QString fileName;
if (doc!=0)
{
PrefsContext* prefs = PrefsManager::instance()->prefsFile->getPluginContext("xpsex");
QString wdir = prefs->get("wdir", ".");
QScopedPointer<CustomFDialog> openDia( new CustomFDialog(doc->scMW(), wdir, QObject::tr("Save as"), QObject::tr("Microsoft XPS (*.xps *.XPS);;All Files (*)"), fdHidePreviewCheckBox) );
 
QFrame *Layout = new QFrame(openDia.data());
QHBoxLayout *Layout1 = new QHBoxLayout(Layout);
Layout1->setSpacing( 5 );
QLabel *text = new QLabel(QObject::tr("Output Settings:"), Layout);
Layout1->addWidget(text);
QComboBox* compress = new QComboBox(Layout);
compress->addItem(QObject::tr("Low Resolution"));
compress->addItem(QObject::tr("Medium Resolution"));
compress->addItem(QObject::tr("High Resolution"));
Layout1->addWidget(compress);
QSpacerItem* spacer = new QSpacerItem( 2, 2, QSizePolicy::Expanding, QSizePolicy::Minimum );
Layout1->addItem( spacer );
compress->setCurrentIndex(1);
openDia->addWidgets(Layout);
QString fna;
if (doc->hasName)
{
QFileInfo fi(doc->DocName);
QString completeBaseName = fi.completeBaseName();
if (completeBaseName.endsWith(".xps", Qt::CaseInsensitive))
completeBaseName.chop(4);
wdir = QDir::fromNativeSeparators( fi.path() );
fna = QDir::fromNativeSeparators( fi.path()+"/"+completeBaseName+".xps" );
}
else
{
wdir = QDir::fromNativeSeparators( wdir );
if (wdir.right(1) != "/")
fna = wdir + "/";
else
fna = wdir;
fna += doc->DocName + ".xps";
}
openDia->setSelection(fna);
openDia->setExtension("xps");
 
if (!openDia->exec())
return true;
fileName = openDia->selectedFile();
QFileInfo fi(fileName);
QString baseDir = fi.absolutePath();
fileName = baseDir + "/" + fi.baseName() + ".xps";
if (fileName.isEmpty())
return true;
prefs->set("wdir", fileName.left(fileName.lastIndexOf("/")));
QFile f(fileName);
if (f.exists())
{
int exit = QMessageBox::warning(doc->scMW(), CommonStrings::trWarning,
QObject::tr("Do you really want to overwrite the file:\n%1 ?").arg(fileName),
QMessageBox::Yes | QMessageBox::No);
if (exit == QMessageBox::No)
return true;
}
XPSExPlug *dia = new XPSExPlug(doc, compress->currentIndex());
dia->doExport(fileName);
delete dia;
}
return true;
}
 
XPSExPlug::XPSExPlug(ScribusDoc* doc, int output_res)
{
m_Doc = doc;
conversionFactor = 96.0 / 72.0;
m_dpi = 96.0;
if (output_res == 0)
m_dpi = 72.0;
else if (output_res == 1)
m_dpi = 150.0;
else if (output_res == 2)
m_dpi = 300.0;
}
 
bool XPSExPlug::doExport(QString fName)
{
zip = new ScZipHandler(true);
if (!zip->open(fName))
{
delete zip;
return false;
}
dir = new QTemporaryDir();
if (dir->isValid())
{
imageCounter = 0;
fontCounter = 0;
xps_fontMap.clear();
baseDir = dir->path();
// Create directory tree
QDir outDir(baseDir);
outDir.mkdir("_rels");
outDir.mkdir("docProps");
outDir.mkdir("Documents");
outDir.cd("Documents");
outDir.mkdir("1");
outDir.cd("1");
outDir.mkdir("_rels");
outDir.mkdir("Pages");
outDir.cd("Pages");
outDir.mkdir("_rels");
outDir.cdUp();
outDir.mkdir("Structure");
outDir.cdUp();
outDir.cdUp();
outDir.mkdir("Resources");
outDir.cd("Resources");
outDir.mkdir("Images");
outDir.mkdir("Fonts");
outDir.cdUp();
writeBaseRel();
writeContentType();
writeCore();
writeDocRels();
// Write Thumbnail
QImage thumb = m_Doc->view()->PageToPixmap(0, 256, false);
thumb.save(baseDir + "/docProps/thumbnail.jpeg", "JPG");
// Write required DocStructure.struct
QFile fts(baseDir + "/Documents/1/Structure/DocStructure.struct");
if (fts.open(QIODevice::WriteOnly))
{
fts.write(QByteArray("<DocumentStructure xmlns=\"http://schemas.microsoft.com/xps/2005/06/documentstructure\">\n</DocumentStructure>"));
fts.close();
}
// Write required FixedDocSeq.fdseq
QFile ft(baseDir + "/FixedDocSeq.fdseq");
if (ft.open(QIODevice::WriteOnly))
{
ft.write(QByteArray("<FixedDocumentSequence xmlns=\"http://schemas.microsoft.com/xps/2005/06\">\n\t<DocumentReference Source=\"/Documents/1/FixedDoc.fdoc\"/>\n</FixedDocumentSequence>"));
ft.close();
}
// Write required FixedDoc.fdoc
f_docu = QDomDocument("xpsdoc");
QString st = "<FixedDocument></FixedDocument>";
f_docu.setContent(st);
QDomElement root = f_docu.documentElement();
root.setAttribute("xmlns", "http://schemas.microsoft.com/xps/2005/06");
f_docu.appendChild(root);
writePages(root);
QFile fdo(baseDir + "/Documents/1/FixedDoc.fdoc");
if (fdo.open(QIODevice::WriteOnly))
{
QString vo = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
QDataStream s(&fdo);
vo += f_docu.toString();
QByteArray utf8wr = vo.toUtf8();
s.writeRawData(utf8wr.data(), utf8wr.length());
fdo.close();
}
zip->write(baseDir);
}
zip->close();
delete zip;
delete dir;
return true;
}
 
void XPSExPlug::writePages(QDomElement &root)
{
for (int a = 0; a < m_Doc->Pages->count(); a++)
{
ScPage* Page = m_Doc->Pages->at(a);
p_docu.setContent(QString("<FixedPage></FixedPage>"));
QDomElement droot = p_docu.documentElement();
droot.setAttribute("xmlns", "http://schemas.microsoft.com/xps/2005/06");
droot.setAttribute("Width", QString("%1").arg(Page->width() * conversionFactor));
droot.setAttribute("Height", QString("%1").arg(Page->height() * conversionFactor));
QString lang = QLocale::system().name();
lang.replace("_", "-");
droot.setAttribute("xml:lang", lang);
r_docu.setContent(QString("<Relationships></Relationships>"));
QDomElement rroot = r_docu.documentElement();
rroot.setAttribute("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships");
writePage(droot, rroot, Page);
p_docu.appendChild(droot);
r_docu.appendChild(rroot);
QFile ft(baseDir + QString("/Documents/1/Pages/%1.fpage").arg(a+1));
if (ft.open(QIODevice::WriteOnly))
{
QString vo = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
QDataStream s(&ft);
vo += p_docu.toString();
QByteArray utf8wr = vo.toUtf8();
s.writeRawData(utf8wr.data(), utf8wr.length());
ft.close();
}
QFile ftr(baseDir + QString("/Documents/1/Pages/_rels/%1.fpage.rels").arg(a+1));
if (ftr.open(QIODevice::WriteOnly))
{
QString vo = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
QDataStream s(&ftr);
vo += r_docu.toString();
QByteArray utf8wr = vo.toUtf8();
s.writeRawData(utf8wr.data(), utf8wr.length());
ftr.close();
}
QDomElement rel1 = f_docu.createElement("PageContent");
rel1.setAttribute("Source", QString("Pages/%1.fpage").arg(a+1));
root.appendChild(rel1);
p_docu.clear();
r_docu.clear();
}
}
 
void XPSExPlug::writePage(QDomElement &doc_root, QDomElement &rel_root, ScPage *Page)
{
ScLayer ll;
ll.isPrintable = false;
for (int la = 0; la < m_Doc->Layers.count(); la++)
{
m_Doc->Layers.levelToLayer(ll, la);
if (ll.isPrintable)
{
ScPage *mpage = m_Doc->MasterPages.at(m_Doc->MasterNames[Page->MPageNam]);
writePageLayer(doc_root, rel_root, mpage, ll);
writePageLayer(doc_root, rel_root, Page, ll);
}
}
}
 
void XPSExPlug::writePageLayer(QDomElement &doc_root, QDomElement &rel_root, ScPage *page, ScLayer& layer)
{
PageItem *Item;
QList<PageItem*> Items;
ScPage* SavedAct = m_Doc->currentPage();
if (page->pageName().isEmpty())
Items = m_Doc->DocItems;
else
Items = m_Doc->MasterItems;
if (Items.count() == 0)
return;
if (!layer.isPrintable)
return;
m_Doc->setCurrentPage(page);
QDomElement layerGroup = p_docu.createElement("Canvas");
if (layer.transparency != 1.0)
layerGroup.setAttribute("Opacity", layer.transparency);
for(int j = 0; j < Items.count(); ++j)
{
Item = Items.at(j);
if (Item->LayerID != layer.ID)
continue;
if (!Item->printEnabled())
continue;
double x = page->xOffset();
double y = page->yOffset();
double w = page->width();
double h = page->height();
double x2 = Item->BoundingX;
double y2 = Item->BoundingY;
double w2 = Item->BoundingW;
double h2 = Item->BoundingH;
if (!( qMax( x, x2 ) <= qMin( x+w, x2+w2 ) && qMax( y, y2 ) <= qMin( y+h, y2+h2 )))
continue;
if ((!page->pageName().isEmpty()) && (Item->OwnPage != static_cast<int>(page->pageNr())) && (Item->OwnPage != -1))
continue;
writeItemOnPage(Item->xPos() - page->xOffset(), Item->yPos() - page->yOffset(), Item, layerGroup, rel_root);
}
doc_root.appendChild(layerGroup);
m_Doc->setCurrentPage(SavedAct);
}
 
void XPSExPlug::writeItemOnPage(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root)
{
switch (Item->itemType())
{
case PageItem::Arc:
case PageItem::Polygon:
case PageItem::PolyLine:
case PageItem::RegularPolygon:
case PageItem::Spiral:
if (checkForFallback(Item))
handleImageFallBack(Item, parentElem, rel_root);
else
{
processPolyItem(xOffset, yOffset, Item, parentElem, rel_root);
if ((Item->lineColor() != CommonStrings::None) && ((Item->startArrowIndex() != 0) || (Item->endArrowIndex() != 0)))
processArrows(xOffset, yOffset, Item, parentElem, rel_root);
}
break;
case PageItem::Line:
if (checkForFallback(Item))
handleImageFallBack(Item, parentElem, rel_root);
else
{
processLineItem(xOffset, yOffset, Item, parentElem, rel_root);
if ((Item->lineColor() != CommonStrings::None) && ((Item->startArrowIndex() != 0) || (Item->endArrowIndex() != 0)))
processArrows(xOffset, yOffset, Item, parentElem, rel_root);
}
break;
case PageItem::ImageFrame:
case PageItem::LatexFrame:
if (checkForFallback(Item))
handleImageFallBack(Item, parentElem, rel_root);
else
processImageItem(xOffset, yOffset, Item, parentElem, rel_root);
break;
case PageItem::TextFrame:
if (checkForFallback(Item))
handleImageFallBack(Item, parentElem, rel_root);
else
processTextItem(xOffset, yOffset, Item, parentElem, rel_root);
break;
case PageItem::PathText:
if (checkForFallback(Item))
handleImageFallBack(Item, parentElem, rel_root);
else
processPathTextItem(xOffset, yOffset, Item, parentElem, rel_root);
break;
case PageItem::Table:
if (checkForFallback(Item))
handleImageFallBack(Item, parentElem, rel_root);
else
processTableItem(xOffset, yOffset, Item, parentElem, rel_root);
break;
case PageItem::Symbol:
if (checkForFallback(Item))
handleImageFallBack(Item, parentElem, rel_root);
else
processSymbolItem(xOffset, yOffset, Item, parentElem, rel_root);
break;
case PageItem::Group:
if (Item->groupItemList.count() > 0)
{
if (checkForFallback(Item))
handleImageFallBack(Item, parentElem, rel_root);
else
{
QDomElement ob = p_docu.createElement("Canvas");
if (Item->GrMask > 0)
handleMask(1, Item, ob, rel_root, xOffset, yOffset);
else
{
if (Item->fillTransparency() != 0)
ob.setAttribute("Opacity", FToStr(1.0 - Item->fillTransparency()));
}
if (Item->groupClipping())
{
FPointArray path = Item->PoLine.copy();
path.scale(conversionFactor, conversionFactor);
path.scale(Item->groupWidth / Item->width(), Item->groupHeight / Item->height());
SetClipAttr(ob, &path, Item->fillRule);
}
QTransform mpx;
mpx.translate(xOffset * conversionFactor, yOffset * conversionFactor);
mpx.scale(Item->width() / Item->groupWidth, Item->height() / Item->groupHeight);
if ((Item->rotation() != 0.0) || Item->imageFlippedH() || Item->imageFlippedV())
{
mpx.rotate(Item->rotation());
if (Item->imageFlippedH())
{
mpx.translate(Item->width() * conversionFactor, 0);
mpx.scale(-1, 1);
}
if (Item->imageFlippedV())
{
mpx.translate(0, Item->height() * conversionFactor);
mpx.scale(1, -1);
}
}
ob.setAttribute("RenderTransform", MatrixToStr(mpx));
for (int em = 0; em < Item->groupItemList.count(); ++em)
{
PageItem* embed = Item->groupItemList.at(em);
writeItemOnPage(embed->gXpos, embed->gYpos, embed, ob, rel_root);
}
parentElem.appendChild(ob);
}
}
break;
default:
handleImageFallBack(Item, parentElem, rel_root);
break;
}
}
 
void XPSExPlug::handleImageFallBack(PageItem *Item, QDomElement &parentElem, QDomElement &rel_root)
{
QDomElement ob = p_docu.createElement("Path");
double maxAdd = 0;
if (Item->hasSoftShadow())
maxAdd = qMax(fabs(Item->softShadowXOffset()), fabs(Item->softShadowYOffset())) + Item->softShadowBlurRadius();
QRectF bounds = Item->getVisualBoundingRect().adjusted(-maxAdd, -maxAdd, maxAdd, maxAdd);
QPainterPath path;
path.moveTo(0, 0);
path.lineTo(bounds.width(), 0);
path.lineTo(bounds.width(), bounds.height());
path.lineTo(0, bounds.height());
path.closeSubpath();
QTransform mpp;
mpp.translate((Item->visualXPos() - m_Doc->currentPage()->xOffset() - maxAdd) * conversionFactor, (Item->visualYPos() - m_Doc->currentPage()->yOffset() - maxAdd) * conversionFactor);
mpp.scale(conversionFactor, conversionFactor);
path = mpp.map(path);
FPointArray fPath;
fPath.fromQPainterPath(path, true);
QString pa = SetClipPath(&fPath, true);
if (Item->fillRule)
pa.prepend("F 0 ");
else
pa.prepend("F 1 ");
ob.setAttribute("Data", pa);
QDomElement obf = p_docu.createElement("Path.Fill");
QDomElement gr = p_docu.createElement("ImageBrush");
double maxSize = qMax(bounds.width(), bounds.height());
maxSize = qMin(3000.0, maxSize * (m_dpi / 72.0));
QImage tmpImg = Item->DrawObj_toImage(maxSize);
tmpImg.save(baseDir + "/Resources/Images/" + QString("%1.png").arg(imageCounter), "PNG");
gr.setAttribute("TileMode", "None");
gr.setAttribute("ViewboxUnits", "Absolute");
gr.setAttribute("ViewportUnits", "Absolute");
gr.setAttribute("Viewport", "0,0,1,1");
gr.setAttribute("Viewbox", QString("0, 0, %1, %2").arg(tmpImg.width()).arg(tmpImg.height()));
gr.setAttribute("Viewport", QString("%1, %2, %3, %4").arg((Item->visualXPos() - m_Doc->currentPage()->xOffset() - maxAdd) * conversionFactor).arg((Item->visualYPos() - m_Doc->currentPage()->yOffset() - maxAdd) * conversionFactor).arg(bounds.width() * conversionFactor).arg(bounds.height() * conversionFactor));
gr.setAttribute("ImageSource", "/Resources/Images/" + QString("%1.png").arg(imageCounter));
QDomElement rel = r_docu.createElement("Relationship");
rel.setAttribute("Id", QString("rIDi%1").arg(imageCounter));
rel.setAttribute("Type", "http://schemas.microsoft.com/xps/2005/06/required-resource");
rel.setAttribute("Target", "/Resources/Images/" + QString("%1.png").arg(imageCounter));
rel_root.appendChild(rel);
imageCounter++;
obf.appendChild(gr);
ob.appendChild(obf);
parentElem.appendChild(ob);
}
 
void XPSExPlug::processPolyItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root)
{
if (((Item->GrType != 0) || (Item->fillColor() != CommonStrings::None)) || ((Item->GrTypeStroke != 0) || (Item->lineColor() != CommonStrings::None) || !Item->NamedLStyle.isEmpty()))
{
if (Item->GrType == 14)
processHatchFill(xOffset, yOffset, Item, parentElem, rel_root);
bool closedPath;
if ((Item->itemType() == PageItem::Polygon) || (Item->itemType() == PageItem::RegularPolygon) || (Item->itemType() == PageItem::Arc))
closedPath = true;
else
closedPath = false;
QDomElement ob = p_docu.createElement("Path");
FPointArray path = Item->PoLine.copy();
QTransform mpx;
if (Item->rotation() != 0.0)
{
mpx.translate(xOffset * conversionFactor, yOffset * conversionFactor);
mpx.rotate(Item->rotation());
mpx.translate(-xOffset * conversionFactor, -yOffset * conversionFactor);
}
path.translate(xOffset, yOffset);
path.scale(conversionFactor, conversionFactor);
QString pa = SetClipPath(&path, closedPath);
if (Item->fillRule)
pa.prepend("F 0 ");
else
pa.prepend("F 1 ");
ob.setAttribute("Data", pa);
if (Item->GrType != 14)
{
if (Item->GrMask > 0)
handleMask(3, Item, ob, rel_root, xOffset, yOffset);
getFillStyle(Item, ob, rel_root, xOffset, yOffset);
}
if (Item->NamedLStyle.isEmpty())
{
if ((!Item->strokePattern().isEmpty()) && (Item->patternStrokePath))
{
processSymbolStroke(xOffset, yOffset, Item, parentElem, rel_root);
}
else
{
getStrokeStyle(Item, ob, rel_root, xOffset, yOffset);
if (Item->rotation() != 0.0)
ob.setAttribute("RenderTransform", MatrixToStr(mpx));
parentElem.appendChild(ob);
}
}
else
{
QDomElement grp2 = p_docu.createElement("Canvas");
multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
for (int it = ml.size()-1; it > -1; it--)
{
if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
{
QDomElement ob3 = p_docu.createElement("Path");
ob3.setAttribute("Data", pa);
GetMultiStroke(&ml[it], ob3);
grp2.appendChild(ob3);
}
}
if (Item->lineTransparency() != 0)
grp2.setAttribute("Opacity", FToStr(1.0 - Item->lineTransparency()));
if (Item->rotation() != 0.0)
grp2.setAttribute("RenderTransform", MatrixToStr(mpx));
parentElem.appendChild(grp2);
}
}
return;
}
 
void XPSExPlug::processLineItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root)
{
if ((Item->GrTypeStroke != 0) || (Item->lineColor() != CommonStrings::None) || !Item->NamedLStyle.isEmpty())
{
QDomElement ob;
double x1 = xOffset * conversionFactor;
double y1 = yOffset * conversionFactor;
double x2 = (Item->width() + xOffset) * conversionFactor;
double y2 = yOffset * conversionFactor;
QLineF line = QLineF(x1, y1, x2, y2);
line.setAngle(-Item->rotation());
if (Item->NamedLStyle.isEmpty())
{
ob = p_docu.createElement("Path");
ob.setAttribute("Data", QString("M %1, %2 L %3, %4").arg(line.p1().x()).arg(line.p1().y()).arg(line.p2().x()).arg(line.p2().y()));
getStrokeStyle(Item, ob, rel_root, xOffset, yOffset);
}
else
{
ob = p_docu.createElement("Canvas");
multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
for (int it = ml.size()-1; it > -1; it--)
{
if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
{
QDomElement ob2 = p_docu.createElement("Path");
ob2.setAttribute("Data", QString("M %1, %2 L %3, %4").arg(line.p1().x()).arg(line.p1().y()).arg(line.p2().x()).arg(line.p2().y()));
GetMultiStroke(&ml[it], ob2);
ob.appendChild(ob2);
}
}
if (Item->lineTransparency() != 0)
ob.setAttribute("Opacity", FToStr(1.0 - Item->lineTransparency()));
}
parentElem.appendChild(ob);
}
return;
}
 
void XPSExPlug::processImageItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root)
{
if (Item->GrType == 14)
processHatchFill(xOffset, yOffset, Item, parentElem, rel_root);
FPointArray path = Item->PoLine.copy();
path.translate(xOffset, yOffset);
path.scale(conversionFactor, conversionFactor);
QString pa = SetClipPath(&path, true);
if (Item->fillRule)
pa.prepend("F 0 ");
else
pa.prepend("F 1 ");
QDomElement grp = p_docu.createElement("Canvas");
QTransform mpx;
if (Item->rotation() != 0.0)
{
mpx.translate(xOffset * conversionFactor, yOffset * conversionFactor);
mpx.rotate(Item->rotation());
mpx.translate(-xOffset * conversionFactor, -yOffset * conversionFactor);
grp.setAttribute("RenderTransform", MatrixToStr(mpx));
}
if (Item->GrType != 14)
{
if (Item->GrMask > 0)
handleMask(1, Item, grp, rel_root, xOffset, yOffset);
else
{
if (Item->fillTransparency() != 0)
grp.setAttribute("Opacity", FToStr(1.0 - Item->fillTransparency()));
}
if ((Item->GrType != 0) || (Item->fillColor() != CommonStrings::None))
{
QDomElement ob = p_docu.createElement("Path");
ob.setAttribute("Data", pa);
getFillStyle(Item, ob, rel_root, xOffset, yOffset, false);
grp.appendChild(ob);
}
}
if ((Item->PictureIsAvailable) && (!Item->Pfile.isEmpty()))
{
QDomElement ob2 = p_docu.createElement("Path");
ob2.setAttribute("Data", pa);
ob2.setAttribute("Clip", pa);
QDomElement obf = p_docu.createElement("Path.Fill");
QDomElement gr = p_docu.createElement("ImageBrush");
ScImage img;
CMSettings cms(m_Doc, Item->IProfile, Item->IRender);
cms.setUseEmbeddedProfile(Item->UseEmbedded);
cms.allowSoftProofing(true);
img.loadPicture(Item->Pfile, Item->pixm.imgInfo.actualPageNumber, cms, ScImage::RGBData, 96);
img.applyEffect(Item->effectsInUse, m_Doc->PageColors, true);
img.qImagePtr()->setDotsPerMeterX(3780);
img.qImagePtr()->setDotsPerMeterY(3780);
img.qImage().save(baseDir + "/Resources/Images/" + QString("%1.png").arg(imageCounter), "PNG");
gr.setAttribute("TileMode", "None");
gr.setAttribute("ViewboxUnits", "Absolute");
gr.setAttribute("ViewportUnits", "Absolute");
gr.setAttribute("Viewport", "0,0,1,1");
gr.setAttribute("Viewbox", QString("0, 0, %1, %2").arg(img.width()).arg(img.height()));
QTransform mpx;
double xpos = Item->imageXOffset() * Item->imageXScale();
double ypos = Item->imageYOffset() * Item->imageYScale();
mpx.translate((xOffset + xpos) * conversionFactor, (yOffset + ypos) * conversionFactor);
mpx.scale(img.width() * Item->imageXScale() * conversionFactor, img.height() * Item->imageYScale() * conversionFactor);
if (Item->imageFlippedH())
{
mpx.translate(Item->width() / (img.width() * Item->imageXScale()), 0);
mpx.scale(-1, 1);
}
if (Item->imageFlippedV())
{
mpx.translate(0, Item->height() / (img.height() * Item->imageYScale()));
mpx.scale(1, -1);
}
mpx.rotate(Item->imageRotation());
gr.setAttribute("Transform", MatrixToStr(mpx));
gr.setAttribute("ImageSource", "/Resources/Images/" + QString("%1.png").arg(imageCounter));
QDomElement rel = r_docu.createElement("Relationship");
rel.setAttribute("Id", QString("rIDi%1").arg(imageCounter));
rel.setAttribute("Type", "http://schemas.microsoft.com/xps/2005/06/required-resource");
rel.setAttribute("Target", "/Resources/Images/" + QString("%1.png").arg(imageCounter));
rel_root.appendChild(rel);
imageCounter++;
obf.appendChild(gr);
ob2.appendChild(obf);
grp.appendChild(ob2);
}
parentElem.appendChild(grp);
if ((Item->GrTypeStroke != 0) || (Item->lineColor() != CommonStrings::None) || !Item->NamedLStyle.isEmpty())
{
if (Item->NamedLStyle.isEmpty())
{
if ((!Item->strokePattern().isEmpty()) && (Item->patternStrokePath))
{
processSymbolStroke(xOffset, yOffset, Item, parentElem, rel_root);
}
else
{
QDomElement ob3 = p_docu.createElement("Path");
ob3.setAttribute("Data", pa);
getStrokeStyle(Item, ob3, rel_root, xOffset, yOffset);
if (Item->rotation() != 0.0)
ob3.setAttribute("RenderTransform", MatrixToStr(mpx));
parentElem.appendChild(ob3);
}
}
else
{
QDomElement grp2 = p_docu.createElement("Canvas");
multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
for (int it = ml.size()-1; it > -1; it--)
{
if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
{
QDomElement ob3 = p_docu.createElement("Path");
ob3.setAttribute("Data", pa);
GetMultiStroke(&ml[it], ob3);
grp2.appendChild(ob3);
}
}
if (Item->lineTransparency() != 0)
grp2.setAttribute("Opacity", FToStr(1.0 - Item->lineTransparency()));
if (Item->rotation() != 0.0)
grp2.setAttribute("RenderTransform", MatrixToStr(mpx));
parentElem.appendChild(grp2);
}
}
return;
}
 
void XPSExPlug::processTextItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root)
{
if (Item->isAnnotation())
return;
if (Item->GrType == 14)
processHatchFill(xOffset, yOffset, Item, parentElem, rel_root);
FPointArray path = Item->PoLine.copy();
path.scale(conversionFactor, conversionFactor);
QString pa = SetClipPath(&path, true);
if (Item->fillRule)
pa.prepend("F 0 ");
else
pa.prepend("F 1 ");
QDomElement grp = p_docu.createElement("Canvas");
QTransform mpx;
QTransform mpl;
mpl.translate(xOffset * conversionFactor, yOffset * conversionFactor);
mpx.translate(xOffset * conversionFactor, yOffset * conversionFactor);
if ((Item->rotation() != 0.0) || Item->imageFlippedH() || Item->imageFlippedV())
{
mpx.rotate(Item->rotation());
mpl.rotate(Item->rotation());
if (Item->imageFlippedH())
{
mpx.translate(Item->width() * conversionFactor, 0);
mpx.scale(-1, 1);
}
if (Item->imageFlippedV())
{
mpx.translate(0, Item->height() * conversionFactor);
mpx.scale(1, -1);
}
}
grp.setAttribute("RenderTransform", MatrixToStr(mpx));
if (Item->isBookmark)
grp.setAttribute("Name", Item->itemName());
if (Item->GrType != 14)
{
if (Item->GrMask > 0)
handleMask(1, Item, grp, rel_root, xOffset, yOffset);
else
{
if (Item->fillTransparency() != 0)
grp.setAttribute("Opacity", FToStr(1.0 - Item->fillTransparency()));
}
if ((Item->GrType != 0) || (Item->fillColor() != CommonStrings::None))
{
FPointArray pathi = Item->PoLine.copy();
if (Item->imageFlippedH() || Item->imageFlippedV())
{
QTransform mpi;
if (Item->imageFlippedH())
{
mpi.translate(Item->width(), 0);
mpi.scale(-1, 1);
}
if (Item->imageFlippedV())
{
mpi.translate(0, Item->height());
mpi.scale(1, -1);
}
pathi.map(mpi);
}
pathi.scale(conversionFactor, conversionFactor);
QString pai = SetClipPath(&pathi, true);
if (Item->fillRule)
pai.prepend("F 0 ");
else
pai.prepend("F 1 ");
QDomElement ob = p_docu.createElement("Path");
ob.setAttribute("Data", pai);
getFillStyle(Item, ob, rel_root, xOffset, yOffset, false);
grp.appendChild(ob);
}
}
for (uint ll=0; ll < Item->textLayout.lines(); ++ll)
{
LineSpec ls = Item->textLayout.line(ll);
QList<txtRunItem> current_run;
QList<QList<txtRunItem> > textRuns;
QList<txtRunItem> specialText;
double CurX = ls.x;
for (int a = ls.firstItem; a <= ls.lastItem; ++a)
{
//ScText *hl = Item->itemText.item_p(a);
QChar chr = Item->itemText.text(a);
CharStyle charStyle = Item->itemText.charStyle(a);
GlyphLayout* glyphs = Item->itemText.getGlyphs(a);
LayoutFlags flags = Item->itemText.flags(a);
const ScFace* font = &charStyle.font();
txtRunItem txItem;
txItem.chr = chr;
txItem.glyphs = glyphs;
txItem.style = charStyle;
txItem.index = a;
txItem.CurX = CurX;
txItem.embItem = Item->itemText.hasObject(a)? Item->itemText.object(a) : NULL;
if (!((font->type() == ScFace::TTF) || (font->type() == ScFace::OTF)))
{
specialText.append(txItem);
textRuns.append(current_run);
current_run.clear();
CurX += txItem.glyphs->wide();
continue;
}
if (SpecialChars::isBreak(chr, true) || (chr == QChar(10)))
{
continue;
}
if (flags & ScLayout_SuppressSpace)
{
continue;
}
if ((chr == SpecialChars::OLD_NBSPACE) || (chr == SpecialChars::OBJECT) || (charStyle.effects() & ScStyle_UserStyles))
{
specialText.append(txItem);
textRuns.append(current_run);
current_run.clear();
CurX += txItem.glyphs->wide();
continue;
}
QString guidFont;
if (!xps_fontMap.contains(font->replacementName()))
{
guidFont = embedFont(font, rel_root);
xps_fontMap.insert(font->replacementName(), guidFont);
}
else
guidFont = xps_fontMap[font->replacementName()];
if (current_run.isEmpty())
current_run.append(txItem);
else
{
txtRunItem txItemL = current_run.last();
double chl = (txItemL.style.fontSize() / 10.0) * qMax(txItemL.glyphs->scaleV, txItemL.glyphs->scaleH) * conversionFactor;
const ScFace* fontL = &txItemL.style.font();
QString guidFontL = xps_fontMap[fontL->replacementName()];
StyleFlag old_sty = txItemL.style.effects();
int old_shade = txItemL.style.fillShade();
QString old_fill = txItemL.style.fillColor();
double chs = (charStyle.fontSize() / 10.0) * qMax(glyphs->scaleV, glyphs->scaleH) * conversionFactor;
if ((chs != chl) || (guidFont != guidFontL) || (charStyle.effects() != old_sty) || (charStyle.fillColor() != old_fill) || (charStyle.fillShade() != old_shade))
{
textRuns.append(current_run);
current_run.clear();
}
current_run.append(txItem);
}
CurX += txItem.glyphs->wide();
}
textRuns.append(current_run);
for (int txr = 0; txr < textRuns.count(); txr++)
{
QString uniString = "";
QString indString = "";
current_run = textRuns[txr];
if (current_run.isEmpty())
continue;
double StartX = current_run[0].CurX;
CurX = current_run[0].CurX;
double chs = (current_run[0].style.fontSize() / 10.0) * qMax(current_run[0].glyphs->scaleV, current_run[0].glyphs->scaleH) * conversionFactor;
for (int cr = 0; cr < current_run.count(); cr++)
{
txtRunItem txItem = current_run[cr];
if ((txItem.chr == SpecialChars::PAGENUMBER) || (txItem.chr == SpecialChars::PAGECOUNT))
{
QString exString = Item->ExpandToken(txItem.index);
for (int ex = 0; ex < exString.count(); ex++)
{
indString += ";";
}
uniString += exString;
}
else if ((SpecialChars::isBreakingSpace(txItem.chr)) || (SpecialChars::isExpandingSpace(txItem.chr)) || (txItem.chr.isSpace()))
{
indString += QString(",%1;").arg((txItem.glyphs->wide() * conversionFactor) / chs * 100);
uniString += " ";
}
else
{
uniString += txItem.chr;
if ((txItem.glyphs->xoffset != 0) || (txItem.glyphs->yoffset != 0))
indString += QString(",%1,%2,%3;").arg((txItem.glyphs->wide() * conversionFactor) / chs * 100).arg((txItem.glyphs->xoffset * conversionFactor) / chs * 100).arg((-txItem.glyphs->yoffset * conversionFactor) / chs * 100);
else
indString += QString(",%1;").arg((txItem.glyphs->wide() * conversionFactor) / chs * 100);
}
CurX += txItem.glyphs->wide();
}
if (!indString.isEmpty())
indString.chop(1);
QDomElement gly = p_docu.createElement("Glyphs");
gly.setAttribute("BidiLevel", "0");
gly.setAttribute("StyleSimulations", "None");
gly.setAttribute("FontRenderingEmSize", FToStr(chs));
const ScFace* fontL = &current_run[0].style.font();
gly.setAttribute("FontUri", xps_fontMap[fontL->replacementName()]);
gly.setAttribute("Fill", SetColor(current_run[0].style.fillColor(), current_run[0].style.fillShade(), 0));
gly.setAttribute("UnicodeString", uniString);
if (current_run.count() == 1)
{
gly.setAttribute("OriginX", FToStr((StartX + current_run[0].glyphs->xoffset) * conversionFactor));
gly.setAttribute("OriginY", FToStr((ls.y + current_run[0].glyphs->yoffset) * conversionFactor));
}
else
{
gly.setAttribute("OriginX", FToStr(StartX * conversionFactor));
gly.setAttribute("OriginY", FToStr(ls.y * conversionFactor));
gly.setAttribute("Indices", indString);
}
grp.appendChild(gly);
}
for (int cr = 0; cr < specialText.count(); cr++)
{
txtRunItem txItem = specialText[cr];
CurX = txItem.CurX;
if (txItem.chr == SpecialChars::OBJECT)
{
if (txItem.embItem != NULL)
{
QDomElement obO = p_docu.createElement("Canvas");
QTransform mm;
mm.translate(CurX * conversionFactor, (ls.y - (txItem.embItem->height() * (txItem.style.scaleV() / 1000.0))) * conversionFactor);
if (txItem.style.baselineOffset() != 0)
mm.translate(0, (txItem.style.baselineOffset() / 1000.0) * conversionFactor);
if (txItem.style.scaleH() != 1000)
mm.scale(txItem.style.scaleH() / 1000.0, 1);
if (txItem.style.scaleV() != 1000)
mm.scale(1, txItem.style.scaleV() / 1000.0);
obO.setAttribute("RenderTransform", MatrixToStr(mm));
QList<PageItem*> emG;
if (txItem.embItem->isGroup())
emG = txItem.embItem->getItemList();
else
emG.append(txItem.embItem);
for (int em = 0; em < emG.count(); ++em)
{
PageItem* embed = emG.at(em);
writeItemOnPage(embed->gXpos, embed->gYpos, embed, obO, rel_root);
}
grp.appendChild(obO);
}
continue;
}
QString chstr = txItem.chr;
if ((txItem.chr == SpecialChars::PAGENUMBER) || (txItem.chr == SpecialChars::PAGECOUNT))
chstr = Item->ExpandToken(txItem.index);
double chs = txItem.style.fontSize();
if (txItem.style.effects() & ScStyle_SmallCaps)
{
if (chstr.toUpper() != chstr)
{
chs = qMax(static_cast<int>(txItem.style.fontSize() * m_Doc->typographicPrefs().valueSmallCaps / 100), 1);
chstr = chstr.toUpper();
}
}
else if (txItem.style.effects() & ScStyle_AllCaps)
chstr = chstr.toUpper();
for (int cx = 0; cx < chstr.count(); cx++)
{
FPointArray pts;
QChar chstrex = chstr[cx];
uint chr = chstrex.unicode();
QTransform chma;
uint gl = txItem.style.font().char2CMap(chr);
if (!chstrex.isSpace())
{
pts = txItem.style.font().glyphOutline(gl);
if (pts.size() < 4)
continue;
chma = QTransform();
chma.scale(txItem.glyphs->scaleH * txItem.style.fontSize() / 100.00, txItem.glyphs->scaleV * txItem.style.fontSize() / 100.0);
pts.map(chma);
if (txItem.style.effects() & (ScStyle_Subscript | ScStyle_Superscript))
pts.translate(0, -(chs / 10.0 * txItem.glyphs->scaleV));
else
pts.translate(0, -(chs / 10.0));
pts.translate(CurX, ls.y);
if (txItem.style.effects() & (ScStyle_Subscript | ScStyle_Superscript))
pts.translate(0, txItem.glyphs->yoffset);
if ((txItem.style.effects() & ScStyle_Shadowed) && (txItem.style.strokeColor() != CommonStrings::None))
{
FPointArray ptsS = pts.copy();
ptsS.translate(txItem.style.fontSize() * txItem.style.shadowXOffset() / 10000.0, -txItem.style.fontSize() * txItem.style.shadowYOffset() / 10000.0);
ptsS.scale(conversionFactor, conversionFactor);
QString paS = SetClipPath(&ptsS, true);
QDomElement glyS = p_docu.createElement("Path");
glyS.setAttribute("Data", paS);
glyS.setAttribute("Fill", SetColor(txItem.style.strokeColor(), txItem.style.strokeShade(), 0));
grp.appendChild(glyS);
}
pts.scale(conversionFactor, conversionFactor);
QString pa = SetClipPath(&pts, true);
QDomElement gly = p_docu.createElement("Path");
gly.setAttribute("Data", pa);
gly.setAttribute("Fill", SetColor(txItem.style.fillColor(), txItem.style.fillShade(), 0));
if (txItem.style.effects() & ScStyle_Outline)
{
gly.setAttribute("StrokeThickness", FToStr((chs * txItem.style.outlineWidth() / 10000.0) * conversionFactor));
gly.setAttribute("Stroke", SetColor(txItem.style.strokeColor(), txItem.style.strokeShade(), 0));
}
grp.appendChild(gly);
}
if ((txItem.style.effects() & ScStyle_Underline) || ((txItem.style.effects() & ScStyle_UnderlineWords) && chstr.toUInt() != txItem.style.font().char2CMap(QChar(' '))))
{
double st, lw;
if ((txItem.style.underlineOffset() != -1) || (txItem.style.underlineWidth() != -1))
{
if (txItem.style.underlineOffset() != -1)
st = (txItem.style.underlineOffset() / 1000.0) * (txItem.style.font().descent(txItem.style.fontSize() / 10.0));
else
st = txItem.style.font().underlinePos(txItem.style.fontSize() / 10.0);
if (txItem.style.underlineWidth() != -1)
lw = (txItem.style.underlineWidth() / 1000.0) * (txItem.style.fontSize() / 10.0);
else
lw = qMax(txItem.style.font().strokeWidth(txItem.style.fontSize() / 10.0), 1.0);
}
else
{
st = txItem.style.font().underlinePos(txItem.style.fontSize() / 10.0);
lw = qMax(txItem.style.font().strokeWidth(txItem.style.fontSize() / 10.0), 1.0);
}
if (txItem.style.baselineOffset() != 0)
st += (txItem.style.fontSize() / 10.0) * txItem.glyphs->scaleV * (txItem.style.baselineOffset() / 1000.0);
QDomElement gly = p_docu.createElement("Path");
if (txItem.style.effects() & ScStyle_Subscript)
gly.setAttribute("Data", QString("M%1,%2 L%3,%4").arg((CurX + txItem.glyphs->xoffset) * conversionFactor).arg((ls.y + txItem.glyphs->yoffset - st) * conversionFactor).arg((CurX + txItem.glyphs->xoffset + txItem.glyphs->xadvance) * conversionFactor).arg((ls.y + txItem.glyphs->yoffset - st) * conversionFactor));
else
gly.setAttribute("Data", QString("M%1,%2 L%3,%4").arg((CurX + txItem.glyphs->xoffset) * conversionFactor).arg((ls.y - st) * conversionFactor).arg((CurX + txItem.glyphs->xoffset + txItem.glyphs->xadvance) * conversionFactor).arg((ls.y - st) * conversionFactor));
gly.setAttribute("Stroke", SetColor(txItem.style.fillColor(), txItem.style.fillShade(), 0));
gly.setAttribute("StrokeThickness", FToStr(lw * conversionFactor));
grp.appendChild(gly);
}
if (txItem.style.effects() & ScStyle_Strikethrough)
{
double st, lw;
if ((txItem.style.strikethruOffset() != -1) || (txItem.style.underlineWidth() != -1))
{
if (txItem.style.strikethruOffset() != -1)
st = (txItem.style.strikethruOffset() / 1000.0) * (txItem.style.font().ascent(txItem.style.fontSize() / 10.0));
else
st = txItem.style.font().strikeoutPos(txItem.style.fontSize() / 10.0);
if (txItem.style.strikethruWidth() != -1)
lw = (txItem.style.strikethruWidth() / 1000.0) * (txItem.style.fontSize() / 10.0);
else
lw = qMax(txItem.style.font().strokeWidth(txItem.style.fontSize() / 10.0), 1.0);
}
else
{
st = txItem.style.font().strikeoutPos(txItem.style.fontSize() / 10.0);
lw = qMax(txItem.style.font().strokeWidth(txItem.style.fontSize() / 10.0), 1.0);
}
if (txItem.style.baselineOffset() != 0)
st += (txItem.style.fontSize() / 10.0) * txItem.glyphs->scaleV * (txItem.style.baselineOffset() / 1000.0);
QDomElement gly = p_docu.createElement("Path");
gly.setAttribute("Data", QString("M%1,%2 L%3,%4").arg((CurX + txItem.glyphs->xoffset) * conversionFactor).arg((ls.y - st) * conversionFactor).arg((CurX + txItem.glyphs->xoffset + txItem.glyphs->xadvance) * conversionFactor).arg((ls.y - st) * conversionFactor));
gly.setAttribute("Stroke", SetColor(txItem.style.fillColor(), txItem.style.fillShade(), 0));
gly.setAttribute("StrokeThickness", FToStr(lw * conversionFactor));
grp.appendChild(gly);
}
}
}
}
parentElem.appendChild(grp);
if ((Item->GrTypeStroke != 0) || (Item->lineColor() != CommonStrings::None) || !Item->NamedLStyle.isEmpty())
{
if (Item->NamedLStyle.isEmpty())
{
if ((!Item->strokePattern().isEmpty()) && (Item->patternStrokePath))
{
processSymbolStroke(xOffset, yOffset, Item, parentElem, rel_root);
}
else
{
QDomElement ob3 = p_docu.createElement("Path");
ob3.setAttribute("Data", pa);
getStrokeStyle(Item, ob3, rel_root, xOffset, yOffset);
ob3.setAttribute("RenderTransform", MatrixToStr(mpl));
parentElem.appendChild(ob3);
}
}
else
{
QDomElement grp2 = p_docu.createElement("Canvas");
multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
for (int it = ml.size()-1; it > -1; it--)
{
if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
{
QDomElement ob3 = p_docu.createElement("Path");
ob3.setAttribute("Data", pa);
GetMultiStroke(&ml[it], ob3);
grp2.appendChild(ob3);
}
}
if (Item->lineTransparency() != 0)
grp2.setAttribute("Opacity", FToStr(1.0 - Item->lineTransparency()));
grp2.setAttribute("RenderTransform", MatrixToStr(mpl));
parentElem.appendChild(grp2);
}
}
}
 
void XPSExPlug::processPathTextItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root)
{
QDomElement grp = p_docu.createElement("Canvas");
QTransform mpx;
mpx.translate(xOffset * conversionFactor, yOffset * conversionFactor);
if ((Item->rotation() != 0.0) || Item->imageFlippedH() || Item->imageFlippedV())
{
mpx.rotate(Item->rotation());
if (Item->imageFlippedH())
{
mpx.translate(Item->width() * conversionFactor, 0);
mpx.scale(-1, 1);
}
if (Item->imageFlippedV())
{
mpx.translate(0, Item->height() * conversionFactor);
mpx.scale(1, -1);
}
}
grp.setAttribute("RenderTransform", MatrixToStr(mpx));
if ((Item->PoShow) && (Item->lineColor() != CommonStrings::None))
{
QDomElement ob = p_docu.createElement("Path");
FPointArray path = Item->PoLine.copy();
path.scale(conversionFactor, conversionFactor);
QString pa = SetClipPath(&path, false);
ob.setAttribute("Data", pa);
if (Item->NamedLStyle.isEmpty())
{
if ((!Item->strokePattern().isEmpty()) && (Item->patternStrokePath))
{
processSymbolStroke(xOffset, yOffset, Item, parentElem, rel_root);
}
else
{
getStrokeStyle(Item, ob, rel_root, xOffset, yOffset);
grp.appendChild(ob);
}
}
else
{
QDomElement grp2 = p_docu.createElement("Canvas");
multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
for (int it = ml.size()-1; it > -1; it--)
{
if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
{
QDomElement ob3 = p_docu.createElement("Path");
ob3.setAttribute("Data", pa);
GetMultiStroke(&ml[it], ob3);
grp2.appendChild(ob3);
}
}
if (Item->lineTransparency() != 0)
grp2.setAttribute("Opacity", FToStr(1.0 - Item->lineTransparency()));
grp.appendChild(grp2);
}
}
QString chstr;
for (int a = 0; a < Item->asPathText()->itemRenderText.length(); ++a)
{
//ScText *hl = Item->asPathText()->itemRenderText.item_p(a);
const CharStyle& charStyle(Item->asPathText()->itemRenderText.charStyle(a));
const PathData* pdata = &(Item->asPathText()->textLayout.point(a));
const GlyphLayout* glyphs = Item->asPathText()->itemRenderText.getGlyphs(a);
PageItem* embItem = Item->asPathText()->itemRenderText.hasObject(a)?
Item->asPathText()->itemRenderText.object(a) : NULL;
chstr = Item->asPathText()->itemRenderText.text(a,1);
if ((chstr == QChar(13)) || (chstr == QChar(29)))
continue;
if (chstr == QChar(30))
{
chstr = Item->ExpandToken(a);
if (chstr == QChar(32))
continue;
}
double chs = charStyle.fontSize();
if (charStyle.effects() & ScStyle_SmallCaps)
{
if (chstr.toUpper() != chstr)
{
chs = qMax(static_cast<int>(charStyle.fontSize() * m_Doc->typographicPrefs().valueSmallCaps / 100), 1);
chstr = chstr.toUpper();
}
}
else if (charStyle.effects() & ScStyle_AllCaps)
chstr = chstr.toUpper();
uint chr = chstr[0].unicode();
QPointF tangt = QPointF( cos(pdata->PRot), sin(pdata->PRot) );
QTransform trafo = QTransform( 1, 0, 0, -1, -pdata->PDx * conversionFactor, 0 );
if (Item->textPathFlipped)
trafo *= QTransform(1, 0, 0, -1, 0, 0);
if (Item->textPathType == 0)
trafo *= QTransform( tangt.x(), tangt.y(), tangt.y(), -tangt.x(), pdata->PtransX * conversionFactor, pdata->PtransY * conversionFactor );
else if (Item->textPathType == 1)
trafo *= QTransform(1, 0, 0, -1, pdata->PtransX * conversionFactor, pdata->PtransY * conversionFactor );
else if (Item->textPathType == 2)
{
double a = 1;
if (tangt.x() < 0)
a = -1;
if (fabs(tangt.x()) > 0.1)
trafo *= QTransform( a, (tangt.y() / tangt.x()) * a, 0, -1, pdata->PtransX * conversionFactor, pdata->PtransY * conversionFactor ); // ID's Skew mode
else
trafo *= QTransform( a, 4 * a, 0, -1, pdata->PtransX * conversionFactor, pdata->PtransY * conversionFactor );
}
if (charStyle.baselineOffset() != 0)
trafo.translate(0, (-charStyle.fontSize() / 10.0) * (charStyle.baselineOffset() / 1000.0));
trafo.translate(0, Item->BaseOffs);
QTransform finalMat = trafo;
if (chr == SpecialChars::OBJECT)
{
if (embItem != NULL)
{
QDomElement obO = p_docu.createElement("Canvas");
QTransform mm = finalMat;
mm.translate(0, (-(embItem->height() * (charStyle.scaleV() / 1000.0))) * conversionFactor);
if (charStyle.scaleH() != 1000)
mm.scale(charStyle.scaleH() / 1000.0, 1);
if (charStyle.scaleV() != 1000)
mm.scale(1, charStyle.scaleV() / 1000.0);
obO.setAttribute("RenderTransform", MatrixToStr(mm));
QList<PageItem*> emG;
if (embItem->isGroup())
emG = embItem->getItemList();
else
emG.append(embItem);
for (int em = 0; em < emG.count(); ++em)
{
PageItem* embed = emG.at(em);
writeItemOnPage(embed->gXpos, embed->gYpos, embed, obO, rel_root);
}
grp.appendChild(obO);
}
continue;
}
finalMat.scale(conversionFactor, conversionFactor);
FPointArray pts;
QTransform chma;
uint gl = charStyle.font().char2CMap(chr);
pts = charStyle.font().glyphOutline(gl);
if (pts.size() < 4)
continue;
chma = QTransform();
chma.scale(glyphs->scaleH * charStyle.fontSize() / 100.00, glyphs->scaleV * charStyle.fontSize() / 100.0);
pts.map(chma);
if (charStyle.effects() & (ScStyle_Subscript | ScStyle_Superscript))
pts.translate(0, -(chs / 10.0 * glyphs->scaleV));
else
pts.translate(0, -(chs / 10.0));
if (charStyle.effects() & (ScStyle_Subscript | ScStyle_Superscript))
pts.translate(0, glyphs->yoffset);
if ((charStyle.effects() & ScStyle_Shadowed) && (charStyle.strokeColor() != CommonStrings::None))
{
FPointArray ptsS = pts.copy();
ptsS.translate(charStyle.fontSize() * charStyle.shadowXOffset() / 10000.0, -charStyle.fontSize() * charStyle.shadowYOffset() / 10000.0);
ptsS.map(finalMat);
QString paS = SetClipPath(&ptsS, true);
QDomElement glyS = p_docu.createElement("Path");
glyS.setAttribute("Data", paS);
glyS.setAttribute("Fill", SetColor(charStyle.strokeColor(), charStyle.strokeShade(), 0));
grp.appendChild(glyS);
}
pts.map(finalMat);
QString pa = SetClipPath(&pts, true);
QDomElement gly = p_docu.createElement("Path");
gly.setAttribute("Data", pa);
gly.setAttribute("Fill", SetColor(charStyle.fillColor(), charStyle.fillShade(), 0));
if (charStyle.effects() & ScStyle_Outline)
{
gly.setAttribute("StrokeThickness", FToStr((chs * charStyle.outlineWidth() / 10000.0) * conversionFactor));
gly.setAttribute("Stroke", SetColor(charStyle.strokeColor(), charStyle.strokeShade(), 0));
}
grp.appendChild(gly);
if ((charStyle.effects() & ScStyle_Underline) || ((charStyle.effects() & ScStyle_UnderlineWords) && chstr.toUInt() != charStyle.font().char2CMap(QChar(' '))))
{
double st, lw;
if ((charStyle.underlineOffset() != -1) || (charStyle.underlineWidth() != -1))
{
if (charStyle.underlineOffset() != -1)
st = (charStyle.underlineOffset() / 1000.0) * (charStyle.font().descent(charStyle.fontSize() / 10.0));
else
st = charStyle.font().underlinePos(charStyle.fontSize() / 10.0);
if (charStyle.underlineWidth() != -1)
lw = (charStyle.underlineWidth() / 1000.0) * (charStyle.fontSize() / 10.0);
else
lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
}
else
{
st = charStyle.font().underlinePos(charStyle.fontSize() / 10.0);
lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
}
if (charStyle.baselineOffset() != 0)
st += (charStyle.fontSize() / 10.0) * glyphs->scaleV * (charStyle.baselineOffset() / 1000.0);
FPointArray ptsS;
ptsS.svgInit();
if (charStyle.effects() & ScStyle_Subscript)
{
ptsS.svgMoveTo(glyphs->xoffset, glyphs->yoffset - st);
ptsS.svgLineTo(glyphs->xoffset + glyphs->xadvance, glyphs->yoffset - st);
}
else
{
ptsS.svgMoveTo(glyphs->xoffset, -st);
ptsS.svgLineTo(glyphs->xoffset + glyphs->xadvance, -st);
}
ptsS.map(finalMat);
QString paS = SetClipPath(&ptsS, true);
QDomElement gly = p_docu.createElement("Path");
gly.setAttribute("Data", paS);
gly.setAttribute("Stroke", SetColor(charStyle.fillColor(), charStyle.fillShade(), 0));
gly.setAttribute("StrokeThickness", FToStr(lw * conversionFactor));
grp.appendChild(gly);
}
if (charStyle.effects() & ScStyle_Strikethrough)
{
double st, lw;
if ((charStyle.strikethruOffset() != -1) || (charStyle.underlineWidth() != -1))
{
if (charStyle.strikethruOffset() != -1)
st = (charStyle.strikethruOffset() / 1000.0) * (charStyle.font().ascent(charStyle.fontSize() / 10.0));
else
st = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0);
if (charStyle.strikethruWidth() != -1)
lw = (charStyle.strikethruWidth() / 1000.0) * (charStyle.fontSize() / 10.0);
else
lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
}
else
{
st = charStyle.font().strikeoutPos(charStyle.fontSize() / 10.0);
lw = qMax(charStyle.font().strokeWidth(charStyle.fontSize() / 10.0), 1.0);
}
if (charStyle.baselineOffset() != 0)
st += (charStyle.fontSize() / 10.0) * glyphs->scaleV * (charStyle.baselineOffset() / 1000.0);
FPointArray ptsS;
ptsS.svgInit();
ptsS.svgMoveTo(glyphs->xoffset, -st);
ptsS.svgLineTo(glyphs->xoffset + glyphs->xadvance, -st);
ptsS.map(finalMat);
QString paS = SetClipPath(&ptsS, true);
QDomElement gly = p_docu.createElement("Path");
gly.setAttribute("Data", paS);
gly.setAttribute("Stroke", SetColor(charStyle.fillColor(), charStyle.fillShade(), 0));
gly.setAttribute("StrokeThickness", FToStr(lw * conversionFactor));
grp.appendChild(gly);
}
}
parentElem.appendChild(grp);
return;
}
 
void XPSExPlug::processSymbolItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root)
{
QDomElement ob = p_docu.createElement("Canvas");
FPointArray path = Item->PoLine.copy();
ScPattern pat = m_Doc->docPatterns[Item->pattern()];
path.scale(conversionFactor, conversionFactor);
path.scale(pat.width / Item->width(), pat.height / Item->height());
SetClipAttr(ob, &path, Item->fillRule);
QTransform mpx;
mpx.translate(xOffset * conversionFactor, yOffset * conversionFactor);
mpx.scale(Item->width() / pat.width, Item->height() / pat.height);
if ((Item->rotation() != 0.0) || Item->imageFlippedH() || Item->imageFlippedV())
{
mpx.rotate(Item->rotation());
if (Item->imageFlippedH())
{
mpx.translate(Item->width() * conversionFactor, 0);
mpx.scale(-1, 1);
}
if (Item->imageFlippedV())
{
mpx.translate(0, Item->height() * conversionFactor);
mpx.scale(1, -1);
}
}
ob.setAttribute("RenderTransform", MatrixToStr(mpx));
if (Item->GrMask > 0)
handleMask(1, Item, ob, rel_root, xOffset, yOffset);
else
{
if (Item->fillTransparency() != 0)
ob.setAttribute("Opacity", FToStr(1.0 - Item->fillTransparency()));
}
for (int em = 0; em < pat.items.count(); ++em)
{
PageItem* embed = pat.items.at(em);
writeItemOnPage(embed->gXpos, embed->gYpos, embed, ob, rel_root);
}
parentElem.appendChild(ob);
return;
}
 
void XPSExPlug::processTableItem(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root)
{
QDomElement ob = p_docu.createElement("Canvas");
QTransform mpx;
mpx.translate(xOffset * conversionFactor, yOffset * conversionFactor);
if (Item->rotation() != 0.0)
mpx.rotate(Item->rotation());
mpx.translate(Item->asTable()->gridOffset().x() * conversionFactor, Item->asTable()->gridOffset().y() * conversionFactor);
ob.setAttribute("RenderTransform", MatrixToStr(mpx));
// Paint table fill.
if (Item->asTable()->fillColor() != CommonStrings::None)
{
int lastCol = Item->asTable()->columns() - 1;
int lastRow = Item->asTable()->rows() - 1;
double x = Item->asTable()->columnPosition(0);
double y = Item->asTable()->rowPosition(0);
double width = Item->asTable()->columnPosition(lastCol) + Item->asTable()->columnWidth(lastCol) - x;
double height = Item->asTable()->rowPosition(lastRow) + Item->asTable()->rowHeight(lastRow) - y;
FPointArray path;
path.svgInit();
path.svgMoveTo(0, 0);
path.svgLineTo(width, 0);
path.svgLineTo(width, height);
path.svgLineTo(0, height);
path.svgClosePath();
path.scale(conversionFactor, conversionFactor);
QString pa = SetClipPath(&path, true);
QDomElement cl = p_docu.createElement("Path");
cl.setAttribute("Data", pa);
cl.setAttribute("Fill", SetColor(Item->asTable()->fillColor(), Item->asTable()->fillShade(), 0));
ob.appendChild(cl);
}
// Pass 1: Paint cell fills.
for (int row = 0; row < Item->asTable()->rows(); ++row)
{
int colSpan = 0;
for (int col = 0; col < Item->asTable()->columns(); col += colSpan)
{
TableCell cell = Item->asTable()->cellAt(row, col);
if (row == cell.row())
{
QString colorName = cell.fillColor();
if (colorName != CommonStrings::None)
{
int row = cell.row();
int col = cell.column();
int lastRow = row + cell.rowSpan() - 1;
int lastCol = col + cell.columnSpan() - 1;
double x = Item->asTable()->columnPosition(col);
double y = Item->asTable()->rowPosition(row);
double width = Item->asTable()->columnPosition(lastCol) + Item->asTable()->columnWidth(lastCol) - x;
double height = Item->asTable()->rowPosition(lastRow) + Item->asTable()->rowHeight(lastRow) - y;
FPointArray path;
path.svgInit();
path.svgMoveTo(x, y);
path.svgLineTo(x + width, y);
path.svgLineTo(x + width, y + height);
path.svgLineTo(x, y + height);
path.svgClosePath();
path.scale(conversionFactor, conversionFactor);
QString pa = SetClipPath(&path, true);
QDomElement cl = p_docu.createElement("Path");
cl.setAttribute("Data", pa);
cl.setAttribute("Fill", SetColor(colorName, cell.fillShade(), 0));
ob.appendChild(cl);
}
}
colSpan = cell.columnSpan();
}
}
// Pass 2: Paint vertical borders.
for (int row = 0; row < Item->asTable()->rows(); ++row)
{
int colSpan = 0;
for (int col = 0; col < Item->asTable()->columns(); col += colSpan)
{
TableCell cell = Item->asTable()->cellAt(row, col);
if (row == cell.row())
{
const int lastRow = cell.row() + cell.rowSpan() - 1;
const int lastCol = cell.column() + cell.columnSpan() - 1;
const double borderX = Item->asTable()->columnPosition(lastCol) + Item->asTable()->columnWidth(lastCol);
QPointF start(borderX, 0.0);
QPointF end(borderX, 0.0);
QPointF startOffsetFactors, endOffsetFactors;
int startRow, endRow;
for (int row = cell.row(); row <= lastRow; row += endRow - startRow + 1)
{
TableCell rightCell = Item->asTable()->cellAt(row, lastCol + 1);
startRow = qMax(cell.row(), rightCell.row());
endRow = qMin(lastRow, rightCell.isValid() ? rightCell.row() + rightCell.rowSpan() - 1 : lastRow);
TableCell topLeftCell = Item->asTable()->cellAt(startRow - 1, lastCol);
TableCell topRightCell = Item->asTable()->cellAt(startRow - 1, lastCol + 1);
TableCell bottomRightCell = Item->asTable()->cellAt(endRow + 1, lastCol + 1);
TableCell bottomLeftCell = Item->asTable()->cellAt(endRow + 1, lastCol);
TableBorder topLeft, top, topRight, border, bottomLeft, bottom, bottomRight;
resolveBordersVertical(topLeftCell, topRightCell, cell, rightCell, bottomLeftCell, bottomRightCell,
&topLeft, &top, &topRight, &border, &bottomLeft, &bottom, &bottomRight, Item->asTable());
if (border.isNull())
continue; // Quit early if the border to paint is null.
start.setY(Item->asTable()->rowPosition(startRow));
end.setY((Item->asTable()->rowPosition(endRow) + Item->asTable()->rowHeight(endRow)));
joinVertical(border, topLeft, top, topRight, bottomLeft, bottom, bottomRight, &start, &end, &startOffsetFactors, &endOffsetFactors);
paintBorder(border, start, end, startOffsetFactors, endOffsetFactors, ob);
}
if (col == 0)
{
const int lastRow = cell.row() + cell.rowSpan() - 1;
const int firstCol = cell.column();
const double borderX = Item->asTable()->columnPosition(firstCol);
QPointF start(borderX, 0.0);
QPointF end(borderX, 0.0);
QPointF startOffsetFactors, endOffsetFactors;
int startRow, endRow;
for (int row = cell.row(); row <= lastRow; row += endRow - startRow + 1)
{
TableCell leftCell = Item->asTable()->cellAt(row, firstCol - 1);
startRow = qMax(cell.row(), leftCell.row());
endRow = qMin(lastRow, leftCell.isValid() ? leftCell.row() + leftCell.rowSpan() - 1 : lastRow);
TableCell topLeftCell = Item->asTable()->cellAt(startRow - 1, firstCol - 1);
TableCell topRightCell = Item->asTable()->cellAt(startRow - 1, firstCol);
TableCell bottomRightCell = Item->asTable()->cellAt(lastRow + 1, firstCol);
TableCell bottomLeftCell = Item->asTable()->cellAt(lastRow + 1, firstCol - 1);
TableBorder topLeft, top, topRight, border, bottomLeft, bottom, bottomRight;
resolveBordersVertical(topLeftCell, topRightCell, leftCell, cell, bottomLeftCell, bottomRightCell,
&topLeft, &top, &topRight, &border, &bottomLeft, &bottom, &bottomRight, Item->asTable());
if (border.isNull())
continue; // Quit early if the border to paint is null.
start.setY(Item->asTable()->rowPosition(startRow));
end.setY((Item->asTable()->rowPosition(endRow) + Item->asTable()->rowHeight(endRow)));
joinVertical(border, topLeft, top, topRight, bottomLeft, bottom, bottomRight, &start, &end, &startOffsetFactors, &endOffsetFactors);
paintBorder(border, start, end, startOffsetFactors, endOffsetFactors, ob);
}
}
}
colSpan = cell.columnSpan();
}
}
// Pass 3: Paint horizontal borders.
for (int row = 0; row < Item->asTable()->rows(); ++row)
{
int colSpan = 0;
for (int col = 0; col < Item->asTable()->columns(); col += colSpan)
{
TableCell cell = Item->asTable()->cellAt(row, col);
if (row == cell.row())
{
const int lastRow = cell.row() + cell.rowSpan() - 1;
const int lastCol = cell.column() + cell.columnSpan() - 1;
const double borderY = (Item->asTable()->rowPosition(lastRow) + Item->asTable()->rowHeight(lastRow));
QPointF start(0.0, borderY);
QPointF end(0.0, borderY);
QPointF startOffsetFactors, endOffsetFactors;
int startCol, endCol;
for (int col = cell.column(); col <= lastCol; col += endCol - startCol + 1)
{
TableCell bottomCell = Item->asTable()->cellAt(lastRow + 1, col);
startCol = qMax(cell.column(), bottomCell.column());
endCol = qMin(lastCol, bottomCell.isValid() ? bottomCell.column() + bottomCell.columnSpan() - 1 : lastCol);
TableCell topLeftCell = Item->asTable()->cellAt(lastRow, startCol - 1);
TableCell topRightCell = Item->asTable()->cellAt(lastRow, endCol + 1);
TableCell bottomRightCell = Item->asTable()->cellAt(lastRow + 1, endCol + 1);
TableCell bottomLeftCell = Item->asTable()->cellAt(lastRow + 1, startCol - 1);
TableBorder topLeft, left, bottomLeft, border, topRight, right, bottomRight;
resolveBordersHorizontal(topLeftCell, cell, topRightCell, bottomLeftCell, bottomCell,
bottomRightCell, &topLeft, &left, &bottomLeft, &border, &topRight, &right, &bottomRight, Item->asTable());
if (border.isNull())
continue; // Quit early if the border is null.
start.setX(Item->asTable()->columnPosition(startCol));
end.setX(Item->asTable()->columnPosition(endCol) + Item->asTable()->columnWidth(endCol));
joinHorizontal(border, topLeft, left, bottomLeft, topRight, right, bottomRight, &start, &end, &startOffsetFactors, &endOffsetFactors);
paintBorder(border, start, end, startOffsetFactors, endOffsetFactors, ob);
}
if (row == 0)
{
const int firstRow = cell.row();
const int lastCol = cell.column() + cell.columnSpan() - 1;
const double borderY = Item->asTable()->rowPosition(firstRow);
QPointF start(0.0, borderY);
QPointF end(0.0, borderY);
QPointF startOffsetFactors, endOffsetFactors;
int startCol, endCol;
for (int col = cell.column(); col <= lastCol; col += endCol - startCol + 1)
{
TableCell topCell = Item->asTable()->cellAt(firstRow - 1, col);
startCol = qMax(cell.column(), topCell.column());
endCol = qMin(lastCol, topCell.isValid() ? topCell.column() + topCell.columnSpan() - 1 : lastCol);
TableCell topLeftCell = Item->asTable()->cellAt(firstRow - 1, startCol - 1);
TableCell topRightCell = Item->asTable()->cellAt(firstRow - 1, endCol + 1);
TableCell bottomRightCell = Item->asTable()->cellAt(firstRow, endCol + 1);
TableCell bottomLeftCell = Item->asTable()->cellAt(firstRow, startCol - 1);
TableBorder topLeft, left, bottomLeft, border, topRight, right, bottomRight;
resolveBordersHorizontal(topLeftCell, topCell, topRightCell, bottomLeftCell, cell,
bottomRightCell, &topLeft, &left, &bottomLeft, &border, &topRight, &right, &bottomRight, Item->asTable());
if (border.isNull())
continue; // Quit early if the border is null.
start.setX(Item->asTable()->columnPosition(startCol));
end.setX(Item->asTable()->columnPosition(endCol) + Item->asTable()->columnWidth(endCol));
joinHorizontal(border, topLeft, left, bottomLeft, topRight, right, bottomRight, &start, &end, &startOffsetFactors, &endOffsetFactors);
paintBorder(border, start, end, startOffsetFactors, endOffsetFactors, ob);
}
}
}
colSpan = cell.columnSpan();
}
}
// Pass 4: Paint cell content.
for (int row = 0; row < Item->asTable()->rows(); ++row)
{
for (int col = 0; col < Item->asTable()->columns(); col ++)
{
TableCell cell = Item->asTable()->cellAt(row, col);
if (cell.row() == row && cell.column() == col)
{
PageItem* textFrame = cell.textFrame();
processTextItem(cell.contentRect().x(), cell.contentRect().y(), textFrame, ob, rel_root);
}
}
}
if (Item->GrMask > 0)
handleMask(1, Item, ob, rel_root, xOffset, yOffset);
else
{
if (Item->fillTransparency() != 0)
ob.setAttribute("Opacity", FToStr(1.0 - Item->fillTransparency()));
}
parentElem.appendChild(ob);
}
 
void XPSExPlug::paintBorder(const TableBorder& border, const QPointF& start, const QPointF& end, const QPointF& startOffsetFactors, const QPointF& endOffsetFactors, QDomElement &ob)
{
QPointF lineStart, lineEnd;
foreach (const TableBorderLine& line, border.borderLines())
{
lineStart.setX(start.x() + line.width() * startOffsetFactors.x());
lineStart.setY(start.y() + line.width() * startOffsetFactors.y());
lineEnd.setX(end.x() + line.width() * endOffsetFactors.x());
lineEnd.setY(end.y() + line.width() * endOffsetFactors.y());
QDomElement cl = p_docu.createElement("Path");
cl.setAttribute("Data", "M"+FToStr(lineStart.x() * conversionFactor)+","+FToStr(lineStart.y() * conversionFactor)+" L"+FToStr(lineEnd.x() * conversionFactor)+" "+FToStr(lineEnd.y() * conversionFactor));
QString dashVals = "";
if (line.style() != Qt::SolidLine)
dashVals = getDashString(line.style(), qMax(line.width(), 1.0));
if (!dashVals.isEmpty())
cl.setAttribute("StrokeDashArray", dashVals);
if (line.color() != CommonStrings::None)
cl.setAttribute("Stroke", SetColor(line.color(), line.shade(), 0));
if (line.width() != 0.0)
cl.setAttribute("StrokeThickness", FToStr(line.width() * conversionFactor));
else
cl.setAttribute("StrokeThickness", FToStr(1.0 * conversionFactor));
ob.appendChild(cl);
}
}
 
void XPSExPlug::processHatchFill(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root)
{
QDomElement obC = p_docu.createElement("Canvas");
FPointArray path = Item->PoLine.copy();
path.scale(conversionFactor, conversionFactor);
SetClipAttr(obC, &path, Item->fillRule);
if (Item->GrMask > 0)
handleMask(1, Item, obC, rel_root, xOffset, yOffset);
else
{
if (Item->fillTransparency() != 0)
obC.setAttribute("Opacity", FToStr(1.0 - Item->fillTransparency()));
}
QTransform mpo;
mpo.translate(xOffset * conversionFactor, yOffset * conversionFactor);
if (Item->rotation() != 0.0)
mpo.rotate(Item->rotation());
obC.setAttribute("RenderTransform", MatrixToStr(mpo));
if (Item->hatchUseBackground)
{
FPointArray path;
path.svgInit();
path.svgMoveTo(0, 0);
path.svgLineTo(Item->width(), 0);
path.svgLineTo(Item->width(), Item->height());
path.svgLineTo(0, Item->height());
path.svgClosePath();
path.scale(conversionFactor, conversionFactor);
QString pa = SetClipPath(&path, true);
QDomElement cl = p_docu.createElement("Path");
cl.setAttribute("Data", pa);
cl.setAttribute("Fill", SetColor(Item->hatchBackground, 100, 0));
obC.appendChild(cl);
}
double lineLen = sqrt((Item->width() / 2.0) * (Item->width() / 2.0) + (Item->height() / 2.0) * (Item->height() / 2.0)) * conversionFactor;
double dist = 0.0;
while (dist < lineLen)
{
QTransform mpx;
mpx.translate((Item->width() / 2.0) * conversionFactor, (Item->height() / 2.0) * conversionFactor);
if (Item->hatchAngle != 0.0)
mpx.rotate(-Item->hatchAngle);
QDomElement ob = p_docu.createElement("Path");
ob.setAttribute("StrokeThickness", FToStr(conversionFactor));
ob.setAttribute("StrokeDashCap", "Flat");
ob.setAttribute("StrokeEndLineCap", "Flat");
ob.setAttribute("StrokeStartLineCap", "Flat");
ob.setAttribute("StrokeLineJoin", "Miter");
ob.setAttribute("Stroke", SetColor(Item->hatchForeground, 100, 0));
ob.setAttribute("Data", QString("M %1, %2 L %3, %4").arg(-lineLen).arg(dist).arg(lineLen).arg(dist));
ob.setAttribute("RenderTransform", MatrixToStr(mpx));
obC.appendChild(ob);
if (dist > 0)
{
QDomElement ob = p_docu.createElement("Path");
ob.setAttribute("StrokeThickness", FToStr(conversionFactor));
ob.setAttribute("StrokeDashCap", "Flat");
ob.setAttribute("StrokeEndLineCap", "Flat");
ob.setAttribute("StrokeStartLineCap", "Flat");
ob.setAttribute("StrokeLineJoin", "Miter");
ob.setAttribute("Stroke", SetColor(Item->hatchForeground, 100, 0));
ob.setAttribute("Data", QString("M %1, %2 L %3, %4").arg(-lineLen).arg(-dist).arg(lineLen).arg(-dist));
ob.setAttribute("RenderTransform", MatrixToStr(mpx));
obC.appendChild(ob);
}
dist += Item->hatchDistance * conversionFactor;
}
if ((Item->hatchType == 1) || (Item->hatchType == 2))
{
dist = 0.0;
while (dist < lineLen)
{
QTransform mpx;
mpx.translate((Item->width() / 2.0) * conversionFactor, (Item->height() / 2.0) * conversionFactor);
if (Item->hatchAngle != 0.0)
mpx.rotate(-Item->hatchAngle + 90);
QDomElement ob = p_docu.createElement("Path");
ob.setAttribute("StrokeThickness", FToStr(conversionFactor));
ob.setAttribute("StrokeDashCap", "Flat");
ob.setAttribute("StrokeEndLineCap", "Flat");
ob.setAttribute("StrokeStartLineCap", "Flat");
ob.setAttribute("StrokeLineJoin", "Miter");
ob.setAttribute("Stroke", SetColor(Item->hatchForeground, 100, 0));
ob.setAttribute("Data", QString("M %1, %2 L %3, %4").arg(-lineLen).arg(dist).arg(lineLen).arg(dist));
ob.setAttribute("RenderTransform", MatrixToStr(mpx));
obC.appendChild(ob);
if (dist > 0)
{
QDomElement ob = p_docu.createElement("Path");
ob.setAttribute("StrokeThickness", FToStr(conversionFactor));
ob.setAttribute("StrokeDashCap", "Flat");
ob.setAttribute("StrokeEndLineCap", "Flat");
ob.setAttribute("StrokeStartLineCap", "Flat");
ob.setAttribute("StrokeLineJoin", "Miter");
ob.setAttribute("Stroke", SetColor(Item->hatchForeground, 100, 0));
ob.setAttribute("Data", QString("M %1, %2 L %3, %4").arg(-lineLen).arg(-dist).arg(lineLen).arg(-dist));
ob.setAttribute("RenderTransform", MatrixToStr(mpx));
obC.appendChild(ob);
}
dist += Item->hatchDistance * conversionFactor;
}
}
if (Item->hatchType == 2)
{
dist = 0.0;
while (dist < lineLen)
{
double dDist = dist * sqrt(2.0);
QTransform mpx;
mpx.translate((Item->width() / 2.0) * conversionFactor, (Item->height() / 2.0) * conversionFactor);
if (Item->hatchAngle != 0.0)
mpx.rotate(-Item->hatchAngle + 45);
QDomElement ob = p_docu.createElement("Path");
ob.setAttribute("StrokeThickness", FToStr(conversionFactor));
ob.setAttribute("StrokeDashCap", "Flat");
ob.setAttribute("StrokeEndLineCap", "Flat");
ob.setAttribute("StrokeStartLineCap", "Flat");
ob.setAttribute("StrokeLineJoin", "Miter");
ob.setAttribute("Stroke", SetColor(Item->hatchForeground, 100, 0));
ob.setAttribute("Data", QString("M %1, %2 L %3, %4").arg(-lineLen).arg(dDist).arg(lineLen).arg(dDist));
ob.setAttribute("RenderTransform", MatrixToStr(mpx));
obC.appendChild(ob);
if (dist > 0)
{
QDomElement ob = p_docu.createElement("Path");
ob.setAttribute("StrokeThickness", FToStr(conversionFactor));
ob.setAttribute("StrokeDashCap", "Flat");
ob.setAttribute("StrokeEndLineCap", "Flat");
ob.setAttribute("StrokeStartLineCap", "Flat");
ob.setAttribute("StrokeLineJoin", "Miter");
ob.setAttribute("Stroke", SetColor(Item->hatchForeground, 100, 0));
ob.setAttribute("Data", QString("M %1, %2 L %3, %4").arg(-lineLen).arg(-dDist).arg(lineLen).arg(-dDist));
ob.setAttribute("RenderTransform", MatrixToStr(mpx));
obC.appendChild(ob);
}
dist += Item->hatchDistance * conversionFactor;
}
}
parentElem.appendChild(obC);
}
 
void XPSExPlug::processSymbolStroke(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root)
{
QDomElement ob = p_docu.createElement("Canvas");
QTransform mpx;
mpx.translate(xOffset * conversionFactor, yOffset * conversionFactor);
ob.setAttribute("RenderTransform", MatrixToStr(mpx));
QPainterPath path = Item->PoLine.toQPainterPath(false);
ScPattern pat = m_Doc->docPatterns[Item->strokePattern()];
double pLen = path.length() - ((pat.width / 2.0) * (Item->patternStrokeScaleX / 100.0));
double adv = pat.width * Item->patternStrokeScaleX / 100.0 * Item->patternStrokeSpace;
double xpos = Item->patternStrokeOffsetX * Item->patternStrokeScaleX / 100.0;
while (xpos < pLen)
{
double currPerc = path.percentAtLength(xpos);
double currAngle = path.angleAtPercent(currPerc);
if (currAngle <= 180.0)
currAngle *= -1.0;
else
currAngle = 360.0 - currAngle;
QPointF currPoint = path.pointAtPercent(currPerc);
QTransform trans;
trans.translate(currPoint.x() * conversionFactor, currPoint.y() * conversionFactor);
trans.rotate(currAngle);
trans.translate(0.0, Item->patternStrokeOffsetY);
trans.rotate(-Item->patternStrokeRotation);
trans.shear(Item->patternStrokeSkewX, -Item->patternStrokeSkewY);
trans.scale(Item->patternStrokeScaleX / 100.0, Item->patternStrokeScaleY / 100.0);
trans.translate(-pat.width / 2.0, -pat.height / 2.0);
if (Item->patternStrokeMirrorX)
{
trans.translate(pat.width, 0);
trans.scale(-1, 1);
}
if (Item->patternStrokeMirrorY)
{
trans.translate(0, pat.height);
trans.scale(1, -1);
}
QDomElement obS = p_docu.createElement("Canvas");
obS.setAttribute("RenderTransform", MatrixToStr(trans));
for (int em = 0; em < pat.items.count(); ++em)
{
PageItem* embed = pat.items.at(em);
writeItemOnPage(embed->gXpos, embed->gYpos, embed, obS, rel_root);
}
ob.appendChild(obS);
xpos += adv;
}
parentElem.appendChild(ob);
return;
}
 
void XPSExPlug::processArrows(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root)
{
if (Item->startArrowIndex() != 0)
{
QTransform arrowTrans;
FPointArray arrow = m_Doc->arrowStyles().at(Item->startArrowIndex()-1).points.copy();
if (Item->itemType() == PageItem::Line)
{
arrowTrans.translate(0, 0);
arrowTrans.scale(Item->startArrowScale() / 100.0, Item->startArrowScale() / 100.0);
if (Item->NamedLStyle.isEmpty())
{
if (Item->lineWidth() != 0.0)
arrowTrans.scale(Item->lineWidth(), Item->lineWidth());
}
else
{
multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
if (ml[ml.size()-1].Width != 0.0)
arrowTrans.scale(ml[ml.size()-1].Width, ml[ml.size()-1].Width);
}
arrowTrans.scale(-1,1);
}
else
{
FPoint Start = Item->PoLine.point(0);
for (int xx = 1; xx < Item->PoLine.size(); xx += 2)
{
FPoint Vector = Item->PoLine.point(xx);
if ((Start.x() != Vector.x()) || (Start.y() != Vector.y()))
{
double r = atan2(Start.y()-Vector.y(),Start.x()-Vector.x())*(180.0/M_PI);
arrowTrans.translate(Start.x(), Start.y());
arrowTrans.rotate(r);
arrowTrans.scale(Item->startArrowScale() / 100.0, Item->startArrowScale() / 100.0);
if (Item->NamedLStyle.isEmpty())
{
if (Item->lineWidth() != 0.0)
arrowTrans.scale(Item->lineWidth(), Item->lineWidth());
}
else
{
multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
if (ml[ml.size()-1].Width != 0.0)
arrowTrans.scale(ml[ml.size()-1].Width, ml[ml.size()-1].Width);
}
break;
}
}
}
arrow.map(arrowTrans);
drawArrow(xOffset, yOffset, Item, parentElem, rel_root, arrow);
}
if (Item->endArrowIndex() != 0)
{
QTransform arrowTrans;
FPointArray arrow = m_Doc->arrowStyles().at(Item->endArrowIndex()-1).points.copy();
if (Item->itemType() == PageItem::Line)
{
arrowTrans.translate(Item->width(), 0);
arrowTrans.scale(Item->endArrowScale() / 100.0, Item->endArrowScale() / 100.0);
if (Item->NamedLStyle.isEmpty())
{
if (Item->lineWidth() != 0.0)
arrowTrans.scale(Item->lineWidth(), Item->lineWidth());
}
else
{
multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
if (ml[ml.size()-1].Width != 0.0)
arrowTrans.scale(ml[ml.size()-1].Width, ml[ml.size()-1].Width);
}
}
else
{
FPoint End = Item->PoLine.point(Item->PoLine.size()-2);
for (uint xx = Item->PoLine.size()-1; xx > 0; xx -= 2)
{
FPoint Vector = Item->PoLine.point(xx);
if ((End.x() != Vector.x()) || (End.y() != Vector.y()))
{
double r = atan2(End.y()-Vector.y(),End.x()-Vector.x())*(180.0/M_PI);
arrowTrans.translate(End.x(), End.y());
arrowTrans.rotate(r);
arrowTrans.scale(Item->endArrowScale() / 100.0, Item->endArrowScale() / 100.0);
if (Item->NamedLStyle.isEmpty())
{
if (Item->lineWidth() != 0.0)
arrowTrans.scale(Item->lineWidth(), Item->lineWidth());
}
else
{
multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
if (ml[ml.size()-1].Width != 0.0)
arrowTrans.scale(ml[ml.size()-1].Width, ml[ml.size()-1].Width);
}
break;
}
}
}
arrow.map(arrowTrans);
drawArrow(xOffset, yOffset, Item, parentElem, rel_root, arrow);
}
return;
}
 
void XPSExPlug::drawArrow(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root, FPointArray &arrow)
{
QTransform mpx;
if (Item->rotation() != 0.0)
{
mpx.translate(xOffset * conversionFactor, yOffset * conversionFactor);
mpx.rotate(Item->rotation());
mpx.translate(-xOffset * conversionFactor, -yOffset * conversionFactor);
}
arrow.translate(xOffset, yOffset);
arrow.scale(conversionFactor, conversionFactor);
QString pa = SetClipPath(&arrow, true);
if (Item->NamedLStyle.isEmpty())
{
QDomElement ob = p_docu.createElement("Path");
ob.setAttribute("Data", pa);
ob.setAttribute("RenderTransform", MatrixToStr(mpx));
getStrokeStyle(Item, ob, rel_root, xOffset, yOffset, true);
parentElem.appendChild(ob);
}
else
{
QDomElement grp2 = p_docu.createElement("Canvas");
grp2.setAttribute("RenderTransform", MatrixToStr(mpx));
multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
if (ml[0].Color != CommonStrings::None)
{
QDomElement ob3 = p_docu.createElement("Path");
ob3.setAttribute("Data", pa);
ob3.setAttribute("Fill", SetColor(ml[0].Color, ml[0].Shade, 0));
GetMultiStroke(&ml[0], ob3);
grp2.appendChild(ob3);
}
for (int it = ml.size()-1; it > 0; it--)
{
if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
{
QDomElement ob3 = p_docu.createElement("Path");
ob3.setAttribute("Data", pa);
GetMultiStroke(&ml[it], ob3);
grp2.appendChild(ob3);
}
}
parentElem.appendChild(grp2);
}
}
 
QString XPSExPlug::embedFont(const ScFace *font, QDomElement &rel_root)
{
QByteArray fontData;
loadRawText(font->fontFilePath(), fontData);
QUuid id = QUuid::createUuid();
QString guidString = id.toString();
guidString = guidString.toUpper();
guidString.remove("{");
guidString.remove("}");
unsigned short guid[16];
const static int indexes[] = {6, 4, 2, 0, 11, 9, 16, 14, 19, 21, 24, 26, 28, 30, 32, 34};
for (int i = 0; i < 16; i++)
{
int hex1 = hex2int(guidString[indexes[i]].cell());
int hex2 = hex2int(guidString[indexes[i]+1].cell());
guid[i] = hex1 * 16 + hex2;
}
// Obfuscation - xor bytes in font binary with bytes from guid (font's filename)
const static int mapping[] = {15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3};
for (int i = 0; i < 16; i++)
{
fontData[i] = fontData[i] ^ guid[mapping[i]];
fontData[i+16] = fontData[i+16] ^ guid[mapping[i]];
}
QFile ft(baseDir + "/Resources/Fonts/" + guidString + ".odttf");
if (ft.open(QIODevice::WriteOnly))
{
ft.write(fontData);
ft.close();
}
QDomElement rel = r_docu.createElement("Relationship");
rel.setAttribute("Id", QString("rIDf%1").arg(fontCounter));
rel.setAttribute("Type", "http://schemas.microsoft.com/xps/2005/06/required-resource");
rel.setAttribute("Target", "/Resources/Fonts/" + guidString + ".odttf");
rel_root.appendChild(rel);
fontCounter++;
return "/Resources/Fonts/" + guidString + ".odttf";
}
 
void XPSExPlug::GetMultiStroke(struct SingleLine *sl, QDomElement &parentElem)
{
parentElem.setAttribute("StrokeThickness", FToStr(sl->Width * conversionFactor));
switch (static_cast<Qt::PenCapStyle>(sl->LineEnd))
{
case Qt::FlatCap:
parentElem.setAttribute("StrokeDashCap", "Flat");
parentElem.setAttribute("StrokeEndLineCap", "Flat");
parentElem.setAttribute("StrokeStartLineCap", "Flat");
break;
case Qt::SquareCap:
parentElem.setAttribute("StrokeDashCap", "Square");
parentElem.setAttribute("StrokeEndLineCap", "Square");
parentElem.setAttribute("StrokeStartLineCap", "Square");
break;
case Qt::RoundCap:
parentElem.setAttribute("StrokeDashCap", "Round");
parentElem.setAttribute("StrokeEndLineCap", "Round");
parentElem.setAttribute("StrokeStartLineCap", "Round");
break;
default:
parentElem.setAttribute("StrokeDashCap", "Flat");
parentElem.setAttribute("StrokeEndLineCap", "Flat");
parentElem.setAttribute("StrokeStartLineCap", "Flat");
break;
}
switch (static_cast<Qt::PenJoinStyle>(sl->LineJoin))
{
case Qt::MiterJoin:
parentElem.setAttribute("StrokeLineJoin", "Miter");
break;
case Qt::BevelJoin:
parentElem.setAttribute("StrokeLineJoin", "Bevel");
break;
case Qt::RoundJoin:
parentElem.setAttribute("StrokeLineJoin", "Round");
break;
default:
parentElem.setAttribute("StrokeLineJoin", "Miter");
break;
}
QString dashVals = "";
if (static_cast<Qt::PenStyle>(sl->Dash) != Qt::SolidLine)
dashVals = getDashString(sl->Dash, 1);
if (!dashVals.isEmpty())
parentElem.setAttribute("StrokeDashArray", dashVals);
if (sl->Color != CommonStrings::None)
parentElem.setAttribute("Stroke", SetColor(sl->Color, sl->Shade, 0));
}
 
void XPSExPlug::getStrokeStyle(PageItem *Item, QDomElement &parentElem, QDomElement &rel_root, double xOffset, double yOffset, bool forArrow)
{
parentElem.setAttribute("StrokeThickness", FToStr(Item->lineWidth() * conversionFactor));
switch (Item->PLineEnd)
{
case Qt::FlatCap:
parentElem.setAttribute("StrokeDashCap", "Flat");
parentElem.setAttribute("StrokeEndLineCap", "Flat");
parentElem.setAttribute("StrokeStartLineCap", "Flat");
break;
case Qt::SquareCap:
parentElem.setAttribute("StrokeDashCap", "Square");
parentElem.setAttribute("StrokeEndLineCap", "Square");
parentElem.setAttribute("StrokeStartLineCap", "Square");
break;
case Qt::RoundCap:
parentElem.setAttribute("StrokeDashCap", "Round");
parentElem.setAttribute("StrokeEndLineCap", "Round");
parentElem.setAttribute("StrokeStartLineCap", "Round");
break;
default:
parentElem.setAttribute("StrokeDashCap", "Flat");
parentElem.setAttribute("StrokeEndLineCap", "Flat");
parentElem.setAttribute("StrokeStartLineCap", "Flat");
break;
}
switch (Item->PLineJoin)
{
case Qt::MiterJoin:
parentElem.setAttribute("StrokeLineJoin", "Miter");
break;
case Qt::BevelJoin:
parentElem.setAttribute("StrokeLineJoin", "Bevel");
break;
case Qt::RoundJoin:
parentElem.setAttribute("StrokeLineJoin", "Round");
break;
default:
parentElem.setAttribute("StrokeLineJoin", "Miter");
break;
}
QString dashVals = "";
if (Item->DashValues.count() != 0)
{
QVector<double>::iterator it;
for ( it = Item->DashValues.begin(); it != Item->DashValues.end(); ++it )
{
dashVals += FToStr((*it) / Item->lineWidth())+" ";
}
}
else
{
if (Item->PLineArt != Qt::SolidLine)
dashVals = getDashString(Item->PLineArt, 1);
}
if (!dashVals.isEmpty())
{
parentElem.setAttribute("StrokeDashArray", dashVals);
if (Item->DashValues.count() != 0)
parentElem.setAttribute("StrokeDashOffset", FToStr(Item->DashOffset));
}
if (Item->GrTypeStroke == 0)
{
if (Item->lineColor() != CommonStrings::None)
{
if (forArrow)
parentElem.setAttribute("Fill", SetColor(Item->lineColor(), Item->lineShade(), Item->lineTransparency()));
else
parentElem.setAttribute("Stroke", SetColor(Item->lineColor(), Item->lineShade(), Item->lineTransparency()));
return;
}
}
else
{
if ((!Item->strokePattern().isEmpty()) && (!Item->patternStrokePath))
{
ScPattern pa = m_Doc->docPatterns[Item->strokePattern()];
QDomElement ob;
if (forArrow)
ob = p_docu.createElement("Path.Fill");
else
ob = p_docu.createElement("Path.Stroke");
QDomElement gr = p_docu.createElement("VisualBrush");
gr.setAttribute("TileMode", "Tile");
gr.setAttribute("ViewboxUnits", "Absolute");
gr.setAttribute("ViewportUnits", "Absolute");
gr.setAttribute("Viewbox", QString("0, 0, %1, %2").arg(pa.width * conversionFactor).arg(pa.height * conversionFactor));
double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY, patternSpace;
Item->strokePatternTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY, patternSpace);
patternScaleX /= 100.0;
patternScaleY /= 100.0;
double lw2 = Item->lineWidth() / 2.0;
gr.setAttribute("Viewport", QString("%1, %2, %3, %4").arg((xOffset + patternOffsetX - lw2) * conversionFactor).arg((yOffset + patternOffsetY - lw2) * conversionFactor).arg((pa.width * patternScaleX) * conversionFactor).arg((pa.height * patternScaleY) * conversionFactor));
bool mirrorX, mirrorY;
Item->strokePatternFlip(mirrorX, mirrorY);
if ((patternRotation != 0) || (patternSkewX != 0) || (patternSkewY != 0) || mirrorX || mirrorY)
{
QTransform mpa;
mpa.rotate(patternRotation);
mpa.shear(-patternSkewX, patternSkewY);
mpa.scale(pa.scaleX, pa.scaleY);
if (mirrorX)
mpa.scale(-1, 1);
if (mirrorY)
mpa.scale(1, -1);
gr.setAttribute("Transform", MatrixToStr(mpa));
}
if (Item->lineTransparency() != 0)
gr.setAttribute("Opacity", FToStr(1.0 - Item->lineTransparency()));
QDomElement grp = p_docu.createElement("VisualBrush.Visual");
for (int em = 0; em < pa.items.count(); ++em)
{
PageItem* embed = pa.items.at(em);
writeItemOnPage(embed->gXpos, embed->gYpos, embed, grp, rel_root);
}
gr.appendChild(grp);
ob.appendChild(gr);
parentElem.appendChild(ob);
}
else if ((Item->GrTypeStroke == 6) || (Item->GrTypeStroke == 7))
{
QDomElement ob;
if (forArrow)
ob = p_docu.createElement("Path.Fill");
else
ob = p_docu.createElement("Path.Stroke");
QDomElement gr;
double GrStartX = (Item->GrStrokeStartX + xOffset) * conversionFactor;
double GrStartY = (Item->GrStrokeStartY + yOffset) * conversionFactor;
double GrFocalX = (Item->GrStrokeFocalX + xOffset) * conversionFactor;
double GrFocalY = (Item->GrStrokeFocalY + yOffset) * conversionFactor;
double GrEndX = (Item->GrStrokeEndX + xOffset) * conversionFactor;
double GrEndY = (Item->GrStrokeEndY + yOffset) * conversionFactor;
if (Item->GrTypeStroke == 6)
{
gr = p_docu.createElement("LinearGradientBrush");
gr.setAttribute("MappingMode", "Absolute");
gr.setAttribute("StartPoint", FToStr(GrStartX) + ", " + FToStr(GrStartY));
gr.setAttribute("EndPoint", FToStr(GrEndX) + ", " + FToStr(GrEndY));
}
else
{
gr = p_docu.createElement("RadialGradientBrush");
double rad = sqrt(pow(GrEndX - GrStartX, 2) + pow(GrEndY - GrStartY,2));
gr.setAttribute("MappingMode", "Absolute");
gr.setAttribute("RadiusX", FToStr(rad));
gr.setAttribute("RadiusY", FToStr(rad));
gr.setAttribute("Center", FToStr(GrStartX) + ", " + FToStr(GrStartY));
gr.setAttribute("GradientOrigin", FToStr(GrFocalX) + ", " + FToStr(GrFocalY));
}
double gradientSkew;
if (Item->GrStrokeSkew == 90)
gradientSkew = 1;
else if (Item->GrStrokeSkew == 180)
gradientSkew = 0;
else if (Item->GrStrokeSkew == 270)
gradientSkew = -1;
else if (Item->GrStrokeSkew == 390)
gradientSkew = 0;
else
gradientSkew = tan(M_PI / 180.0 * Item->GrStrokeSkew);
QTransform qmatrix;
if (Item->GrTypeStroke == 6)
{
qmatrix.translate(GrStartX, GrStartY);
qmatrix.shear(-gradientSkew, 0);
qmatrix.translate(-GrStartX, -GrStartY);
}
else
{
double rotEnd = xy2Deg(GrEndX - GrStartX, GrEndY - GrStartY);
qmatrix.translate(GrStartX, GrStartY);
qmatrix.rotate(rotEnd);
qmatrix.shear(gradientSkew, 0);
qmatrix.translate(0, GrStartY * (1.0 - Item->GrStrokeScale));
qmatrix.translate(-GrStartX, -GrStartY);
qmatrix.scale(1, Item->GrStrokeScale);
}
gr.setAttribute("Transform", MatrixToStr(qmatrix));
if (Item->lineTransparency() != 0)
gr.setAttribute("Opacity", FToStr(1.0 - Item->lineTransparency()));
QDomElement grs;
if (Item->GrTypeStroke == 6)
grs = p_docu.createElement("LinearGradientBrush.GradientStops");
else
grs = p_docu.createElement("RadialGradientBrush.GradientStops");
bool isFirst = true;
double actualStop = 0.0, lastStop = 0.0;
QList<VColorStop*> cstops = Item->stroke_gradient.colorStops();
for (uint cst = 0; cst < Item->stroke_gradient.Stops(); ++cst)
{
actualStop = cstops.at(cst)->rampPoint;
if ((actualStop != lastStop) || (isFirst))
{
QDomElement itcl = p_docu.createElement("GradientStop");
itcl.setAttribute("Offset", FToStr(cstops.at(cst)->rampPoint));
itcl.setAttribute("Color", SetColor(cstops.at(cst)->name, cstops.at(cst)->shade, 1.0 - cstops.at(cst)->opacity));
grs.appendChild(itcl);
lastStop = actualStop;
isFirst = false;
}
}
gr.appendChild(grs);
ob.appendChild(gr);
parentElem.appendChild(ob);
}
}
}
 
void XPSExPlug::getFillStyle(PageItem *Item, QDomElement &parentElem, QDomElement &rel_root, double xOffset, double yOffset, bool withTransparency)
{
if (Item->GrType == 0)
{
if (Item->fillColor() != CommonStrings::None)
{
if ((withTransparency) || (Item->GrMask == 0))
parentElem.setAttribute("Fill", SetColor(Item->fillColor(), Item->fillShade(), Item->fillTransparency()));
else
parentElem.setAttribute("Fill", SetColor(Item->fillColor(), Item->fillShade(), 0));
}
return;
}
else
{
if ((Item->GrType == 6) || (Item->GrType == 7))
{
QDomElement ob = p_docu.createElement("Path.Fill");
QDomElement gr;
double GrStartX = (Item->GrStartX + xOffset) * conversionFactor;
double GrStartY = (Item->GrStartY + yOffset) * conversionFactor;
double GrFocalX = (Item->GrFocalX + xOffset) * conversionFactor;
double GrFocalY = (Item->GrFocalY + yOffset) * conversionFactor;
double GrEndX = (Item->GrEndX + xOffset) * conversionFactor;
double GrEndY = (Item->GrEndY + yOffset) * conversionFactor;
if (Item->GrType == 6)
{
gr = p_docu.createElement("LinearGradientBrush");
gr.setAttribute("MappingMode", "Absolute");
gr.setAttribute("StartPoint", FToStr(GrStartX) + ", " + FToStr(GrStartY));
gr.setAttribute("EndPoint", FToStr(GrEndX) + ", " + FToStr(GrEndY));
}
else
{
gr = p_docu.createElement("RadialGradientBrush");
double rad = sqrt(pow(GrEndX - GrStartX, 2) + pow(GrEndY - GrStartY,2));
gr.setAttribute("MappingMode", "Absolute");
gr.setAttribute("RadiusX", FToStr(rad));
gr.setAttribute("RadiusY", FToStr(rad));
gr.setAttribute("Center", FToStr(GrStartX) + ", " + FToStr(GrStartY));
gr.setAttribute("GradientOrigin", FToStr(GrFocalX) + ", " + FToStr(GrFocalY));
}
double gradientSkew;
if (Item->GrSkew == 90)
gradientSkew = 1;
else if (Item->GrSkew == 180)
gradientSkew = 0;
else if (Item->GrSkew == 270)
gradientSkew = -1;
else if (Item->GrSkew == 390)
gradientSkew = 0;
else
gradientSkew = tan(M_PI / 180.0 * Item->GrSkew);
QTransform qmatrix;
if (Item->GrType == 6)
{
qmatrix.translate(GrStartX, GrStartY);
qmatrix.shear(-gradientSkew, 0);
qmatrix.translate(-GrStartX, -GrStartY);
}
else
{
double rotEnd = xy2Deg(GrEndX - GrStartX, GrEndY - GrStartY);
qmatrix.translate(GrStartX, GrStartY);
qmatrix.rotate(rotEnd);
qmatrix.shear(gradientSkew, 0);
qmatrix.translate(0, GrStartY * (1.0 - Item->GrScale));
qmatrix.translate(-GrStartX, -GrStartY);
qmatrix.scale(1, Item->GrScale);
}
gr.setAttribute("Transform", MatrixToStr(qmatrix));
if ((Item->fillTransparency() != 0) && ((withTransparency) || (Item->GrMask == 0)))
gr.setAttribute("Opacity", FToStr(1.0 - Item->fillTransparency()));
QDomElement grs;
if (Item->GrType == 6)
grs = p_docu.createElement("LinearGradientBrush.GradientStops");
else
grs = p_docu.createElement("RadialGradientBrush.GradientStops");
bool isFirst = true;
double actualStop = 0.0, lastStop = 0.0;
QList<VColorStop*> cstops = Item->fill_gradient.colorStops();
for (uint cst = 0; cst < Item->fill_gradient.Stops(); ++cst)
{
actualStop = cstops.at(cst)->rampPoint;
if ((actualStop != lastStop) || (isFirst))
{
QDomElement itcl = p_docu.createElement("GradientStop");
itcl.setAttribute("Offset", FToStr(cstops.at(cst)->rampPoint));
itcl.setAttribute("Color", SetColor(cstops.at(cst)->name, cstops.at(cst)->shade, 1.0 - cstops.at(cst)->opacity));
grs.appendChild(itcl);
lastStop = actualStop;
isFirst = false;
}
}
gr.appendChild(grs);
ob.appendChild(gr);
parentElem.appendChild(ob);
}
else if (Item->GrType == 8)
{
ScPattern pa = m_Doc->docPatterns[Item->pattern()];
QDomElement ob = p_docu.createElement("Path.Fill");
QDomElement gr = p_docu.createElement("VisualBrush");
gr.setAttribute("TileMode", "Tile");
gr.setAttribute("ViewboxUnits", "Absolute");
gr.setAttribute("ViewportUnits", "Absolute");
gr.setAttribute("Viewbox", QString("0, 0, %1, %2").arg(pa.width * conversionFactor).arg(pa.height * conversionFactor));
double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY;
Item->patternTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY);
patternScaleX /= 100.0;
patternScaleY /= 100.0;
gr.setAttribute("Viewport", QString("%1, %2, %3, %4").arg((xOffset + patternOffsetX) * conversionFactor).arg((yOffset + patternOffsetY) * conversionFactor).arg((pa.width * patternScaleX) * conversionFactor).arg((pa.height * patternScaleY) * conversionFactor));
bool mirrorX, mirrorY;
Item->patternFlip(mirrorX, mirrorY);
if ((patternRotation != 0) || (patternSkewX != 0) || (patternSkewY != 0) || mirrorX || mirrorY)
{
QTransform mpa;
mpa.rotate(patternRotation);
mpa.shear(-patternSkewX, patternSkewY);
mpa.scale(pa.scaleX, pa.scaleY);
if (mirrorX)
mpa.scale(-1, 1);
if (mirrorY)
mpa.scale(1, -1);
gr.setAttribute("Transform", MatrixToStr(mpa));
}
if ((Item->fillTransparency() != 0) && ((withTransparency) || (Item->GrMask == 0)))
gr.setAttribute("Opacity", FToStr(1.0 - Item->fillTransparency()));
QDomElement grp = p_docu.createElement("VisualBrush.Visual");
for (int em = 0; em < pa.items.count(); ++em)
{
PageItem* embed = pa.items.at(em);
writeItemOnPage(embed->gXpos, embed->gYpos, embed, grp, rel_root);
}
gr.appendChild(grp);
ob.appendChild(gr);
parentElem.appendChild(ob);
}
}
}
 
void XPSExPlug::handleMask(int type, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root, double xOffset, double yOffset)
{
QDomElement ob;
if (type == 1)
ob = p_docu.createElement("Canvas.OpacityMask");
else if (type == 2)
ob = p_docu.createElement("Glyph.OpacityMask");
else
ob = p_docu.createElement("Path.OpacityMask");
if ((Item->GrMask == 1) || (Item->GrMask == 2))
{
QDomElement gr;
double GrStartX = (Item->GrMaskStartX + xOffset) * conversionFactor;
double GrStartY = (Item->GrMaskStartY + yOffset) * conversionFactor;
double GrFocalX = (Item->GrMaskFocalX + xOffset) * conversionFactor;
double GrFocalY = (Item->GrMaskFocalY + yOffset) * conversionFactor;
double GrEndX = (Item->GrMaskEndX + xOffset) * conversionFactor;
double GrEndY = (Item->GrMaskEndY + yOffset) * conversionFactor;
if ((Item->GrMask == 1) || (Item->GrMask == 4))
{
gr = p_docu.createElement("LinearGradientBrush");
gr.setAttribute("MappingMode", "Absolute");
gr.setAttribute("StartPoint", FToStr(GrStartX) + ", " + FToStr(GrStartY));
gr.setAttribute("EndPoint", FToStr(GrEndX) + ", " + FToStr(GrEndY));
}
else
{
gr = p_docu.createElement("RadialGradientBrush");
double rad = sqrt(pow(GrEndX - GrStartX, 2) + pow(GrEndY - GrStartY,2));
gr.setAttribute("MappingMode", "Absolute");
gr.setAttribute("RadiusX", FToStr(rad));
gr.setAttribute("RadiusY", FToStr(rad));
gr.setAttribute("Center", FToStr(GrStartX) + ", " + FToStr(GrStartY));
gr.setAttribute("GradientOrigin", FToStr(GrFocalX) + ", " + FToStr(GrFocalY));
}
double gradientSkew;
if (Item->GrMaskSkew == 90)
gradientSkew = 1;
else if (Item->GrMaskSkew == 180)
gradientSkew = 0;
else if (Item->GrMaskSkew == 270)
gradientSkew = -1;
else if (Item->GrMaskSkew == 390)
gradientSkew = 0;
else
gradientSkew = tan(M_PI / 180.0 * Item->GrMaskSkew);
QTransform qmatrix;
if (Item->GrMask == 1)
{
qmatrix.translate(GrStartX, GrStartY);
qmatrix.shear(-gradientSkew, 0);
qmatrix.translate(-GrStartX, -GrStartY);
}
else
{
double rotEnd = xy2Deg(GrEndX - GrStartX, GrEndY - GrStartY);
qmatrix.translate(GrStartX, GrStartY);
qmatrix.rotate(rotEnd);
qmatrix.shear(gradientSkew, 0);
qmatrix.translate(0, GrStartY * (1.0 - Item->GrMaskScale));
qmatrix.translate(-GrStartX, -GrStartY);
qmatrix.scale(1, Item->GrMaskScale);
}
gr.setAttribute("Transform", MatrixToStr(qmatrix));
QDomElement grs;
if (Item->GrMask == 1)
grs = p_docu.createElement("LinearGradientBrush.GradientStops");
else
grs = p_docu.createElement("RadialGradientBrush.GradientStops");
bool isFirst = true;
double actualStop = 0.0, lastStop = 0.0;
QList<VColorStop*> cstops = Item->mask_gradient.colorStops();
for (uint cst = 0; cst < Item->mask_gradient.Stops(); ++cst)
{
actualStop = cstops.at(cst)->rampPoint;
if ((actualStop != lastStop) || (isFirst))
{
QDomElement itcl = p_docu.createElement("GradientStop");
itcl.setAttribute("Offset", FToStr(cstops.at(cst)->rampPoint));
itcl.setAttribute("Color", SetColor(cstops.at(cst)->name, cstops.at(cst)->shade, 1.0 - cstops.at(cst)->opacity));
grs.appendChild(itcl);
lastStop = actualStop;
isFirst = false;
}
}
gr.appendChild(grs);
ob.appendChild(gr);
}
else if (Item->GrMask == 3)
{
ScPattern pa = m_Doc->docPatterns[Item->patternMask()];
QDomElement gr = p_docu.createElement("VisualBrush");
gr.setAttribute("TileMode", "Tile");
gr.setAttribute("ViewboxUnits", "Absolute");
gr.setAttribute("ViewportUnits", "Absolute");
gr.setAttribute("Viewbox", QString("0, 0, %1, %2").arg(pa.width * conversionFactor).arg(pa.height * conversionFactor));
double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY;
Item->maskTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY);
patternScaleX /= 100.0;
patternScaleY /= 100.0;
gr.setAttribute("Viewport", QString("%1, %2, %3, %4").arg((xOffset + patternOffsetX) * conversionFactor).arg((yOffset + patternOffsetY) * conversionFactor).arg((pa.width * patternScaleX) * conversionFactor).arg((pa.height * patternScaleY) * conversionFactor));
bool mirrorX, mirrorY;
Item->maskFlip(mirrorX, mirrorY);
if ((patternRotation != 0) || (patternSkewX != 0) || (patternSkewY != 0) || mirrorX || mirrorY)
{
QTransform mpa;
mpa.rotate(patternRotation);
mpa.shear(-patternSkewX, patternSkewY);
mpa.scale(pa.scaleX, pa.scaleY);
if (mirrorX)
mpa.scale(-1, 1);
if (mirrorY)
mpa.scale(1, -1);
gr.setAttribute("Transform", MatrixToStr(mpa));
}
QDomElement grp = p_docu.createElement("VisualBrush.Visual");
for (int em = 0; em < pa.items.count(); ++em)
{
PageItem* embed = pa.items.at(em);
writeItemOnPage(embed->gXpos, embed->gYpos, embed, grp, rel_root);
}
gr.appendChild(grp);
ob.appendChild(gr);
}
parentElem.appendChild(ob);
}
 
QString XPSExPlug::SetColor(QString farbe, int shad, double transparency)
{
if (farbe == CommonStrings::None)
return "#00FFFFFF";
const ScColor& col = m_Doc->PageColors[farbe];
QString color = ScColorEngine::getShadeColorProof(col, m_Doc, shad).name().mid(1);
color = color.toUpper();
QString alpha = "";
alpha.setNum(qRound((1.0 - transparency) * 255), 16);
alpha = alpha.toUpper();
if (alpha.length() == 1)
alpha.prepend("0");
return "#" + alpha + color;
}
 
void XPSExPlug::SetClipAttr(QDomElement &elem, FPointArray *ite, bool fillRule)
{
QString pathStr = SetClipPath(ite, true);
if (pathStr.length() > 0)
{
if (fillRule)
pathStr.prepend("F 0 ");
else
pathStr.prepend("F 1 ");
elem.setAttribute("Clip", pathStr);
}
}
 
QString XPSExPlug::SetClipPath(FPointArray *ite, bool closed)
{
QString tmp;
FPoint np, np1, np2, np3, np4, firstP;
bool nPath = true;
bool first = true;
if (ite->size() <= 3)
return tmp;
 
for (int poi=0; poi<ite->size()-3; poi += 4)
{
if (ite->isMarker(poi))
{
nPath = true;
continue;
}
if (nPath)
{
np = ite->point(poi);
if ((!first) && (closed) && (np4 == firstP))
tmp += "Z ";
tmp += QString("M%1,%2 ").arg(np.x()).arg(np.y());
nPath = false;
first = false;
firstP = np;
np4 = np;
}
np = ite->point(poi);
np1 = ite->point(poi+1);
np2 = ite->point(poi+3);
np3 = ite->point(poi+2);
if ((np == np1) && (np2 == np3))
tmp += QString("L%1,%2 ").arg(np3.x()).arg(np3.y());
else
tmp += QString("C%1,%2 %3,%4 %5,%6 ").arg(np1.x()).arg(np1.y()).arg(np2.x()).arg(np2.y()).arg(np3.x()).arg(np3.y());
np4 = np3;
}
if (closed)
tmp += "Z";
return tmp;
}
 
void XPSExPlug::writeDocRels()
{
// Create and write required "Documents/1/_rels/FixedDoc.fdoc.rels" file
QDomDocument doc("rels");
QString st = "<Relationships></Relationships>";
doc.setContent(st);
QDomElement root = doc.documentElement();
root.setAttribute("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships");
doc.appendChild(root);
QFile ft(baseDir + "/Documents/1/_rels/FixedDoc.fdoc.rels");
if (ft.open(QIODevice::WriteOnly))
{
QString vo = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
QDataStream s(&ft);
vo += doc.toString();
QByteArray utf8wr = vo.toUtf8();
s.writeRawData(utf8wr.data(), utf8wr.length());
ft.close();
}
}
 
void XPSExPlug::writeCore()
{
// Create and write required "docProps/core.xml" file
QDomDocument doc("rels");
QString st = "<cp:coreProperties></cp:coreProperties>";
doc.setContent(st);
QDomElement root = doc.documentElement();
root.setAttribute("xmlns:cp", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
root.setAttribute("xmlns:dc", "http://purl.org/dc/elements/1.1/");
root.setAttribute("xmlns:dcterms", "http://purl.org/dc/terms/");
root.setAttribute("xmlns:dcmitype", "http://purl.org/dc/dcmitype/");
root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
QDomElement rel1 = doc.createElement("dc:creator");
rel1.setNodeValue("");
root.appendChild(rel1);
QDomElement rel2 = doc.createElement("dcterms:created");
rel2.setAttribute("xsi:type", "dcterms:W3CDTF");
rel2.setNodeValue("");
root.appendChild(rel2);
QDomElement rel3 = doc.createElement("dcterms:modified");
rel3.setNodeValue("");
rel3.setAttribute("xsi:type", "dcterms:W3CDTF");
root.appendChild(rel3);
doc.appendChild(root);
QFile ft(baseDir + "/docProps/core.xml");
if (ft.open(QIODevice::WriteOnly))
{
QString vo = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
QDataStream s(&ft);
vo += doc.toString();
QByteArray utf8wr = vo.toUtf8();
s.writeRawData(utf8wr.data(), utf8wr.length());
ft.close();
}
}
 
void XPSExPlug::writeContentType()
{
// Create and write required "[Content_Type].xml" file
QDomDocument doc("Content_Type");
QString st = "<Types></Types>";
doc.setContent(st);
QDomElement root = doc.documentElement();
root.setAttribute("xmlns", "http://schemas.openxmlformats.org/package/2006/content-types");
QDomElement rel1 = doc.createElement("Default");
rel1.setAttribute("Extension", "png");
rel1.setAttribute("ContentType", "image/png");
root.appendChild(rel1);
QDomElement rel2 = doc.createElement("Default");
rel2.setAttribute("Extension", "jpeg");
rel2.setAttribute("ContentType", "image/jpeg");
root.appendChild(rel2);
QDomElement rel3 = doc.createElement("Default");
rel3.setAttribute("Extension", "jpg");
rel3.setAttribute("ContentType", "image/jpeg");
root.appendChild(rel3);
QDomElement rel4 = doc.createElement("Default");
rel4.setAttribute("Extension", "rels");
rel4.setAttribute("ContentType", "application/vnd.openxmlformats-package.relationships+xml");
root.appendChild(rel4);
QDomElement rel5 = doc.createElement("Default");
rel5.setAttribute("Extension", "xml");
rel5.setAttribute("ContentType", "application/xml");
root.appendChild(rel5);
QDomElement rel6 = doc.createElement("Default");
rel6.setAttribute("Extension", "fdseq");
rel6.setAttribute("ContentType", "application/vnd.ms-package.xps-fixeddocumentsequence+xml");
root.appendChild(rel6);
QDomElement rel7 = doc.createElement("Default");
rel7.setAttribute("Extension", "fpage");
rel7.setAttribute("ContentType", "application/vnd.ms-package.xps-fixedpage+xml");
root.appendChild(rel7);
QDomElement rel8 = doc.createElement("Default");
rel8.setAttribute("Extension", "struct");
rel8.setAttribute("ContentType", "application/vnd.ms-package.xps-documentstructure+xml");
root.appendChild(rel8);
QDomElement rel9 = doc.createElement("Default");
rel9.setAttribute("Extension", "fdoc");
rel9.setAttribute("ContentType", "application/vnd.ms-package.xps-fixeddocument+xml");
root.appendChild(rel9);
QDomElement rel10 = doc.createElement("Default");
rel10.setAttribute("Extension", "odttf");
rel10.setAttribute("ContentType", "application/vnd.ms-package.obfuscated-opentype");
root.appendChild(rel10);
QDomElement rel11 = doc.createElement("Default");
rel11.setAttribute("Extension", "dict");
rel11.setAttribute("ContentType", "application/vnd.ms-package.xps-resourcedictionary+xml");
root.appendChild(rel11);
QDomElement rel12 = doc.createElement("Override");
rel12.setAttribute("PartName", "/docProps/core.xml");
rel12.setAttribute("ContentType", "application/vnd.openxmlformats-package.core-properties+xml");
root.appendChild(rel12);
doc.appendChild(root);
QFile ft(baseDir + "/[Content_Types].xml");
if (ft.open(QIODevice::WriteOnly))
{
QString vo = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
QDataStream s(&ft);
vo += doc.toString();
QByteArray utf8wr = vo.toUtf8();
s.writeRawData(utf8wr.data(), utf8wr.length());
ft.close();
}
}
 
void XPSExPlug::writeBaseRel()
{
// Create and write required "_rels/.rels" file
QDomDocument doc("rels");
QString st = "<Relationships></Relationships>";
doc.setContent(st);
QDomElement root = doc.documentElement();
root.setAttribute("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships");
QDomElement rel1 = doc.createElement("Relationship");
rel1.setAttribute("Id", "rID1");
rel1.setAttribute("Type", "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties");
rel1.setAttribute("Target", "docProps/core.xml");
root.appendChild(rel1);
QDomElement rel2 = doc.createElement("Relationship");
rel2.setAttribute("Id", "rID2");
rel2.setAttribute("Type", "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail");
rel2.setAttribute("Target", "docProps/thumbnail.jpeg");
root.appendChild(rel2);
QDomElement rel3 = doc.createElement("Relationship");
rel3.setAttribute("Id", "rID3");
rel3.setAttribute("Type", "http://schemas.microsoft.com/xps/2005/06/fixedrepresentation");
rel3.setAttribute("Target", "FixedDocSeq.fdseq");
root.appendChild(rel3);
doc.appendChild(root);
QFile ft(baseDir + "/_rels/.rels");
if (ft.open(QIODevice::WriteOnly))
{
QString vo = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
QDataStream s(&ft);
vo += doc.toString();
QByteArray utf8wr = vo.toUtf8();
s.writeRawData(utf8wr.data(), utf8wr.length());
ft.close();
}
}
 
QString XPSExPlug::FToStr(double c)
{
QString cc;
return cc.setNum(c);
}
 
QString XPSExPlug::IToStr(int c)
{
QString cc;
return cc.setNum(c);
}
 
QString XPSExPlug::MatrixToStr(QTransform &mat)
{
QString cc("%1, %2, %3, %4, %5, %6");
return cc.arg(mat.m11()).arg(mat.m12()).arg(mat.m21()).arg(mat.m22()).arg(mat.dx()).arg(mat.dy());
}
 
int XPSExPlug::hex2int(char hex)
{
QChar hexchar = QLatin1Char(hex);
int v;
if (hexchar.isDigit())
v = hexchar.digitValue();
else if (hexchar >= QLatin1Char('A') && hexchar <= QLatin1Char('F'))
v = hexchar.cell() - 'A' + 10;
else if (hexchar >= QLatin1Char('a') && hexchar <= QLatin1Char('f'))
v = hexchar.cell() - 'a' + 10;
else
v = -1;
return v;
}
 
bool XPSExPlug::checkForFallback(PageItem *Item)
{
bool ret = false;
int GrType = Item->GrType;
int GrMask = Item->GrMask;
if ((GrType == 9) || (GrType == 10) || (GrType == 11) || (GrType == 12) || (GrType == 13))
ret = true;
if ((GrMask == 4) || (GrMask == 5) || (GrMask == 6) || (GrMask == 7) || (GrMask == 8))
ret = true;
if (Item->fillBlendmode() != 0)
ret = true;
if (Item->lineBlendmode() != 0)
ret = true;
if (Item->hasSoftShadow())
ret = true;
return ret;
}
 
XPSExPlug::~XPSExPlug()
{
}
/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/
/***************************************************************************
xpsexport.cpp - description
-------------------
begin : Sun Nov 24 08:00:00 CEST 2013
copyright : (C) 2013 by Franz Schmid
email : Franz.Schmid@altmuehlnet.de
***************************************************************************/
 
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
 
#include <QBuffer>
#include <QByteArray>
#include <QComboBox>
#include <QDataStream>
#include <QFile>
#include <QList>
#include <QMessageBox>
#include <QScopedPointer>
#include <QTemporaryDir>
#include <QTextStream>
#include <QUuid>
 
#include "xpsexplugin.h"
 
#include "scconfig.h"
#include "canvas.h"
#include "cmsettings.h"
#include "commonstrings.h"
#include "pageitem_pathtext.h"
#include "pageitem_table.h"
#include "prefsmanager.h"
#include "prefsfile.h"
#include "prefscontext.h"
#include "scpage.h"
#include "scpattern.h"
#include "scribuscore.h"
#include "scribusdoc.h"
#include "scribusview.h"
#include "sctextstruct.h"
#include "tableutils.h"
#include "util.h"
#include "ui/customfdialog.h"
#include "ui/guidemanager.h"
#include "ui/scmessagebox.h"
#include "sccolorengine.h"
#include "util_formats.h"
#include "util_math.h"
#include "third_party/zip/scribus_zip.h"
 
int xpsexplugin_getPluginAPIVersion()
{
return PLUGIN_API_VERSION;
}
 
ScPlugin* xpsexplugin_getPlugin()
{
XPSExportPlugin* plug = new XPSExportPlugin();
Q_CHECK_PTR(plug);
return plug;
}
 
void xpsexplugin_freePlugin(ScPlugin* plugin)
{
XPSExportPlugin* plug = dynamic_cast<XPSExportPlugin*>(plugin);
Q_ASSERT(plug);
delete plug;
}
 
using namespace TableUtils;
 
XPSExportPlugin::XPSExportPlugin() : ScActionPlugin()
{
// Set action info in languageChange, so we only have to do
// it in one place.
languageChange();
}
 
XPSExportPlugin::~XPSExportPlugin() {};
 
void XPSExportPlugin::languageChange()
{
// Note that we leave the unused members unset. They'll be initialised
// with their default ctors during construction.
// Action name
m_actionInfo.name = "ExportAsXPS";
// Action text for menu, including accel
m_actionInfo.text = tr("Save as XPS...");
// Menu
m_actionInfo.menu = "FileExport";
m_actionInfo.enabledOnStartup = false;
m_actionInfo.needsNumObjects = -1;
}
 
const QString XPSExportPlugin::fullTrName() const
{
return QObject::tr("XPS Export");
}
 
const ScActionPlugin::AboutData* XPSExportPlugin::getAboutData() const
{
AboutData* about = new AboutData;
about->authors = "Franz Schmid <franz@scribus.info>";
about->shortDescription = tr("Exports XPS Files");
about->description = tr("Exports the current document into an XPS file.");
about->license = "GPL";
Q_CHECK_PTR(about);
return about;
}
 
void XPSExportPlugin::deleteAboutData(const AboutData* about) const
{
Q_ASSERT(about);
delete about;
}
 
bool XPSExportPlugin::run(ScribusDoc* doc, QString filename)
{
Q_ASSERT(filename.isEmpty());
QString fileName;
if (doc!=0)
{
PrefsContext* prefs = PrefsManager::instance()->prefsFile->getPluginContext("xpsex");
QString wdir = prefs->get("wdir", ".");
QScopedPointer<CustomFDialog> openDia( new CustomFDialog(doc->scMW(), wdir, QObject::tr("Save as"), QObject::tr("Microsoft XPS (*.xps *.XPS);;All Files (*)"), fdHidePreviewCheckBox) );
 
QFrame *Layout = new QFrame(openDia.data());
QHBoxLayout *Layout1 = new QHBoxLayout(Layout);
Layout1->setSpacing( 5 );
QLabel *text = new QLabel(QObject::tr("Output Settings:"), Layout);
Layout1->addWidget(text);
QComboBox* compress = new QComboBox(Layout);
compress->addItem(QObject::tr("Low Resolution"));
compress->addItem(QObject::tr("Medium Resolution"));
compress->addItem(QObject::tr("High Resolution"));
Layout1->addWidget(compress);
QSpacerItem* spacer = new QSpacerItem( 2, 2, QSizePolicy::Expanding, QSizePolicy::Minimum );
Layout1->addItem( spacer );
compress->setCurrentIndex(1);
openDia->addWidgets(Layout);
QString fna;
if (doc->hasName)
{
QFileInfo fi(doc->DocName);
QString completeBaseName = fi.completeBaseName();
if (completeBaseName.endsWith(".xps", Qt::CaseInsensitive))
completeBaseName.chop(4);
wdir = QDir::fromNativeSeparators( fi.path() );
fna = QDir::fromNativeSeparators( fi.path()+"/"+completeBaseName+".xps" );
}
else
{
wdir = QDir::fromNativeSeparators( wdir );
if (wdir.right(1) != "/")
fna = wdir + "/";
else
fna = wdir;
fna += doc->DocName + ".xps";
}
openDia->setSelection(fna);
openDia->setExtension("xps");
 
if (!openDia->exec())
return true;
fileName = openDia->selectedFile();
QFileInfo fi(fileName);
QString baseDir = fi.absolutePath();
fileName = baseDir + "/" + fi.baseName() + ".xps";
if (fileName.isEmpty())
return true;
prefs->set("wdir", fileName.left(fileName.lastIndexOf("/")));
QFile f(fileName);
if (f.exists())
{
int exit = ScMessageBox::warning(doc->scMW(), CommonStrings::trWarning,
QObject::tr("Do you really want to overwrite the file:\n%1 ?").arg(fileName),
QMessageBox::Yes | QMessageBox::No,
QMessageBox::NoButton, // GUI default
QMessageBox::Yes); // batch default
if (exit == QMessageBox::No)
return true;
}
XPSExPlug *dia = new XPSExPlug(doc, compress->currentIndex());
dia->doExport(fileName);
delete dia;
}
return true;
}
 
XPSExPlug::XPSExPlug(ScribusDoc* doc, int output_res)
{
m_Doc = doc;
conversionFactor = 96.0 / 72.0;
m_dpi = 96.0;
if (output_res == 0)
m_dpi = 72.0;
else if (output_res == 1)
m_dpi = 150.0;
else if (output_res == 2)
m_dpi = 300.0;
}
 
bool XPSExPlug::doExport(QString fName)
{
zip = new ScZipHandler(true);
if (!zip->open(fName))
{
delete zip;
return false;
}
dir = new QTemporaryDir();
if (dir->isValid())
{
imageCounter = 0;
fontCounter = 0;
xps_fontMap.clear();
baseDir = dir->path();
// Create directory tree
QDir outDir(baseDir);
outDir.mkdir("_rels");
outDir.mkdir("docProps");
outDir.mkdir("Documents");
outDir.cd("Documents");
outDir.mkdir("1");
outDir.cd("1");
outDir.mkdir("_rels");
outDir.mkdir("Pages");
outDir.cd("Pages");
outDir.mkdir("_rels");
outDir.cdUp();
outDir.mkdir("Structure");
outDir.cdUp();
outDir.cdUp();
outDir.mkdir("Resources");
outDir.cd("Resources");
outDir.mkdir("Images");
outDir.mkdir("Fonts");
outDir.cdUp();
writeBaseRel();
writeContentType();
writeCore();
writeDocRels();
// Write Thumbnail
QImage thumb = m_Doc->view()->PageToPixmap(0, 256, false);
thumb.save(baseDir + "/docProps/thumbnail.jpeg", "JPG");
// Write required DocStructure.struct
QFile fts(baseDir + "/Documents/1/Structure/DocStructure.struct");
if (fts.open(QIODevice::WriteOnly))
{
fts.write(QByteArray("<DocumentStructure xmlns=\"http://schemas.microsoft.com/xps/2005/06/documentstructure\">\n</DocumentStructure>"));
fts.close();
}
// Write required FixedDocSeq.fdseq
QFile ft(baseDir + "/FixedDocSeq.fdseq");
if (ft.open(QIODevice::WriteOnly))
{
ft.write(QByteArray("<FixedDocumentSequence xmlns=\"http://schemas.microsoft.com/xps/2005/06\">\n\t<DocumentReference Source=\"/Documents/1/FixedDoc.fdoc\"/>\n</FixedDocumentSequence>"));
ft.close();
}
// Write required FixedDoc.fdoc
f_docu = QDomDocument("xpsdoc");
QString st = "<FixedDocument></FixedDocument>";
f_docu.setContent(st);
QDomElement root = f_docu.documentElement();
root.setAttribute("xmlns", "http://schemas.microsoft.com/xps/2005/06");
f_docu.appendChild(root);
writePages(root);
QFile fdo(baseDir + "/Documents/1/FixedDoc.fdoc");
if (fdo.open(QIODevice::WriteOnly))
{
QString vo = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
QDataStream s(&fdo);
vo += f_docu.toString();
QByteArray utf8wr = vo.toUtf8();
s.writeRawData(utf8wr.data(), utf8wr.length());
fdo.close();
}
zip->write(baseDir);
}
zip->close();
delete zip;
delete dir;
return true;
}
 
void XPSExPlug::writePages(QDomElement &root)
{
for (int a = 0; a < m_Doc->Pages->count(); a++)
{
ScPage* Page = m_Doc->Pages->at(a);
p_docu.setContent(QString("<FixedPage></FixedPage>"));
QDomElement droot = p_docu.documentElement();
droot.setAttribute("xmlns", "http://schemas.microsoft.com/xps/2005/06");
droot.setAttribute("Width", QString("%1").arg(Page->width() * conversionFactor));
droot.setAttribute("Height", QString("%1").arg(Page->height() * conversionFactor));
QString lang = QLocale::system().name();
lang.replace("_", "-");
droot.setAttribute("xml:lang", lang);
r_docu.setContent(QString("<Relationships></Relationships>"));
QDomElement rroot = r_docu.documentElement();
rroot.setAttribute("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships");
writePage(droot, rroot, Page);
p_docu.appendChild(droot);
r_docu.appendChild(rroot);
QFile ft(baseDir + QString("/Documents/1/Pages/%1.fpage").arg(a+1));
if (ft.open(QIODevice::WriteOnly))
{
QString vo = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
QDataStream s(&ft);
vo += p_docu.toString();
QByteArray utf8wr = vo.toUtf8();
s.writeRawData(utf8wr.data(), utf8wr.length());
ft.close();
}
QFile ftr(baseDir + QString("/Documents/1/Pages/_rels/%1.fpage.rels").arg(a+1));
if (ftr.open(QIODevice::WriteOnly))
{
QString vo = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
QDataStream s(&ftr);
vo += r_docu.toString();
QByteArray utf8wr = vo.toUtf8();
s.writeRawData(utf8wr.data(), utf8wr.length());
ftr.close();
}
QDomElement rel1 = f_docu.createElement("PageContent");
rel1.setAttribute("Source", QString("Pages/%1.fpage").arg(a+1));
root.appendChild(rel1);
p_docu.clear();
r_docu.clear();
}
}
 
void XPSExPlug::writePage(QDomElement &doc_root, QDomElement &rel_root, ScPage *Page)
{
ScLayer ll;
ll.isPrintable = false;
for (int la = 0; la < m_Doc->Layers.count(); la++)
{
m_Doc->Layers.levelToLayer(ll, la);
if (ll.isPrintable)
{
ScPage *mpage = m_Doc->MasterPages.at(m_Doc->MasterNames[Page->MPageNam]);
writePageLayer(doc_root, rel_root, mpage, ll);
writePageLayer(doc_root, rel_root, Page, ll);
}
}
}
 
void XPSExPlug::writePageLayer(QDomElement &doc_root, QDomElement &rel_root, ScPage *page, ScLayer& layer)
{
PageItem *Item;
QList<PageItem*> Items;
ScPage* SavedAct = m_Doc->currentPage();
if (page->pageName().isEmpty())
Items = m_Doc->DocItems;
else
Items = m_Doc->MasterItems;
if (Items.count() == 0)
return;
if (!layer.isPrintable)
return;
m_Doc->setCurrentPage(page);
QDomElement layerGroup = p_docu.createElement("Canvas");
if (layer.transparency != 1.0)
layerGroup.setAttribute("Opacity", layer.transparency);
for(int j = 0; j < Items.count(); ++j)
{
Item = Items.at(j);
if (Item->LayerID != layer.ID)
continue;
if (!Item->printEnabled())
continue;
double x = page->xOffset();
double y = page->yOffset();
double w = page->width();
double h = page->height();
double x2 = Item->BoundingX;
double y2 = Item->BoundingY;
double w2 = Item->BoundingW;
double h2 = Item->BoundingH;
if (!( qMax( x, x2 ) <= qMin( x+w, x2+w2 ) && qMax( y, y2 ) <= qMin( y+h, y2+h2 )))
continue;
if ((!page->pageName().isEmpty()) && (Item->OwnPage != static_cast<int>(page->pageNr())) && (Item->OwnPage != -1))
continue;
writeItemOnPage(Item->xPos() - page->xOffset(), Item->yPos() - page->yOffset(), Item, layerGroup, rel_root);
}
doc_root.appendChild(layerGroup);
m_Doc->setCurrentPage(SavedAct);
}
 
void XPSExPlug::writeItemOnPage(double xOffset, double yOffset, PageItem *Item, QDomElement &parentElem, QDomElement &rel_root)
{
switch (Item->itemType())
{
case PageItem::Arc:
case PageItem::Polygon:
case PageItem::PolyLine:
case PageItem::RegularPolygon:
case PageItem::Spiral:
if (checkForFallback(Item))
handleImageFallBack(Item, parentElem, rel_root);
else
{
processPolyItem(xOffset, yOffset, Item, parentElem, rel_root);
if ((Item->lineColor() != CommonStrings::None) && ((Item->startArrowIndex() != 0) || (Item->endArrowIndex() != 0)))
processArrows(xOffset, yOffset, Item, parentElem, rel_root);
}
break;
case PageItem::Line:
if (checkForFallback(Item))
handleImageFallBack(Item, parentElem, rel_root);
else
{
processLineItem(xOffset, yOffset, Item, parentElem, rel_root);
if ((Item->lineColor() != CommonStrings::None) && ((Item->startArrowIndex() != 0) || (Item->endArrowIndex() != 0)))
processArrows(xOffset, yOffset, Item, parentElem, rel_root);
}
break;
case PageItem::ImageFrame:
case PageItem::LatexFrame:
if (checkForFallback(Item))
handleImageFallBack(Item, parentElem, rel_root);
else
processImageItem(xOffset, yOffset, Item, parentElem, rel_root);
break;
case PageItem::TextFrame:
if (checkForFallback(Item))
handleImageFallBack(Item, parentElem, rel_root);
else
processTextItem(xOffset, yOffset, Item, parentElem, rel_root);
break;
case PageItem::PathText:
if (checkForFallback(Item))
handleImageFallBack(Item, parentElem, rel_root);
else
processPathTextItem(xOffset, yOffset, Item, parentElem, rel_root);
break;
case PageItem::Table:
if (checkForFallback(Item))
handleImageFallBack(Item, parentElem, rel_root);
else
processTableItem(xOffset, yOffset, Item, parentElem, rel_root);
break;
case PageItem::Symbol:
if (checkForFallback(Item))
handleImageFallBack(Item, parentElem, rel_root);
else
processSymbolItem(xOffset, yOffset, Item, parentElem, rel_root);
break;
case PageItem::Group:
if (Item->groupItemList.count() > 0)
{
if (checkForFallback(Item))
handleImageFallBack(Item, parentElem, rel_root);
else
{
QDomElement ob = p_docu.createElement("Canvas");
if (Item->GrMask > 0)
handleMask(1, Item, ob, rel_root, xOffset, yOffset);
else
{
if (Item->fillTransparency() != 0)
ob.setAttribute("Opacity", FToStr(1.0 - Item->fillTransparency()));
}
if (Item->groupClipping())
{
FPointArray path = Item->PoLine.copy();
path.scale(conversionFactor, conversionFactor);
path.scale(Item->groupWidth / Item->width(), Item->groupHeight / Item->height());
SetClipAttr(ob, &path, Item->fillRule);
}
QTransform mpx;
mpx.translate(xOffset * conversionFactor, yOffset * conversionFactor);
mpx.scale(Item->width() / Item->groupWidth, Item->height() / Item->groupHeight);
if ((Item->rotation() != 0.0) || Item->imageFlippedH() || Item->imageFlippedV())
{
mpx.rotate(Item->rotation());
if (Item->imageFlippedH())
{
mpx.translate(Item->width() * conversionFactor, 0);
mpx.scale(-1, 1);
}
if (Item->imageFlippedV())
{
mpx.translate(0, Item->height() * conversionFactor);
mpx.scale(1, -1);
}
}
ob.setAttribute("RenderTransform", MatrixToStr(mpx));
for (int em = 0; em < Item->groupItemList.count(); ++em)
{
PageItem* embed = Item->groupItemList.at(em);
writeItemOnPage(embed->gXpos, embed->gYpos, embed, ob, rel_root);
}
parentElem.appendChild(ob);
}
}
break;
default:
handleImageFallBack(Item, parentElem, rel_root);
break;
}
}
 
void XPSExPlug::handleImageFallBack(PageItem *Item, QDomElement &parentElem, QDomElement &rel_root)
{
QDomElement ob = p_docu.createElement("Path");
double maxAdd = 0;
if (Item->hasSoftShadow())
maxAdd = qMax(fabs(Item->softShadowXOffset()), fabs(Item->softShadowYOffset())) + Item->softShadowBlurRadius();
QRectF bounds = Item->getVisualBoundingRect().adjusted(-maxAdd, -maxAdd, maxAdd, maxAdd);
QPainterPath path;
path.moveTo(0, 0);
path.lineTo(bounds.width(), 0);
path.lineTo(bounds.width(), bounds.height());
path.lineTo(0, bounds.height());
path.closeSubpath();
QTransform mpp;
mpp.translate((Item->visualXPos() - m_Doc->currentPage()->xOffset() - maxAdd) * conversionFactor, (Item->visualYPos() - m_Doc->currentPage()->yOffset() - maxAdd) * conversionFactor);
mpp.scale(conversionFactor, conversionFactor);
path = mpp.map(path);
FPointArray fPath;
fPath.fromQPainterPath(path, true);
QString pa = SetClipPath(&fPath, true);
if (Item->fillRule)
pa.prepend("F 0 ");
else
pa.prepend("F 1 ");
ob.setAttribute("Data", pa);
QDomElement obf = p_docu.createElement("Path.Fill");
QDomElement gr = p_docu.createElement("ImageBrush");
double maxSize = qMax(bounds.width(), bounds.height());
max