diff --git a/active/main.cpp b/active/main.cpp index deb4297fafb..759738462c9 100644 --- a/active/main.cpp +++ b/active/main.cpp @@ -1,64 +1,64 @@ /* * This file is part of the KDE project * * Copyright (C) 2011 Shantanu Tushar * Copyright (C) 2012 Sujith Haridasan * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 sure * USA */ #include "src/MainWindow.h" -#include -#include -#include +#include +#include +#include int main(int argc, char *argv[]) { KAboutData aboutData("calligraactive", 0, ki18n("Calligra Active"), "1.0 Beta", ki18n("Calligra application for tablets"), KAboutData::License_GPL_V2, ki18n("Copyright (c) 2011-2012")); aboutData.addAuthor(ki18n("Shantanu Tushar"), ki18n("Maintainer and main developer"), "shantanu@kde.org", "http://www.shantanutushar.com"); aboutData.addAuthor(ki18n("Sujith Haridasan"), ki18n("Maintainer and main developer"), "sujith.haridasan@kdemail.net", "http://www.sujithh.info"); KCmdLineArgs::init(argc, argv, &aboutData); KCmdLineOptions options; options.add("+[file]", ki18n("File to open")); KCmdLineArgs::addCmdLineOptions(options); KApplication app; MainWindow mw; KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); if(args->count()) { mw.openFile(args->arg(0)); } args->clear(); mw.show(); return app.exec(); } diff --git a/active/src/CAAbstractDocumentHandler.h b/active/src/CAAbstractDocumentHandler.h index deef892e2b3..8eb7aa0ceda 100644 --- a/active/src/CAAbstractDocumentHandler.h +++ b/active/src/CAAbstractDocumentHandler.h @@ -1,92 +1,92 @@ /* * This file is part of the KDE project * * Copyright (C) 2011 Shantanu Tushar * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef CAABSTRACTDOCUMENTHANDLER_H #define CAABSTRACTDOCUMENTHANDLER_H -#include -#include +#include +#include #include class KoDocument; class QGraphicsItem; class KoCanvasController; class KoCanvasBase; class CADocumentController; class CAAbstractDocumentHandler : public QObject { Q_OBJECT Q_ENUMS (FlickModes) Q_PROPERTY(QString topToolbarSource READ topToolbarSource CONSTANT) Q_PROPERTY(QString rightToolbarSource READ rightToolbarSource CONSTANT) Q_PROPERTY(QString bottomToolbarSource READ bottomToolbarSource CONSTANT) Q_PROPERTY(QString leftToolbarSource READ leftToolbarSource CONSTANT) Q_PROPERTY(QString centerOverlaySource READ centerOverlaySource CONSTANT) Q_PROPERTY(QString previousPageImage READ previousPageImage NOTIFY previousPageImageChanged) Q_PROPERTY(QString nextPageImage READ nextPageImage NOTIFY nextPageImageChanged) Q_PROPERTY(FlickModes flickMode READ flickMode CONSTANT) public: enum FlickModes { FlickAutomatically, FlickHorizontally, FlickVertically, FlickBoth }; explicit CAAbstractDocumentHandler (CADocumentController* documentController); virtual ~CAAbstractDocumentHandler(); virtual QStringList supportedMimetypes() = 0; virtual bool openDocument (const QString& uri) = 0; virtual QString documentTypeName() = 0; virtual KoZoomMode::Mode preferredZoomMode() const = 0; virtual KoDocument* document() = 0; bool canOpenDocument (const QString& uri); KoCanvasBase* canvas() const; virtual QString topToolbarSource() const; virtual QString rightToolbarSource() const; virtual QString bottomToolbarSource() const; virtual QString leftToolbarSource() const; virtual QString centerOverlaySource() const; virtual QString previousPageImage() const; virtual QString nextPageImage() const; virtual FlickModes flickMode() const; public slots: virtual void gotoPreviousPage(); virtual void gotoNextPage(); signals: void previousPageImageChanged(); void nextPageImageChanged(); protected: class Private; Private* const d; void setCanvas (KoCanvasBase* canvas); CADocumentController* documentController() const; }; #endif // CAABSTRACTDOCUMENTHANDLER_H diff --git a/active/src/CACanvasController.cpp b/active/src/CACanvasController.cpp index 34e9ef377dd..8a2b26ba74d 100644 --- a/active/src/CACanvasController.cpp +++ b/active/src/CACanvasController.cpp @@ -1,349 +1,349 @@ /* * This file is part of the KDE project * * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2010 Boudewijn Rempt * Copyright (C) 2010-2011 Jarosław Staniek * Copyright (C) 2011 Shantanu Tushar * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "CACanvasController.h" #include "CACanvasItem.h" #include "CADocumentController.h" #include "CAAbstractDocumentHandler.h" #include #include #include #include -#include +#include #include -#include -#include -#include +#include +#include +#include #include CACanvasController::CACanvasController (QDeclarativeItem* parent) : QDeclarativeItem (parent), KoCanvasController (0), m_zoomHandler (0), m_zoomController (0), m_caDocumentHandler(0), m_currentPoint (QPoint (0, 0)), m_documentSize (QSizeF (0, 0)) { setFlag (QGraphicsItem::ItemHasNoContents, false); setClip (true); } void CACanvasController::setVastScrolling (qreal factor) { //kDebug() << factor; } void CACanvasController::setZoomWithWheel (bool zoom) { //kDebug() << zoom; } void CACanvasController::updateDocumentSize (const QSize& sz, bool recalculateCenter) { m_caCanvasItem->updateDocumentSize(sz, recalculateCenter); KoCanvasController::setDocumentSize(sz); } void CACanvasController::setScrollBarValue (const QPoint& value) { //kDebug() << value; } QPoint CACanvasController::scrollBarValue() const { return QPoint(); } void CACanvasController::pan (const QPoint& distance) { setCameraX(cameraX() + distance.x()); setCameraY(cameraY() + distance.y()); } QPointF CACanvasController::preferredCenter() const { //TODO: is this the correct value? return QPointF(width()/2, height()/2); } void CACanvasController::setPreferredCenter (const QPointF& viewPoint) { //kDebug() << viewPoint; } void CACanvasController::recenterPreferred() { } void CACanvasController::zoomTo (const QRect& rect) { //kDebug() << rect; } void CACanvasController::zoomBy (const QPoint& center, qreal zoom) { proxyObject->emitZoomRelative(zoom, center); canvas()->canvasItem()->update(); } void CACanvasController::zoomOut (const QPoint& center) { //kDebug() << center; } void CACanvasController::zoomIn (const QPoint& center) { //kDebug() << center; } void CACanvasController::ensureVisible (KoShape* shape) { ensureVisible(shape->boundingRect(), false); } void CACanvasController::ensureVisible (const QRectF& rect, bool smooth) { if (m_caCanvasItem->editable()) return; QRect currentVisible(canvasOffsetX(), canvasOffsetY(), visibleWidth(), visibleHeight()); QRect viewRect = rect.toRect(); viewRect.translate(m_caCanvasItem->koCanvas()->documentOrigin()); if (!viewRect.isValid() || currentVisible.contains(viewRect)) return; // its visible. Nothing to do. // if we move, we move a little more so the amount of times we have to move is less. int jumpWidth = smooth ? 0 : currentVisible.width() / 5; int jumpHeight = smooth ? 0 : currentVisible.height() / 5; if (!smooth && viewRect.width() + jumpWidth > currentVisible.width()) jumpWidth = 0; if (!smooth && viewRect.height() + jumpHeight > currentVisible.height()) jumpHeight = 0; int horizontalMove = 0; if (currentVisible.width() <= viewRect.width()) // center view horizontalMove = viewRect.center().x() - currentVisible.center().x(); else if (currentVisible.x() > viewRect.x()) // move left horizontalMove = viewRect.x() - currentVisible.x() - jumpWidth; else if (currentVisible.right() < viewRect.right()) // move right horizontalMove = viewRect.right() - qMax(0, currentVisible.right() - jumpWidth); int verticalMove = 0; if (currentVisible.height() <= viewRect.height()) // center view verticalMove = viewRect.center().y() - currentVisible.center().y(); if (currentVisible.y() > viewRect.y()) // move up verticalMove = viewRect.y() - currentVisible.y() - jumpHeight; else if (currentVisible.bottom() < viewRect.bottom()) // move down verticalMove = viewRect.bottom() - qMax(0, currentVisible.bottom() - jumpHeight); pan(QPoint(horizontalMove, verticalMove)); } int CACanvasController::canvasOffsetY() const { return m_caCanvasItem ? cameraY() - height()/2 : 0; } int CACanvasController::canvasOffsetX() const { return m_caCanvasItem ? cameraX() - width()/2 : 0; } int CACanvasController::visibleHeight() const { if (m_caCanvasItem == 0) return 0; QGraphicsWidget *canvasItem = m_caCanvasItem->koCanvas()->canvasItem(); int height1; if (canvasItem == 0) height1 = height(); else height1 = qMin(height(), canvasItem->boundingRect().height()); int height2 = height(); return qMin(height1, height2); } int CACanvasController::visibleWidth() const { if (m_caCanvasItem == 0) return 0; QGraphicsWidget *canvasItem = m_caCanvasItem->koCanvas()->canvasItem(); int width1; if (canvasItem == 0) width1 = width(); else width1 = qMin(width(), canvasItem->boundingRect().width()); int width2 = width(); return qMin(width1, width2); } KoCanvasBase* CACanvasController::canvas() const { return m_caCanvasItem->koCanvas(); } KoCanvasControllerProxyObject* CACanvasController::canvasControllerProxyObject() { return proxyObject; } QObject* CACanvasController::caCanvasItem() { return dynamic_cast(m_caCanvasItem); } void CACanvasController::setCACanvasItem(QObject* caCanvas) { m_caCanvasItem = static_cast(caCanvas); } void CACanvasController::setCanvas (KoCanvasBase* canvas) { canvas->setCanvasController(this); m_caCanvasItem->setKoCanvas(canvas); emit caCanvasItemChanged(); } void CACanvasController::setDrawShadow (bool drawShadow) { //kDebug() << drawShadow; } QSize CACanvasController::viewportSize() const { return QSize(width(), height()); } void CACanvasController::scrollContentsBy (int dx, int dy) { //kDebug() << dx << dy; } int CACanvasController::cameraX() const { return m_currentPoint.x(); } int CACanvasController::cameraY() const { return m_currentPoint.y(); } void CACanvasController::setCameraX (int cameraX) { cameraX -= std::min(m_caCanvasItem->width()/2, width()/2); if (m_caDocumentHandler && m_caDocumentHandler->preferredZoomMode() == KoZoomMode::ZOOM_WIDTH) { cameraX = 0; } m_currentPoint.setX (cameraX); emit cameraXChanged(); } void CACanvasController::setCameraY (int cameraY) { cameraY -= std::min(m_caCanvasItem->height()/2, height()/2); if (m_caDocumentHandler && m_caDocumentHandler->preferredZoomMode() == KoZoomMode::ZOOM_PAGE) { cameraY = 0; } m_currentPoint.setY (cameraY); emit cameraYChanged(); } void CACanvasController::alignLeftWith(int x) { m_currentPoint.setX(x); emit cameraXChanged(); } void CACanvasController::alignTopWith(int y) { m_currentPoint.setY(y); emit cameraYChanged(); } CACanvasController::~CACanvasController() { } void CACanvasController::zoomToFit() { } void CACanvasController::updateCanvas() { emit needCanvasUpdate(); } void CACanvasController::setDocumentHandler(CAAbstractDocumentHandler* documentHandler) { m_caDocumentHandler = documentHandler; } void CACanvasController::geometryChanged (const QRectF& newGeometry, const QRectF& oldGeometry) { if (m_caCanvasItem->koCanvas() && zoomController() && m_caDocumentHandler) { zoomController()->setZoomMode(m_caDocumentHandler->preferredZoomMode()); emit proxyObject->emitSizeChanged(newGeometry.size().toSize()); updateCanvas(); } QDeclarativeItem::geometryChanged (newGeometry, oldGeometry); } KoZoomController* CACanvasController::zoomController() { return m_zoomController; } KoZoomHandler* CACanvasController::zoomHandler() { return m_zoomHandler; } void CACanvasController::setZoomHandler (KoZoomHandler* zoomHandler) { if (!m_zoomController) { m_zoomHandler = zoomHandler; m_zoomController = new KoZoomController(this, zoomHandler, new KActionCollection(this)); zoomController()->setZoom(m_caDocumentHandler->preferredZoomMode(), 1); } } void CACanvasController::setZoom(qreal zoom) { } qreal CACanvasController::zoom() const { return m_zoom; } void CACanvasController::updateZoomValue(KoZoomMode::Mode mode, qreal zoom) { m_zoom = zoom; } #include "CACanvasController.moc" diff --git a/active/src/CACanvasItem.cpp b/active/src/CACanvasItem.cpp index 9ba50a3c39c..ea499539d3f 100644 --- a/active/src/CACanvasItem.cpp +++ b/active/src/CACanvasItem.cpp @@ -1,133 +1,133 @@ /* * This file is part of the KDE project * * Copyright (C) 2012 Shantanu Tushar * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "CACanvasItem.h" #include -#include +#include #include -#include -#include +#include +#include CACanvasItem::CACanvasItem(QDeclarativeItem* parent) : QDeclarativeItem(parent) , m_koCanvas(0) , m_shouldIgnoreGeometryChange(false) , m_editable(false) { setFlag (QGraphicsItem::ItemHasNoContents, false); } KoCanvasBase* CACanvasItem::koCanvas() { return m_koCanvas; } void CACanvasItem::setKoCanvas(KoCanvasBase* koCanvas) { if (!koCanvas) return; if (m_koCanvasGraphicsWidget) { m_koCanvasGraphicsWidget->removeEventFilter(this); m_koCanvasGraphicsWidget->disconnect(this); } m_koCanvas = koCanvas; m_koCanvasGraphicsWidget = dynamic_cast(koCanvas); m_koCanvasGraphicsWidget->setParentItem(this); m_koCanvasGraphicsWidget->installEventFilter(this); m_koCanvasGraphicsWidget->setVisible(true); m_koCanvasGraphicsWidget->setGeometry(x(), y(), width(), height()); connect(m_koCanvasGraphicsWidget, SIGNAL(geometryChanged()), SLOT(resizeToCanvas())); } bool CACanvasItem::eventFilter(QObject* o, QEvent* e) { if (o == m_koCanvasGraphicsWidget) { if (e->type() == QEvent::Move) { m_shouldIgnoreGeometryChange = true; QMoveEvent *moveEvent = static_cast(e); setPos(QPointF(moveEvent->pos())); } else if (e->type() == QEvent::Resize) { m_shouldIgnoreGeometryChange = true; QResizeEvent *resizeEvent = static_cast(e); setWidth(resizeEvent->size().width()); setHeight(resizeEvent->size().height()); } else if (m_editable) { return false; } else if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease || e->type() == QEvent::MouseMove || e->type() == QEvent::MouseTrackingChange) { return true; } else { return false; } } QTimer::singleShot(0, this, SLOT(resetShouldIgnoreGeometryChange())); return QDeclarativeItem::eventFilter(o, e); } void CACanvasItem::resetShouldIgnoreGeometryChange() { m_shouldIgnoreGeometryChange = false; } void CACanvasItem::resizeToCanvas() { if (!m_koCanvasGraphicsWidget) return; m_shouldIgnoreGeometryChange = true; setPos(m_koCanvasGraphicsWidget->geometry().topLeft()); setWidth(m_koCanvasGraphicsWidget->geometry().size().width()); setHeight(m_koCanvasGraphicsWidget->geometry().size().height()); QTimer::singleShot(0, this, SLOT(resetShouldIgnoreGeometryChange())); } bool CACanvasItem::editable() const { return m_editable; } void CACanvasItem::setEditable(bool value) { m_editable = value; emit editableChanged(); } void CACanvasItem::updateDocumentSize(QSize sz, bool recalculateCenter) { setHeight(sz.height()); setWidth(sz.width()); if (m_koCanvasGraphicsWidget) { m_koCanvasGraphicsWidget->setGeometry(x(), y(), width(), height()); } } CACanvasItem::~CACanvasItem() { } #include "CACanvasItem.moc" diff --git a/active/src/CACanvasItem.h b/active/src/CACanvasItem.h index 4be7287b463..2c0c43a6675 100644 --- a/active/src/CACanvasItem.h +++ b/active/src/CACanvasItem.h @@ -1,62 +1,62 @@ /* * This file is part of the KDE project * * Copyright (C) 2012 Shantanu Tushar * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef CACANVASITEM_H #define CACANVASITEM_H -#include +#include class QGraphicsWidget; class KoCanvasBase; class CACanvasItem : public QDeclarativeItem { Q_OBJECT Q_PROPERTY (bool editable READ editable WRITE setEditable NOTIFY editableChanged) public: CACanvasItem(QDeclarativeItem* parent = 0); virtual ~CACanvasItem(); KoCanvasBase *koCanvas(); void setKoCanvas(KoCanvasBase *koCanvas); bool editable() const; void setEditable(bool value); void updateDocumentSize(QSize sz, bool recalculateCenter); signals: void koCanvasChanged(); void editableChanged(); protected: virtual bool eventFilter(QObject* o, QEvent* e); private slots: void resetShouldIgnoreGeometryChange(); void resizeToCanvas(); private: KoCanvasBase *m_koCanvas; QGraphicsWidget *m_koCanvasGraphicsWidget; bool m_shouldIgnoreGeometryChange; bool m_editable; }; #endif // CACANVASITEM_H diff --git a/active/src/CAImageProvider.cpp b/active/src/CAImageProvider.cpp index bd3cba5abc6..9df048b8abf 100644 --- a/active/src/CAImageProvider.cpp +++ b/active/src/CAImageProvider.cpp @@ -1,70 +1,70 @@ /* * This file is part of the KDE project * * Copyright (C) 2011 Shantanu Tushar * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "CAImageProvider.h" -#include +#include const char *CAImageProvider::identificationString = "caimage"; class CAImageProvider::Singleton { public: CAImageProvider q; }; K_GLOBAL_STATIC( CAImageProvider::Singleton, singleton ) CAImageProvider * CAImageProvider::instance() { return &( singleton->q ); } CAImageProvider::CAImageProvider() : QDeclarativeImageProvider(Image) { } CAImageProvider::~CAImageProvider() { } QImage CAImageProvider::requestImage(const QString& id, QSize* size, const QSize& requestedSize) { if (m_images.contains(id)) { QImage image = m_images.value(id); *size = image.size(); return requestedSize.isValid() ? image.scaled(requestedSize, Qt::KeepAspectRatioByExpanding) : image; } size = new QSize(); return QImage(); } void CAImageProvider::addImage(const QString& id, const QImage& image) { m_images[id] = image; } bool CAImageProvider::containsId(const QString& id) { return m_images.contains(id); } diff --git a/active/src/CAImageProvider.h b/active/src/CAImageProvider.h index e41b8bf4561..488a8e30471 100644 --- a/active/src/CAImageProvider.h +++ b/active/src/CAImageProvider.h @@ -1,45 +1,45 @@ /* * This file is part of the KDE project * * Copyright (C) 2011 Shantanu Tushar * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef CAIMAGEPROVIDER_H #define CAIMAGEPROVIDER_H -#include -#include +#include +#include class CAImageProvider : public QDeclarativeImageProvider { public: static const char *identificationString; class Singleton; virtual ~CAImageProvider(); static CAImageProvider *instance(); virtual QImage requestImage(const QString& id, QSize* size, const QSize& requestedSize); void addImage(const QString& id, const QImage &image); bool containsId(const QString &id); private: CAImageProvider(); QHash m_images; }; #endif // CAIMAGEPROVIDER_H diff --git a/active/src/CAPresentationHandler.cpp b/active/src/CAPresentationHandler.cpp index 950326ebb91..b0ff628938e 100644 --- a/active/src/CAPresentationHandler.cpp +++ b/active/src/CAPresentationHandler.cpp @@ -1,425 +1,425 @@ /* * This file is part of the KDE project * * Copyright (C) 2011 Shantanu Tushar * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "CAPresentationHandler.h" #include "CAPAView.h" #include "CADocumentController.h" #include "CACanvasController.h" #include "CAPADocumentModel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include -#include +#include +#include #include class CAPresentationHandler::Private { public: Private() { currentSlideNum = -1; paDocumentModel = 0; findText = 0; countMatchesPerSlide = 0; searchSlideNumber = 0; matchFound = false; } QString searchString; KPrDocument* document; CAPAView* paView; int currentSlideNum; int countMatchesPerSlide; int searchSlideNumber; bool matchFound; QList texts; KoFindText* findText; QTimer slideshowTimer; QList slideShow; CAPADocumentModel *paDocumentModel; }; CAPresentationHandler::CAPresentationHandler (CADocumentController* documentController) : CAAbstractDocumentHandler (documentController) , d (new Private()) { QList texts; d->findText = new KoFindText(this); connect(&d->slideshowTimer, SIGNAL(timeout()), SLOT(advanceSlideshow())); connect (d->findText, SIGNAL (updateCanvas()), SLOT (updateCanvas())); connect (d->findText, SIGNAL (matchFound (KoFindMatch)), SLOT (findMatchFound (KoFindMatch))); connect (d->findText, SIGNAL (noMatchFound()), SLOT (findNoMatchFound())); } CAPresentationHandler::~CAPresentationHandler() { delete d; } KoZoomMode::Mode CAPresentationHandler::preferredZoomMode() const { return KoZoomMode::ZOOM_PAGE; } KoDocument* CAPresentationHandler::document() { return d->document; } bool CAPresentationHandler::openDocument (const QString& uri) { QString error; QString mimetype = KMimeType::findByPath (uri)->name(); KoPart *part = KMimeTypeTrader::createInstanceFromQuery(mimetype, QLatin1String("CalligraPart"), 0, QString(), QVariantList(), &error); if (!part) { kDebug() << "Doc can't be openend" << error; return false; } d->document = qobject_cast (part->document()); d->document->openUrl (KUrl (uri)); KoCanvasBase* paCanvas = dynamic_cast (part->canvasItem()); KoPACanvasItem* paCanvasItem = dynamic_cast (paCanvas); if (!paCanvasItem) { kDebug() << "Failed to fetch a canvas item"; return false; } if (paCanvasItem) { d->paView = new CAPAView (documentController()->canvasController(), dynamic_cast (paCanvas), d->document); paCanvasItem->setView (d->paView); documentController()->canvasController()->setZoomHandler (static_cast (paCanvasItem->viewConverter())); d->paView->connectToZoomController(); // update the canvas whenever we scroll, the canvas controller must emit this signal on scrolling/panning connect (documentController()->canvasController()->canvasControllerProxyObject(), SIGNAL (moveDocumentOffset (const QPoint&)), paCanvasItem, SLOT (slotSetDocumentOffset (QPoint))); // whenever the size of the document viewed in the canvas changes, inform the zoom controller connect (paCanvasItem, SIGNAL (documentSize (QSize)), this, SLOT (tellZoomControllerToSetDocumentSize (QSize))); paCanvasItem->update(); } setCanvas (paCanvas); KoToolManager::instance()->addController (documentController()->canvasController()); connect(documentController()->canvasController(), SIGNAL(needsCanvasResize(QSizeF)), SLOT(resizeCanvas(QSizeF))); connect (documentController()->canvasController(), SIGNAL (needCanvasUpdate()), SLOT (updateCanvas())); d->paDocumentModel = new CAPADocumentModel(this, d->document); emit totalNumberOfSlidesChanged(); QTimer::singleShot(0, this, SLOT(nextSlide())); return true; } QStringList CAPresentationHandler::supportedMimetypes() { QStringList supportedTypes; supportedTypes << "application/vnd.oasis.opendocument.presentation" << "application/vnd.ms-powerpoint"; return supportedTypes; } void CAPresentationHandler::nextSlide() { if (d->currentSlideNum == d->document->pageCount()-1) return; d->currentSlideNum++; emit currentSlideNumberChanged(); gotoCurrentSlide(); zoomToFit(); } void CAPresentationHandler::previousSlide() { if (d->currentSlideNum > 0) { d->currentSlideNum--; emit currentSlideNumberChanged(); } gotoCurrentSlide(); zoomToFit(); } void CAPresentationHandler::gotoCurrentSlide() { d->paView->doUpdateActivePage (d->document->pageByIndex (d->currentSlideNum, false)); emit previousPageImageChanged(); emit nextPageImageChanged(); } void CAPresentationHandler::setTextData(int slideNumber) { d->texts.clear(); KoFindText::findTextInShapes(d->document->pageByIndex(slideNumber,false)->shapes(), d->texts); d->findText->setDocuments(d->texts); } void CAPresentationHandler::zoomToFit() { updateCanvas(); setTextData(d->currentSlideNum); } void CAPresentationHandler::tellZoomControllerToSetDocumentSize (const QSize& size) { documentController()->canvasController()->zoomController()->setDocumentSize (size); } void CAPresentationHandler::updateCanvas() { dynamic_cast (canvas())->update(); } QString CAPresentationHandler::documentTypeName() { return "presentation"; } void CAPresentationHandler::resizeCanvas (const QSizeF& canvasSize) { QSizeF pageSize = d->paView->activePage()->boundingRect().size(); QGraphicsWidget* canvasItem = canvas()->canvasItem(); QSizeF newSize (pageSize); newSize.scale (canvasSize, Qt::KeepAspectRatio); if (canvasSize.width() < canvasSize.height()) { canvasItem->setGeometry (0, (canvasSize.height() - newSize.height()) / 2, newSize.width(), newSize.height()); documentController()->canvasController()->zoomHandler()->setZoom (canvasSize.width() / pageSize.width() * 0.75); } else { canvasItem->setGeometry ( (canvasSize.width() - newSize.width()) / 2, 0, newSize.width(), newSize.height()); documentController()->canvasController()->zoomHandler()->setZoom (canvasSize.height() / pageSize.height() * 0.75); } } QString CAPresentationHandler::searchString() const { return d->searchString; } void CAPresentationHandler::setSearchString (const QString& searchString) { d->searchString = searchString; d->findText->find(searchString); emit searchStringChanged(); } void CAPresentationHandler::searchOtherSlides(SearchDirection direction) { //Reset the count d->countMatchesPerSlide = 0; if( direction == SearchForward) { d->searchSlideNumber = d->currentSlideNum + 1; } else if ( direction == SearchBackwards) { if( d->currentSlideNum != 0) { d->searchSlideNumber = d->currentSlideNum - 1; } else { return; } } while ((d->searchSlideNumber < totalNumberOfSlides()) && (d->searchSlideNumber >= 0)) { setTextData(d->searchSlideNumber); setSearchString(d->searchString); if(d->matchFound == true) { d->currentSlideNum = d->searchSlideNumber; setCurrentSlideNumber(d->currentSlideNum); setSearchString(d->searchString); if(direction == SearchBackwards) { d->countMatchesPerSlide = d->findText->matches().count() - 1; d->findText->findPrevious(); } break; } if(direction == SearchForward) { d->searchSlideNumber++; } else if(direction == SearchBackwards) { d->searchSlideNumber--; } } } void CAPresentationHandler::findNext() { d->countMatchesPerSlide++; d->findText->findNext(); if((d->countMatchesPerSlide >= d->findText->matches().count()) or (d->findText->matches().count() == 0)) { searchOtherSlides(SearchForward); } } void CAPresentationHandler::findPrevious() { d->countMatchesPerSlide--; d->findText->findPrevious(); if( d->countMatchesPerSlide < 0) { searchOtherSlides(SearchBackwards); } } void CAPresentationHandler::findMatchFound (const KoFindMatch& match) { QTextCursor cursor = match.location().value(); updateCanvas(); canvas()->resourceManager()->setResource (KoText::CurrentTextAnchor, cursor.anchor()); canvas()->resourceManager()->setResource (KoText::CurrentTextPosition, cursor.position()); d->matchFound = true; } void CAPresentationHandler::findNoMatchFound() { d->matchFound = false; kDebug() << "Match for " << searchString() << " not found"; } QString CAPresentationHandler::topToolbarSource() const { return "PresentationTopToolbar.qml"; } QString CAPresentationHandler::leftToolbarSource() const { return "PresentationLeftToolbar.qml"; } QString CAPresentationHandler::rightToolbarSource() const { return "PresentationRightToolbar.qml"; } QString CAPresentationHandler::centerOverlaySource() const { return "PresentationCenterOverlay.qml"; } QString CAPresentationHandler::bottomToolbarSource() const { return "FindToolbar.qml"; } void CAPresentationHandler::setSlideshowDelay(int delay) { d->slideshowTimer.setInterval(delay*1000); } int CAPresentationHandler::slideshowDelay() const { return d->slideshowTimer.interval()/1000; } void CAPresentationHandler::startSlideshow() { d->slideShow = d->document->slideShow(); d->currentSlideNum = 0; d->paView->doUpdateActivePage(d->slideShow.at(d->currentSlideNum)); d->slideshowTimer.start(); emit slideshowStarted(); } void CAPresentationHandler::stopSlideshow() { d->slideshowTimer.stop(); emit slideshowStopped(); } void CAPresentationHandler::advanceSlideshow() { d->paView->doUpdateActivePage(d->slideShow.at(++(d->currentSlideNum))); if (d->currentSlideNum == d->slideShow.count() - 1) { stopSlideshow(); } } int CAPresentationHandler::currentSlideNumber() const { return d->currentSlideNum + 1; } int CAPresentationHandler::totalNumberOfSlides() const { return d->document->pageCount(); } CAPADocumentModel* CAPresentationHandler::paDocumentModel() const { return d->paDocumentModel; } void CAPresentationHandler::setCurrentSlideNumber(int number) { d->currentSlideNum = number; gotoCurrentSlide(); emit currentSlideNumberChanged(); } QString CAPresentationHandler::nextPageImage() const { return paDocumentModel()->data(paDocumentModel()->index(d->currentSlideNum+1, 0), CAPADocumentModel::SlideImageRole).toString(); } QString CAPresentationHandler::previousPageImage() const { return paDocumentModel()->data(paDocumentModel()->index(d->currentSlideNum-1, 0), CAPADocumentModel::SlideImageRole).toString(); } void CAPresentationHandler::gotoNextPage() { nextSlide(); } void CAPresentationHandler::gotoPreviousPage() { previousSlide(); } CAAbstractDocumentHandler::FlickModes CAPresentationHandler::flickMode() const { return FlickHorizontally; } #include "CAPresentationHandler.moc" diff --git a/active/src/MainWindow.cpp b/active/src/MainWindow.cpp index b54f870ddbc..68d8d333966 100644 --- a/active/src/MainWindow.cpp +++ b/active/src/MainWindow.cpp @@ -1,141 +1,141 @@ /* * This file is part of the KDE project * * Copyright (C) 2011 Shantanu Tushar * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "MainWindow.h" #include "CACanvasController.h" #include "CADocumentInfo.h" #include "CADocumentController.h" #include "CACanvasItem.h" #include "CAPADocumentModel.h" #include "CATextDocumentModel.h" #include "CAImageProvider.h" #include "CAAbstractDocumentHandler.h" #include "calligra_active_global.h" #include -#include -#include -#include +#include +#include +#include #include #include #include #include #include #include #include MainWindow::MainWindow (QWidget* parent) { qmlRegisterType ("CalligraActive", 1, 0, "CanvasController"); qmlRegisterType ("CalligraActive", 1, 0, "CADocumentInfo"); qmlRegisterType ("CalligraActive", 1, 0, "CADocumentController"); qmlRegisterType ("CalligraActive", 1, 0, "CACanvasItem"); qmlRegisterUncreatableType ("CalligraActive", 1, 0, "CAPADocumentModel", "Not allowed"); qmlRegisterUncreatableType ("CalligraActive", 1, 0, "CATextDocumentModel", "Not allowed"); qmlRegisterInterface ("KoCanvasController"); qmlRegisterUncreatableType("CalligraActive", 1, 0, "CAAbstractDocumentHandler", "Not allowed"); m_view = new QDeclarativeView (this); kdeclarative.setDeclarativeEngine(m_view->engine()); kdeclarative.initialize(); kdeclarative.setupBindings(); QList recentFiles; QList recentTextDocs; QList recentSpreadsheets; QList recentPresentations; QSettings settings; foreach (const QString &string, settings.value ("recentFiles").toStringList()) { CADocumentInfo* docInfo = CADocumentInfo::fromStringList (string.split (";")); recentFiles.append (docInfo); switch (docInfo->type()) { case CADocumentInfo::TextDocument: recentTextDocs.append (docInfo); break; case CADocumentInfo::Spreadsheet: recentSpreadsheets.append (docInfo); break; case CADocumentInfo::Presentation: recentPresentations.append (docInfo); break; } } foreach (const QString & importPath, KGlobal::dirs()->findDirs ("module", "imports")) { m_view->engine()->addImportPath (importPath); } m_view->rootContext()->setContextProperty("mainwindow", this); m_view->rootContext()->setContextProperty("_calligra_version_string", CALLIGRA_VERSION_STRING); m_view->engine()->addImageProvider(CAImageProvider::identificationString, CAImageProvider::instance()); m_view->setSource (QUrl::fromLocalFile (CalligraActive::Global::installPrefix() + "/share/calligraactive/qml/Doc.qml")); m_view->setResizeMode (QDeclarativeView::SizeRootObjectToView); connect (m_view, SIGNAL (sceneResized (QSize)), SLOT (adjustWindowSize (QSize))); resize (1024, 768); setCentralWidget (m_view); QTimer::singleShot(0, this, SLOT(checkForAndOpenDocument())); } void MainWindow::openFile (const QString& path) { documentPath = path; QObject* object = m_view->rootObject(); if (object) { QMetaObject::invokeMethod (object, "hideOpenButton"); } } void MainWindow::adjustWindowSize (QSize size) { resize (size); } void MainWindow::openFileDialog() { const QString path = QFileDialog::getOpenFileName (this, i18n("Open File"), QDesktopServices::storageLocation (QDesktopServices::DocumentsLocation)); if (!path.isEmpty()) { QObject* object = m_view->rootObject(); Q_ASSERT (object); QMetaObject::invokeMethod (object, "openDocument", Q_ARG (QVariant, QVariant (path))); } } MainWindow::~MainWindow() { } void MainWindow::checkForAndOpenDocument() { if (!documentPath.isEmpty()) { QObject* object = m_view->rootObject(); QMetaObject::invokeMethod (object, "openDocument", Q_ARG (QVariant, QVariant (documentPath))); } } #include "MainWindow.moc" diff --git a/filters/karbon/xfig/XFigImportFilter.cpp b/filters/karbon/xfig/XFigImportFilter.cpp index b2f42f12849..6f279ccd87b 100644 --- a/filters/karbon/xfig/XFigImportFilter.cpp +++ b/filters/karbon/xfig/XFigImportFilter.cpp @@ -1,85 +1,85 @@ /* This file is part of the Calligra project, made within the KDE community. Copyright 2012 Friedrich W. H. Kossebau This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "XFigImportFilter.h" // filter #include "XFigParser.h" #include "XFigDocument.h" #include "XFigOdgWriter.h" // Calligra core #include #include #include // KDE #include // Qt -#include +#include K_PLUGIN_FACTORY(CdrImportFactory, registerPlugin();) K_EXPORT_PLUGIN(CdrImportFactory("calligrafilters")) XFigImportFilter::XFigImportFilter( QObject* parent, const QVariantList& ) : KoFilter(parent) { } XFigImportFilter::~XFigImportFilter() { } KoFilter::ConversionStatus XFigImportFilter::convert( const QByteArray& from, const QByteArray& to ) { if ((from != "image/x-xfig") || (to != "application/vnd.oasis.opendocument.graphics")) { return KoFilter::NotImplemented; } // prepare input QFile inputFile( m_chain->inputFile() ); if( ! inputFile.open(QIODevice::ReadOnly) ) { return KoFilter::FileNotFound; } // prepare output KoStore* outputStore = KoStore::createStore( m_chain->outputFile(), KoStore::Write, KoOdf::mimeType(KoOdf::Graphics), KoStore::Zip ); if( ! outputStore ) { return KoFilter::StorageCreationError; } XFigOdgWriter odgWriter( outputStore ); // translate! XFigDocument* document = XFigParser::parse( &inputFile ); if( ! document ) { return KoFilter::CreationError; } const bool isWritten = odgWriter.write(document); delete document; return isWritten ? KoFilter::OK : KoFilter::CreationError; } diff --git a/filters/karbon/xfig/XFigOdgWriter.h b/filters/karbon/xfig/XFigOdgWriter.h index 59d3d813491..d24753843c0 100644 --- a/filters/karbon/xfig/XFigOdgWriter.h +++ b/filters/karbon/xfig/XFigOdgWriter.h @@ -1,122 +1,122 @@ /* This file is part of the Calligra project, made within the KDE community. Copyright 2012 Friedrich W. H. Kossebau This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef XFIGODGWRITER_H #define XFIGODGWRITER_H // Calligra #include #include // Qt -#include +#include class XFigDocument; class XFigPage; class XFigCompoundObject; class XFigEllipseObject; class XFigPolylineObject; class XFigPolygonObject; class XFigBoxObject; class XFigPictureBoxObject; class XFigSplineObject; class XFigArcObject; class XFigTextObject; class XFigAbstractGraphObject; class XFigAbstractObject; class XFigLineable; class XFigLineEndable; class XFigFillable; class XFigArrowHead; struct XFigPoint; class KoXmlWriter; class KoStore; class KoGenStyle; template class QVector; class XFigOdgWriter { public: explicit XFigOdgWriter( KoStore* outputStore ); ~XFigOdgWriter(); bool write( XFigDocument* document ); private: enum LineEndType { LineStart, LineEnd }; void storePixelImageFiles(); void storeMetaXml(); void storeContentXml(); void writeMasterPage(); void writePage( const XFigPage* page ); void writeObject( const XFigAbstractObject* object ); void writeCompoundObject( const XFigCompoundObject* groupObject ); void writeEllipseObject( const XFigEllipseObject* object ); void writePolylineObject( const XFigPolylineObject* object ); void writePolygonObject( const XFigPolygonObject* object ); void writeBoxObject( const XFigBoxObject* object ); void writePictureBoxObject( const XFigPictureBoxObject* object ); void writeSplineObject( const XFigSplineObject* pathObject ); void writeArcObject( const XFigArcObject* pathObject ); void writeTextObject( const XFigTextObject* object ); void writeParagraphStyle( KoGenStyle& odfStyle, const XFigTextObject* textObject ); void writeFont( KoGenStyle& odfStyle, const XFigTextObject* textObject ); void writeFill( KoGenStyle& odfStyle, const XFigFillable* fillable, qint32 penColorId ); void writeStroke( KoGenStyle& odfStyle, const XFigLineable* lineable ); void writeDotDash( KoGenStyle& odfStyle, int lineType, double distance ); void writeJoinType(KoGenStyle& odfStyle, int joinType); void writeCapType( KoGenStyle& odfStyle, const XFigLineEndable* lineEndable ); void writeArrow(KoGenStyle& odfStyle, const XFigArrowHead* arrow, LineEndType lineEndType); void writeHatch(KoGenStyle& odfStyle, int patternType, const QString& colorString); void writeComment(const XFigAbstractObject* object); void writePoints( const QVector& points ); /// Writes z-index and sets layer name void writeZIndex( const XFigAbstractGraphObject* graphObject ); /// Returns the XFig x coord as ODF x coord (in pt) double odfXCoord( qint32 x ) const; /// Returns the XFig y coord as ODF y coord (in pt) double odfYCoord( qint32 y ) const; /// Returns the XFig length as ODF length (in pt) double odfLength( qint32 length ) const; double odfLength( double length ) const; private: QLocale m_CLocale; KoOdfWriteStore m_OdfWriteStore; KoStore* m_OutputStore; KoXmlWriter* m_ManifestWriter; KoXmlWriter* m_BodyWriter; KoGenStyles m_StyleCollector; QString m_MasterPageStyleName; int m_PageCount; XFigDocument* m_Document; }; #endif diff --git a/filters/sheets/latex/export/latexexportAdaptor.h b/filters/sheets/latex/export/latexexportAdaptor.h index 5534d37ac3a..4ad632f0a92 100644 --- a/filters/sheets/latex/export/latexexportAdaptor.h +++ b/filters/sheets/latex/export/latexexportAdaptor.h @@ -1,46 +1,46 @@ /* This file is part of the KDE project Copyright (C) 2003 Robert JACOLIN Copyright (C) 2006 Fredrik Edemar This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef __LATEXEXPORTADAPTOR_H__ #define __LATEXEXPORTADAPTOR_H__ #include -#include +#include class KSpreadLatexExportDiaImpl; class LatexExportAdaptor: public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.calligra.filter.kspread.latex") public: LatexExportAdaptor(KSpreadLatexExportDiaImpl* dia); ~LatexExportAdaptor(); public Q_SLOTS: // METHODS Q_SCRIPTABLE void useDefaultConfig(); private: KSpreadLatexExportDiaImpl* _dialog; }; #endif /* __LATEXEXPORTADAPTOR_H__ */ diff --git a/karbon/ui/KarbonKoDocument.cpp b/karbon/ui/KarbonKoDocument.cpp index e42e8d1a1f2..d16b84d1472 100644 --- a/karbon/ui/KarbonKoDocument.cpp +++ b/karbon/ui/KarbonKoDocument.cpp @@ -1,458 +1,458 @@ /* This file is part of the KDE project * Copyright (C) 2001-2002 Lennart Kudling * Copyright (C) 2001-2007 Rob Buis * Copyright (C) 2002-2006 Laurent Montel * Copyright (C) 2002 Werner Trobin * Copyright (C) 2002-2006 David Faure * Copyright (C) 2002 Stephan Kulow * Copyright (C) 2002 Benoit Vautrin * Copyright (C) 2003 Thomas Nagy * Copyright (C) 2003,2006 Dirk Mueller * Copyright (C) 2004 Brad Hards * Copyright (C) 2004-2006 Peter Simonsson * Copyright (C) 2004-2005 Fredrik Edemar * Copyright (C) 2005-2006 Tim Beaulen * Copyright (C) 2005 Sven Langkamp * Copyright (C) 2005-2007 Jan Hambrecht * Copyright (C) 2005-2007 Thomas Zander * Copyright (C) 2005-2006 Inge Wallin * Copyright (C) 2005 Johannes Schaub * Copyright (C) 2006 Gabor Lehel * Copyright (C) 2006 Stefan Nikolaus * Copyright (C) 2006 Jaison Lee * Copyright (C) 2006 Casper Boemann * Copyright (C) 2006-2007 Thorsten Zachmann * Copyright (C) 2007 Matthias Kretz * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KarbonKoDocument.h" #include "KarbonPart.h" #include "KarbonFactory.h" #include "KarbonView.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include -#include +#include +#include #include #include #include // Make sure an appropriate DTD is available in www/calligra/DTD if changing this value // static const char * CURRENT_DTD_VERSION = "1.2"; class KarbonKoDocument::Private { public: Private() : showStatusBar(true), merge(false), maxRecentFiles(10) {} qreal getAttribute(KoXmlElement &element, const char *attributeName, qreal defaultValue) { QString value = element.attribute(attributeName); if (! value.isEmpty()) return value.toDouble(); else return defaultValue; } int getAttribute(KoXmlElement &element, const char *attributeName, int defaultValue) { QString value = element.attribute(attributeName); if (! value.isEmpty()) return value.toInt(); else return defaultValue; } KarbonDocument document; ///< store non-visual doc info bool showStatusBar; ///< enable/disable status bar in attached view(s) bool merge; uint maxRecentFiles; ///< max. number of files shown in open recent menu item }; KarbonKoDocument::KarbonKoDocument(KarbonPart* part) : KoDocument(part) , d(new Private()) { d->document.setResourceManager(resourceManager()); resourceManager()->setUndoStack(undoStack()); initConfig(); SvgShapeFactory::addToRegistry(); // set as default paper KoPageLayout pl = pageLayout(); pl.format = KoPageFormat::defaultFormat(); pl.orientation = KoPageFormat::Portrait; pl.width = MM_TO_POINT(KoPageFormat::width(pl.format, pl.orientation)); pl.height = MM_TO_POINT(KoPageFormat::height(pl.format, pl.orientation)); setPageLayout(pl); } KarbonKoDocument::~KarbonKoDocument() { delete d; } void KarbonKoDocument::setPageLayout(const KoPageLayout& layout) { KoDocument::setPageLayout(layout); setPageSize(QSizeF(layout.width, layout.height)); } bool KarbonKoDocument::loadXML(const KoXmlDocument&, KoStore*) { return false; } bool KarbonKoDocument::loadOdf(KoOdfReadStore & odfStore) { kDebug(38000) << "Start loading OASIS document..." /*<< doc.toString()*/; KoXmlElement contents = odfStore.contentDoc().documentElement(); kDebug(38000) << "Start loading OASIS document..." << contents.text(); kDebug(38000) << "Start loading OASIS contents..." << contents.lastChild().localName(); kDebug(38000) << "Start loading OASIS contents..." << contents.lastChild().namespaceURI(); kDebug(38000) << "Start loading OASIS contents..." << contents.lastChild().isElement(); KoXmlElement body(KoXml::namedItemNS(contents, KoXmlNS::office, "body")); if (body.isNull()) { kDebug(38000) << "No office:body found!"; setErrorMessage(i18n("Invalid OASIS document. No office:body tag found.")); return false; } body = KoXml::namedItemNS(body, KoXmlNS::office, "drawing"); if (body.isNull()) { kDebug(38000) << "No office:drawing found!"; setErrorMessage(i18n("Invalid OASIS document. No office:drawing tag found.")); return false; } KoXmlElement page(KoXml::namedItemNS(body, KoXmlNS::draw, "page")); if (page.isNull()) { kDebug(38000) << "No office:drawing found!"; setErrorMessage(i18n("Invalid OASIS document. No draw:page tag found.")); return false; } KoXmlElement * master = 0; if (odfStore.styles().masterPages().contains("Standard")) master = odfStore.styles().masterPages().value("Standard"); else if (odfStore.styles().masterPages().contains("Default")) master = odfStore.styles().masterPages().value("Default"); else if (! odfStore.styles().masterPages().empty()) master = odfStore.styles().masterPages().begin().value(); if (master) { const QString pageStyleName = master->attributeNS(KoXmlNS::style, "page-layout-name", QString()); const KoXmlElement *style = odfStore.styles().findStyle(pageStyleName); if (style) { KoPageLayout layout; layout.loadOdf(*style); setPageLayout(layout); } } else { kWarning() << "No master page found!"; return false; } KoOdfLoadingContext context(odfStore.styles(), odfStore.store()); KoShapeLoadingContext shapeContext(context, resourceManager()); d->document.loadOasis(page, shapeContext); if (d->document.pageSize().isEmpty()) { QSizeF pageSize = d->document.contentRect().united(QRectF(0, 0, 1, 1)).size(); setPageSize(pageSize); } loadOasisSettings(odfStore.settingsDoc()); return true; } bool KarbonKoDocument::completeLoading(KoStore* store) { bool ok = true; foreach(KoDataCenterBase *dataCenter, dataCenterMap()) { ok = ok && dataCenter->completeLoading(store); } return ok; } void KarbonKoDocument::loadOasisSettings(const KoXmlDocument & settingsDoc) { if (settingsDoc.isNull()) return ; // not an error if some file doesn't have settings.xml KoOasisSettings settings(settingsDoc); KoOasisSettings::Items viewSettings = settings.itemSet("view-settings"); if (!viewSettings.isNull()) { setUnit(KoUnit::fromSymbol(viewSettings.parseConfigItemString("unit"))); // FIXME: add other config here. } guidesData().loadOdfSettings(settingsDoc); gridData().loadOdfSettings(settingsDoc); } void KarbonKoDocument::saveOasisSettings(KoStore * store) { KoStoreDevice settingsDev(store); KoXmlWriter * settingsWriter = KoOdfWriteStore::createOasisXmlWriter(&settingsDev, "office:document-settings"); settingsWriter->startElement("office:settings"); settingsWriter->startElement("config:config-item-set"); settingsWriter->addAttribute("config:name", "view-settings"); saveUnitOdf(settingsWriter); settingsWriter->endElement(); // config:config-item-set settingsWriter->startElement("config:config-item-set"); settingsWriter->addAttribute("config:name", "ooo:view-settings"); settingsWriter->startElement("config:config-item-map-indexed"); settingsWriter->addAttribute("config:name", "Views"); settingsWriter->startElement("config:config-item-map-entry"); guidesData().saveOdfSettings(*settingsWriter); gridData().saveOdfSettings(*settingsWriter); settingsWriter->endElement(); // config:config-item-map-entry settingsWriter->endElement(); // config:config-item-map-indexed settingsWriter->endElement(); // config:config-item-set settingsWriter->endElement(); // office:settings settingsWriter->endElement(); // office:document-settings settingsWriter->endDocument(); delete settingsWriter; } bool KarbonKoDocument::saveOdf(SavingContext &documentContext) { if (! d->document.saveOdf(documentContext, pageLayout())) return false; KoStore * store = documentContext.odfStore.store(); if (! store->open("settings.xml")) return false; saveOasisSettings(store); if (! store->close()) return false; documentContext.odfStore.manifestWriter()->addManifestEntry("settings.xml", "text/xml"); setModified(false); return true; } void KarbonKoDocument::slotDocumentRestored() { setModified(false); } void KarbonKoDocument::paintContent(QPainter &painter, const QRect& rect) { KoShapePainter shapePainter; shapePainter.setShapes(d->document.shapes()); shapePainter.paint(painter, rect, QRectF(QPointF(), d->document.pageSize())); } KarbonDocument& KarbonKoDocument::document() { return d->document; } bool KarbonKoDocument::showStatusBar() const { return d->showStatusBar; } void KarbonKoDocument::setShowStatusBar(bool b) { d->showStatusBar = b; } uint KarbonKoDocument::maxRecentFiles() const { return d->maxRecentFiles; } void KarbonKoDocument::reorganizeGUI() { foreach(KoView* view, documentPart()->views()) { KarbonView * kv = qobject_cast(view); if (kv) { kv->reorganizeGUI(); emit applyCanvasConfiguration(kv->canvasWidget()); } } } void KarbonKoDocument::initConfig() { KSharedConfigPtr config = KarbonFactory::componentData().config(); // disable grid by default gridData().setShowGrid(false); if (config->hasGroup("Interface")) { KConfigGroup interfaceGroup = config->group("Interface"); setAutoSave(interfaceGroup.readEntry("AutoSave", defaultAutoSave() / 60) * 60); d->maxRecentFiles = interfaceGroup.readEntry("NbRecentFile", 10); setShowStatusBar(interfaceGroup.readEntry("ShowStatusBar" , true)); setBackupFile(interfaceGroup.readEntry("BackupFile", true)); } int undos = 30; QString defaultUnitSymbol = QLatin1String((KGlobal::locale()->measureSystem() == KLocale::Imperial)?"in":"cm"); if (config->hasGroup("Misc")) { KConfigGroup miscGroup = config->group("Misc"); undos = miscGroup.readEntry("UndoRedo", -1); defaultUnitSymbol = miscGroup.readEntry("Units", defaultUnitSymbol); } undoStack()->setUndoLimit(undos); setUnit(KoUnit::fromSymbol(defaultUnitSymbol)); if (config->hasGroup("Grid")) { KoGridData defGrid; KConfigGroup gridGroup = config->group("Grid"); qreal spacingX = gridGroup.readEntry("SpacingX", defGrid.gridX()); qreal spacingY = gridGroup.readEntry("SpacingY", defGrid.gridY()); gridData().setGrid(spacingX, spacingY); QColor color = gridGroup.readEntry("Color", defGrid.gridColor()); gridData().setGridColor(color); } } bool KarbonKoDocument::mergeNativeFormat(const QString &file) { d->merge = true; bool result = loadNativeFormat(file); if (!result) documentPart()->showLoadingErrorDialog(); d->merge = false; return result; } void KarbonKoDocument::addShape(KoShape* shape) { KoCanvasController* canvasController = KoToolManager::instance()->activeCanvasController(); KoShapeLayer *layer = dynamic_cast(shape); if (layer) { d->document.insertLayer(layer); if (canvasController) { KoSelection *selection = canvasController->canvas()->shapeManager()->selection(); selection->setActiveLayer(layer); } } else { // only add shape to active layer if it has no parent yet if (! shape->parent()) { kDebug(38000) << "shape has no parent, adding to the active layer!"; KoShapeLayer *activeLayer = 0; if (canvasController) activeLayer = canvasController->canvas()->shapeManager()->selection()->activeLayer(); else if (d->document.layers().count()) activeLayer = d->document.layers().first(); if (activeLayer) activeLayer->addShape(shape); } d->document.add(shape); foreach(KoView *view, documentPart()->views()) { KarbonCanvas *canvas = ((KarbonView*)view)->canvasWidget(); canvas->shapeManager()->addShape(shape); } } setModified(true); emit shapeCountChanged(); } void KarbonKoDocument::removeShape(KoShape* shape) { KoShapeLayer *layer = dynamic_cast(shape); if (layer) { d->document.removeLayer(layer); } else { d->document.remove(shape); foreach(KoView *view, documentPart()->views()) { KarbonCanvas *canvas = ((KarbonView*)view)->canvasWidget(); canvas->shapeManager()->remove(shape); } } setModified(true); emit shapeCountChanged(); } QMap KarbonKoDocument::dataCenterMap() const { return d->document.dataCenterMap(); } void KarbonKoDocument::setPageSize(const QSizeF &pageSize) { d->document.setPageSize(pageSize); foreach(KoView *view, documentPart()->views()) { KarbonCanvas *canvas = ((KarbonView*)view)->canvasWidget(); canvas->resourceManager()->setResource(KoCanvasResourceManager::PageSize, pageSize); } } #include "KarbonKoDocument.moc" diff --git a/kexi/kexiutils/tests/TestIdentifier.h b/kexi/kexiutils/tests/TestIdentifier.h index db90b7afa82..952da5c0596 100644 --- a/kexi/kexiutils/tests/TestIdentifier.h +++ b/kexi/kexiutils/tests/TestIdentifier.h @@ -1,35 +1,35 @@ /* This file is part of the KDE project Copyright (C) 2012 Jarosław Staniek This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KEXIUTILS_TESTIDENTIFIER_H #define KEXIUTILS_TESTIDENTIFIER_H -#include +#include class TestIdentifier : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void testString2FileName_data(); void testString2FileName(); void cleanupTestCase(); }; #endif diff --git a/kexi/main/startup/KexiWelcomeStatusBar.cpp b/kexi/main/startup/KexiWelcomeStatusBar.cpp index 28b58250b8b..5564afbe6a7 100644 --- a/kexi/main/startup/KexiWelcomeStatusBar.cpp +++ b/kexi/main/startup/KexiWelcomeStatusBar.cpp @@ -1,1124 +1,1124 @@ /* This file is part of the KDE project Copyright (C) 2011-2012 Jarosław Staniek This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KexiWelcomeStatusBar.h" #include "KexiWelcomeStatusBar_p.h" #include #include #include #include #include "KexiUserFeedbackAgent.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include +#include #include #include #include #include #include #include #include static const int GUI_UPDATE_INTERVAL = 60; // update interval for GUI, in minutes static const int UPDATE_FILES_LIST_SIZE_LIMIT = 1024 * 128; static const int UPDATE_FILES_COUNT_LIMIT = 128; // returns x.y.0 static QString stableVersionStringDot0() { return QString::number(Kexi::stableVersionMajor()) + '.' + QString::number(Kexi::stableVersionMinor()) + ".0"; } static QString basePath() { return QString("kexi/status/") + stableVersionStringDot0(); } static QString findFilename(const QString &guiFileName) { const QString result = KStandardDirs::locate("data", basePath() + '/' + guiFileName); kDebug() << result; return result; } // --- class KexiWelcomeStatusBarGuiUpdater::Private { public: Private() : configGroup(KConfigGroup(KGlobal::config()->group("User Feedback"))) { } KConfigGroup configGroup; QStringList fileNamesToUpdate; QString tempDir; }; KexiWelcomeStatusBarGuiUpdater::KexiWelcomeStatusBarGuiUpdater() : QObject() , d(new Private) { } KexiWelcomeStatusBarGuiUpdater::~KexiWelcomeStatusBarGuiUpdater() { delete d; } QString KexiWelcomeStatusBarGuiUpdater::uiPath(const QString &fname) const { KexiUserFeedbackAgent *f = KexiMainWindowIface::global()->userFeedbackAgent(); return f->serviceUrl() + QString("/ui/%1/").arg(stableVersionStringDot0()) + fname; } void KexiWelcomeStatusBarGuiUpdater::update() { QDateTime lastStatusBarUpdate = d->configGroup.readEntry("LastStatusBarUpdate", QDateTime()); if (lastStatusBarUpdate.isValid()) { int minutes = lastStatusBarUpdate.secsTo(QDateTime::currentDateTime()) / 60; if (minutes < GUI_UPDATE_INTERVAL) { kDebug() << "gui updated" << minutes << "min. ago, next auto-update in" << (GUI_UPDATE_INTERVAL - minutes) << "min."; return; } } d->configGroup.writeEntry("LastStatusBarUpdate", QDateTime::currentDateTime()); KexiUserFeedbackAgent *f = KexiMainWindowIface::global()->userFeedbackAgent(); f->waitForRedirect(this, SLOT(slotRedirectLoaded())); } void KexiWelcomeStatusBarGuiUpdater::slotRedirectLoaded() { QByteArray postData = stableVersionStringDot0().toLatin1(); KIO::Job* sendJob = KIO::storedHttpPost(postData, KUrl(uiPath(".list")), KIO::HideProgressInfo); connect(sendJob, SIGNAL(result(KJob*)), this, SLOT(sendRequestListFilesFinished(KJob*))); sendJob->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded"); } void KexiWelcomeStatusBarGuiUpdater::sendRequestListFilesFinished(KJob* job) { if (job->error()) { kWarning() << "Error while receiving .list file - no files will be updated"; //! @todo error... return; } KIO::StoredTransferJob* sendJob = qobject_cast(job); QString result = sendJob->data(); if (result.length() > UPDATE_FILES_LIST_SIZE_LIMIT) { // anit-DOS protection kWarning() << "Too large .list file (" << result.length() << "); the limit is" << UPDATE_FILES_LIST_SIZE_LIMIT << "- no files will be updated"; return; } kDebug() << result; QStringList data = result.split('\n', QString::SkipEmptyParts); result.clear(); d->fileNamesToUpdate.clear(); if (data.count() > UPDATE_FILES_COUNT_LIMIT) { // anti-DOS protection kWarning() << "Too many files to update (" << data.count() << "); the limit is" << UPDATE_FILES_COUNT_LIMIT << "- no files will be updated"; return; } // OK, try to update (stage 1: check, stage 2: checking) for (int stage = 1; stage <= 2; stage++) { int i = 0; for (QStringList::ConstIterator it(data.constBegin()); it!=data.constEnd(); ++it, i++) { const QByteArray hash((*it).left(32).toLatin1()); const QString remoteFname((*it).mid(32 + 2)); if (stage == 1) { if (hash.length() != 32) { kWarning() << "Invalid hash" << hash << "in line" << i+1 << "- no files will be updated"; return; } if ((*it).mid(32, 2) != " ") { kWarning() << "Two spaces expected but found" << (*it).mid(32, 2) << "in line" << i+1 << "- no files will be updated"; return; } if (remoteFname.contains(QRegExp("\\s"))) { kWarning() << "Filename expected without whitespace but found" << remoteFname << "in line" << i+1 << "- no files will be updated"; return; } } else if (stage == 2) { checkFile(hash, remoteFname, &d->fileNamesToUpdate); } } } // update files KUrl::List sourceFiles; foreach (const QString &fname, d->fileNamesToUpdate) { sourceFiles.append(KUrl(uiPath(fname))); } KTempDir tempDir(KStandardDirs::locateLocal("tmp", "kexi-status")); tempDir.setAutoRemove(false); d->tempDir = tempDir.name(); kDebug() << tempDir.name(); KIO::CopyJob *copyJob = KIO::copy(sourceFiles, KUrl("file://" + tempDir.name()), KIO::HideProgressInfo | KIO::Overwrite); connect(copyJob, SIGNAL(result(KJob*)), this, SLOT(filesCopyFinished(KJob*))); //kDebug() << "copying from" << KUrl(uiPath(fname)) << "to" // << (dir + fname); } void KexiWelcomeStatusBarGuiUpdater::checkFile(const QByteArray &hash, const QString &remoteFname, QStringList *fileNamesToUpdate) { QString localFname = findFilename(remoteFname); if (localFname.isEmpty()) { fileNamesToUpdate->append(remoteFname); kDebug() << "missing filename" << remoteFname << "- download it"; return; } QFile file(localFname); if (!file.open(QIODevice::ReadOnly)) { kWarning() << "could not open file" << localFname << "- update it"; fileNamesToUpdate->append(remoteFname); return; } KMD5 md5(""); if (!md5.update(file)) { kWarning() << "could not check MD5 for file" << localFname << "- update it"; fileNamesToUpdate->append(remoteFname); return; } if (!md5.verify(hash)) { kDebug() << "not matching file" << localFname << "- update it"; fileNamesToUpdate->append(remoteFname); } } void KexiWelcomeStatusBarGuiUpdater::filesCopyFinished(KJob* job) { if (job->error()) { //! @todo error... kDebug() << "ERROR:" << job->errorString(); return; } KIO::CopyJob* copyJob = qobject_cast(job); kDebug() << "DONE" << copyJob->destUrl(); QString dir(KStandardDirs::locateLocal("data", basePath() + '/', true /*create*/)); kDebug() << dir; foreach (const QString &fname, d->fileNamesToUpdate) { if (0 != KDE::rename(d->tempDir + fname, dir + fname)) { kWarning() << "cannot move" << (d->tempDir + fname) << "to" << (dir + fname); } } KTempDir::removeDir(d->tempDir); } // --- //! @internal class ScrollArea : public QScrollArea { public: ScrollArea(QWidget *parent = 0) : QScrollArea(parent) { setFrameShape(QFrame::NoFrame); setBackgroundRole(QPalette::Base); setWidgetResizable(true); } void setEnabled(bool set) { if (set != isEnabled()) { QScrollArea::setEnabled(set); updateColors(); } } protected: virtual void changeEvent(QEvent* event) { switch (event->type()) { case QEvent::EnabledChange: case QEvent::PaletteChange: updateColors(); break; default:; } QScrollArea::changeEvent(event); } void updateColors() { if (!widget()) return; KColorScheme scheme(palette().currentColorGroup()); QColor linkColor = scheme.foreground(KColorScheme::LinkText).color(); //kDebug() << "_____________" << isEnabled(); foreach(QLabel* lbl, widget()->findChildren()) { QString t = lbl->text(); QRegExp re(""); re.setMinimal(true); int pos = 0; int oldPos = 0; QString newText; //kDebug() << "t:" << t; while ((pos = re.indexIn(t, pos)) != -1) { //kDebug() << "pos:" << pos; //kDebug() << "newText += t.mid(oldPos, pos - oldPos)" // << t.mid(oldPos, pos - oldPos); newText += t.mid(oldPos, pos - oldPos); //kDebug() << "newText1:" << newText; //kDebug() << lbl->objectName() << "~~~~" << t.mid(pos, re.matchedLength()); QString a = t.mid(pos, re.matchedLength()); //kDebug() << "a:" << a; int colPos = a.indexOf("color:"); if (colPos == -1) { // add color a.insert(a.length() - 1, " style=\"color:" + linkColor.name() + ";\""); } else { // replace color colPos += qstrlen("color:"); for (;colPos < a.length() && a[colPos] == ' '; colPos++) ; if (colPos < a.length() && a[colPos] == '#') { colPos++; int i = colPos; for (;i < a.length(); i++) { if (a[i] == ';' || a[i] == ' ' || a[i] == '"' || a[i] == '\'') break; } //kDebug() << "******" << a.mid(colPos, i - colPos); a.replace(colPos, i - colPos, linkColor.name().mid(1)); } } //kDebug() << "a2:" << a; newText += a; //kDebug() << "newText2:" << newText; pos += re.matchedLength(); oldPos = pos; //kDebug() << "pos2:" << pos; } //kDebug() << "oldPos:" << oldPos; newText += t.mid(oldPos); //kDebug() << "newText3:" << newText; lbl->setText(newText); } #if 0 QString text; text = QString("%3") .arg(link).arg(linkColor.name()).arg(linkText); if (!format.isEmpty()) { text = QString(format).replace("%L", text); } q->setText(text); #endif } }; // --- class KexiWelcomeStatusBar::Private { public: Private(KexiWelcomeStatusBar* _q) : statusWidget(0), helpAction(0), shareAction(0), cancelAction(0), q(_q) { rccFname = findFilename("status.rcc"); if (!rccFname.isEmpty()) { QResource::registerResource(rccFname); } scores.insert(KexiUserFeedbackAgent::BasicArea, 4); scores.insert(KexiUserFeedbackAgent::SystemInfoArea, 4); scores.insert(KexiUserFeedbackAgent::ScreenInfoArea, 2); scores.insert(KexiUserFeedbackAgent::RegionalSettingsArea, 2); totalFeedbackScore = 0; foreach (int s, scores.values()) { totalFeedbackScore += s; } kDebug() << "totalFeedbackScore:" << totalFeedbackScore; } ~Private() { delete msgWidget; if (!rccFname.isEmpty()) { QResource::unregisterResource(rccFname); } } int currentFeedbackScore() const { int score = 0; KexiUserFeedbackAgent *f = KexiMainWindowIface::global()->userFeedbackAgent(); KexiUserFeedbackAgent::Areas areas = f->enabledAreas(); for (QMap::ConstIterator it(scores.constBegin()); it!=scores.constEnd(); ++it) { if (areas & it.key()) { score += it.value(); } } kDebug() << score; return score; } template T widgetOfClass(T parent, const char *widgetName) const { T w = qFindChild(parent, widgetName); if (!w) { kWarning() << "NO SUCH widget" << widgetName << "in" << parent; } return w; } QWidget* widget(QWidget *parent, const char *widgetName) const { return widgetOfClass(parent, widgetName); } QObject* object(QObject *parent, const char *objectName) const { QObject *o = qFindChild(parent, objectName); if (!o) { kWarning() << "NO SUCH object" << objectName << "in" << parent; } return o; } void setProperty(QWidget *parent, const char *widgetName, const char *propertyName, const QVariant &value) { QWidget *w = widget(parent, widgetName); if (w) { w->setProperty(propertyName, value); } } QVariant property(QWidget *parent, const char *widgetName, const char *propertyName) const { QWidget *w = widget(parent, widgetName); return w ? w->property(propertyName) : QVariant(); } void connect(QWidget *parent, const char *widgetName, const char *signalName, QObject *receiver, const char *slotName) { QWidget *w = widget(parent, widgetName); if (w) { QObject::connect(w, signalName, receiver, slotName); } } void animatedHide(QWidget *parent, const char *widgetName) { QWidget *w = widget(parent, widgetName); if (!w) return; KFadeWidgetEffect *animation = new KFadeWidgetEffect(w); QObject::connect(animation, SIGNAL(destroyed()), w, SLOT(hide())); animation->start(); } QWidget* loadGui(const QString &guiFileName, QWidget *parentWidget = 0) { QString fname = findFilename(guiFileName); if (fname.isEmpty()) { kWarning() << "filename" << fname << "not found"; return 0; } QFile file(fname); if (!file.open(QIODevice::ReadOnly)) { kWarning() << "could not open file" << fname; return 0; } QUiLoader loader; QWidget* widget = loader.load(&file, parentWidget); if (!widget) { kWarning() << "could load ui from file" << fname; } file.close(); return widget; } void updateStatusWidget() { QWidget *widget = loadGui("status.ui", statusScrollArea); if (!widget) { return; } int smallFontSize = qFloor((KGlobalSettings::smallestReadableFont().pointSizeF() + q->font().pointSizeF()) / 2.0); smallFont = q->font(); smallFont.setPointSizeF(smallFontSize); widget->setFont(smallFont); delete statusWidget; statusWidget = widget; statusScrollArea->setWidget(statusWidget); setProperty(statusWidget, "contribution_progress", "minimumHeight", q->fontMetrics().height()); setProperty(statusWidget, "contribution_progress", "maximumHeight", q->fontMetrics().height()); label_involved_text_mask = property(statusWidget, "label_involved", "text").toString(); setProperty(statusWidget, "link_share_usage_info", "text", property(statusWidget, "link_share_usage_info", "text").toString().arg(totalFeedbackScore)); link_share_more_usage_info_mask = property(statusWidget, "link_share_more_usage_info", "text").toString(); updateUserProgress(); updateContributionLinksVisibility(); // do not alter background palette QPalette pal(widget->palette()); pal.setColor(QPalette::Disabled, QPalette::Base, pal.color(QPalette::Normal, QPalette::Base)); widget->setPalette(pal); connect(statusWidget, "link_contribute_show_help", SIGNAL(linkActivated(QString)), q, SLOT(showContributionHelp())); connect(statusWidget, "link_share_usage_info", SIGNAL(linkActivated(QString)), q, SLOT(showShareUsageInfo())); connect(statusWidget, "link_share_more_usage_info", SIGNAL(linkActivated(QString)), q, SLOT(showShareUsageInfo())); connect(statusWidget, "link_show_contribution_details", SIGNAL(linkActivated(QString)), q, SLOT(showContributionDetails())); #if 0 baseFname = QString("status/%1/status.html").arg(Kexi::stableVersionString()); fname = KStandardDirs::locate("data", "kexi/" + baseFname); QString html; if (!fname.isEmpty()) { QFile file(fname); if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { html = file.readAll(); file.close(); } } if (html.isEmpty()) { //! @todo hardcode simplest version } QString newHtml = transform(html); kDebug() << html; kDebug() << "-----------"; kDebug() << newHtml; html = newHtml; title = translate("You in Kexi Project"); // Your Status in Kexi Project //TODO: replace every ${..} QString t = "What's New?"; // html += QString( "
" "

%1

" "

Fruits of CSS2: Office Forms

" "

See all News »

" ).arg(t); t = "Recent Releases"; html += QString( "
" "

%1

" "

" "" "" "

Stable release:

2.3.3

Preview release:

2.4 Beta 6

" "

See more Releases »

" ).arg(t); QString htmlHead(QLatin1String( "" "" "")); doc->setHtml(htmlHead + html + ""); statusBrowser->setDocument(doc); kDebug() << statusBrowser->toHtml(); #endif } void setUserProgress(int progress) { setProperty(statusWidget, "contribution_progress", "value", progress); setProperty(statusWidget, "label_involved", "text", label_involved_text_mask.arg(progress)); } void updateUserProgress() { int progress = 0; progress += currentFeedbackScore(); setUserProgress(progress); } void updateContributionLinksVisibility() { KexiUserFeedbackAgent *f = KexiMainWindowIface::global()->userFeedbackAgent(); int availableLinks = 0; bool noneEnabled = f->enabledAreas() == KexiUserFeedbackAgent::NoAreas; bool allEnabled = f->enabledAreas() == KexiUserFeedbackAgent::AllAreas; setProperty(statusWidget, "share_usage_info", "visible", noneEnabled); if (noneEnabled) { availableLinks++; } setProperty(statusWidget, "share_more_usage_info", "visible", !noneEnabled && !allEnabled); if (!noneEnabled && !allEnabled) { availableLinks++; } setProperty(statusWidget, "link_share_more_usage_info", "text", link_share_more_usage_info_mask.arg(totalFeedbackScore - currentFeedbackScore())); setProperty(statusWidget, "lbl_contribute", "visible", availableLinks > 0); } enum CalloutAlignment { AlignToBar, AlignToWidget }; //! Aligns callout pointer position of msgWidget to widget named @a alignToWidgetName void setMessageWidgetCalloutPointerPosition( const QString& alignToWidgetName, CalloutAlignment calloutAlignment = AlignToBar) { kDebug() << q->pos() << q->mapToGlobal(QPoint(0, 100)); QPoint p(q->mapToGlobal(QPoint(0, 100))); QWidget *alignToWidget = this->widget(statusWidget, alignToWidgetName.toLatin1()); if (alignToWidget) { p.setY( alignToWidget->mapToGlobal( QPoint(-5, alignToWidget->height() / 2)).y()); if (calloutAlignment == AlignToWidget) { p.setX(alignToWidget->mapToGlobal(QPoint(-5, 0)).x()); kDebug() << p << "++++++++++"; } } else { kWarning() << alignToWidgetName << "not found!"; } msgWidget->setCalloutPointerPosition(p, alignToWidget); } //! Shows message widget taking maximum space within the welcome page //! Returns created layout for further use into @a layout. //! Created widge is assigned to msgWidget. //! Calls slot @a slotToCallAfterShow after animated showing, if provided. //! Call msgWidget->animatedShow() afterwards. void showMaximizedMessageWidget(const QString &alignToWidgetName, QPointer *layout, const char* slotToCallAfterShow, CalloutAlignment calloutAlignment = AlignToBar) { QWidget *alignToWidget = this->widget(statusWidget, alignToWidgetName.toLatin1()); int msgWidth; if (alignToWidget && calloutAlignment == AlignToWidget) { msgWidth = q->parentWidget()->width() - alignToWidget->width() - 10; } else { msgWidth = q->parentWidget()->width() - q->width(); } QWidget *widget = new QWidget; *layout = new QGridLayout(widget); if (msgWidth > 100) { // nice text margin (*layout)->setColumnMinimumWidth(0, 50); } kDebug() << (q->parentWidget()->width() - q->width()) << "***"; KexiContextMessage msg(widget); if (msgWidget) { delete static_cast(msgWidget); } msgWidget = new KexiContextMessageWidget(q->parentWidget()->parentWidget(), 0, 0, msg); msgWidget->setCalloutPointerDirection(KMessageWidget::Right); msgWidget->setMessageType(KMessageWidget::Information); msgWidget->setCloseButtonVisible(true); int offset_y = 0; if (alignToWidget) { offset_y = alignToWidget->mapToGlobal(QPoint(0, 0)).y() - q->parentWidget()->mapToGlobal(QPoint(0, 0)).y(); } else { kWarning() << alignToWidgetName << "not found!"; } msgWidget->resize(msgWidth, q->parentWidget()->height() - offset_y); setMessageWidgetCalloutPointerPosition(alignToWidgetName, calloutAlignment); msgWidget->setResizeTrackingPolicy(Qt::Horizontal | Qt::Vertical); statusScrollArea->setEnabled(false); // async show to for speed up if (slotToCallAfterShow) { QObject::connect(msgWidget, SIGNAL(animatedShowFinished()), q, slotToCallAfterShow); } QObject::connect(msgWidget, SIGNAL(animatedHideFinished()), q, SLOT(slotMessageWidgetClosed())); } ScrollArea *statusScrollArea; QWidget *statusWidget; QVBoxLayout *lyr; QPointer msgWidget; QFont smallFont; KAction *helpAction; KAction *shareAction; KAction *cancelAction; QString label_involved_text_mask; QString link_share_more_usage_info_mask; QPointer contributionHelpLayout; QPointer contributionDetailsLayout; QPointer contributionDetailsWidget; QMap scores; QString countryMask; QString languageMask; bool detailsDataVisible; int totalFeedbackScore; KexiWelcomeStatusBarGuiUpdater guiUpdater; private: QString rccFname; KexiWelcomeStatusBar *q; QMap dict; }; KexiWelcomeStatusBar::KexiWelcomeStatusBar(QWidget* parent) : QWidget(parent), d(new Private(this)) { d->lyr = new QVBoxLayout(this); init(); } KexiWelcomeStatusBar::~KexiWelcomeStatusBar() { delete d; } void KexiWelcomeStatusBar::init() { #if 0

${YOU_IN_KEXI} (?)

${PERCENT_INVOLVED}

${CONTRIBUTE} (${WHY}?)

${SHARE_USAGE_INFO} (+5%)

QString title("You in Kexi Project"); // Your Status in Kexi Project QString html = QString( "

%1 (?)

" "

%2% involved

" "

Contribute (Why?)

" "

Share Usage Info (+5%)

" ).arg(title).arg(d->userProgressBar.value()); #endif d->statusScrollArea = new ScrollArea(this); d->lyr->addWidget(d->statusScrollArea); d->updateStatusWidget(); QTimer::singleShot(10, &d->guiUpdater, SLOT(update())); } void KexiWelcomeStatusBar::showContributionHelp() { d->showMaximizedMessageWidget("link_contribute_show_help", &d->contributionHelpLayout, SLOT(slotShowContributionHelpContents())); d->msgWidget->animatedShow(); /* int msgWidth = parentWidget()->width() - width(); QWidget *widget = new QWidget; d->contributionHelpLayout = new QGridLayout(widget); if (msgWidth > 100) { // nice text margin d->contributionHelpLayout->setColumnMinimumWidth(0, 50); } kDebug() << (parentWidget()->width() - width()) << "***"; KexiContextMessage msg(widget); if (d->msgWidget) { delete static_cast(d->msgWidget); } d->msgWidget = new KexiContextMessageWidget(parentWidget(), 0, 0, msg); d->msgWidget->setCalloutPointerDirection(KMessageWidget::Right); kDebug() << pos() << mapToGlobal(QPoint(0, 100)); QPoint p(mapToGlobal(QPoint(0, 100))); QWidget *link_contribute_show_help = d->widget("link_contribute_show_help"); if (link_contribute_show_help) { p.setY( link_contribute_show_help->mapToGlobal( QPoint(-5, link_contribute_show_help->height() / 2)).y()); } d->msgWidget->setMessageType(KMessageWidget::Information); d->msgWidget->setCalloutPointerPosition(p); d->msgWidget->setCloseButtonVisible(true); d->msgWidget->resize(msgWidth, parentWidget()->height() - 12); d->statusScrollArea->setEnabled(false); // async show to for speed up connect(d->msgWidget, SIGNAL(animatedShowFinished()), this, SLOT(slotShowContributionHelpContents())); connect(d->msgWidget, SIGNAL(animatedHideFinished()), this, SLOT(slotContributionHelpClosed())); d->msgWidget->animatedShow();*/ } void KexiWelcomeStatusBar::slotShowContributionHelpContents() { QWidget *helpWidget = d->loadGui("contribution_help.ui"); d->contributionHelpLayout->addWidget(helpWidget, 1, 1); d->msgWidget->setPaletteInherited(); } void KexiWelcomeStatusBar::slotMessageWidgetClosed() { d->statusScrollArea->setEnabled(true); d->updateUserProgress(); d->updateContributionLinksVisibility(); } void KexiWelcomeStatusBar::showShareUsageInfo() { if (!sender()) { return; } QWidget *widget = d->loadGui("status_strings.ui"); if (!widget) { return; } QLabel *lbl = qFindChild(widget, "question"); if (!lbl) { return; } KexiContextMessage msg(lbl->text()); delete widget; if (!d->helpAction) { d->helpAction = new KAction(KStandardGuiItem::help().icon(), KStandardGuiItem::help().text(), this); connect(d->helpAction, SIGNAL(triggered()), this, SLOT(showContributionHelp())); } if (!d->shareAction) { d->shareAction = new KAction(KStandardGuiItem::yes().icon(), i18n("Share"), this); connect(d->shareAction, SIGNAL(triggered()), this, SLOT(slotShareFeedback())); } if (!d->cancelAction) { d->cancelAction = new KAction(KStandardGuiItem::cancel().icon(), KStandardGuiItem::cancel().text(), this); QObject::connect(d->cancelAction, SIGNAL(triggered()), this, SLOT(slotCancelled())); } msg.addAction(d->helpAction, KexiContextMessage::AlignLeft); msg.addAction(d->shareAction); msg.addAction(d->cancelAction); if (d->msgWidget) { delete static_cast(d->msgWidget); } d->msgWidget = new KexiContextMessageWidget(parentWidget(), 0, 0, msg); d->msgWidget->setMessageType(KMessageWidget::Information); d->msgWidget->setCalloutPointerDirection(KMessageWidget::Right); d->setMessageWidgetCalloutPointerPosition(sender()->objectName()); d->statusScrollArea->setEnabled(false); d->msgWidget->setMaximumWidth(parentWidget()->width() - width()); d->msgWidget->setResizeTrackingPolicy(Qt::Horizontal); /*foreach (QLabel *lbl, d->statusScrollArea->findChildren()) { if (lbl->isEnabled()) { //d->enabledLinks.append(w); lbl->setEnabled(false); } }*/ d->msgWidget->animatedShow(); } void KexiWelcomeStatusBar::slotShareFeedback() { d->statusScrollArea->setEnabled(true); d->msgWidget->animatedHide(); KexiMainWindowIface::global()->userFeedbackAgent() ->setEnabledAreas(KexiUserFeedbackAgent::AllAreas); d->animatedHide(d->statusWidget, "share_usage_info"); d->animatedHide(d->statusWidget, "share_more_usage_info"); d->animatedHide(d->statusWidget, "lbl_contribute"); d->updateUserProgress(); } void KexiWelcomeStatusBar::slotCancelled() { d->statusScrollArea->setEnabled(true); } // Contribution Details BEGIN void KexiWelcomeStatusBar::showContributionDetails() { d->showMaximizedMessageWidget("link_show_contribution_details", &d->contributionDetailsLayout, 0, KexiWelcomeStatusBar::Private::AlignToWidget); d->contributionDetailsLayout->setColumnMinimumWidth(0, 6); // smaller d->contributionDetailsWidget = d->loadGui("contribution_details.ui"); KexiUserFeedbackAgent *f = KexiMainWindowIface::global()->userFeedbackAgent(); d->setProperty(d->contributionDetailsWidget, "group_share", "checked", f->enabledAreas() != KexiUserFeedbackAgent::NoAreas); d->setProperty(d->contributionDetailsWidget, "group_basic", "title", d->property(d->contributionDetailsWidget, "group_basic", "title") .toString().arg(d->scores.value(KexiUserFeedbackAgent::BasicArea))); updateContributionGroupCheckboxes(); d->setProperty(d->contributionDetailsWidget, "group_system", "title", d->property(d->contributionDetailsWidget, "group_system", "title") .toString().arg(d->scores.value(KexiUserFeedbackAgent::SystemInfoArea))); d->connect(d->contributionDetailsWidget, "group_system", SIGNAL(toggled(bool)), this, SLOT(slotShareContributionDetailsGroupToggled(bool))); d->setProperty(d->contributionDetailsWidget, "group_screen", "title", d->property(d->contributionDetailsWidget, "group_screen", "title") .toString().arg(d->scores.value(KexiUserFeedbackAgent::ScreenInfoArea))); d->connect(d->contributionDetailsWidget, "group_screen", SIGNAL(toggled(bool)), this, SLOT(slotShareContributionDetailsGroupToggled(bool))); d->setProperty(d->contributionDetailsWidget, "group_regional_settings", "title", d->property(d->contributionDetailsWidget, "group_regional_settings", "title") .toString().arg(d->scores.value(KexiUserFeedbackAgent::RegionalSettingsArea))); d->connect(d->contributionDetailsWidget, "group_regional_settings", SIGNAL(toggled(bool)), this, SLOT(slotShareContributionDetailsGroupToggled(bool))); d->detailsDataVisible = false; slotShareContributionDetailsToggled( d->property(d->contributionDetailsWidget, "group_share", "checked").toBool()); d->detailsDataVisible = true; // to switch off slotToggleContributionDetailsDataVisibility(); d->connect(d->contributionDetailsWidget, "group_share", SIGNAL(toggled(bool)), this, SLOT(slotShareContributionDetailsToggled(bool))); d->connect(d->contributionDetailsWidget, "link_show_shared_info", SIGNAL(linkActivated(QString)), this, SLOT(slotToggleContributionDetailsDataVisibility())); d->setProperty(d->contributionDetailsWidget, "label_where_is_info_sent", "visible", false); ScrollArea *contributionDetailsArea = new ScrollArea(d->msgWidget); d->contributionDetailsLayout->addWidget(contributionDetailsArea, 1, 1); contributionDetailsArea->setWidget(d->contributionDetailsWidget); d->msgWidget->animatedShow(); d->msgWidget->setPaletteInherited(); } void KexiWelcomeStatusBar::updateContributionGroupCheckboxes() { KexiUserFeedbackAgent *f = KexiMainWindowIface::global()->userFeedbackAgent(); d->setProperty(d->contributionDetailsWidget, "group_system", "checked", bool(f->enabledAreas() & KexiUserFeedbackAgent::SystemInfoArea)); d->setProperty(d->contributionDetailsWidget, "group_screen", "checked", bool(f->enabledAreas() & KexiUserFeedbackAgent::ScreenInfoArea)); d->setProperty(d->contributionDetailsWidget, "group_regional_settings", "checked", bool(f->enabledAreas() & KexiUserFeedbackAgent::RegionalSettingsArea)); } void KexiWelcomeStatusBar::slotShareContributionDetailsToggled(bool on) { //kDebug() << sender(); QWidget* group_share = d->widget(d->contributionDetailsWidget, "group_share"); KexiUserFeedbackAgent *f = KexiMainWindowIface::global()->userFeedbackAgent(); if (sender() == group_share) { f->setEnabledAreas(on ? KexiUserFeedbackAgent::AllAreas : KexiUserFeedbackAgent::NoAreas); updateContributionGroupCheckboxes(); } if (!group_share) { return; } for (int i=0; i < group_share->layout()->count(); i++) { QWidget *w = group_share->layout()->itemAt(i)->widget(); if (w) { /*if (w->objectName() == "group_basic" && on) { // do nothing } else*/ { w->setVisible(on); } } } if (d->detailsDataVisible) { slotToggleContributionDetailsDataVisibility(); } // fill shared values foreach(QLabel* lbl, d->contributionDetailsWidget->findChildren()) { if (lbl->objectName().startsWith(QLatin1String("value_"))) { QString name = lbl->objectName().mid(6); // cut "value_" QVariant value; if (name == QLatin1String("screen_size")) { value = QString("%1 x %2").arg(f->value("screen_width").toString()) .arg(f->value("screen_height").toString()); } else if (name == QLatin1String("country")) { if (d->countryMask.isEmpty()) { d->countryMask = lbl->text(); } value = d->countryMask .arg(KGlobal::locale()->countryCodeToName(f->value(name).toString())) .arg(f->value(name).toString()); } else if (name == QLatin1String("language")) { if (d->languageMask.isEmpty()) { d->languageMask = lbl->text(); } value = d->languageMask .arg(KGlobal::locale()->languageCodeToName(f->value(name).toString())) .arg(f->value(name).toString()); } else { value = f->value(name); } if (value.type() == QVariant::Bool) { value = value.toBool() ? KStandardGuiItem::yes().plainText() : KStandardGuiItem::no().plainText(); } if (!value.isNull()) { lbl->setText(value.toString()); } } else if (lbl->objectName().startsWith(QLatin1String("desc_"))) { // QFont f(lbl->font()); // f.setPointSizeF(KGlobalSettings::smallestReadableFont().pointSizeF()); lbl->setFont(d->smallFont); /* QPalette pal(lbl->palette()); QColor c(pal.color(QPalette::WindowText)); c.setAlpha(100); pal.setColor(QPalette::WindowText, Qt::red); pal.setColor(QPalette::Text, Qt::green); lbl->setPalette(pal);*/ } } } static void setArea(KexiUserFeedbackAgent::Areas *areas, KexiUserFeedbackAgent::Area area, bool on) { *areas |= area; if (!on) { *areas ^= area; } } void KexiWelcomeStatusBar::slotShareContributionDetailsGroupToggled(bool on) { if (!sender()) { return; } const QString name = sender()->objectName(); KexiUserFeedbackAgent *f = KexiMainWindowIface::global()->userFeedbackAgent(); KexiUserFeedbackAgent::Areas areas = f->enabledAreas(); //kDebug() << areas; if (name == "group_system") { setArea(&areas, KexiUserFeedbackAgent::SystemInfoArea, on); } else if (name == "group_screen") { setArea(&areas, KexiUserFeedbackAgent::ScreenInfoArea, on); } else if (name == "group_regional_settings") { setArea(&areas, KexiUserFeedbackAgent::RegionalSettingsArea, on); } if (areas) { areas |= KexiUserFeedbackAgent::AnonymousIdentificationArea; } f->setEnabledAreas(areas); kDebug() << f->enabledAreas(); } void KexiWelcomeStatusBar::slotToggleContributionDetailsDataVisibility() { /* QWidget* group_share = d->widget(d->contributionDetailsWidget, "group_share"); if (!group_share) { return; } bool enabled = group_share->property("checked");*/ QWidget* value_app_ver = d->widget(d->contributionDetailsWidget, "value_app_ver"); if (!value_app_ver) { return; } d->detailsDataVisible = !d->detailsDataVisible; if (d->detailsDataVisible) { d->setProperty(d->contributionDetailsWidget, "link_show_shared_info", "visible", false); d->setProperty(d->contributionDetailsWidget, "label_where_is_info_sent", "visible", true); } bool show = d->contributionDetailsWidget->isVisible(); QList list; d->contributionDetailsWidget->hide(); QWidget* group_basic = d->widget(d->contributionDetailsWidget, "group_basic"); if (group_basic) { list += group_basic->findChildren(); } // if (group_basic) { // group_basic->setVisible(d->detailsDataVisible); // } QWidget* group_system = d->widget(d->contributionDetailsWidget, "group_system"); if (group_system) { list += group_system->findChildren(); } QWidget* group_screen = d->widget(d->contributionDetailsWidget, "group_screen"); if (group_screen) { list += group_screen->findChildren(); } QWidget* group_regional_settings = d->widget(d->contributionDetailsWidget, "group_regional_settings"); if (group_regional_settings) { list += group_regional_settings->findChildren(); } foreach (QWidget* w, list) { if (qobject_cast(w) && !w->objectName().startsWith(QLatin1String("desc_"))) { //kDebug() << "+++" << w; w->setVisible(d->detailsDataVisible); } } if (show) { d->contributionDetailsWidget->show(); } } // Contribution Details END #include "KexiWelcomeStatusBar.moc" #include "KexiWelcomeStatusBar_p.moc" diff --git a/krita/benchmarks/kis_composition_benchmark.h b/krita/benchmarks/kis_composition_benchmark.h index 9dabf65b061..6ac536fa658 100644 --- a/krita/benchmarks/kis_composition_benchmark.h +++ b/krita/benchmarks/kis_composition_benchmark.h @@ -1,53 +1,53 @@ /* * Copyright (c) 2012 Dmitry Kazakov * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_COMPOSITION_BENCHMARK_H #define __KIS_COMPOSITION_BENCHMARK_H -#include +#include class KisCompositionBenchmark : public QObject { Q_OBJECT private slots: void checkRoundingAlphaDarken(); void checkRoundingOver(); void compareAlphaDarkenOps(); void compareAlphaDarkenOpsNoMask(); void compareOverOps(); void compareOverOpsNoMask(); void testRgb8CompositeAlphaDarkenLegacy(); void testRgb8CompositeAlphaDarkenOptimized(); void testRgb8CompositeOverLegacy(); void testRgb8CompositeOverOptimized(); void testRgb8CompositeAlphaDarkenReal_Aligned(); void testRgb8CompositeOverReal_Aligned(); void benchmarkMemcpy(); void benchmarkUintFloat(); void benchmarkUintIntFloat(); void benchmarkFloatUint(); void benchmarkFloatIntUint(); }; #endif /* __KIS_COMPOSITION_BENCHMARK_H */ diff --git a/krita/benchmarks/kis_low_memory_benchmark.h b/krita/benchmarks/kis_low_memory_benchmark.h index c3e8316be08..9d58d22ed8e 100644 --- a/krita/benchmarks/kis_low_memory_benchmark.h +++ b/krita/benchmarks/kis_low_memory_benchmark.h @@ -1,43 +1,43 @@ /* * Copyright (c) 2012 Dmitry Kazakov * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_LOW_MEMORY_BENCHMARK_H #define __KIS_LOW_MEMORY_BENCHMARK_H -#include +#include class KisLowMemoryBenchmark : public QObject { Q_OBJECT private slots: void unlimitedMemoryNoHistoryNoPool(); void unlimitedMemoryHistoryNoPool(); void unlimitedMemoryHistoryPool50(); private: void benchmarkWideArea(const QString presetFileName, const QRectF &rect, qreal vstep, int numCycles, bool createTransaction, int hardLimitMiB, int softLimitMiB, int poolLimitMiB, int index); }; #endif /* __KIS_LOW_MEMORY_BENCHMARK_H */ diff --git a/krita/plugins/paintops/libbrush/abr_struct_parser.cpp b/krita/plugins/paintops/libbrush/abr_struct_parser.cpp index 8f37cd533fc..4fc0d6b900c 100644 --- a/krita/plugins/paintops/libbrush/abr_struct_parser.cpp +++ b/krita/plugins/paintops/libbrush/abr_struct_parser.cpp @@ -1,290 +1,290 @@ /* * Copyright (c) 2010 Valek Filippov * Copyright (c) 2010 Lukáš Tvrdý * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include -#include +#include #include "abr_struct_parser.h" #include "kis_abr_translator.h" AbrStructParser::AbrStructParser() { m_types.insert(PATT, P_PATT); m_types.insert(DESC, P_DESC); m_types.insert(VLLS, P_VLLS); m_types.insert(TEXT, P_TEXT); m_types.insert(OBJC, P_OBJC); m_types.insert(UNTF, P_UNTF); m_types.insert(BOOL, P_BOOL); m_types.insert(LONG, P_LONG); m_types.insert(DOUB, P_DOUB); m_types.insert(ENUM, P_ENUM); m_types.insert(TDTA, P_TDTA); } AbrStructParser::~AbrStructParser() { } QString AbrStructParser::p_patt(QDataStream &buf){ // didn't rev.engineered yet Q_UNUSED(buf); return QString(""); } QString AbrStructParser::p_tdta(QDataStream &buf){ quint32 size; buf >> size; ushort * text = new ushort[size]; for (quint32 i = 0; i < size;i++){ buf >> text[i]; } return "(tdta:" + QString::number(size) + ')' + QString::fromUtf16(text,size); } QString AbrStructParser::p_desc(QDataStream &buf){ // convert 4 bytes as big-endian unsigned long quint32 size; // 22 + 4 buf >> size; buf.skipRawData(22); return QString::number( size ); } QString AbrStructParser::p_long(QDataStream &buf){ quint32 size; buf >> size; return QString::number(size); } QString AbrStructParser::p_vlls(QDataStream &buf){ quint32 size; buf >> size; return QString::number(size); } QString AbrStructParser::p_text(QDataStream &buf){ quint32 size; buf >> size; ushort * text = new ushort[size+1]; for (quint32 i = 0; i < size;i++){ buf >> text[i]; } text[size] = '\0'; return QString::fromUtf16(text); } QString AbrStructParser::p_objc(QDataStream &buf){ // here we lost some data definitly // objnamelen is always 1 and objname is empty string quint32 objnamelen; buf >> objnamelen; char * objname = new char[objnamelen*2+1]; buf.readRawData(objname,objnamelen*2); objname[ objnamelen * 2 ] = '\0'; Q_ASSERT(objnamelen == 1); quint32 objtypelen; buf >> objtypelen; if (objtypelen == 0){ objtypelen = 4; } char * typeName = new char[objtypelen+1]; buf.readRawData(typeName,objtypelen); typeName [objtypelen] = '\0'; quint32 value; buf >> value; //return QString::fromLatin1( objname ) + ' ' + QString::fromLatin1(typeName) + ' ' + QString::number(value); return QString::fromLatin1(typeName) + ' ' + QString::number(value); } QString AbrStructParser::p_untf(QDataStream &buf){ char * type = new char[5]; buf.readRawData(type, 4); type[4] = '\0'; double value; buf >> value; return QString::fromLatin1(type) + ' ' + QString::number(value); } QString AbrStructParser::p_bool(QDataStream &buf){ //# ord converts 1 byte number char byte; buf.device()->getChar(&byte); if (byte) return QString("1"); else return QString("0"); } QString AbrStructParser::p_doub(QDataStream &buf){ // unpack 8 bytes ieee 754 value to floating point number double value; buf >> value; return QString::number(value); } QString AbrStructParser::p_enum(QDataStream &buf){ quint32 size1, size2; buf >> size1; if (size1 == 0){ size1 = 4; } char * name1 = new char[size1+1]; buf.readRawData(name1,size1); name1[size1] = '\0'; buf >> size2 ; if (size2 == 0){ size2 = 4; } char * name2 = new char[size2+1]; buf.readRawData(name2,size2); name2[size2] = '\0'; return QString::fromLatin1(name1) + ' ' + QString::fromLatin1(name2); } quint32 AbrStructParser::parseEntry(QDataStream &buf){ quint32 nlen; buf >> nlen; if (nlen == 0){ nlen = 4; } QString value = ""; if (nlen == MAGIC_OBJC_LENGTH){ value = p_objc(buf); qDebug() << ABR_PRESET_START << ABR_OBJECT << value; // start to create the preset here m_translator.addEntry(ABR_PRESET_START, ABR_OBJECT, value); }else{ // read char with nlen bytes and convert to String char * name = new char[ nlen+1 ]; int status = buf.readRawData(name, nlen); if (status == -1){ qDebug() << "Error, name can't be readed"; } name[nlen] = '\0'; char * type = new char[5]; status = buf.readRawData(type, 4); type[4] = '\0'; QString key = QString::fromLatin1(type); if (m_types.contains(key)) { enumFuncNames enumName = m_types[key]; switch (enumName){ case P_PATT: value = p_patt(buf); break; case P_DESC: value = p_desc(buf); break; case P_VLLS: value = p_vlls(buf); break; case P_TEXT: value = p_text(buf); break; case P_OBJC: value = p_objc(buf); break; case P_UNTF: value = p_untf(buf); break; case P_BOOL: value = p_bool(buf); break; case P_LONG: value = p_long(buf); break; case P_DOUB: value = p_doub(buf); break; case P_ENUM: value = p_enum(buf); break; case P_TDTA: value = p_tdta(buf); break; default: qDebug() << "Freak error occurred!"; break; } QString attributeName = QString::fromLatin1(name); //qDebug() << attributeName << key << value; m_translator.addEntry(attributeName, key, value); // airbrush is the last parsed attribute of the preset if (attributeName == ABR_AIRBRUSH) { m_translator.finishPreset(); qDebug() << m_translator.toString(); } }else { qDebug() << "Unknown key:\t" << name << type; //qDebug() << p_unkn(buf); return -1; } } return 0; } void AbrStructParser::parse(QString fileName){ QFile file(fileName); if (!file.open(QIODevice::ReadOnly)) { qDebug() << "Can't open file " << fileName; return; } QDataStream buf(&file); // offset in bytes short int vermaj, vermin; buf >> vermaj; buf >> vermin; qDebug() << "Version: " << vermaj << "." << vermin; int index = file.readAll().indexOf("8BIMdesc"); buf.device()->seek(index); int status = 0; while (!buf.atEnd()){ status = parseEntry(buf); if (status == -1){ // something to break the parsing with fail? qDebug() << "Finishing with fail..."; break; } } qDebug() << m_doc.toString(); } int main(int argc, const char * argv[] ){ QString fileName; if (argc != 2) { fileName = "test.abr"; }else{ fileName = QString::fromLatin1(argv[1]); } AbrStructParser parser; parser.parse(fileName); return 0; } diff --git a/krita/plugins/paintops/libbrush/tests/kis_imagepipe_brush_test.h b/krita/plugins/paintops/libbrush/tests/kis_imagepipe_brush_test.h index 9b3cdbef437..c8b3ca6f1eb 100644 --- a/krita/plugins/paintops/libbrush/tests/kis_imagepipe_brush_test.h +++ b/krita/plugins/paintops/libbrush/tests/kis_imagepipe_brush_test.h @@ -1,42 +1,42 @@ /* * Copyright (c) 2012 Dmitry Kazakov * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_IMAGEPIPE_BRUSH_TEST_H #define __KIS_IMAGEPIPE_BRUSH_TEST_H -#include +#include class KisImagePipeBrush; class KisImagePipeBrushTest : public QObject { Q_OBJECT private slots: void testLoading(); void testChangingBrushes(); void testSimpleDabApplication(); void testColoredDab(); void testColoredDabWash(); void testTextBrushNoPipes(); void testTextBrushPiped(); private: void checkConsistency(KisImagePipeBrush *brush); }; #endif /* __KIS_IMAGEPIPE_BRUSH_TEST_H */ diff --git a/krita/sdk/createtest.py b/krita/sdk/createtest.py index e02947e6fe2..4b7843fc48f 100755 --- a/krita/sdk/createtest.py +++ b/krita/sdk/createtest.py @@ -1,116 +1,116 @@ #!/usr/bin/env python import sys import getopt import os.path from string import Template GPL=Template("""/* * Copyright (c) $YEAR $AUTHOR $EMAIL * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ """) HEADER=Template("""${GPL} #ifndef ${HEADER_GUARD}_TEST_H #define ${HEADER_GUARD}_TEST_H -#include +#include class ${CLASSNAME}Test : public QObject { Q_OBJECT private slots: void testCreation(); }; #endif """) IMPLEMENTATION=Template("""${GPL} #include #include "${HEADER}_test.h" #include "${HEADER}.h" void ${CLASSNAME}Test::testCreation() { ${CLASSNAME} test; } QTEST_KDEMAIN(${CLASSNAME}Test, GUI); #include "${HEADER}_test.moc" """) CMAKE=""" ########### next target ############### set(%(HEADER)s_test_SRCS %(HEADER)s_test.cpp ) kde4_add_unit_test(%(CLASSNAME)sTest TESTNAME krita-image-%(CLASSNAME)sTest ${%(HEADER)s_test_SRCS}) target_link_libraries(%(CLASSNAME)sTest ${KDE4_KDEUI_LIBS} komain kritaimage ${QT_QTTEST_LIBRARY}) """ def convertheaderToClassName(header): if header.find(".h") >= 0: header = header[:-2] nextIsCap = True classname = "" cleanheader = "" for c in header: if "./".find(c) < 0: cleanheader += c if "._/".find(c) < 0: if nextIsCap: classname += c.upper() nextIsCap = False else: classname += c if "._/".find(c) >= 0: nextIsCap = True return (cleanheader, classname) def createTest(header, year, author, email): strippedheader, classname = convertheaderToClassName(header) headerguard = strippedheader.upper() if os.path.exists(strippedheader + "_test.h"): print "test for " + header + " already exists." return gpl = GPL.substitute(AUTHOR=author, YEAR = year, EMAIL=email) headerfile = HEADER.substitute(GPL=gpl, HEADER_GUARD=headerguard, CLASSNAME=classname) implementationfile = IMPLEMENTATION.substitute(GPL=gpl, HEADER=strippedheader, CLASSNAME=classname) cmake = CMAKE % {"HEADER" : strippedheader, "CLASSNAME" : classname} open(strippedheader + "_test.h", "w+").write(headerfile) open(strippedheader + "_test.cpp", "w+").write(implementationfile) open("CMakeLists.txt", "a+").write(cmake) def main(): year = "2007" author = "Boudewijn Rempt" email = "boud@valdyas.org" for header in sys.argv[1:]: createTest(header, year, author, email) if __name__ == "__main__": sys.exit(main()) diff --git a/krita/ui/input/kis_input_manager.h b/krita/ui/input/kis_input_manager.h index 5a269d328a1..1334e7f087a 100644 --- a/krita/ui/input/kis_input_manager.h +++ b/krita/ui/input/kis_input_manager.h @@ -1,99 +1,99 @@ /* This file is part of the KDE project * Copyright (C) 2012 Arjen Hiemstra * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_INPUTMANAGER_H #define KIS_INPUTMANAGER_H -#include +#include class QPointF; class QTabletEvent; class KoToolProxy; class KisCanvas2; class KisInputAction; /** * \brief Central object to manage canvas input. * * The Input Manager class manages all canvas input. It is created * by KisCanvas2 and processes all events related to input sent to the * canvas. * * The Input Manager keeps track of a set of actions and a set of * shortcuts. The actions are pre-defined while the shortcuts are * set from configuration. * * For each event, it will try to determine if there is a shortcut that * matches the input. It will then activate this action and pass all * consecutive events on to this action. * * \sa KisAbstractInputAction * * \todo Implement shortcut configuration */ class KisInputManager : public QObject { Q_OBJECT public: /** * Constructor. * * \param canvas The parent canvas. * \param proxy The application's tool proxy. */ explicit KisInputManager(KisCanvas2* canvas, KoToolProxy* proxy); /** * Destructor. */ ~KisInputManager(); /** * Event filter method. Overridden from QObject. */ bool eventFilter(QObject* object, QEvent* event ); /** * Return the canvas this input manager is associated with. */ KisCanvas2 *canvas() const; /** * The tool proxy of the current application. */ KoToolProxy *toolProxy() const; /** * Returns the event object for the last tablet event * happened. Returns null if there was no tablet event recently */ QTabletEvent *lastTabletEvent() const; /** * Convert a widget position to a pixel position. */ QPointF widgetToPixel(const QPointF &position); private Q_SLOTS: void setMirrorAxis(); void slotToolChanged(); private: class Private; Private* const d; }; #endif // KIS_INPUTMANAGER_H diff --git a/krita/ui/kis_cursor.cc b/krita/ui/kis_cursor.cc index b92160a089f..34d9e83680c 100644 --- a/krita/ui/kis_cursor.cc +++ b/krita/ui/kis_cursor.cc @@ -1,416 +1,416 @@ /* * kis_cursor.cc - part of KImageShop * * Copyright (c) 1999 Matthias Elter * Copyright (c) 2004 Adrian Page * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_cursor.h" #include #include #include #include #include -#include +#include #include #include #include #include "kis_factory2.h" KisCursor::KisCursor() {} /* * Predefined Qt cursors */ QCursor KisCursor::arrowCursor() { return Qt::ArrowCursor; } QCursor KisCursor::upArrowCursor() { return Qt::UpArrowCursor; } QCursor KisCursor::crossCursor() { return load("cursor-cross.xpm"); } QCursor KisCursor::roundCursor() { return load("cursor-round.xpm"); } QCursor KisCursor::waitCursor() { return Qt::WaitCursor; } QCursor KisCursor::ibeamCursor() { return Qt::IBeamCursor; } QCursor KisCursor::sizeVerCursor() { return Qt::SizeVerCursor; } QCursor KisCursor::sizeHorCursor() { return Qt::SizeHorCursor; } QCursor KisCursor::sizeBDiagCursor() { return Qt::SizeBDiagCursor; } QCursor KisCursor::sizeFDiagCursor() { return Qt::SizeFDiagCursor; } QCursor KisCursor::sizeAllCursor() { return Qt::SizeAllCursor; } QCursor KisCursor::blankCursor() { return Qt::BlankCursor; } QCursor KisCursor::splitVCursor() { return Qt::SplitVCursor; } QCursor KisCursor::splitHCursor() { return Qt::SplitHCursor; } QCursor KisCursor::pointingHandCursor() { return Qt::PointingHandCursor; } /* * Existing custom KimageShop cursors. Use the 'load' function for all new cursors. */ QCursor KisCursor::pickerCursor() { static unsigned char picker_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x34, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7d, 0x00, 0x80, 0x7e, 0x00, 0x60, 0x3f, 0x00, 0xd0, 0x1f, 0x00, 0xa0, 0x0f, 0x00, 0x50, 0x07, 0x00, 0xc8, 0x06, 0x00, 0xe4, 0x02, 0x00, 0x72, 0x01, 0x00, 0x39, 0x00, 0x80, 0x1c, 0x00, 0x40, 0x0e, 0x00, 0x20, 0x07, 0x00, 0x90, 0x03, 0x00, 0xc8, 0x01, 0x00, 0xe4, 0x00, 0x00, 0x74, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00 }; QBitmap picker_bitmap = bitmapFromData(QSize(24, 24), picker_bits); QBitmap picker_mask = picker_bitmap.createHeuristicMask(false); return QCursor(picker_bitmap, picker_mask, 1, 22); } QCursor KisCursor::pickerPlusCursor() { static unsigned char pickerplus_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x34, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7d, 0x00, 0x80, 0x7e, 0x00, 0x60, 0x3f, 0x00, 0xd0, 0x1f, 0x00, 0xa0, 0x0f, 0x00, 0x50, 0x07, 0x00, 0xc8, 0x06, 0x00, 0xe4, 0x02, 0x00, 0x72, 0x01, 0x00, 0x39, 0x0c, 0x80, 0x1c, 0x0c, 0x40, 0x0e, 0x0c, 0x20, 0x07, 0x0c, 0x90, 0x83, 0x7f, 0xc8, 0x81, 0x7f, 0xe4, 0x00, 0x0c, 0x74, 0x00, 0x0c, 0x32, 0x00, 0x0c, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00 }; QBitmap picker_bitmap = bitmapFromData(QSize(24, 24), pickerplus_bits); QBitmap picker_mask = picker_bitmap.createHeuristicMask(false); return QCursor(picker_bitmap, picker_mask, 1, 22); } QCursor KisCursor::pickerMinusCursor() { static unsigned char pickerminus_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x34, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7d, 0x00, 0x80, 0x7e, 0x00, 0x60, 0x3f, 0x00, 0xd0, 0x1f, 0x00, 0xa0, 0x0f, 0x00, 0x50, 0x07, 0x00, 0xc8, 0x06, 0x00, 0xe4, 0x02, 0x00, 0x72, 0x01, 0x00, 0x39, 0x00, 0x80, 0x1c, 0x00, 0x40, 0x0e, 0x00, 0x20, 0x07, 0x00, 0x90, 0xc3, 0x7f, 0xc8, 0xc1, 0x7f, 0xe4, 0x00, 0x00, 0x74, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00 }; QBitmap picker_bitmap = bitmapFromData(QSize(24, 24), pickerminus_bits); QBitmap picker_mask = picker_bitmap.createHeuristicMask(false); return QCursor(picker_bitmap, picker_mask, 1, 22); } QCursor KisCursor::penCursor() { static unsigned char pen_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x7d, 0x00, 0x80, 0x7e, 0x00, 0x40, 0x7f, 0x00, 0xa0, 0x3f, 0x00, 0xd0, 0x1f, 0x00, 0xe8, 0x0f, 0x00, 0xf4, 0x07, 0x00, 0xfa, 0x03, 0x00, 0xfd, 0x01, 0x80, 0xfe, 0x00, 0x40, 0x7f, 0x00, 0xa0, 0x3f, 0x00, 0xf0, 0x1f, 0x00, 0xd0, 0x0f, 0x00, 0x88, 0x07, 0x00, 0x88, 0x03, 0x00, 0xe4, 0x01, 0x00, 0x7c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00 }; QBitmap pen_bitmap = bitmapFromData(QSize(24, 24), pen_bits); QBitmap pen_mask = pen_bitmap.createHeuristicMask(false); return QCursor(pen_bitmap, pen_mask, 1, 22); } QCursor KisCursor::brushCursor() { static unsigned char brush_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x80, 0x7e, 0x00, 0x00, 0x40, 0x3f, 0x00, 0x00, 0xa0, 0x1f, 0x00, 0x00, 0xd0, 0x0f, 0x00, 0x00, 0xe8, 0x07, 0x00, 0x00, 0xf4, 0x03, 0x00, 0x00, 0xe4, 0x01, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x80, 0x41, 0x00, 0x00, 0x40, 0x32, 0x00, 0x00, 0xa0, 0x0f, 0x00, 0x00, 0xd0, 0x0f, 0x00, 0x00, 0xd0, 0x0f, 0x00, 0x00, 0xe8, 0x07, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; QBitmap brush_bitmap = bitmapFromData(QSize(25, 23), brush_bits); QBitmap brush_mask = brush_bitmap.createHeuristicMask(false); return QCursor(brush_bitmap, brush_mask, 1, 21); } QCursor KisCursor::airbrushCursor() { static unsigned char airbrush_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x68, 0x00, 0x00, 0x74, 0x00, 0x00, 0x7a, 0xf0, 0x00, 0x3d, 0x08, 0x81, 0x1e, 0xe8, 0x41, 0x0f, 0xe8, 0xa1, 0x07, 0xe8, 0xd1, 0x03, 0xe8, 0xe9, 0x01, 0xe8, 0xf5, 0x00, 0xe8, 0x7b, 0x00, 0xf0, 0x33, 0x00, 0xf0, 0x23, 0x1f, 0xa0, 0x9f, 0x3f, 0xd0, 0xff, 0x31, 0xe8, 0xf7, 0x30, 0xf4, 0x03, 0x18, 0xfc, 0x01, 0x0c, 0xf8, 0x00, 0x06, 0x76, 0x00, 0x03, 0x36, 0x00, 0x03, 0x00, 0x00, 0x00 }; QBitmap airbrush_bitmap = bitmapFromData(QSize(24, 24), airbrush_bits); QBitmap airbrush_mask = airbrush_bitmap.createHeuristicMask(false); return QCursor(airbrush_bitmap, airbrush_mask, 1, 22); } QCursor KisCursor::eraserCursor() { static unsigned char eraser_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x80, 0x3e, 0x00, 0x00, 0x40, 0x7f, 0x00, 0x00, 0xa0, 0xff, 0x00, 0x00, 0xd0, 0xff, 0x00, 0x00, 0xe8, 0x7f, 0x00, 0x00, 0xf4, 0x3f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xf9, 0x0f, 0x00, 0x80, 0xf2, 0x07, 0x00, 0x40, 0xe7, 0x03, 0x00, 0xa0, 0xcf, 0x01, 0x00, 0xd0, 0x9f, 0x00, 0x00, 0xe8, 0x7f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xf2, 0x1f, 0x00, 0x00, 0xe2, 0x0f, 0x00, 0x00, 0xc4, 0x07, 0x00, 0x00, 0x88, 0x03, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; QBitmap eraser_bitmap = bitmapFromData(QSize(25, 24), eraser_bits); QBitmap eraser_mask = eraser_bitmap.createHeuristicMask(false); return QCursor(eraser_bitmap, eraser_mask, 7, 22); } QCursor KisCursor::fillerCursor() { static unsigned char filler_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x28, 0x00, 0x00, 0x54, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x85, 0x00, 0x80, 0x0a, 0x01, 0x40, 0x11, 0x01, 0xe0, 0x00, 0x02, 0x58, 0x01, 0x04, 0x2c, 0x02, 0x04, 0x44, 0x04, 0x08, 0x0c, 0x08, 0x18, 0x3c, 0x00, 0x14, 0x5c, 0x00, 0x0a, 0x9c, 0x01, 0x05, 0x1c, 0x82, 0x02, 0x18, 0x4c, 0x01, 0x18, 0xb0, 0x00, 0x08, 0x60, 0x00, 0x00, 0x00, 0x00 }; QBitmap filler_bitmap = bitmapFromData(QSize(22, 22), filler_bits); QBitmap filler_mask = filler_bitmap.createHeuristicMask(false); return QCursor(filler_bitmap, filler_mask, 3, 20); } QCursor KisCursor::colorChangerCursor() { static unsigned char colorChanger_bits[] = { 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x10, 0x01, 0x0e, 0x08, 0x02, 0x11, 0x04, 0x82, 0x20, 0x64, 0x84, 0x20, 0x92, 0x44, 0x46, 0x12, 0x49, 0x5f, 0x12, 0x31, 0x5f, 0x22, 0x01, 0x5f, 0xc2, 0x00, 0x4e, 0x02, 0x00, 0x40, 0xc2, 0x00, 0x46, 0xe2, 0x01, 0x4f, 0xe4, 0x19, 0x2f, 0xe4, 0x3d, 0x2f, 0xe8, 0x3d, 0x17, 0xd0, 0x3c, 0x10, 0x20, 0x38, 0x08, 0x40, 0x00, 0x06, 0x80, 0x81, 0x01, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00 }; QBitmap colorChanger_bitmap = bitmapFromData(QSize(24, 23), colorChanger_bits); QBitmap colorChanger_mask = colorChanger_bitmap.createHeuristicMask(false); return QCursor(colorChanger_bitmap, colorChanger_mask, 12, 10); } QCursor KisCursor::zoomCursor() { static unsigned char zoom_bits[] = { 0x00, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0xf0, 0x3f, 0x00, 0x38, 0x70, 0x00, 0x8c, 0xcf, 0x00, 0x0c, 0xdf, 0x00, 0x36, 0xbf, 0x01, 0xb6, 0xbf, 0x01, 0xf6, 0xbf, 0x01, 0xf6, 0xbf, 0x01, 0xe6, 0x9f, 0x00, 0xcc, 0xcf, 0x00, 0x9c, 0xe7, 0x01, 0x38, 0x70, 0x03, 0xf0, 0xbf, 0x05, 0xc0, 0xef, 0x0b, 0x00, 0xc0, 0x17, 0x00, 0x80, 0x2f, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00 }; QBitmap zoom_bitmap = bitmapFromData(QSize(24, 23), zoom_bits); QBitmap zoom_mask = zoom_bitmap.createHeuristicMask(false); return QCursor(zoom_bitmap, zoom_mask, 9, 8); } QCursor KisCursor::moveCursor() { static unsigned char move_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xff, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x10, 0x18, 0x08, 0x18, 0x18, 0x18, 0x1c, 0x18, 0x38, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0x1c, 0x18, 0x38, 0x18, 0x18, 0x18, 0x10, 0x18, 0x08, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00 }; QBitmap move_bitmap = bitmapFromData(QSize(24, 24), move_bits); QBitmap move_mask = move_bitmap.createHeuristicMask(false); return QCursor(move_bitmap, move_mask, 12, 11); } QCursor KisCursor::handCursor() { return Qt::PointingHandCursor; } QCursor KisCursor::selectCursor() { static unsigned char select_bits[] = { 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00 }; QBitmap select_bitmap = bitmapFromData(QSize(23, 23), select_bits); QBitmap select_mask = select_bitmap.createHeuristicMask(false); return QCursor(select_bitmap, select_mask, 11, 11); } QCursor KisCursor::openHandCursor() { return Qt::OpenHandCursor; } QCursor KisCursor::closedHandCursor() { return Qt::ClosedHandCursor; } QCursor KisCursor::rotateCursor() { return load("rotate_cursor.xpm"); } QCursor KisCursor::load(const QString & iconName, int hotspotX, int hotspotY) { QString filename = KisFactory2::componentData().dirs()->findResource("kis_pics", iconName); QImage cursorImage; cursorImage.load(filename); Q_ASSERT(!cursorImage.isNull()); Q_ASSERT(cursorImage.hasAlphaChannel()); #ifdef Q_WS_WIN // cursor width must be multiple of 16 on Windows int bitmapWidth = qCeil(cursorImage.width() / 16.0) * 16; if (hotspotX < 0) { hotspotX = cursorImage.width() / 2; } QBitmap bitmap(bitmapWidth, cursorImage.height()); QBitmap mask(bitmapWidth, cursorImage.height()); if (bitmapWidth != cursorImage.width()) { bitmap.clear(); mask.clear(); } #else QBitmap bitmap(cursorImage.width(), cursorImage.height()); QBitmap mask(cursorImage.width(), cursorImage.height()); #endif QPainter bitmapPainter(&bitmap); QPainter maskPainter(&mask); for (qint32 x = 0; x < cursorImage.width(); ++x) { for (qint32 y = 0; y < cursorImage.height(); ++y) { QRgb pixel = cursorImage.pixel(x, y); if (qAlpha(pixel) < 128) { bitmapPainter.setPen(Qt::color0); maskPainter.setPen(Qt::color0); } else { maskPainter.setPen(Qt::color1); if (qGray(pixel) < 128) { bitmapPainter.setPen(Qt::color1); } else { bitmapPainter.setPen(Qt::color0); } } bitmapPainter.drawPoint(x, y); maskPainter.drawPoint(x, y); } } return QCursor(bitmap, mask, hotspotX, hotspotY); } QBitmap KisCursor::bitmapFromData(const QSize& size, unsigned char* data) { QBitmap result(32, 32); result.fill(Qt::color0); QPainter painter(&result); painter.drawPixmap(0, 0, QBitmap::fromData(size, data)); return result; } diff --git a/krita/ui/tests/kis_dummies_facade_base_test.h b/krita/ui/tests/kis_dummies_facade_base_test.h index d21e4c53057..fc065cbc7cf 100644 --- a/krita/ui/tests/kis_dummies_facade_base_test.h +++ b/krita/ui/tests/kis_dummies_facade_base_test.h @@ -1,68 +1,68 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_DUMMIES_FACADE_BASE_TEST_H #define __KIS_DUMMIES_FACADE_BASE_TEST_H -#include +#include #include "empty_nodes_test.h" class KisNodeDummy; class KisDummiesFacadeBase; class KisDummiesFacadeBaseTest : public QObject, public TestUtil::EmptyNodesTest { Q_OBJECT public: virtual ~KisDummiesFacadeBaseTest(); protected: virtual KisDummiesFacadeBase* dummiesFacadeFactory() = 0; virtual void destroyDummiesFacade(KisDummiesFacadeBase *dummiesFacade) = 0; private slots: void slotNodeActivated(KisNodeSP node); void slotEndInsertDummy(KisNodeDummy *dummy); void slotBeginRemoveDummy(KisNodeDummy *dummy); private slots: void init(); void cleanup(); void testSetImage(); void testAddNode(); void testRemoveNode(); void testMoveNodeSameParent(); void testMoveNodeDifferentParent(); void testSubstituteRootNode(); void testAddSelectionMasksNoActivation(); private: void verifyActivatedNodes(const QString &nodes); void verifyMovedDummies(const QString &nodes); private: KisDummiesFacadeBase *m_dummiesFacade; QString m_activatedNodes; QString m_movedDummies; }; #endif /* __KIS_DUMMIES_FACADE_BASE_TEST_H */ diff --git a/krita/ui/tests/kis_input_manager_test.h b/krita/ui/tests/kis_input_manager_test.h index 429fc33829e..d987aea5e23 100644 --- a/krita/ui/tests/kis_input_manager_test.h +++ b/krita/ui/tests/kis_input_manager_test.h @@ -1,35 +1,35 @@ /* * Copyright (c) 2012 Dmitry Kazakov * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_INPUT_MANAGER_TEST_H #define __KIS_INPUT_MANAGER_TEST_H -#include +#include class KisInputManagerTest : public QObject { Q_OBJECT private slots: void testSingleActionShortcut(); void testStrokeShortcut(); void testKeyEvents(); void testReleaseUnnecessaryModifiers(); void testMouseMoves(); }; #endif /* __KIS_INPUT_MANAGER_TEST_H */ diff --git a/krita/ui/tests/kis_model_index_converter_test.h b/krita/ui/tests/kis_model_index_converter_test.h index b3e657fe505..1f22ab292a2 100644 --- a/krita/ui/tests/kis_model_index_converter_test.h +++ b/krita/ui/tests/kis_model_index_converter_test.h @@ -1,68 +1,68 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_MODEL_INDEX_CONVERTER_TEST_H #define __KIS_MODEL_INDEX_CONVERTER_TEST_H -#include +#include #include "empty_nodes_test.h" class KisDummiesFacadeBase; class KisNodeModel; class KisModelIndexConverterBase; class KisModelIndexConverterTest : public QObject, public TestUtil::EmptyNodesTest { Q_OBJECT private slots: void init(); void cleanup(); void testIndexFromDummy(); void testIndexFromAddedAllowedDummy(); void testIndexFromAddedDeniedDummy(); void testDummyFromRow(); void testRowCount(); void testIndexFromDummyShowAll(); void testIndexFromAddedAllowedDummyShowAll(); void testIndexFromAddedDeniedDummyShowAll(); void testDummyFromRowShowAll(); void testRowCountShowAll(); private: inline void checkIndexFromDummy(KisNodeSP node, int row); inline void checkInvalidIndexFromDummy(KisNodeSP node); inline void checkIndexFromAddedAllowedDummy(KisNodeSP parent, int index, int parentRow, int childRow, bool parentValid); inline void checkIndexFromAddedDeniedDummy(KisNodeSP parent, int index, int parentRow, int childRow, bool parentValid); inline void checkIndexFromAddedDummy(KisNodeSP parent, int index, const QString &type, int parentRow, int childRow, bool parentValid); inline void checkInvalidIndexFromAddedAllowedDummy(KisNodeSP parent, int index); inline void checkInvalidIndexFromAddedDeniedDummy(KisNodeSP parent, int index); inline void checkInvalidIndexFromAddedDummy(KisNodeSP parent, int index, const QString &type); inline void checkDummyFromRow(KisNodeSP parent, int row, KisNodeSP expectedNode); inline void checkRowCount(KisNodeSP parent, int rowCount); private: KisDummiesFacadeBase *m_dummiesFacade; KisNodeModel *m_nodeModel; KisModelIndexConverterBase *m_indexConverter; }; #endif /* __KIS_MODEL_INDEX_CONVERTER_TEST_H */ diff --git a/krita/ui/tests/kis_zoom_and_pan_test.h b/krita/ui/tests/kis_zoom_and_pan_test.h index ffcde44b076..241a7293dc6 100644 --- a/krita/ui/tests/kis_zoom_and_pan_test.h +++ b/krita/ui/tests/kis_zoom_and_pan_test.h @@ -1,75 +1,75 @@ /* * Copyright (c) 2012 Dmitry Kazakov * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_ZOOM_AND_PAN_TEST_H #define __KIS_ZOOM_AND_PAN_TEST_H -#include +#include class ZoomAndPanTester; class KisZoomAndPanTest : public QObject { Q_OBJECT private slots: void testZoom100ChangingWidgetSize(); void testZoomOnBorderZoomLevels(); void testSequentialActionZoomAndPan(); void testSequentialActionZoomAndPanFullscreen(); void testSequentialActionZoomAndPanRotate(); void testSequentialActionZoomAndPanRotateFullscreen(); void testSequentialActionZoomAndPanMirror(); void testSequentialWheelZoomAndPan(); void testSequentialWheelZoomAndPanFullscreen(); void testSequentialWheelZoomAndPanRotate(); void testSequentialWheelZoomAndPanRotateFullscreen(); void testSequentialWheelZoomAndPanMirror(); void testRotation_VastScrolling_1_0(); void testRotation_VastScrolling_0_5(); void testRotation_NoVastScrolling_1_0(); void testRotation_NoVastScrolling_0_5(); private: bool checkInvariants(const QPointF &baseFlakePoint, const QPoint &oldOffset, const QPointF &oldPreferredCenter, qreal oldZoom, const QPoint &newOffset, const QPointF &newPreferredCenter, qreal newZoom, const QPointF &newTopLeft, const QSize &oldDocumentSize); bool checkZoomWithAction(ZoomAndPanTester &t, qreal newZoom, bool limitedZoom = false); bool checkZoomWithWheel(ZoomAndPanTester &t, const QPoint &widgetPoint, qreal zoomCoeff, bool limitedZoom = false); bool checkPan(ZoomAndPanTester &t, QPoint shift); bool checkRotation(ZoomAndPanTester &t, qreal angle); void initializeViewport(ZoomAndPanTester &t, bool fullscreenMode, bool rotate, bool mirror); void testSequentialActionZoomAndPan(bool fullscreenMode, bool rotate, bool mirror); void testSequentialWheelZoomAndPan(bool fullscreenMode, bool rotate, bool mirror); void testRotation(qreal vastScrolling, qreal zoom); }; #endif /* __KIS_ZOOM_AND_PAN_TEST_H */ diff --git a/libs/db/tests/ConnectionTest.h b/libs/db/tests/ConnectionTest.h index 119ee7d555e..f33249461f0 100644 --- a/libs/db/tests/ConnectionTest.h +++ b/libs/db/tests/ConnectionTest.h @@ -1,34 +1,34 @@ /* This file is part of the KDE project Copyright (C) 2012 Jarosław Staniek This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef CALLIGRADB_CONNECTIONTEST_H #define CALLIGRADB_CONNECTIONTEST_H -#include +#include class ConnectionTest : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void testCreateDb(); void cleanupTestCase(); }; #endif diff --git a/libs/db/tests/TestUtils.h b/libs/db/tests/TestUtils.h index 49063b89ca0..f103ee82142 100644 --- a/libs/db/tests/TestUtils.h +++ b/libs/db/tests/TestUtils.h @@ -1,34 +1,34 @@ /* This file is part of the KDE project Copyright (C) 2012 Jarosław Staniek This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KEXIDBUTILSTEST_H #define KEXIUTILS_IDENTIFIERTEST_H -#include +#include class TestUtils : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void testIsIdentifier(); void cleanupTestCase(); }; #endif diff --git a/libs/flake/KoCanvasControllerWidget.cpp b/libs/flake/KoCanvasControllerWidget.cpp index 66590448215..a85337a8e4d 100644 --- a/libs/flake/KoCanvasControllerWidget.cpp +++ b/libs/flake/KoCanvasControllerWidget.cpp @@ -1,653 +1,653 @@ /* This file is part of the KDE project * * Copyright (C) 2006, 2008-2009 Thomas Zander * Copyright (C) 2006 Peter Simonsson * Copyright (C) 2006, 2009 Thorsten Zachmann * Copyright (C) 2007-2010 Boudewijn Rempt * Copyright (C) 2007 C. Boemann * Copyright (C) 2006-2008 Jan Hambrecht * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KoCanvasControllerWidget.h" #include "KoCanvasControllerWidgetViewport_p.h" #include "KoShape.h" #include "KoViewConverter.h" #include "KoCanvasBase.h" #include "KoCanvasObserverBase.h" #include "KoCanvasSupervisor.h" #include "KoToolManager_p.h" #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_OPENGL -#include +#include #endif class KoCanvasControllerWidget::Private { public: Private(KoCanvasControllerWidget *qq) : q(qq) , canvas(0) , lastActivatedCanvas(0) , ignoreScrollSignals(false) , zoomWithWheel(false) , vastScrollingFactor(0) { } /** * Gets called by the tool manager if this canvas controller is the current active canvas controller. */ void setDocumentOffset(); void resetScrollBars(); void emitPointerPositionChangedSignals(QEvent *event); void activate(); void unsetCanvas(); KoCanvasControllerWidget *q; KoCanvasBase *canvas; KoCanvasBase *lastActivatedCanvas; Viewport *viewportWidget; bool ignoreScrollSignals; bool zoomWithWheel; qreal vastScrollingFactor; }; void KoCanvasControllerWidget::Private::setDocumentOffset() { // The margins scroll the canvas widget inside the viewport, not // the document. The documentOffset is meant to be the value that // the canvas must add to the update rect in its paint event, to // compensate. QPoint pt(q->horizontalScrollBar()->value(), q->verticalScrollBar()->value()); q->proxyObject->emitMoveDocumentOffset(pt); QWidget *canvasWidget = canvas->canvasWidget(); if (canvasWidget) { bool isCanvasOpenGL = false; QWidget *canvasWidget = canvas->canvasWidget(); if (canvasWidget) { #ifdef HAVE_OPENGL if (qobject_cast(canvasWidget) != 0) { isCanvasOpenGL = true; } #endif } if (!isCanvasOpenGL) { QPoint diff = q->documentOffset() - pt; if (q->canvasMode() == Spreadsheet && canvasWidget->layoutDirection() == Qt::RightToLeft) { canvasWidget->scroll(-diff.x(), diff.y()); } else { canvasWidget->scroll(diff.x(), diff.y()); } } } q->setDocumentOffset(pt); } void KoCanvasControllerWidget::Private::resetScrollBars() { // The scrollbar value always points at the top-left corner of the // bit of image we paint. int docH = q->documentSize().height() + q->margin(); int docW = q->documentSize().width() + q->margin(); int drawH = viewportWidget->height(); int drawW = viewportWidget->width(); QScrollBar *hScroll = q->horizontalScrollBar(); QScrollBar *vScroll = q->verticalScrollBar(); int horizontalReserve = vastScrollingFactor * drawW; int verticalReserve = vastScrollingFactor * drawH; int xMin = -horizontalReserve; int yMin = -verticalReserve; int xMax = docW - drawW + horizontalReserve; int yMax = docH - drawH + verticalReserve; hScroll->setRange(xMin, xMax); vScroll->setRange(yMin, yMax); int fontheight = QFontMetrics(q->font()).height(); vScroll->setPageStep(drawH); vScroll->setSingleStep(fontheight); hScroll->setPageStep(drawW); hScroll->setSingleStep(fontheight); } void KoCanvasControllerWidget::Private::emitPointerPositionChangedSignals(QEvent *event) { if (!canvas) return; if (!canvas->viewConverter()) return; QPoint pointerPos; QMouseEvent *mouseEvent = dynamic_cast(event); if (mouseEvent) { pointerPos = mouseEvent->pos(); } else { QTabletEvent *tabletEvent = dynamic_cast(event); if (tabletEvent) { pointerPos = tabletEvent->pos(); } } QPoint pixelPos = (pointerPos - canvas->documentOrigin()) + q->documentOffset(); QPointF documentPos = canvas->viewConverter()->viewToDocument(pixelPos); q->proxyObject->emitDocumentMousePositionChanged(documentPos); q->proxyObject->emitCanvasMousePositionChanged(pointerPos); } void KoCanvasControllerWidget::Private::activate() { QWidget *parent = q; while (parent->parentWidget()) { parent = parent->parentWidget(); } KoCanvasSupervisor *observerProvider = dynamic_cast(parent); if (!observerProvider) { return; } // Only notify the canvasobservers that the canvas has changed if it has, // indeed, been changed. Doesn't excuse the canvasdockers from properly // disconnecting if (q->canvas() != lastActivatedCanvas) { foreach(KoCanvasObserverBase *docker, observerProvider->canvasObservers()) { KoCanvasObserverBase *observer = dynamic_cast(docker); if (observer) { observer->setCanvas(q->canvas()); } } lastActivatedCanvas = q->canvas(); } } void KoCanvasControllerWidget::Private::unsetCanvas() { QWidget *parent = q; while (parent->parentWidget()) { parent = parent->parentWidget(); } KoCanvasSupervisor *observerProvider = dynamic_cast(parent); if (!observerProvider) { return; } foreach(KoCanvasObserverBase *docker, observerProvider->canvasObservers()) { KoCanvasObserverBase *observer = dynamic_cast(docker); if (observer) { observer->unsetCanvas(); } } } //////////// KoCanvasControllerWidget::KoCanvasControllerWidget(KActionCollection * actionCollection, QWidget *parent) : QAbstractScrollArea(parent) , KoCanvasController(actionCollection) , d(new Private(this)) { setFrameShape(NoFrame); d->viewportWidget = new Viewport(this); setViewport(d->viewportWidget); //setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); setAutoFillBackground(false); /* Fixes: apps starting at zero zoom. Details: Since the document is set on the mainwindow before loading commences the inial show/layout can choose to set the document to be very small, even to be zero pixels tall. Setting a sane minimum size on the widget means we no loger get rounding errors in zooming and we no longer end up with zero-zoom. Note: KoPage apps should probably startup with a sane document size; for Krita that's impossible */ setMinimumSize(QSize(50, 50)); setMouseTracking(true); connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(updateCanvasOffsetX())); connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(updateCanvasOffsetY())); connect(d->viewportWidget, SIGNAL(sizeChanged()), this, SLOT(updateCanvasOffsetX())); connect(proxyObject, SIGNAL(moveDocumentOffset(const QPoint&)), d->viewportWidget, SLOT(documentOffsetMoved(const QPoint&))); } KoCanvasControllerWidget::~KoCanvasControllerWidget() { d->unsetCanvas(); delete d; } void KoCanvasControllerWidget::activate() { d->activate(); } void KoCanvasControllerWidget::scrollContentsBy(int dx, int dy) { Q_UNUSED(dx); Q_UNUSED(dy); d->setDocumentOffset(); } QSize KoCanvasControllerWidget::viewportSize() const { return viewport()->size(); } void KoCanvasControllerWidget::setDrawShadow(bool drawShadow) { d->viewportWidget->setDrawShadow(drawShadow); } void KoCanvasControllerWidget::resizeEvent(QResizeEvent *resizeEvent) { proxyObject->emitSizeChanged(resizeEvent->size()); // XXX: When resizing, keep the area we're looking at now in the // center of the resized view. d->resetScrollBars(); d->setDocumentOffset(); } void KoCanvasControllerWidget::setCanvas(KoCanvasBase *canvas) { Q_ASSERT(canvas); // param is not null if (d->canvas) { d->unsetCanvas(); proxyObject->emitCanvasRemoved(this); canvas->setCanvasController(0); d->canvas->canvasWidget()->removeEventFilter(this); } canvas->setCanvasController(this); d->canvas = canvas; d->viewportWidget->setCanvas(canvas->canvasWidget()); d->canvas->canvasWidget()->installEventFilter(this); d->canvas->canvasWidget()->setMouseTracking(true); setFocusProxy(d->canvas->canvasWidget()); proxyObject->emitCanvasSet(this); QTimer::singleShot(0, this, SLOT(activate())); setPreferredCenterFractionX(0); setPreferredCenterFractionY(0); } KoCanvasBase* KoCanvasControllerWidget::canvas() const { return d->canvas; } void KoCanvasControllerWidget::changeCanvasWidget(QWidget *widget) { Q_ASSERT(d->viewportWidget->canvas()); widget->setCursor(d->viewportWidget->canvas()->cursor()); d->viewportWidget->canvas()->removeEventFilter(this); d->viewportWidget->setCanvas(widget); widget->installEventFilter(this); widget->setMouseTracking(true); } int KoCanvasControllerWidget::visibleHeight() const { if (d->canvas == 0) return 0; QWidget *canvasWidget = canvas()->canvasWidget(); int height1; if (canvasWidget == 0) height1 = viewport()->height(); else height1 = qMin(viewport()->height(), canvasWidget->height()); int height2 = height(); return qMin(height1, height2); } int KoCanvasControllerWidget::visibleWidth() const { if (d->canvas == 0) return 0; QWidget *canvasWidget = canvas()->canvasWidget(); int width1; if (canvasWidget == 0) width1 = viewport()->width(); else width1 = qMin(viewport()->width(), canvasWidget->width()); int width2 = width(); return qMin(width1, width2); } int KoCanvasControllerWidget::canvasOffsetX() const { int offset = -horizontalScrollBar()->value(); if (d->canvas) { offset += d->canvas->canvasWidget()->x() + frameWidth(); } return offset; } int KoCanvasControllerWidget::canvasOffsetY() const { int offset = -verticalScrollBar()->value(); if (d->canvas) { offset += d->canvas->canvasWidget()->y() + frameWidth(); } return offset; } void KoCanvasControllerWidget::updateCanvasOffsetX() { proxyObject->emitCanvasOffsetXChanged(canvasOffsetX()); if (d->ignoreScrollSignals) return; setPreferredCenterFractionX((horizontalScrollBar()->value() + viewport()->width() / 2.0) / documentSize().width()); } void KoCanvasControllerWidget::updateCanvasOffsetY() { proxyObject->emitCanvasOffsetYChanged(canvasOffsetY()); if (d->ignoreScrollSignals) return; setPreferredCenterFractionY((verticalScrollBar()->value() + viewport()->height() / 2.0) / documentSize().height()); } bool KoCanvasControllerWidget::eventFilter(QObject *watched, QEvent *event) { if (d->canvas && d->canvas->canvasWidget() && (watched == d->canvas->canvasWidget())) { if (event->type() == QEvent::MouseMove || event->type() == QEvent::TabletMove) { d->emitPointerPositionChangedSignals(event); } } return false; } void KoCanvasControllerWidget::ensureVisible(KoShape *shape) { Q_ASSERT(shape); ensureVisible(d->canvas->viewConverter()->documentToView(shape->boundingRect())); } void KoCanvasControllerWidget::ensureVisible(const QRectF &rect, bool smooth) { QRect currentVisible(-canvasOffsetX(), -canvasOffsetY(), visibleWidth(), visibleHeight()); QRect viewRect = rect.toRect(); viewRect.translate(d->canvas->documentOrigin()); if (!viewRect.isValid() || currentVisible.contains(viewRect)) return; // its visible. Nothing to do. // if we move, we move a little more so the amount of times we have to move is less. int jumpWidth = smooth ? 0 : currentVisible.width() / 5; int jumpHeight = smooth ? 0 : currentVisible.height() / 5; if (!smooth && viewRect.width() + jumpWidth > currentVisible.width()) jumpWidth = 0; if (!smooth && viewRect.height() + jumpHeight > currentVisible.height()) jumpHeight = 0; int horizontalMove = 0; if (currentVisible.width() <= viewRect.width()) // center view horizontalMove = viewRect.center().x() - currentVisible.center().x(); else if (currentVisible.x() > viewRect.x()) // move left horizontalMove = viewRect.x() - currentVisible.x() - jumpWidth; else if (currentVisible.right() < viewRect.right()) // move right horizontalMove = viewRect.right() - qMax(0, currentVisible.right() - jumpWidth); int verticalMove = 0; if (currentVisible.height() <= viewRect.height()) // center view verticalMove = viewRect.center().y() - currentVisible.center().y(); if (currentVisible.y() > viewRect.y()) // move up verticalMove = viewRect.y() - currentVisible.y() - jumpHeight; else if (currentVisible.bottom() < viewRect.bottom()) // move down verticalMove = viewRect.bottom() - qMax(0, currentVisible.bottom() - jumpHeight); pan(QPoint(horizontalMove, verticalMove)); } void KoCanvasControllerWidget::recenterPreferred() { const bool oldIgnoreScrollSignals = d->ignoreScrollSignals; d->ignoreScrollSignals = true; QPointF center = preferredCenter(); // convert into a viewport based point center.rx() += d->canvas->canvasWidget()->x() + frameWidth(); center.ry() += d->canvas->canvasWidget()->y() + frameWidth(); // scroll to a new center point QPointF topLeft = center - 0.5 * QPointF(viewport()->width(), viewport()->height()); setScrollBarValue(topLeft.toPoint()); d->ignoreScrollSignals = oldIgnoreScrollSignals; } void KoCanvasControllerWidget::zoomIn(const QPoint ¢er) { zoomBy(center, sqrt(2.0)); } void KoCanvasControllerWidget::zoomOut(const QPoint ¢er) { zoomBy(center, sqrt(0.5)); } void KoCanvasControllerWidget::zoomBy(const QPoint ¢er, qreal zoom) { setPreferredCenterFractionX(1.0 * center.x() / documentSize().width()); setPreferredCenterFractionY(1.0 * center.y() / documentSize().height()); const bool oldIgnoreScrollSignals = d->ignoreScrollSignals; d->ignoreScrollSignals = true; proxyObject->emitZoomRelative(zoom, preferredCenter()); d->ignoreScrollSignals = oldIgnoreScrollSignals; } void KoCanvasControllerWidget::zoomTo(const QRect &viewRect) { qreal scale; if (1.0 * viewport()->width() / viewRect.width() > 1.0 * viewport()->height() / viewRect.height()) scale = 1.0 * viewport()->height() / viewRect.height(); else scale = 1.0 * viewport()->width() / viewRect.width(); zoomBy(viewRect.center(), scale); } void KoCanvasControllerWidget::setToolOptionWidgets(const QList&widgetMap) { emit toolOptionWidgetsChanged(widgetMap); } void KoCanvasControllerWidget::updateDocumentSize(const QSize &sz, bool recalculateCenter) { // Don't update if the document-size didn't changed to prevent infinite loops and unneeded updates. if (KoCanvasController::documentSize() == sz) return; if (!recalculateCenter) { // assume the distance from the top stays equal and recalculate the center. setPreferredCenterFractionX(documentSize().width() * preferredCenterFractionX() / sz.width()); setPreferredCenterFractionY(documentSize().height() * preferredCenterFractionY() / sz.height()); } const bool oldIgnoreScrollSignals = d->ignoreScrollSignals; d->ignoreScrollSignals = true; KoCanvasController::setDocumentSize(sz); d->viewportWidget->setDocumentSize(sz); d->resetScrollBars(); // Always emit the new offset. updateCanvasOffsetX(); updateCanvasOffsetY(); d->ignoreScrollSignals = oldIgnoreScrollSignals; } void KoCanvasControllerWidget::setZoomWithWheel(bool zoom) { d->zoomWithWheel = zoom; } void KoCanvasControllerWidget::setVastScrolling(qreal factor) { d->vastScrollingFactor = factor; } void KoCanvasControllerWidget::pan(const QPoint &distance) { QPoint sourcePoint = scrollBarValue(); setScrollBarValue(sourcePoint + distance); } void KoCanvasControllerWidget::setPreferredCenter(const QPointF &viewPoint) { setPreferredCenterFractionX(viewPoint.x() / documentSize().width()); setPreferredCenterFractionY(viewPoint.y() / documentSize().height()); recenterPreferred(); } QPointF KoCanvasControllerWidget::preferredCenter() const { QPointF center; center.setX(preferredCenterFractionX() * documentSize().width()); center.setY(preferredCenterFractionY() * documentSize().height()); return center; } void KoCanvasControllerWidget::paintEvent(QPaintEvent *event) { QPainter gc(viewport()); d->viewportWidget->handlePaintEvent(gc, event); } void KoCanvasControllerWidget::dragEnterEvent(QDragEnterEvent *event) { d->viewportWidget->handleDragEnterEvent(event); } void KoCanvasControllerWidget::dropEvent(QDropEvent *event) { d->viewportWidget->handleDropEvent(event); } void KoCanvasControllerWidget::dragMoveEvent(QDragMoveEvent *event) { d->viewportWidget->handleDragMoveEvent(event); } void KoCanvasControllerWidget::dragLeaveEvent(QDragLeaveEvent *event) { d->viewportWidget->handleDragLeaveEvent(event); } void KoCanvasControllerWidget::keyPressEvent(QKeyEvent *event) { KoToolManager::instance()->priv()->switchToolByShortcut(event); } void KoCanvasControllerWidget::wheelEvent(QWheelEvent *event) { if (d->zoomWithWheel != ((event->modifiers() & Qt::ControlModifier) == Qt::ControlModifier)) { const qreal zoomCoeff = event->delta() > 0 ? sqrt(2.0) : sqrt(0.5); zoomRelativeToPoint(event->pos(), zoomCoeff); event->accept(); } else QAbstractScrollArea::wheelEvent(event); } void KoCanvasControllerWidget::zoomRelativeToPoint(const QPoint &widgetPoint, qreal zoomCoeff) { const QPoint offset = scrollBarValue(); const QPoint mousePos(widgetPoint + offset); const bool oldIgnoreScrollSignals = d->ignoreScrollSignals; d->ignoreScrollSignals = true; proxyObject->emitZoomRelative(zoomCoeff, mousePos); d->ignoreScrollSignals = oldIgnoreScrollSignals; } bool KoCanvasControllerWidget::focusNextPrevChild(bool) { // we always return false meaning the canvas takes keyboard focus, but never gives it away. return false; } void KoCanvasControllerWidget::setMargin(int margin) { KoCanvasController::setMargin(margin); Q_ASSERT(d->viewportWidget); d->viewportWidget->setMargin(margin); } QPoint KoCanvasControllerWidget::scrollBarValue() const { QScrollBar * hBar = horizontalScrollBar(); QScrollBar * vBar = verticalScrollBar(); return QPoint(hBar->value(), vBar->value()); } void KoCanvasControllerWidget::setScrollBarValue(const QPoint &value) { QScrollBar * hBar = horizontalScrollBar(); QScrollBar * vBar = verticalScrollBar(); hBar->setValue(value.x()); vBar->setValue(value.y()); } KoCanvasControllerWidget::Private *KoCanvasControllerWidget::priv() { return d; } #include diff --git a/libs/main/KoApplication.cpp b/libs/main/KoApplication.cpp index d0900b9a82a..46e99de339e 100644 --- a/libs/main/KoApplication.cpp +++ b/libs/main/KoApplication.cpp @@ -1,535 +1,535 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999 Torben Weis Copyright (C) 2009 Thomas Zander Copyright (C) 2012 Boudewijn Rempt This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KoApplication.h" #include "KoGlobal.h" #ifndef QT_NO_DBUS #include "KoApplicationAdaptor.h" -#include +#include #endif #include "KoPrintJob.h" #include "KoDocumentEntry.h" #include "KoDocument.h" #include "KoMainWindow.h" #include "KoAutoSaveRecoveryDialog.h" #include #include "KoServiceProvider.h" #include "KoPart.h" #include #include #include #include #include #include #include #include #include #if KDE_IS_VERSION(4,6,0) #include #endif #include #include #include bool KoApplication::m_starting = true; namespace { const QTime appStartTime(QTime::currentTime()); } class KoApplicationPrivate { public: KoApplicationPrivate() : splashScreen(0) {} QSplashScreen *splashScreen; QList partList; }; KoApplication::KoApplication() : KApplication(initHack()) , d(new KoApplicationPrivate) { // Tell the iconloader about share/apps/calligra/icons KIconLoader::global()->addAppDir("calligra"); // Initialize all Calligra directories etc. KoGlobal::initialize(); #ifndef QT_NO_DBUS new KoApplicationAdaptor(this); QDBusConnection::sessionBus().registerObject("/application", this); #endif m_starting = true; #ifdef Q_WS_WIN QSysInfo::WinVersion version = QSysInfo::windowsVersion(); printf("setting windows style %i", version); switch (version) { case QSysInfo::WV_NT: case QSysInfo::WV_2000: setStyle("windows"); break; case QSysInfo::WV_XP: case QSysInfo::WV_2003: setStyle("windowsxp"); break; case QSysInfo::WV_VISTA: case QSysInfo::WV_WINDOWS7: default: setStyle("windowsvista"); } #endif } // This gets called before entering KApplication::KApplication bool KoApplication::initHack() { KCmdLineOptions options; options.add("print", ki18n("Only print and exit")); options.add("template", ki18n("Open a new document with a template")); options.add("dpi ", ki18n("Override display DPI")); options.add("export-pdf", ki18n("Only export to PDF and exit")); options.add("export-filename ", ki18n("Filename for export-pdf")); options.add("benchmark-loading", ki18n("just load the file and then exit")); options.add("benchmark-loading-show-window", ki18n("load the file, show the window and progressbar and then exit")); options.add("profile-filename ", ki18n("Filename to write profiling information into.")); options.add("roundtrip-filename ", ki18n("Load a file and save it as an ODF file. Meant for debugging.")); KCmdLineArgs::addCmdLineOptions(options, ki18n("Calligra"), "calligra", "kde"); return true; } // Small helper for start() so that we don't forget to reset m_starting before a return class KoApplication::ResetStarting { public: ResetStarting(QSplashScreen *splash = 0) : m_splash(splash) { } ~ResetStarting() { KoApplication::m_starting = false; if (m_splash) { m_splash->hide(); } } QSplashScreen *m_splash; }; bool KoApplication::start() { if (d->splashScreen) { d->splashScreen->show(); d->splashScreen->showMessage("."); } ResetStarting resetStarting(d->splashScreen); // reset m_starting to false when we're done Q_UNUSED(resetStarting); // Find the *.desktop file corresponding to the kapp instance name KoDocumentEntry entry = KoDocumentEntry(KoServiceProvider::readNativeService()); if (entry.isEmpty()) { kError(30003) << KGlobal::mainComponent().componentName() << "part.desktop not found." << endl; kError(30003) << "Run 'kde4-config --path services' to see which directories were searched, assuming kde startup had the same environment as your current shell." << endl; kError(30003) << "Check your installation (did you install Calligra in a different prefix than KDE, without adding the prefix to /etc/kderc ?)" << endl; return false; } // Get the command line arguments which we have to parse KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); int argsCount = args->count(); KCmdLineArgs *koargs = KCmdLineArgs::parsedArgs("calligra"); QString dpiValues = koargs->getOption("dpi"); if (!dpiValues.isEmpty()) { int sep = dpiValues.indexOf(QRegExp("[x, ]")); int dpiX; int dpiY = 0; bool ok = true; if (sep != -1) { dpiY = dpiValues.mid(sep + 1).toInt(&ok); dpiValues.truncate(sep); } if (ok) { dpiX = dpiValues.toInt(&ok); if (ok) { if (!dpiY) dpiY = dpiX; KoDpi::setDPI(dpiX, dpiY); } } } // No argument -> create an empty document if (!argsCount) { #if KDE_IS_VERSION(4,6,0) // if there's no document, add the current working directory // to the recent dirs so the open dialog and open pane show // the directory from where the app was started, instead of // the last directory from where we opened a file KRecentDirs::add(":OpenDialog", QDir::currentPath()); #endif QString errorMsg; KoPart *part = entry.createKoPart(&errorMsg); if (!part) { if (!errorMsg.isEmpty()) KMessageBox::error(0, errorMsg); return false; } // XXX: the document should be separate plugin KoDocument *doc = part->document(); KoMainWindow *shell = new KoMainWindow(part->componentData()); shell->show(); QObject::connect(doc, SIGNAL(sigProgress(int)), shell, SLOT(slotProgress(int))); // for initDoc to fill in the recent docs list // and for KoDocument::slotStarted part->addShell(shell); // Check for autosave files from a previous run. There can be several, and // we want to offer a restore for every one. Including a nice thumbnail! QStringList autoSaveFiles; // get all possible autosave files in the home dir, this is for unsaved document autosave files // Using the extension allows to avoid relying on the mime magic when opening KMimeType::Ptr mime = KMimeType::mimeType(doc->nativeFormatMimeType()); if (!mime) { qFatal("It seems your installation is broken/incomplete because we failed to load the native mimetype \"%s\".", doc->nativeFormatMimeType().constData()); } QString extension = mime->property("X-KDE-NativeExtension").toString(); if (extension.isEmpty()) extension = mime->mainExtension(); QStringList filters; filters << QString(".%1-%2-%3-autosave%4").arg(part->componentData().componentName()).arg("*").arg("*").arg(extension); QDir dir = QDir::home(); // all autosave files for our application autoSaveFiles = dir.entryList(filters, QDir::Files | QDir::Hidden); QStringList pids; QString ourPid; ourPid.setNum(kapp->applicationPid()); #ifndef QT_NO_DBUS // all running instances of our application -- bit hackish, but we cannot get at the dbus name here, for some reason QDBusReply reply = QDBusConnection::sessionBus().interface()->registeredServiceNames(); foreach (QString name, reply.value()) { if (name.contains(part->componentData().componentName())) { // we got another instance of ourselves running, let's get the pid QString pid = name.split("-").last(); if (pid != ourPid) { pids << pid; } } } #endif // remove the autosave files that are saved for other, open instances of ourselves foreach(const QString &autoSaveFileName, autoSaveFiles) { if (!QFile::exists(QDir::homePath() + "/" + autoSaveFileName)) { autoSaveFiles.removeAll(autoSaveFileName); continue; } QStringList split = autoSaveFileName.split("-"); if (split.size() == 4) { if (pids.contains(split[1])) { // We've got an active, owned autosave file. Remove. autoSaveFiles.removeAll(autoSaveFileName); } } } // Allow the user to make their selection if (autoSaveFiles.size() > 0) { KoAutoSaveRecoveryDialog dlg(autoSaveFiles); if (dlg.exec() == QDialog::Accepted) { QStringList filesToRecover = dlg.recoverableFiles(); foreach (const QString &autosaveFile, autoSaveFiles) { if (!filesToRecover.contains(autosaveFile)) { // remove the files the user didn't want to recover QFile::remove(QDir::homePath() + "/" + autosaveFile); } } autoSaveFiles = filesToRecover; } else { // don't recover any of the files, but don't delete them either autoSaveFiles.clear(); } } if (autoSaveFiles.size() > 0) { short int numberOfOpenDocuments = 0; // number of documents open KUrl url; // bah, we need to re-use the document that was already created url.setPath(QDir::homePath() + "/" + autoSaveFiles.takeFirst()); if (shell->openDocument(part, doc, url)) { doc->resetURL(); doc->setModified(true); QFile::remove(url.toLocalFile()); numberOfOpenDocuments++; } // And then for the other autosave files, we copy & paste the code // and loop through them. foreach(const QString &autoSaveFile, autoSaveFiles) { // For now create an empty document QString errorMsg; KoPart *part = entry.createKoPart(&errorMsg); if (part) { url.setPath(QDir::homePath() + "/" + autoSaveFile); KoMainWindow *shell = new KoMainWindow(part->componentData()); shell->show(); if (shell->openDocument(part, doc, url)) { doc->resetURL(); doc->setModified(true); QFile::remove(url.toLocalFile()); numberOfOpenDocuments++; } } } return (numberOfOpenDocuments > 0); } else { part->showStartUpWidget(shell); } } else { const bool print = koargs->isSet("print"); const bool exportAsPdf = koargs->isSet("export-pdf"); const QString pdfFileName = koargs->getOption("export-filename"); const QString roundtripFileName = koargs->getOption("roundtrip-filename"); const bool doTemplate = koargs->isSet("template"); const bool benchmarkLoading = koargs->isSet("benchmark-loading") || koargs->isSet("benchmark-loading-show-window") || !roundtripFileName.isEmpty(); // only show the shell when no command-line mode option is passed const bool showShell = koargs->isSet("benchmark-loading-show-window") || ( !koargs->isSet("export-pdf") && !koargs->isSet("benchmark-loading") && !koargs->isSet("roundtrip-filename") && roundtripFileName.isEmpty()); const QString profileFileName = koargs->getOption("profile-filename"); koargs->clear(); QTextStream profileoutput; QFile profileFile(profileFileName); if (!profileFileName.isEmpty() && profileFile.open(QFile::WriteOnly | QFile::Truncate)) { profileoutput.setDevice(&profileFile); } // Loop through arguments short int numberOfOpenDocuments = 0; // number of documents open short int nPrinted = 0; for (int argNumber = 0; argNumber < argsCount; argNumber++) { // For now create an empty document QString errorMsg; KoPart *part = entry.createKoPart(&errorMsg); if (part) { KoDocument *doc = part->document(); // show a shell asap KoMainWindow *shell = new KoMainWindow(part->componentData()); if (showShell) { shell->show(); } if (benchmarkLoading) { doc->setReadWrite(false); } if (profileoutput.device()) { doc->setProfileStream(&profileoutput); profileoutput << "KoApplication::start\t" << appStartTime.msecsTo(QTime::currentTime()) <<"\t0" << endl; doc->setAutoErrorHandlingEnabled(false); } doc->setProfileReferenceTime(appStartTime); // are we just trying to open a template? if (doTemplate) { QStringList paths; if (args->url(argNumber).isLocalFile() && QFile::exists(args->url(argNumber).toLocalFile())) { paths << QString(args->url(argNumber).toLocalFile()); kDebug(30003) << "using full path..."; } else { QString desktopName(args->arg(argNumber)); QString appName = KGlobal::mainComponent().componentName(); paths = KGlobal::dirs()->findAllResources("data", appName + "/templates/*/" + desktopName); if (paths.isEmpty()) { paths = KGlobal::dirs()->findAllResources("data", appName + "/templates/" + desktopName); } if (paths.isEmpty()) { KMessageBox::error(0, i18n("No template found for: %1", desktopName)); delete shell; } else if (paths.count() > 1) { KMessageBox::error(0, i18n("Too many templates found for: %1", desktopName)); delete shell; } } if (!paths.isEmpty()) { KUrl templateBase; templateBase.setPath(paths[0]); KDesktopFile templateInfo(paths[0]); QString templateName = templateInfo.readUrl(); KUrl templateURL; templateURL.setPath(templateBase.directory() + '/' + templateName); if (shell->openDocument(part, doc, templateURL)) { doc->resetURL(); doc->setEmpty(); doc->setTitleModified(); kDebug(30003) << "Template loaded..."; numberOfOpenDocuments++; } else { KMessageBox::error(0, i18n("Template %1 failed to load.", templateURL.prettyUrl())); delete shell; } } // now try to load } else if (shell->openDocument(part, doc, args->url(argNumber))) { if (benchmarkLoading) { if (profileoutput.device()) { profileoutput << "KoApplication::start\t" << appStartTime.msecsTo(QTime::currentTime()) <<"\t100" << endl; } if (!roundtripFileName.isEmpty()) { part->saveAs(KUrl("file:"+roundtripFileName)); } // close the document shell->slotFileQuit(); return true; // only load one document! } else if (print) { shell->slotFilePrint(); // delete shell; done by ~KoDocument nPrinted++; } else if (exportAsPdf) { KoPrintJob *job = shell->exportToPdf(pdfFileName); if (job) connect (job, SIGNAL(destroyed(QObject*)), shell, SLOT(slotFileQuit()), Qt::QueuedConnection); nPrinted++; } else { // Normal case, success numberOfOpenDocuments++; } } else { // .... if failed // delete doc; done by openDocument // delete shell; done by ~KoDocument } if (profileoutput.device()) { profileoutput << "KoApplication::start\t" << appStartTime.msecsTo(QTime::currentTime()) <<"\t100" << endl; } d->partList << part; } } if (benchmarkLoading) { return false; // no valid urls found. } if (print || exportAsPdf) return nPrinted > 0; if (numberOfOpenDocuments == 0) // no doc, e.g. all URLs were malformed return false; } args->clear(); // not calling this before since the program will quit there. return true; } KoApplication::~KoApplication() { // delete d->m_appIface; delete d; } bool KoApplication::isStarting() { return KoApplication::m_starting; } void KoApplication::setSplashScreen(QSplashScreen *splashScreen) { d->splashScreen = splashScreen; } QList KoApplication::partList() const { return d->partList; } void KoApplication::addPart(KoPart* part) { d->partList << part; } int KoApplication::documents() { QSet nameList; QList parts = d->partList; foreach(KoPart* part, parts) { nameList.insert(part->document()->objectName()); } return nameList.size(); } bool KoApplication::notify(QObject *receiver, QEvent *event) { try { return QApplication::notify(receiver, event); } catch (std::exception &e) { qWarning("Error %s sending event %i to object %s", e.what(), event->type(), qPrintable(receiver->objectName())); } catch (...) { qWarning("Error sending event %i to object %s", event->type(), qPrintable(receiver->objectName())); } return false; } #include diff --git a/libs/main/KoApplicationAdaptor.h b/libs/main/KoApplicationAdaptor.h index 8e4af76123b..972e60fa83b 100644 --- a/libs/main/KoApplicationAdaptor.h +++ b/libs/main/KoApplicationAdaptor.h @@ -1,87 +1,87 @@ /* This file is part of the KDE project Copyright (C) 2000 David Faure Copyright (C) 2006 Fredrik Edemar This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef __KoApplicationAdaptor_h__ #define __KoApplicationAdaptor_h__ #include -#include +#include #include "komain_export.h" template class QList; template class QMap; class QString; class QStringList; class KoApplication; /** * D-BUS interface for any Calligra application (entry point) */ class KOMAIN_EXPORT KoApplicationAdaptor : public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.calligra.application") public: explicit KoApplicationAdaptor(KoApplication *parent); virtual ~KoApplicationAdaptor(); public slots: // METHODS /** * Creates a new document for the given native mimetype * Use it to create a shell and to load an existing file, if any */ Q_SCRIPTABLE QString createDocument(const QString &nativeFormat); /** * @return a list of references to all the documents * (see KoDocumentIface) */ Q_SCRIPTABLE QStringList getDocuments(); /** * @return a list of references to all the views * (see KoViewIface) * Convenience method to avoid iterating over all documents to get all the views. */ Q_SCRIPTABLE QStringList getViews(); /** * @return a list of references to all the windows * (see KoMainWindowIface) */ Q_SCRIPTABLE QStringList getWindows(); signals: /** * emitted when a new document is opened. */ void documentOpened(const QString &ref); /** * emitted when an old document is closed. */ void documentClosed(const QString &ref); private: KoApplication *m_application; }; #endif diff --git a/libs/main/KoDocument.cpp b/libs/main/KoDocument.cpp index a27f9e2cab0..817cbf714a0 100644 --- a/libs/main/KoDocument.cpp +++ b/libs/main/KoDocument.cpp @@ -1,2215 +1,2215 @@ /* This file is part of the KDE project * Copyright (C) 1998, 1999 Torben Weis * Copyright (C) 2000-2005 David Faure * Copyright (C) 2007-2008 Thorsten Zachmann * Copyright (C) 2010-2012 Boudewijn Rempt * Copyright (C) 2011 Inge Wallin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KoMainWindow.h" // XXX: remove #include // XXX: remove #include // XXX: remove #include "KoDocument.h" #include "KoPart.h" #include "KoServiceProvider.h" #include "KoGlobal.h" #include "KoEmbeddedDocumentSaver.h" #include "KoFilterManager.h" #include "KoDocumentInfo.h" #ifdef SHOULD_BUILD_RDF #include "rdf/KoDocumentRdf.h" #endif #include "KoOdfStylesReader.h" #include "KoOdfReadStore.h" #include "KoOdfWriteStore.h" #include "KoXmlNS.h" #include "KoApplication.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef QT_NO_DBUS -#include +#include #endif #include // Define the protocol used here for embedded documents' URL // This used to "store" but KUrl didn't like it, // so let's simply make it "tar" ! #define STORE_PROTOCOL "tar" // The internal path is a hack to make KUrl happy and for document children #define INTERNAL_PROTOCOL "intern" #define INTERNAL_PREFIX "intern:/" // Warning, keep it sync in koStore.cc #include #include "KoUndoStackAction.h" using namespace std; /********************************************************** * * KoDocument * **********************************************************/ //static QString KoDocument::newObjectName() { static int s_docIFNumber = 0; QString name; name.setNum(s_docIFNumber++); name.prepend("document_"); return name; } class KoDocument::Private { public: Private() : progressUpdater(0), progressProxy(0), profileStream(0), filterManager(0), specialOutputFlag(0), // default is native format isImporting(false), isExporting(false), password(QString()), modifiedAfterAutosave(false), autosaving(false), shouldCheckAutoSaveFile(true), autoErrorHandlingEnabled(true), backupFile(true), backupPath(QString()), doNotSaveExtDoc(false), storeInternal(false), isLoading(false), undoStack(0), parentPart(0) { confirmNonNativeSave[0] = true; confirmNonNativeSave[1] = true; if (KGlobal::locale()->measureSystem() == KLocale::Imperial) { unit = KoUnit::Inch; } else { unit = KoUnit::Centimeter; } } KoDocumentInfo *docInfo; #ifdef SHOULD_BUILD_RDF KoDocumentRdf *docRdf; #else KoDocumentRdfBase *docRdf; #endif KoProgressUpdater *progressUpdater; KoProgressProxy *progressProxy; QTextStream *profileStream; QTime profileReferenceTime; KoUnit unit; KoFilterManager *filterManager; // The filter-manager to use when loading/saving [for the options] QByteArray mimeType; // The actual mimetype of the document QByteArray outputMimeType; // The mimetype to use when saving bool confirmNonNativeSave [2]; // used to pop up a dialog when saving for the // first time if the file is in a foreign format // (Save/Save As, Export) int specialOutputFlag; // See KoFileDialog in koMainWindow.cc bool isImporting; bool isExporting; // File --> Import/Export vs File --> Open/Save QString password; // The password used to encrypt an encrypted document QTimer autoSaveTimer; QString lastErrorMessage; // see openFile() int autoSaveDelay; // in seconds, 0 to disable. bool modifiedAfterAutosave; bool autosaving; bool shouldCheckAutoSaveFile; // usually true bool autoErrorHandlingEnabled; // usually true bool backupFile; QString backupPath; bool doNotSaveExtDoc; // makes it possible to save only internally stored child documents bool storeInternal; // Store this doc internally even if url is external bool isLoading; // True while loading (openUrl is async) QList versionInfo; KUndo2Stack *undoStack; KoGridData gridData; KoGuidesData guidesData; KService::Ptr nativeService; bool isEmpty; KoPageLayout pageLayout; KoPart *parentPart; }; KoDocument::KoDocument(KoPart *parent, KUndo2Stack *undoStack) : d(new Private) { d->parentPart = parent; d->isEmpty = true; connect(&d->autoSaveTimer, SIGNAL(timeout()), this, SLOT(slotAutoSave())); setAutoSave(defaultAutoSave()); setObjectName(newObjectName()); d->docInfo = new KoDocumentInfo(this); d->docRdf = 0; #ifdef SHOULD_BUILD_RDF { KConfigGroup cfgGrp(d->parentPart->componentData().config(), "RDF"); bool rdfEnabled = cfgGrp.readEntry("rdf_enabled", false); if (rdfEnabled) { setDocumentRdf(new KoDocumentRdf(this)); } } #endif d->pageLayout.width = 0; d->pageLayout.height = 0; d->pageLayout.topMargin = 0; d->pageLayout.bottomMargin = 0; d->pageLayout.leftMargin = 0; d->pageLayout.rightMargin = 0; d->undoStack = undoStack; d->undoStack->setParent(this); KConfigGroup cfgGrp(d->parentPart->componentData().config(), "Undo"); d->undoStack->setUndoLimit(cfgGrp.readEntry("UndoLimit", 1000)); connect(d->undoStack, SIGNAL(indexChanged(int)), this, SLOT(slotUndoStackIndexChanged(int))); } KoDocument::~KoDocument() { d->autoSaveTimer.stop(); delete d->filterManager; delete d; } KoPart *KoDocument::documentPart() { return d->parentPart; } bool KoDocument::exportDocument(const KUrl & _url) { bool ret; d->isExporting = true; // // Preserve a lot of state here because we need to restore it in order to // be able to fake a File --> Export. Can't do this in saveFile() because, // for a start, KParts has already set url and m_file and because we need // to restore the modified flag etc. and don't want to put a load on anyone // reimplementing saveFile() (Note: importDocument() and exportDocument() // will remain non-virtual). // KUrl oldURL = d->parentPart->url(); QString oldFile = d->parentPart->localFilePath(); bool wasModified = isModified(); QByteArray oldMimeType = mimeType(); // save... ret = d->parentPart->saveAs(_url); // // This is sooooo hacky :( // Hopefully we will restore enough state. // kDebug(30003) << "Restoring KoDocument state to before export"; // always restore url & m_file because KParts has changed them // (regardless of failure or success) d->parentPart->setUrl(oldURL); d->parentPart->setLocalFilePath(oldFile); // on successful export we need to restore modified etc. too // on failed export, mimetype/modified hasn't changed anyway if (ret) { setModified(wasModified); d->mimeType = oldMimeType; } d->isExporting = false; return ret; } bool KoDocument::saveFile() { kDebug(30003) << "doc=" << d->parentPart->url().url(); // Save it to be able to restore it after a failed save const bool wasModified = isModified(); // The output format is set by koMainWindow, and by openFile QByteArray outputMimeType = d->outputMimeType; if (outputMimeType.isEmpty()) outputMimeType = d->outputMimeType = nativeFormatMimeType(); QApplication::setOverrideCursor(Qt::WaitCursor); if (backupFile()) { if (d->parentPart->url().isLocalFile()) KSaveFile::backupFile(d->parentPart->url().toLocalFile(), d->backupPath); else { KIO::UDSEntry entry; if (KIO::NetAccess::stat(d->parentPart->url(), entry, d->parentPart->currentShell())) { // this file exists => backup emit statusBarMessage(i18n("Making backup...")); KUrl backup; if (d->backupPath.isEmpty()) backup = d->parentPart->url(); else backup = d->backupPath + '/' + d->parentPart->url().fileName(); backup.setPath(backup.path() + QString::fromLatin1("~")); KFileItem item(entry, d->parentPart->url()); Q_ASSERT(item.name() == d->parentPart->url().fileName()); KIO::FileCopyJob *job = KIO::file_copy(d->parentPart->url(), backup, item.permissions(), KIO::Overwrite | KIO::HideProgressInfo); job->exec(); } } } emit statusBarMessage(i18n("Saving...")); bool ret = false; bool suppressErrorDialog = false; if (!isNativeFormat(outputMimeType, ForExport)) { kDebug(30003) << "Saving to format" << outputMimeType << "in" << d->parentPart->localFilePath(); // Not native format : save using export filter if (!d->filterManager) d->filterManager = new KoFilterManager(this); KoFilter::ConversionStatus status = d->filterManager->exportDocument(d->parentPart->localFilePath(), outputMimeType); ret = status == KoFilter::OK; suppressErrorDialog = (status == KoFilter::UserCancelled || status == KoFilter::BadConversionGraph); } else { // Native format => normal save Q_ASSERT(!d->parentPart->localFilePath().isEmpty()); ret = saveNativeFormat(d->parentPart->localFilePath()); } if (ret) { d->undoStack->setClean(); removeAutoSaveFiles(); // Restart the autosave timer // (we don't want to autosave again 2 seconds after a real save) setAutoSave(d->autoSaveDelay); } QApplication::restoreOverrideCursor(); if (!ret) { if (!suppressErrorDialog) { d->parentPart->showSavingErrorDialog(); } // couldn't save file so this new URL is invalid // FIXME: we should restore the current document's true URL instead of // setting it to nothing otherwise anything that depends on the URL // being correct will not work (i.e. the document will be called // "Untitled" which may not be true) // // Update: now the URL is restored in KoMainWindow but really, this // should still be fixed in KoDocument/KParts (ditto for file). // We still resetURL() here since we may or may not have been called // by KoMainWindow - Clarence resetURL(); // As we did not save, restore the "was modified" status setModified(wasModified); } if (ret) { d->mimeType = outputMimeType; setConfirmNonNativeSave(isExporting(), false); } emit clearStatusBarMessage(); if (ret) { KNotification *notify = new KNotification("DocumentSaved"); notify->setText(i18n("Document %1 saved", d->parentPart->url().url())); notify->addContext("url", d->parentPart->url().url()); QTimer::singleShot(0, notify, SLOT(sendEvent())); } return ret; } QByteArray KoDocument::mimeType() const { return d->mimeType; } void KoDocument::setMimeType(const QByteArray & mimeType) { d->mimeType = mimeType; } void KoDocument::setOutputMimeType(const QByteArray & mimeType, int specialOutputFlag) { d->outputMimeType = mimeType; d->specialOutputFlag = specialOutputFlag; } QByteArray KoDocument::outputMimeType() const { return d->outputMimeType; } int KoDocument::specialOutputFlag() const { return d->specialOutputFlag; } bool KoDocument::confirmNonNativeSave(const bool exporting) const { // "exporting ? 1 : 0" is different from "exporting" because a bool is // usually implemented like an "int", not "unsigned : 1" return d->confirmNonNativeSave [ exporting ? 1 : 0 ]; } void KoDocument::setConfirmNonNativeSave(const bool exporting, const bool on) { d->confirmNonNativeSave [ exporting ? 1 : 0] = on; } bool KoDocument::saveInBatchMode() const { if (d->filterManager) { return d->filterManager->getBatchMode(); } return true; } void KoDocument::setSaveInBatchMode(const bool batchMode) { if (!d->filterManager) { d->filterManager = new KoFilterManager(this, d->progressUpdater); } d->filterManager->setBatchMode(batchMode); } bool KoDocument::isImporting() const { return d->isImporting; } bool KoDocument::isExporting() const { return d->isExporting; } void KoDocument::setCheckAutoSaveFile(bool b) { d->shouldCheckAutoSaveFile = b; } void KoDocument::setAutoErrorHandlingEnabled(bool b) { d->autoErrorHandlingEnabled = b; } bool KoDocument::isAutoErrorHandlingEnabled() const { return d->autoErrorHandlingEnabled; } void KoDocument::slotAutoSave() { if (isModified() && d->modifiedAfterAutosave && !d->isLoading) { // Give a warning when trying to autosave an encrypted file when no password is known (should not happen) if (d->specialOutputFlag == SaveEncrypted && d->password.isNull()) { // That advice should also fix this error from occurring again emit statusBarMessage(i18n("The password of this encrypted document is not known. Autosave aborted! Please save your work manually.")); } else { connect(this, SIGNAL(sigProgress(int)), d->parentPart->currentShell(), SLOT(slotProgress(int))); emit statusBarMessage(i18n("Autosaving...")); d->autosaving = true; bool ret = saveNativeFormat(autoSaveFile(d->parentPart->localFilePath())); setModified(true); if (ret) { d->modifiedAfterAutosave = false; d->autoSaveTimer.stop(); // until the next change } d->autosaving = false; emit clearStatusBarMessage(); disconnect(this, SIGNAL(sigProgress(int)), d->parentPart->currentShell(), SLOT(slotProgress(int))); if (!ret) { emit statusBarMessage(i18n("Error during autosave! Partition full?")); } } } } void KoDocument::setReadWrite(bool readwrite) { d->parentPart->setReadWrite(readwrite); setAutoSave(d->autoSaveDelay); } void KoDocument::setAutoSave(int delay) { d->autoSaveDelay = delay; if (d->parentPart->isReadWrite() && d->autoSaveDelay > 0) d->autoSaveTimer.start(d->autoSaveDelay * 1000); else d->autoSaveTimer.stop(); } KoDocumentInfo *KoDocument::documentInfo() const { return d->docInfo; } KoDocumentRdfBase *KoDocument::documentRdf() const { #ifdef SHOULD_BUILD_RDF if (d->docRdf && d->docRdf->model()) { return d->docRdf; } #endif return 0; } void KoDocument::setDocumentRdf(KoDocumentRdf *rdfDocument) { delete d->docRdf; d->docRdf = 0; #ifdef SHOULD_BUILD_RDF if (rdfDocument->model()) { d->docRdf = rdfDocument; } #endif } KoDocumentRdfBase *KoDocument::documentRdfBase() const { return d->docRdf; } bool KoDocument::isModified() const { if (d->parentPart->isModified()) { //kDebug(30003)<<" Modified doc='"<specialOutputFlag == SaveAsDirectoryStore) { backend = KoStore::Directory; kDebug(30003) << "Saving as uncompressed XML, using directory store."; } #ifdef QCA2 else if (d->specialOutputFlag == SaveEncrypted) { backend = KoStore::Encrypted; kDebug(30003) << "Saving using encrypted backend."; } #endif else if (d->specialOutputFlag == SaveAsFlatXML) { kDebug(30003) << "Saving as a flat XML file."; QFile f(file); if (f.open(QIODevice::WriteOnly | QIODevice::Text)) { bool success = saveToStream(&f); f.close(); return success; } else return false; } kDebug(30003) << "KoDocument::saveNativeFormat nativeFormatMimeType=" << nativeFormatMimeType(); // OLD: bool oasis = d->specialOutputFlag == SaveAsOASIS; // OLD: QCString mimeType = oasis ? nativeOasisMimeType() : nativeFormatMimeType(); QByteArray mimeType = d->outputMimeType; kDebug(30003) << "KoDocument::savingTo mimeType=" << mimeType; QByteArray nativeOasisMime = nativeOasisMimeType(); bool oasis = !mimeType.isEmpty() && (mimeType == nativeOasisMime || mimeType == nativeOasisMime + "-template" || mimeType.startsWith("application/vnd.oasis.opendocument")); // TODO: use std::auto_ptr or create store on stack [needs API fixing], // to remove all the 'delete store' in all the branches KoStore *store = KoStore::createStore(file, KoStore::Write, mimeType, backend); if (d->specialOutputFlag == SaveEncrypted && !d->password.isNull()) store->setPassword(d->password); if (store->bad()) { d->lastErrorMessage = i18n("Could not create the file for saving"); // more details needed? delete store; return false; } if (oasis) { return saveNativeFormatODF(store, mimeType); } else { return saveNativeFormatCalligra(store); } } bool KoDocument::saveNativeFormatODF(KoStore *store, const QByteArray &mimeType) { kDebug(30003) << "Saving to OASIS format"; // Tell KoStore not to touch the file names store->disallowNameExpansion(); KoOdfWriteStore odfStore(store); KoXmlWriter *manifestWriter = odfStore.manifestWriter(mimeType); KoEmbeddedDocumentSaver embeddedSaver; SavingContext documentContext(odfStore, embeddedSaver); if (!saveOdf(documentContext)) { kDebug(30003) << "saveOdf failed"; odfStore.closeManifestWriter(false); delete store; return false; } // Save embedded objects if (!embeddedSaver.saveEmbeddedDocuments(documentContext)) { kDebug(30003) << "save embedded documents failed"; odfStore.closeManifestWriter(false); delete store; return false; } if (store->open("meta.xml")) { if (!d->docInfo->saveOasis(store) || !store->close()) { odfStore.closeManifestWriter(false); delete store; return false; } manifestWriter->addManifestEntry("meta.xml", "text/xml"); } else { d->lastErrorMessage = i18n("Not able to write '%1'. Partition full?", QString("meta.xml")); odfStore.closeManifestWriter(false); delete store; return false; } if (d->docRdf && !d->docRdf->saveOasis(store, manifestWriter)) { d->lastErrorMessage = i18n("Not able to write RDF metadata. Partition full?"); odfStore.closeManifestWriter(false); delete store; return false; } if (store->open("Thumbnails/thumbnail.png")) { if (!saveOasisPreview(store, manifestWriter) || !store->close()) { d->lastErrorMessage = i18n("Error while trying to write '%1'. Partition full?", QString("Thumbnails/thumbnail.png")); odfStore.closeManifestWriter(false); delete store; return false; } // No manifest entry! } else { d->lastErrorMessage = i18n("Not able to write '%1'. Partition full?", QString("Thumbnails/thumbnail.png")); odfStore.closeManifestWriter(false); delete store; return false; } if (!d->versionInfo.isEmpty()) { if (store->open("VersionList.xml")) { KoStoreDevice dev(store); KoXmlWriter *xmlWriter = KoOdfWriteStore::createOasisXmlWriter(&dev, "VL:version-list"); for (int i = 0; i < d->versionInfo.size(); ++i) { KoVersionInfo *version = &d->versionInfo[i]; xmlWriter->startElement("VL:version-entry"); xmlWriter->addAttribute("VL:title", version->title); xmlWriter->addAttribute("VL:comment", version->comment); xmlWriter->addAttribute("VL:creator", version->saved_by); xmlWriter->addAttribute("dc:date-time", version->date.toString(Qt::ISODate)); xmlWriter->endElement(); } xmlWriter->endElement(); // root element xmlWriter->endDocument(); delete xmlWriter; store->close(); manifestWriter->addManifestEntry("VersionList.xml", "text/xml"); for (int i = 0; i < d->versionInfo.size(); ++i) { KoVersionInfo *version = &d->versionInfo[i]; store->addDataToFile(version->data, "Versions/" + version->title); } } else { d->lastErrorMessage = i18n("Not able to write '%1'. Partition full?", QString("VersionList.xml")); odfStore.closeManifestWriter(false); delete store; return false; } } // Write out manifest file if (!odfStore.closeManifestWriter()) { d->lastErrorMessage = i18n("Error while trying to write '%1'. Partition full?", QString("META-INF/manifest.xml")); delete store; return false; } // Remember the given password, if necessary if (store->isEncrypted() && !d->isExporting) d->password = store->password(); delete store; return true; } bool KoDocument::saveNativeFormatCalligra(KoStore *store) { kDebug(30003) << "Saving root"; if (store->open("root")) { KoStoreDevice dev(store); if (!saveToStream(&dev) || !store->close()) { kDebug(30003) << "saveToStream failed"; delete store; return false; } } else { d->lastErrorMessage = i18n("Not able to write '%1'. Partition full?", QString("maindoc.xml")); delete store; return false; } if (store->open("documentinfo.xml")) { QDomDocument doc = d->docInfo->save(); KoStoreDevice dev(store); QByteArray s = doc.toByteArray(); // this is already Utf8! (void)dev.write(s.data(), s.size()); (void)store->close(); } if (store->open("preview.png")) { // ### TODO: missing error checking (The partition could be full!) savePreview(store); (void)store->close(); } if (!completeSaving(store)) { delete store; return false; } kDebug(30003) << "Saving done of url:" << d->parentPart->url().url(); if (!store->finalize()) { delete store; return false; } // Success delete store; return true; } bool KoDocument::saveToStream(QIODevice *dev) { QDomDocument doc = saveXML(); // Save to buffer QByteArray s = doc.toByteArray(); // utf8 already dev->open(QIODevice::WriteOnly); int nwritten = dev->write(s.data(), s.size()); if (nwritten != (int)s.size()) kWarning(30003) << "wrote " << nwritten << "- expected" << s.size(); return nwritten == (int)s.size(); } QString KoDocument::checkImageMimeTypes(const QString &mimeType, const KUrl &url) const { if (!url.isLocalFile()) return mimeType; QStringList imageMimeTypes; imageMimeTypes << "image/jpeg" << "image/x-psd" << "image/photoshop" << "image/x-photoshop" << "image/x-vnd.adobe.photoshop" << "image/vnd.adobe.photoshop" << "image/x-portable-pixmap" << "image/x-portable-graymap" << "image/x-portable-bitmap" << "application/pdf" << "image/x-exr" << "image/x-xcf" << "image/x-eps" << "image/png" << "image/bmp" << "image/x-xpixmap" << "image/gif" << "image/x-xbitmap" << "image/tiff" << "image/jp2"; if (!imageMimeTypes.contains(mimeType)) return mimeType; int accuracy = 0; QFile f(url.toLocalFile()); f.open(QIODevice::ReadOnly); QByteArray ba = f.read(qMin(f.size(), (qint64)512)); // should be enough for images KMimeType::Ptr mime = KMimeType::findByContent(ba, &accuracy); f.close(); return mime->name(); } // Called for embedded documents bool KoDocument::saveToStore(KoStore *_store, const QString & _path) { kDebug(30003) << "Saving document to store" << _path; // Use the path as the internal url if (_path.startsWith(STORE_PROTOCOL)) d->parentPart->setUrl(KUrl(_path)); else // ugly hack to pass a relative URI d->parentPart->setUrl(KUrl(INTERNAL_PREFIX + _path)); // In the current directory we're the king :-) if (_store->open("root")) { KoStoreDevice dev(_store); if (!saveToStream(&dev)) { _store->close(); return false; } if (!_store->close()) return false; } if (!completeSaving(_store)) return false; // Now that we're done leave the directory again _store->popDirectory(); kDebug(30003) << "Saved document to store"; return true; } bool KoDocument::saveOasisPreview(KoStore *store, KoXmlWriter *manifestWriter) { const QPixmap pix = generatePreview(QSize(128, 128)); if (pix.isNull()) return true; //no thumbnail to save, but the process succeeded QImage preview(pix.toImage().convertToFormat(QImage::Format_ARGB32, Qt::ColorOnly)); if (preview.isNull()) return false; //thumbnail to save, but the process failed // ### TODO: freedesktop.org Thumbnail specification (date...) KoStoreDevice io(store); if (!io.open(QIODevice::WriteOnly)) return false; if (! preview.save(&io, "PNG", 0)) return false; io.close(); manifestWriter->addManifestEntry("Thumbnails/thumbnail.png", "image/png"); return true; } bool KoDocument::savePreview(KoStore *store) { QPixmap pix = generatePreview(QSize(256, 256)); const QImage preview(pix.toImage().convertToFormat(QImage::Format_ARGB32, Qt::ColorOnly)); KoStoreDevice io(store); if (!io.open(QIODevice::WriteOnly)) return false; if (! preview.save(&io, "PNG")) // ### TODO What is -9 in quality terms? return false; io.close(); return true; } QPixmap KoDocument::generatePreview(const QSize& size) { qreal docWidth, docHeight; int pixmapSize = qMax(size.width(), size.height()); if (d->pageLayout.width > 1.0) { docWidth = d->pageLayout.width / 72 * KoDpi::dpiX(); docHeight = d->pageLayout.height / 72 * KoDpi::dpiY(); } else { // If we don't have a page layout, just draw the top left hand corner docWidth = 500.0; docHeight = 500.0; } qreal ratio = docWidth / docHeight; int previewWidth, previewHeight; if (ratio > 1.0) { previewWidth = (int) pixmapSize; previewHeight = (int)(pixmapSize / ratio); } else { previewWidth = (int)(pixmapSize * ratio); previewHeight = (int) pixmapSize; } QPixmap pix((int)docWidth, (int)docHeight); pix.fill(QColor(245, 245, 245)); QRect rc(0, 0, pix.width(), pix.height()); QPainter p; p.begin(&pix); paintContent(p, rc); p.end(); return pix.scaled(QSize(previewWidth, previewHeight), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } QString KoDocument::autoSaveFile(const QString & path) const { QString retval; // Using the extension allows to avoid relying on the mime magic when opening KMimeType::Ptr mime = KMimeType::mimeType(nativeFormatMimeType()); if (! mime) { qFatal("It seems your installation is broken/incomplete because we failed to load the native mimetype \"%s\".", nativeFormatMimeType().constData()); } QString extension = mime->property("X-KDE-NativeExtension").toString(); if (extension.isEmpty()) extension = mime->mainExtension(); if (path.isEmpty()) { // Never saved? Use a temp file in $HOME then. Mark it with the pid so two instances don't overwrite each other's autosave file retval = QString("%1/.%2-%3-%4-autosave%5").arg(QDir::homePath()).arg(d->parentPart->componentData().componentName()).arg(kapp->applicationPid()).arg(objectName()).arg(extension); } else { KUrl url = KUrl::fromPath(path); Q_ASSERT(url.isLocalFile()); QString dir = url.directory(KUrl::AppendTrailingSlash); QString filename = url.fileName(); retval = QString("%1.%2-autosave%3").arg(dir).arg(filename).arg(extension); } return retval; } bool KoDocument::importDocument(const KUrl & _url) { bool ret; kDebug(30003) << "url=" << _url.url(); d->isImporting = true; // open... ret = openUrl(_url); // reset url & m_file (kindly? set by KParts::openUrl()) to simulate a // File --> Import if (ret) { kDebug(30003) << "success, resetting url"; resetURL(); setTitleModified(); } d->isImporting = false; return ret; } // XXX going to go to KoPart... bool KoDocument::openUrl(const KUrl & _url) { kDebug(30003) << "url=" << _url.url(); d->lastErrorMessage.clear(); // Reimplemented, to add a check for autosave files and to improve error reporting if (!_url.isValid()) { d->lastErrorMessage = i18n("Malformed URL\n%1", _url.url()); // ## used anywhere ? return false; } // XXX //d->parentPart->abortLoad(); KUrl url(_url); bool autosaveOpened = false; d->isLoading = true; if (url.isLocalFile() && d->shouldCheckAutoSaveFile) { QString file = url.toLocalFile(); QString asf = autoSaveFile(file); if (QFile::exists(asf)) { //kDebug(30003) <<"asf=" << asf; // ## TODO compare timestamps ? int res = KMessageBox::warningYesNoCancel(0, i18n("An autosaved file exists for this document.\nDo you want to open it instead?")); switch (res) { case KMessageBox::Yes : url.setPath(asf); autosaveOpened = true; break; case KMessageBox::No : QFile::remove(asf); break; default: // Cancel d->isLoading = false; return false; } } } bool ret = d->parentPart->openUrl(url); if (autosaveOpened) { resetURL(); // Force save to act like 'Save As' setReadWrite(true); // enable save button QFile::remove(url.toLocalFile()); // and remove the autosave file } else { d->parentPart->addRecentURLToAllShells(_url); if (ret) { // Detect readonly local-files; remote files are assumed to be writable, unless we add a KIO::stat here (async). KFileItem file(url, mimeType(), KFileItem::Unknown); setReadWrite(file.isWritable()); } } return ret; } // It seems that people have started to save .docx files as .doc and // similar for xls and ppt. So let's make a small replacement table // here and see if we can open the files anyway. static struct MimetypeReplacement { const char *typeFromName; // If the mime type from the name is this... const char *typeFromContents; // ...and findByFileContents() reports this type... const char *useThisType; // ...then use this type for real. } replacementMimetypes[] = { // doc / docx { "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/vnd.openxmlformats-officedocument.wordprocessingml.document" }, { "application/msword", "application/zip", "application/vnd.openxmlformats-officedocument.wordprocessingml.document" }, { "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/msword", "application/msword" }, { "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/x-ole-storage", "application/msword" }, // xls / xlsx { "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }, { "application/vnd.ms-excel", "application/zip", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }, { "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.ms-excel", "application/vnd.ms-excel" }, { "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/x-ole-storage", "application/vnd.ms-excel" }, // ppt / pptx { "application/vnd.ms-powerpoint", "application/vnd.openxmlformats-officedocument.presentationml.presentation", "application/vnd.openxmlformats-officedocument.presentationml.presentation" }, { "application/vnd.ms-powerpoint", "application/zip", "application/vnd.openxmlformats-officedocument.presentationml.presentation" }, { "application/vnd.openxmlformats-officedocument.presentationml.presentation", "application/vnd.ms-powerpoint", "application/vnd.ms-powerpoint" }, { "application/vnd.openxmlformats-officedocument.presentationml.presentation", "application/x-ole-storage", "application/vnd.ms-powerpoint" } }; bool KoDocument::openFile() { //kDebug(30003) <<"for" << localFilePath(); if (!QFile::exists(d->parentPart->localFilePath())) { QApplication::restoreOverrideCursor(); if (d->autoErrorHandlingEnabled) // Maybe offer to create a new document with that name ? KMessageBox::error(0, i18n("The file %1 does not exist.", d->parentPart->localFilePath())); d->isLoading = false; return false; } QApplication::setOverrideCursor(Qt::WaitCursor); d->specialOutputFlag = 0; QByteArray _native_format = nativeFormatMimeType(); KUrl u(d->parentPart->localFilePath()); QString typeName = d->parentPart->arguments().mimeType(); if (typeName.isEmpty()) { typeName = KMimeType::findByUrl(u, 0, true)->name(); } // for images, always check content. typeName = checkImageMimeTypes(typeName, u); // Sometimes it seems that arguments().mimeType() contains a much // too generic mime type. In that case, let's try some educated // guesses based on what we know about file extension. // // FIXME: Should we just ignore this and always call // KMimeType::findByUrl()? David Faure says that it's // impossible for findByUrl() to fail to initiate the // mimetype for "*.doc" to application/msword. This hints // that we should do that. But why does it happen like // this at all? if (typeName == "application/zip") { QString filename = u.fileName(); // None of doc, xls or ppt are really zip files. But docx, // xlsx and pptx are. This miscategorization seems to only // crop up when there is a, say, docx file saved as doc. The // conversion to the docx mimetype will happen below. if (filename.endsWith(".doc")) typeName = "application/msword"; else if (filename.endsWith(".xls")) typeName = "application/vnd.ms-excel"; else if (filename.endsWith(".ppt")) typeName = "application/vnd.ms-powerpoint"; // Potentially more guesses here... } else if (typeName == "application/x-ole-storage") { QString filename = u.fileName(); // None of docx, xlsx or pptx are really OLE files. But doc, // xls and ppt are. This miscategorization seems to only crop // up when there is a, say, doc file saved as docx. The // conversion to the doc mimetype will happen below. if (filename.endsWith(".docx")) typeName = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; else if (filename.endsWith(".xlsx")) typeName = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; else if (filename.endsWith(".pptx")) typeName = "application/vnd.openxmlformats-officedocument.presentationml.presentation"; // Potentially more guesses here... } //kDebug(30003) << "mimetypes 3:" << typeName; // In some cases docx files are saved as doc and similar. We have // a small hardcoded table for those cases. Check if this is // applicable here. for (uint i = 0; i < sizeof(replacementMimetypes) / sizeof(struct MimetypeReplacement); ++i) { struct MimetypeReplacement *replacement = &replacementMimetypes[i]; if (typeName == replacement->typeFromName) { //kDebug(30003) << "found potential replacement target:" << typeName; int accuracy; QString typeFromContents = KMimeType::findByFileContent(u.path(), &accuracy)->name(); //kDebug(30003) << "found potential replacement:" << typeFromContents; if (typeFromContents == replacement->typeFromContents) { typeName = replacement->useThisType; //kDebug(30003) << "So really use this:" << typeName; break; } } } //kDebug(30003) << "mimetypes 4:" << typeName; // Allow to open backup files, don't keep the mimetype application/x-trash. if (typeName == "application/x-trash") { QString path = u.path(); KMimeType::Ptr mime = KMimeType::mimeType(typeName); const QStringList patterns = mime ? mime->patterns() : QStringList(); // Find the extension that makes it a backup file, and remove it for (QStringList::ConstIterator it = patterns.begin(); it != patterns.end(); ++it) { QString ext = *it; if (!ext.isEmpty() && ext[0] == '*') { ext.remove(0, 1); if (path.endsWith(ext)) { path.truncate(path.length() - ext.length()); break; } } } typeName = KMimeType::findByPath(path, 0, true)->name(); } // Special case for flat XML files (e.g. using directory store) if (u.fileName() == "maindoc.xml" || u.fileName() == "content.xml" || typeName == "inode/directory") { typeName = _native_format; // Hmm, what if it's from another app? ### Check mimetype d->specialOutputFlag = SaveAsDirectoryStore; kDebug(30003) << "loading" << u.fileName() << ", using directory store for" << d->parentPart->localFilePath() << "; typeName=" << typeName; } kDebug(30003) << d->parentPart->localFilePath() << "type:" << typeName; QString importedFile = d->parentPart->localFilePath(); // create the main progress monitoring object for loading, this can // contain subtasks for filtering and loading KoProgressProxy *progressProxy = 0; if (d->progressProxy) { progressProxy = d->progressProxy; } d->progressUpdater = new KoProgressUpdater(progressProxy, KoProgressUpdater::Unthreaded, d->profileStream); d->progressUpdater->setReferenceTime(d->profileReferenceTime); d->progressUpdater->start(); setupOpenFileSubProgress(); if (!isNativeFormat(typeName.toLatin1(), ForImport)) { if (!d->filterManager) d->filterManager = new KoFilterManager(this, d->progressUpdater); KoFilter::ConversionStatus status; importedFile = d->filterManager->importDocument(d->parentPart->localFilePath(), typeName, status); if (status != KoFilter::OK) { QApplication::restoreOverrideCursor(); QString msg; switch (status) { case KoFilter::OK: break; case KoFilter::FilterCreationError: msg = i18n("Could not create the filter plugin"); break; case KoFilter::CreationError: msg = i18n("Could not create the output document"); break; case KoFilter::FileNotFound: msg = i18n("File not found"); break; case KoFilter::StorageCreationError: msg = i18n("Cannot create storage"); break; case KoFilter::BadMimeType: msg = i18n("Bad MIME type"); break; case KoFilter::EmbeddedDocError: msg = i18n("Error in embedded document"); break; case KoFilter::WrongFormat: msg = i18n("Format not recognized"); break; case KoFilter::NotImplemented: msg = i18n("Not implemented"); break; case KoFilter::ParsingError: msg = i18n("Parsing error"); break; case KoFilter::PasswordProtected: msg = i18n("Document is password protected"); break; case KoFilter::InvalidFormat: msg = i18n("Invalid file format"); break; case KoFilter::InternalError: case KoFilter::UnexpectedEOF: case KoFilter::UnexpectedOpcode: case KoFilter::StupidError: // ?? what is this ?? case KoFilter::UsageError: msg = i18n("Internal error"); break; case KoFilter::OutOfMemory: msg = i18n("Out of memory"); break; case KoFilter::FilterEntryNull: msg = i18n("Empty Filter Plugin"); break; case KoFilter::NoDocumentCreated: msg = i18n("Trying to load into the wrong kind of document"); break; case KoFilter::DownloadFailed: msg = i18n("Failed to download remote file"); break; case KoFilter::UserCancelled: case KoFilter::BadConversionGraph: // intentionally we do not prompt the error message here break; default: msg = i18n("Unknown error"); break; } if (d->autoErrorHandlingEnabled && !msg.isEmpty()) { #ifndef Q_OS_WIN QString errorMsg(i18n("Could not open\n%2.\nReason: %1", msg, prettyPathOrUrl())); KMessageBox::error(0, errorMsg); #else QString errorMsg(i18n("Could not open\n%1.\nThe filter plugins have not been properly registered. Please reboot Windows. Krita Sketch will now close.", prettyPathOrUrl())); KMessageBox::error(0, errorMsg); #endif } d->isLoading = false; delete d->progressUpdater; d->progressUpdater = 0; return false; } d->isEmpty = false; kDebug(30003) << "importedFile" << importedFile << "status:" << static_cast(status); } QApplication::restoreOverrideCursor(); bool ok = true; if (!importedFile.isEmpty()) { // Something to load (tmp or native file) ? // The filter, if any, has been applied. It's all native format now. if (!loadNativeFormat(importedFile)) { ok = false; if (d->autoErrorHandlingEnabled) { d->parentPart->showLoadingErrorDialog(); } } } if (importedFile != d->parentPart->localFilePath()) { // We opened a temporary file (result of an import filter) // Set document URL to empty - we don't want to save in /tmp ! // But only if in readwrite mode (no saving problem otherwise) // -- // But this isn't true at all. If this is the result of an // import, then importedFile=temporary_file.kwd and // file/m_url=foreignformat.ext so m_url is correct! // So don't resetURL() or else the caption won't be set when // foreign files are opened (an annoying bug). // - Clarence // #if 0 if (isReadWrite()) resetURL(); #endif // remove temp file - uncomment this to debug import filters if (!importedFile.isEmpty()) { #ifndef NDEBUG if (!getenv("CALLIGRA_DEBUG_FILTERS")) #endif QFile::remove(importedFile); } } if (ok) { setMimeTypeAfterLoading(typeName); KNotification *notify = new KNotification("DocumentLoaded"); notify->setText(i18n("Document %1 loaded", d->parentPart->url().url())); notify->addContext("url", d->parentPart->url().url()); QTimer::singleShot(0, notify, SLOT(sendEvent())); d->parentPart->deleteOpenPane(); } if (progressUpdater()) { QPointer updater = progressUpdater()->startSubtask(1, "clear undo stack"); updater->setProgress(0); undoStack()->clear(); updater->setProgress(100); } delete d->progressUpdater; d->progressUpdater = 0; d->isLoading = false; return ok; } KoProgressUpdater *KoDocument::progressUpdater() const { return d->progressUpdater; } void KoDocument::setProgressProxy(KoProgressProxy *progressProxy) { d->progressProxy = progressProxy; } // shared between openFile and koMainWindow's "create new empty document" code void KoDocument::setMimeTypeAfterLoading(const QString& mimeType) { d->mimeType = mimeType.toLatin1(); d->outputMimeType = d->mimeType; const bool needConfirm = !isNativeFormat(d->mimeType, ForImport); setConfirmNonNativeSave(false, needConfirm); setConfirmNonNativeSave(true, needConfirm); } // The caller must call store->close() if loadAndParse returns true. bool KoDocument::oldLoadAndParse(KoStore *store, const QString& filename, KoXmlDocument& doc) { //kDebug(30003) <<"Trying to open" << filename; if (!store->open(filename)) { kWarning(30003) << "Entry " << filename << " not found!"; d->lastErrorMessage = i18n("Could not find %1", filename); return false; } // Error variables for QDomDocument::setContent QString errorMsg; int errorLine, errorColumn; bool ok = doc.setContent(store->device(), &errorMsg, &errorLine, &errorColumn); store->close(); if (!ok) { kError(30003) << "Parsing error in " << filename << "! Aborting!" << endl << " In line: " << errorLine << ", column: " << errorColumn << endl << " Error message: " << errorMsg << endl; d->lastErrorMessage = i18n("Parsing error in %1 at line %2, column %3\nError message: %4" , filename , errorLine, errorColumn , QCoreApplication::translate("QXml", errorMsg.toUtf8(), 0, QCoreApplication::UnicodeUTF8)); return false; } kDebug(30003) << "File" << filename << " loaded and parsed"; return true; } bool KoDocument::loadNativeFormat(const QString & file_) { QString file = file_; QFileInfo fileInfo(file); if (!fileInfo.exists()) { // check duplicated from openUrl, but this is useful for templates d->lastErrorMessage = i18n("The file %1 does not exist.", file); return false; } if (!fileInfo.isFile()) { file = file += "/content.xml"; QFileInfo fileInfo2(file); if (!fileInfo2.exists() || !fileInfo2.isFile()) { d->lastErrorMessage = i18n("%1 is not a file." , file_); return false; } } QApplication::setOverrideCursor(Qt::WaitCursor); kDebug(30003) << file; QFile in; bool isRawXML = false; if (d->specialOutputFlag != SaveAsDirectoryStore) { // Don't try to open a directory ;) in.setFileName(file); if (!in.open(QIODevice::ReadOnly)) { QApplication::restoreOverrideCursor(); d->lastErrorMessage = i18n("Could not open the file for reading (check read permissions)."); return false; } char buf[6]; buf[5] = 0; int pos = 0; do { if (in.read(buf + pos , 1) < 1) { QApplication::restoreOverrideCursor(); in.close(); d->lastErrorMessage = i18n("Could not read the beginning of the file."); return false; } if (QChar(buf[pos]).isSpace()) continue; pos++; } while (pos < 5); isRawXML = (strncasecmp(buf, "lastErrorMessage = i18n("parsing error in the main document at line %1, column %2\nError message: %3", errorLine, errorColumn, i18n(errorMsg.toUtf8())); res = false; } QApplication::restoreOverrideCursor(); in.close(); d->isEmpty = false; return res; } else { // It's a calligra store (tar.gz, zip, directory, etc.) in.close(); return loadNativeFormatFromStore(file); } } bool KoDocument::loadNativeFormatFromStore(const QString& file) { KoStore::Backend backend = (d->specialOutputFlag == SaveAsDirectoryStore) ? KoStore::Directory : KoStore::Auto; KoStore *store = KoStore::createStore(file, KoStore::Read, "", backend); if (store->bad()) { d->lastErrorMessage = i18n("Not a valid Calligra file: %1", file); delete store; QApplication::restoreOverrideCursor(); return false; } // Remember that the file was encrypted if (d->specialOutputFlag == 0 && store->isEncrypted() && !d->isImporting) d->specialOutputFlag = SaveEncrypted; const bool success = loadNativeFormatFromStoreInternal(store); // Retrieve the password after loading the file, only then is it guaranteed to exist if (success && store->isEncrypted() && !d->isImporting) d->password = store->password(); delete store; return success; } bool KoDocument::loadNativeFormatFromStore(QByteArray &data) { bool succes; KoStore::Backend backend = (d->specialOutputFlag == SaveAsDirectoryStore) ? KoStore::Directory : KoStore::Auto; QBuffer buffer(&data); KoStore *store = KoStore::createStore(&buffer, KoStore::Read, "", backend); if (store->bad()) { delete store; return false; } // Remember that the file was encrypted if (d->specialOutputFlag == 0 && store->isEncrypted() && !d->isImporting) d->specialOutputFlag = SaveEncrypted; succes = loadNativeFormatFromStoreInternal(store); // Retrieve the password after loading the file, only then is it guaranteed to exist if (succes && store->isEncrypted() && !d->isImporting) d->password = store->password(); delete store; return succes; } bool KoDocument::loadNativeFormatFromStoreInternal(KoStore *store) { bool oasis = true; if (oasis && store->hasFile("manifest.rdf") && d->docRdf) { d->docRdf->loadOasis(store); } // OASIS/OOo file format? if (store->hasFile("content.xml")) { store->disallowNameExpansion(); // We could check the 'mimetype' file, but let's skip that and be tolerant. if (!loadOasisFromStore(store)) { QApplication::restoreOverrideCursor(); return false; } } else if (store->hasFile("root")) { // Fallback to "old" file format (maindoc.xml) oasis = false; KoXmlDocument doc = KoXmlDocument(true); bool ok = oldLoadAndParse(store, "root", doc); if (ok) ok = loadXML(doc, store); if (!ok) { QApplication::restoreOverrideCursor(); return false; } } else { kError(30003) << "ERROR: No maindoc.xml" << endl; d->lastErrorMessage = i18n("Invalid document: no file 'maindoc.xml'."); QApplication::restoreOverrideCursor(); return false; } if (oasis && store->hasFile("meta.xml")) { KoXmlDocument metaDoc; KoOdfReadStore oasisStore(store); if (oasisStore.loadAndParse("meta.xml", metaDoc, d->lastErrorMessage)) { d->docInfo->loadOasis(metaDoc); } } else if (!oasis && store->hasFile("documentinfo.xml")) { KoXmlDocument doc = KoXmlDocument(true); if (oldLoadAndParse(store, "documentinfo.xml", doc)) { d->docInfo->load(doc); } } else { //kDebug( 30003 ) <<"cannot open document info"; delete d->docInfo; d->docInfo = new KoDocumentInfo(this); } if (oasis && store->hasFile("VersionList.xml")) { KNotification *notify = new KNotification("DocumentHasVersions"); notify->setText(i18n("Document %1 contains several versions. Go to File->Versions to open an old version.", store->urlOfStore().url())); notify->addContext("url", store->urlOfStore().url()); QTimer::singleShot(0, notify, SLOT(sendEvent())); KoXmlDocument versionInfo; KoOdfReadStore oasisStore(store); if (oasisStore.loadAndParse("VersionList.xml", versionInfo, d->lastErrorMessage)) { KoXmlNode list = KoXml::namedItemNS(versionInfo, KoXmlNS::VL, "version-list"); KoXmlElement e; forEachElement(e, list) { if (e.localName() == "version-entry" && e.namespaceURI() == KoXmlNS::VL) { KoVersionInfo version; version.comment = e.attribute("comment"); version.title = e.attribute("title"); version.saved_by = e.attribute("creator"); version.date = QDateTime::fromString(e.attribute("date-time"), Qt::ISODate); store->extractFile("Versions/" + version.title, version.data); d->versionInfo.append(version); } } } } bool res = completeLoading(store); QApplication::restoreOverrideCursor(); d->isEmpty = false; return res; } // For embedded documents bool KoDocument::loadFromStore(KoStore *_store, const QString& url) { if (_store->open(url)) { KoXmlDocument doc = KoXmlDocument(true); doc.setContent(_store->device()); if (!loadXML(doc, _store)) { _store->close(); return false; } _store->close(); } else { kWarning() << "couldn't open " << url; } _store->pushDirectory(); // Store as document URL if (url.startsWith(STORE_PROTOCOL)) { d->parentPart->setUrl(url); } else { d->parentPart->setUrl(KUrl(INTERNAL_PREFIX + url)); _store->enterDirectory(url); } bool result = completeLoading(_store); // Restore the "old" path _store->popDirectory(); return result; } bool KoDocument::loadOasisFromStore(KoStore *store) { KoOdfReadStore odfStore(store); if (! odfStore.loadAndParse(d->lastErrorMessage)) { return false; } return loadOdf(odfStore); } bool KoDocument::addVersion(const QString& comment) { kDebug(30003) << "Saving the new version...."; KoStore::Backend backend = KoStore::Auto; if (d->specialOutputFlag != 0) return false; QByteArray mimeType = d->outputMimeType; QByteArray nativeOasisMime = nativeOasisMimeType(); bool oasis = !mimeType.isEmpty() && (mimeType == nativeOasisMime || mimeType == nativeOasisMime + "-template"); if (!oasis) return false; // TODO: use std::auto_ptr or create store on stack [needs API fixing], // to remove all the 'delete store' in all the branches QByteArray data; QBuffer buffer(&data); KoStore *store = KoStore::createStore(&buffer/*file*/, KoStore::Write, mimeType, backend); if (store->bad()) { delete store; return false; } kDebug(30003) << "Saving to OASIS format"; // Tell KoStore not to touch the file names store->disallowNameExpansion(); KoOdfWriteStore odfStore(store); KoXmlWriter *manifestWriter = odfStore.manifestWriter(mimeType); Q_UNUSED(manifestWriter); // XXX why? KoEmbeddedDocumentSaver embeddedSaver; SavingContext documentContext(odfStore, embeddedSaver); if (!saveOdf(documentContext)) { kDebug(30003) << "saveOdf failed"; delete store; return false; } // Save embedded objects if (!embeddedSaver.saveEmbeddedDocuments(documentContext)) { kDebug(30003) << "save embedded documents failed"; delete store; return false; } // Write out manifest file if (!odfStore.closeManifestWriter()) { d->lastErrorMessage = i18n("Error while trying to write '%1'. Partition full?", QString("META-INF/manifest.xml")); delete store; return false; } if (!store->finalize()) { delete store; return false; } delete store; KoVersionInfo version; version.comment = comment; version.title = "Version" + QString::number(d->versionInfo.count() + 1); version.saved_by = documentInfo()->authorInfo("creator"); version.date = QDateTime::currentDateTime(); version.data = data; d->versionInfo.append(version); d->parentPart->save(); //finally save the document + the new version return true; } bool KoDocument::isStoredExtern() const { return !storeInternal() && hasExternURL(); } void KoDocument::setModified(bool mod) { if (isAutosaving()) // ignore setModified calls due to autosaving return; //kDebug(30003)<<" url:" << url.path(); //kDebug(30003)<<" mod="<parentPart->url().fileName(); if (name.isEmpty()) name = i18n("Untitled"); int res = KMessageBox::warningYesNoCancel(0, i18n("

The document '%1' has been modified.

Do you want to save it?

", name)); switch (res) { case KMessageBox::Yes : d->parentPart->save(); // NOTE: External files always in native format. ###TODO: Handle non-native format setModified(false); // Now when queryClose() is called by closeEvent it won't do anything. break; case KMessageBox::No : removeAutoSaveFiles(); setModified(false); // Now when queryClose() is called by closeEvent it won't do anything. break; default : // case KMessageBox::Cancel : return res; // cancels the rest of the files } return res; } QString KoDocument::prettyPathOrUrl() const { QString url( d->parentPart->url().pathOrUrl() ); #ifdef Q_WS_WIN if (d->parentPart->url().isLocalFile()) { url = QDir::convertSeparators(url); } #endif return url; } // Get caption from document info (title(), in about page) QString KoDocument::caption() const { QString c; if (documentInfo()) { c = documentInfo()->aboutInfo("title"); } const QString url(d->parentPart->url().fileName()); if (!c.isEmpty() && !url.isEmpty()) { c = QString("%1 - %2").arg(c).arg(url); } else if (c.isEmpty()) { c = url; // Fall back to document URL } return c; } void KoDocument::setTitleModified() { emit titleModified(caption(), isModified()); } bool KoDocument::completeLoading(KoStore*) { return true; } bool KoDocument::completeSaving(KoStore*) { return true; } QDomDocument KoDocument::createDomDocument(const QString& tagName, const QString& version) const { return createDomDocument(d->parentPart->componentData().componentName(), tagName, version); } //static QDomDocument KoDocument::createDomDocument(const QString& appName, const QString& tagName, const QString& version) { QDomImplementation impl; QString url = QString("http://www.calligra.org/DTD/%1-%2.dtd").arg(appName).arg(version); QDomDocumentType dtype = impl.createDocumentType(tagName, QString("-//KDE//DTD %1 %2//EN").arg(appName).arg(version), url); // The namespace URN doesn't need to include the version number. QString namespaceURN = QString("http://www.calligra.org/DTD/%1").arg(appName); QDomDocument doc = impl.createDocument(namespaceURN, tagName, dtype); doc.insertBefore(doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""), doc.documentElement()); return doc; } QDomDocument KoDocument::saveXML() { kError(30003) << "not implemented" << endl; d->lastErrorMessage = i18n("Internal error: saveXML not implemented"); return QDomDocument(); } KService::Ptr KoDocument::nativeService() { if (!d->nativeService) d->nativeService = KoServiceProvider::readNativeService(d->parentPart->componentData()); return d->nativeService; } QByteArray KoDocument::nativeFormatMimeType() const { KService::Ptr service = const_cast(this)->nativeService(); if (!service) { kWarning(30003) << "No native service defined to read NativeMimeType from desktop file!"; return QByteArray(); } QByteArray nativeMimeType = service->property("X-KDE-NativeMimeType").toString().toLatin1(); #ifndef NDEBUG if (nativeMimeType.isEmpty()) { // shouldn't happen, let's find out why it happened if (!service->serviceTypes().contains("CalligraPart")) kWarning(30003) << "Wrong desktop file, CalligraPart isn't mentioned"; else if (!KServiceType::serviceType("CalligraPart")) kWarning(30003) << "The CalligraPart service type isn't installed!"; else kWarning(30003) << "Failed to read NativeMimeType from desktop file!"; } #endif return nativeMimeType; } QByteArray KoDocument::nativeOasisMimeType() const { KService::Ptr service = const_cast(this)->nativeService(); if (!service) { return KoDocument::nativeFormatMimeType(); } return service->property("X-KDE-NativeOasisMimeType").toString().toLatin1(); } bool KoDocument::isNativeFormat(const QByteArray& mimetype, ImportExportType importExportType) const { if (mimetype == nativeFormatMimeType()) return true; return extraNativeMimeTypes(importExportType).contains(mimetype); } QStringList KoDocument::extraNativeMimeTypes(KoDocument::ImportExportType importExportType) const { Q_UNUSED(importExportType); QStringList lst; // This implementation is temporary while we treat both calligra-1.3 and OASIS formats as native. // But it's good to have this virtual method, in case some app want to // support more than one native format. KService::Ptr service = const_cast(this)->nativeService(); if (!service) // can't happen return lst; return service->property("X-KDE-ExtraNativeMimeTypes").toStringList(); } int KoDocument::supportedSpecialFormats() const { // Apps which support special output flags can add reimplement and add to this. // E.g. this is how did "saving in the 1.1 format". // SaveAsDirectoryStore is a given since it's implemented by KoDocument itself. // SaveEncrypted is implemented in KoDocument as well, if QCA2 was found. #ifdef QCA2 return SaveAsDirectoryStore | SaveEncrypted; #else return SaveAsDirectoryStore; #endif } void KoDocument::setErrorMessage(const QString& errMsg) { d->lastErrorMessage = errMsg; } QString KoDocument::errorMessage() const { return d->lastErrorMessage; } bool KoDocument::isAutosaving() const { return d->autosaving; } bool KoDocument::isLoading() const { return d->isLoading; } void KoDocument::removeAutoSaveFiles() { // Eliminate any auto-save file QString asf = autoSaveFile(d->parentPart->localFilePath()); // the one in the current dir if (QFile::exists(asf)) QFile::remove(asf); asf = autoSaveFile(QString()); // and the one in $HOME if (QFile::exists(asf)) QFile::remove(asf); } void KoDocument::setBackupFile(bool _b) { d->backupFile = _b; } bool KoDocument::backupFile()const { return d->backupFile; } void KoDocument::setBackupPath(const QString & _path) { d->backupPath = _path; } QString KoDocument::backupPath()const { return d->backupPath; } bool KoDocument::storeInternal() const { return d->storeInternal; } void KoDocument::setStoreInternal(bool i) { d->storeInternal = i; //kDebug(30003)<<"="<storeInternal<<" doc:"<parentPart->url().protocol().isEmpty() && d->parentPart->url().protocol() != STORE_PROTOCOL && d->parentPart->url().protocol() != INTERNAL_PROTOCOL; } static const struct { const char *localName; const char *documentType; } TN2DTArray[] = { { "text", I18N_NOOP("a word processing") }, { "spreadsheet", I18N_NOOP("a spreadsheet") }, { "presentation", I18N_NOOP("a presentation") }, { "chart", I18N_NOOP("a chart") }, { "drawing", I18N_NOOP("a drawing") } }; static const unsigned int numTN2DT = sizeof(TN2DTArray) / sizeof(*TN2DTArray); QString KoDocument::tagNameToDocumentType(const QString& localName) { for (unsigned int i = 0 ; i < numTN2DT ; ++i) if (localName == TN2DTArray[i].localName) return i18n(TN2DTArray[i].documentType); return localName; } KoPageLayout KoDocument::pageLayout(int /*pageNumber*/) const { return d->pageLayout; } void KoDocument::setPageLayout(const KoPageLayout &pageLayout) { d->pageLayout = pageLayout; } KoUnit KoDocument::unit() const { return d->unit; } void KoDocument::setUnit(const KoUnit &unit) { if (d->unit != unit) { d->unit = unit; emit unitChanged(unit); } } void KoDocument::saveUnitOdf(KoXmlWriter *settingsWriter) const { settingsWriter->addConfigItem("unit", unit().symbol()); } void KoDocument::initEmpty() { setEmpty(); setModified(false); } QList & KoDocument::versionList() { return d->versionInfo; } KUndo2Stack *KoDocument::undoStack() { return d->undoStack; } void KoDocument::addCommand(KUndo2Command *command) { if (command) d->undoStack->push(command); } void KoDocument::beginMacro(const QString & text) { d->undoStack->beginMacro(text); } void KoDocument::endMacro() { d->undoStack->endMacro(); } void KoDocument::slotUndoStackIndexChanged(int idx) { // even if the document was already modified, call setModified to re-start autosave timer setModified(idx != d->undoStack->cleanIndex()); } void KoDocument::setProfileStream(QTextStream *profilestream) { d->profileStream = profilestream; } void KoDocument::setProfileReferenceTime(const QTime& referenceTime) { d->profileReferenceTime = referenceTime; } void KoDocument::clearUndoHistory() { d->undoStack->clear(); } KoGridData &KoDocument::gridData() { return d->gridData; } KoGuidesData &KoDocument::guidesData() { return d->guidesData; } bool KoDocument::isEmpty() const { return d->isEmpty; } void KoDocument::setEmpty() { d->isEmpty = true; } // static int KoDocument::defaultAutoSave() { return 300; } void KoDocument::resetURL() { d->parentPart->setUrl(KUrl()); d->parentPart->setLocalFilePath(QString()); } int KoDocument::pageCount() const { return 1; } void KoDocument::setupOpenFileSubProgress() {} void KoDocument::setModified() { d->parentPart->setModified(); } QString KoDocument::localFilePath() const { return d->parentPart->localFilePath(); } KUrl KoDocument::url() const { return d->parentPart->url(); } void KoDocument::setUrl(const KUrl& url) { d->parentPart->setUrl(url); } #include diff --git a/libs/main/KoFindText.cpp b/libs/main/KoFindText.cpp index 449f1574af9..f193a3ce62c 100644 --- a/libs/main/KoFindText.cpp +++ b/libs/main/KoFindText.cpp @@ -1,355 +1,355 @@ /* This file is part of the KDE project * * Copyright (c) 2010 Arjen Hiemstra * Copyright (C) 2011 Thorsten Zachmann * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KoFindText.h" #include #include #include #include #include #include #include #include -#include -#include +#include +#include #include #include #include #include #include #include "KoFindOptionSet.h" #include "KoFindOption.h" #include "KoDocument.h" class KoFindText::Private { public: Private(KoFindText* qq) : q(qq), selectionStart(-1), selectionEnd(-1) { } void updateSelections(); void updateDocumentList(); void documentDestroyed(QObject *document); void updateCurrentMatch(int position); static void initializeFormats(); KoFindText *q; QList documents; QTextCursor currentCursor; QTextCursor selection; QHash > selections; int selectionStart; int selectionEnd; static QTextCharFormat highlightFormat; static QTextCharFormat currentMatchFormat; static QTextCharFormat currentSelectionFormat; static QTextCharFormat replacedFormat; static bool formatsInitialized; QPair currentMatch; }; QTextCharFormat KoFindText::Private::highlightFormat; QTextCharFormat KoFindText::Private::currentMatchFormat; QTextCharFormat KoFindText::Private::currentSelectionFormat; QTextCharFormat KoFindText::Private::replacedFormat; bool KoFindText::Private::formatsInitialized = false; KoFindText::KoFindText(QObject* parent) : KoFindBase(parent), d(new Private(this)) { d->initializeFormats(); KoFindOptionSet *options = new KoFindOptionSet(); options->addOption("caseSensitive", i18n("Case Sensitive"), i18n("Match cases when searching"), QVariant::fromValue(false)); options->addOption("wholeWords", i18n("Whole Words Only"), i18n("Match only whole words"), QVariant::fromValue(false)); options->addOption("fromCursor", i18n("Find from Cursor"), i18n("Start searching from the current cursor"), QVariant::fromValue(true)); setOptions(options); } KoFindText::~KoFindText() { delete d; } void KoFindText::findImplementation(const QString &pattern, QList & matchList) { KoFindOptionSet *opts = options(); QTextDocument::FindFlags flags = 0; if(opts->option("caseSensitive")->value().toBool()) { flags |= QTextDocument::FindCaseSensitively; } if(opts->option("wholeWords")->value().toBool()) { flags |= QTextDocument::FindWholeWords; } int start = 0; bool findInSelection = false; if(d->documents.size() == 0) { kWarning() << "No document available for searching!"; return; } bool before = opts->option("fromCursor")->value().toBool() && !d->currentCursor.isNull(); QList matchBefore; foreach(QTextDocument* document, d->documents) { QTextCursor cursor = document->find(pattern, start, flags); QVector selections; while(!cursor.isNull()) { if(findInSelection && d->selectionEnd <= cursor.position()) { break; } if (before && document == d->currentCursor.document() && d->currentCursor < cursor) { before = false; } QAbstractTextDocumentLayout::Selection selection; selection.cursor = cursor; selection.format = d->highlightFormat; selections.append(selection); KoFindMatch match; match.setContainer(QVariant::fromValue(document)); match.setLocation(QVariant::fromValue(cursor)); if (before) { matchBefore.append(match); } else { matchList.append(match); } cursor = document->find(pattern, cursor, flags); } if (before && document == d->currentCursor.document()) { before = false; } d->selections.insert(document, selections); } matchList.append(matchBefore); if (hasMatches()) { setCurrentMatch(0); d->updateCurrentMatch(0); } d->updateSelections(); } void KoFindText::replaceImplementation(const KoFindMatch &match, const QVariant &value) { if (!match.isValid() || !match.location().canConvert() || !match.container().canConvert()) { return; } QTextCursor cursor = match.location().value(); //Search for the selection matching this match. QVector selections = d->selections.value(match.container().value()); int index = 0; foreach(const QAbstractTextDocumentLayout::Selection &sel, selections) { if(sel.cursor == cursor) { break; } index++; } cursor.insertText(value.toString()); cursor.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, value.toString().length()); selections[index].cursor = cursor; selections[index].format = d->replacedFormat; d->selections.insert(match.container().value(), selections); d->updateCurrentMatch(0); d->updateSelections(); } void KoFindText::clearMatches() { d->selections.clear(); foreach(QTextDocument* doc, d->documents) { d->selections.insert(doc, QVector()); } d->updateSelections(); d->selectionStart = -1; d->selectionEnd = -1; setCurrentMatch(0); d->currentMatch.first = 0; } QList< QTextDocument* > KoFindText::documents() const { return d->documents; } void KoFindText::findNext() { if(d->selections.size() == 0) { return; } KoFindBase::findNext(); d->updateCurrentMatch(currentMatchIndex()); d->updateSelections(); } void KoFindText::findPrevious() { if(d->selections.size() == 0) { return; } KoFindBase::findPrevious(); d->updateCurrentMatch(currentMatchIndex()); d->updateSelections(); } void KoFindText::setCurrentCursor(const QTextCursor &cursor) { d->currentCursor = cursor; } void KoFindText::setDocuments(const QList &documents) { clearMatches(); d->documents = documents; d->updateDocumentList(); } void KoFindText::findTextInShapes(const QList &shapes, QList &append) { foreach(KoShape* shape, shapes) { KoShapeContainer *container = dynamic_cast(shape); if(container) { findTextInShapes(container->shapes(), append); } KoTextShapeData *shapeData = dynamic_cast(shape->userData()); if (!shapeData) continue; if(shapeData->document()) { if(!append.contains(shapeData->document())) { append.append(shapeData->document()); } } } } void KoFindText::Private::updateSelections() { QHash< QTextDocument*, QVector >::iterator itr; for(itr = selections.begin(); itr != selections.end(); ++itr) { KoTextDocument doc(itr.key()); doc.setSelections(itr.value()); } } void KoFindText::Private::updateDocumentList() { foreach(QTextDocument *document, documents) { connect(document, SIGNAL(destroyed(QObject*)), q, SLOT(documentDestroyed(QObject*)), Qt::UniqueConnection); } } void KoFindText::Private::documentDestroyed(QObject *document) { QTextDocument* doc = qobject_cast(document); if(doc) { selections.remove(doc); documents.removeOne(doc); } } void KoFindText::Private::updateCurrentMatch(int position) { Q_UNUSED(position); if (currentMatch.first != 0) { QVector sel = selections.value(currentMatch.first); Q_ASSERT(currentMatch.second < sel.count()); if(sel[currentMatch.second].format == currentMatchFormat) { sel[currentMatch.second].format = highlightFormat; } selections.insert(currentMatch.first, sel); } const KoFindMatch match = q->currentMatch(); if (match.isValid() && match.location().canConvert() && match.container().canConvert()) { QTextCursor cursor = match.location().value(); QTextDocument *document = match.container().value(); QVector sel = selections.value(document); for (int i = 0; i < sel.size(); ++i) { if (sel[i].cursor == cursor) { sel[i].format = currentMatchFormat; selections.insert(document, sel); currentMatch.first = document; currentMatch.second = i; break; } } } } void KoFindText::Private::initializeFormats() { if (!formatsInitialized) { highlightFormat.setBackground(Qt::yellow); currentMatchFormat.setBackground(qApp->palette().highlight()); currentMatchFormat.setForeground(qApp->palette().highlightedText()); currentSelectionFormat.setBackground(qApp->palette().alternateBase()); replacedFormat.setBackground(Qt::green); formatsInitialized = true; } } void KoFindText::setFormat(FormatType formatType, const QTextCharFormat &format) { KoFindText::Private::initializeFormats(); switch (formatType) { case HighlightFormat: KoFindText::Private::highlightFormat = format; break; case CurrentMatchFormat: KoFindText::Private::currentMatchFormat = format; break; case SelectionFormat: KoFindText::Private::currentSelectionFormat = format; break; case ReplacedFormat: KoFindText::Private::replacedFormat = format; break; } } #include "KoFindText.moc" diff --git a/libs/main/KoFindToolbar.cpp b/libs/main/KoFindToolbar.cpp index 14490ab55da..c4b8edb937c 100644 --- a/libs/main/KoFindToolbar.cpp +++ b/libs/main/KoFindToolbar.cpp @@ -1,317 +1,317 @@ /* This file is part of the KDE project * * Copyright (c) 2010 Arjen Hiemstra * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KoFindToolbar.h" #include #include #include #include #include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include "KoFindBase.h" #include "KoFindOptionSet.h" #include "KoFindOption.h" class KoFindToolbar::Private { public: Private(KoFindToolbar *qq) : q(qq) { } void matchFound(); void noMatchFound(); void searchWrapped(bool direction); void addToHistory(); void find(const QString &pattern); void optionChanged(); void replace(); void replaceAll(); void inputTimeout(); KoFindToolbar *q; KoFindBase *finder; QToolButton *closeButton; KHistoryComboBox *searchLine; KHistoryComboBox *replaceLine; QToolButton *previousButton; QToolButton *nextButton; QToolButton *optionsButton; QToolButton *replaceButton; QToolButton *replaceAllButton; QLabel *replaceLabel; KSqueezedTextLabel *information; QLabel *matchCounter; QTimer *textTimeout; static QStringList searchCompletionItems; static QStringList replaceCompletionItems; }; QStringList KoFindToolbar::Private::searchCompletionItems = QStringList(); QStringList KoFindToolbar::Private::replaceCompletionItems = QStringList(); KoFindToolbar::KoFindToolbar(KoFindBase *finder, KActionCollection *ac, QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f), d(new Private(this)) { QGridLayout *layout = new QGridLayout(); d->finder = finder; connect(d->finder, SIGNAL(matchFound(KoFindMatch)), this, SLOT(matchFound())); connect(d->finder, SIGNAL(noMatchFound()), this, SLOT(noMatchFound())); connect(d->finder, SIGNAL(wrapAround(bool)), this, SLOT(searchWrapped(bool))); d->textTimeout = new QTimer(this); d->textTimeout->setInterval(1000); d->textTimeout->setSingleShot(true); connect(d->textTimeout, SIGNAL(timeout()), this, SLOT(inputTimeout())); d->closeButton = new QToolButton(this); d->closeButton->setAutoRaise(true); d->closeButton->setIcon(koIcon("dialog-close")); d->closeButton->setShortcut(QKeySequence(Qt::Key_Escape)); connect(d->closeButton, SIGNAL(clicked(bool)), this, SLOT(hide())); connect(d->closeButton, SIGNAL(clicked(bool)), d->finder, SLOT(finished())); connect(d->closeButton, SIGNAL(clicked()), d->textTimeout, SLOT(stop())); layout->addWidget(d->closeButton, 0, 0); layout->addWidget(new QLabel(i18nc("Label for the Find text input box", "Find:"), this), 0, 1, Qt::AlignRight); d->searchLine = new KHistoryComboBox(true, this); d->searchLine->setCompletedItems(d->searchCompletionItems); d->searchLine->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); connect(d->searchLine, SIGNAL(editTextChanged(QString)), d->textTimeout, SLOT(start())); connect(d->searchLine, SIGNAL(returnPressed()), d->finder, SLOT(findNext())); connect(d->searchLine, SIGNAL(returnPressed(QString)), d->searchLine, SLOT(addToHistory(QString))); connect(d->searchLine, SIGNAL(cleared()), finder, SLOT(finished())); layout->addWidget(d->searchLine, 0, 2); d->nextButton = new QToolButton(this); d->nextButton->setIcon(koIcon("go-down-search")); d->nextButton->setText(i18nc("Next search result", "Next")); d->nextButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); d->nextButton->setEnabled(false); connect(d->nextButton, SIGNAL(clicked(bool)), d->finder, SLOT(findNext())); connect(d->nextButton, SIGNAL(clicked(bool)), this, SLOT(addToHistory())); connect(d->finder, SIGNAL(hasMatchesChanged(bool)), d->nextButton, SLOT(setEnabled(bool))); layout->addWidget(d->nextButton, 0, 3); d->previousButton = new QToolButton(this); d->previousButton->setIcon(koIcon("go-up-search")); d->previousButton->setText(i18nc("Previous search result", "Previous")); d->previousButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); d->previousButton->setEnabled(false); connect(d->previousButton, SIGNAL(clicked(bool)), d->finder, SLOT(findPrevious())); connect(d->previousButton, SIGNAL(clicked(bool)), this, SLOT(addToHistory())); connect(d->finder, SIGNAL(hasMatchesChanged(bool)), d->previousButton, SLOT(setEnabled(bool))); layout->addWidget(d->previousButton, 0, 4); d->optionsButton = new QToolButton(this); d->optionsButton->setText(i18nc("Search options", "Options")); QMenu *menu = new QMenu(d->optionsButton); QList options = finder->options()->options(); foreach(KoFindOption * option, options) { if(option->value().type() == QVariant::Bool) { KAction *action = new KAction(option->title(), menu); action->setHelpText(option->description()); action->setObjectName(option->name()); action->setCheckable(true); action->setChecked(option->value().toBool()); connect(action, SIGNAL(triggered(bool)), this, SLOT(optionChanged())); menu->addAction(action); } } d->optionsButton->setMenu(menu); d->optionsButton->setPopupMode(QToolButton::InstantPopup); if(menu->actions().count() == 0) { d->optionsButton->setEnabled(false); } layout->addWidget(d->optionsButton, 0, 5); d->information = new KSqueezedTextLabel(this); layout->addWidget(d->information, 0, 6); d->replaceLabel = new QLabel(i18nc("Label for the Replace text input box", "Replace:"), this); layout->addWidget(d->replaceLabel, 1, 1, Qt::AlignRight); d->replaceLine = new KHistoryComboBox(true, this); d->replaceLine->setHistoryItems(d->replaceCompletionItems); d->replaceLine->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); connect(d->replaceLine, SIGNAL(returnPressed()), this, SLOT(replace())); layout->addWidget(d->replaceLine, 1, 2); d->replaceButton = new QToolButton(this); d->replaceButton->setText(i18nc("Replace the current match", "Replace")); d->replaceButton->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); connect(d->replaceButton, SIGNAL(clicked(bool)), this, SLOT(replace())); layout->addWidget(d->replaceButton, 1, 3); d->replaceAllButton = new QToolButton(this); d->replaceAllButton->setText(i18nc("Replace all found matches", "Replace All")); d->replaceAllButton->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); connect(d->replaceAllButton, SIGNAL(clicked(bool)), this, SLOT(replaceAll())); layout->addWidget(d->replaceAllButton, 1, 4); setLayout(layout); ac->addAction(KStandardAction::Find, "edit_find", this, SLOT(activateSearch())); ac->addAction(KStandardAction::Replace, "edit_replace", this, SLOT(activateReplace())); KAction *findNextAction = ac->addAction(KStandardAction::FindNext, "edit_findnext", d->nextButton, SIGNAL(clicked(bool))); connect(finder, SIGNAL(hasMatchesChanged(bool)), findNextAction, SLOT(setEnabled(bool))); connect(findNextAction, SIGNAL(triggered(bool)), this, SLOT(activateSearch())); findNextAction->setEnabled(false); KAction *findPrevAction = ac->addAction(KStandardAction::FindPrev, "edit_findprevious", d->previousButton, SIGNAL(clicked(bool))); connect(finder, SIGNAL(hasMatchesChanged(bool)), findPrevAction, SLOT(setEnabled(bool))); connect(findPrevAction, SIGNAL(triggered(bool)), this, SLOT(activateSearch())); findPrevAction->setEnabled(false); } KoFindToolbar::~KoFindToolbar() { delete d; } void KoFindToolbar::activateSearch() { d->replaceLabel->setVisible(false); d->replaceLine->setVisible(false); d->replaceButton->setVisible(false); d->replaceAllButton->setVisible(false); if(!isVisible()) { show(); } d->searchLine->setFocus(); if(d->finder->matches().size() == 0) { d->textTimeout->start(); } } void KoFindToolbar::activateReplace() { if(!isVisible()) { show(); } d->searchLine->setFocus(); d->replaceLabel->setVisible(true); d->replaceLine->setVisible(true); d->replaceButton->setVisible(true); d->replaceAllButton->setVisible(true); if(d->finder->matches().size() == 0) { d->textTimeout->start(); } } void KoFindToolbar::Private::matchFound() { QPalette current = searchLine->palette(); KColorScheme::adjustBackground(current, KColorScheme::PositiveBackground); searchLine->setPalette(current); replaceLine->setPalette(current); information->setText(i18ncp("Total number of matches", "1 match found", "%1 matches found", finder->matches().count())); } void KoFindToolbar::Private::noMatchFound() { QPalette current = searchLine->palette(); KColorScheme::adjustBackground(current, KColorScheme::NegativeBackground); searchLine->setPalette(current); replaceLine->setPalette(current); information->setText(i18n("No matches found")); } void KoFindToolbar::Private::searchWrapped(bool direction) { if(direction) { information->setText(i18n("Search hit bottom, continuing from top.")); } else { information->setText(i18n("Search hit top, continuing from bottom.")); } } void KoFindToolbar::Private::addToHistory() { searchLine->addToHistory(searchLine->currentText()); } void KoFindToolbar::Private::find(const QString &pattern) { textTimeout->stop(); if(pattern.length() > 0) { finder->find(pattern); } else { finder->finished(); information->setText(QString()); searchLine->setPalette(qApp->palette()); replaceLine->setPalette(qApp->palette()); } } void KoFindToolbar::Private::optionChanged() { QAction *action = qobject_cast(q->sender()); if(action) { finder->options()->setOptionValue(action->objectName(), action->isChecked()); find(searchLine->currentText()); } } void KoFindToolbar::Private::replace() { finder->replaceCurrent(replaceLine->currentText()); replaceLine->addToHistory(replaceLine->currentText()); } void KoFindToolbar::Private::replaceAll() { finder->replaceAll(replaceLine->currentText()); replaceLine->addToHistory(replaceLine->currentText()); } void KoFindToolbar::Private::inputTimeout() { find(searchLine->currentText()); } #include "KoFindToolbar.moc" diff --git a/libs/main/KoPartAdaptor.h b/libs/main/KoPartAdaptor.h index 5c61d7fcfa7..2a900fc08b6 100644 --- a/libs/main/KoPartAdaptor.h +++ b/libs/main/KoPartAdaptor.h @@ -1,138 +1,138 @@ /* This file is part of the KDE project Copyright (C) 2000 David Faure Copyright (C) 2006 Fredrik Edemar This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KODOCUMENTADAPTOR_H #define KODOCUMENTADAPTOR_H #include #include -#include +#include #include #include "komain_export.h" class KoPart; /** * DBUS interface for any Calligra document * Use KoApplicationIface to get hold of an existing document's interface, * or to create a document. */ class KOMAIN_EXPORT KoPartAdaptor : public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.calligra.document") public: explicit KoPartAdaptor(KoPart* doc); ~KoPartAdaptor(); public slots: // METHODS /** * Returns the URL for this document (empty, real URL, or internal one) */ Q_SCRIPTABLE QString url(); /** * Opens a document stored in @p url * Warning: this is asynchronous. The document might not be loaded yet when * this call returns. See isLoading. */ Q_SCRIPTABLE void openUrl(const QString & url); /** * @return TRUE is the document is still loading */ Q_SCRIPTABLE bool isLoading(); /** * @return TRUE is the document has been modified */ Q_SCRIPTABLE bool isModified(); /** * @return the number of views this document is displayed in */ Q_SCRIPTABLE int viewCount(); /** * @return a representing the view with index @p idx */ Q_SCRIPTABLE QString view(int idx); /** * @return list of actions */ Q_SCRIPTABLE QStringList actions(); /** * Saves the document under its existing filename */ Q_SCRIPTABLE void save(); /** * Saves the document under a new name */ Q_SCRIPTABLE void saveAs(const QString & url); Q_SCRIPTABLE void setOutputMimeType(const QByteArray & mimetype); Q_SCRIPTABLE QString documentInfoAuthorName() const; Q_SCRIPTABLE QString documentInfoEmail() const; Q_SCRIPTABLE QString documentInfoCompanyName() const; Q_SCRIPTABLE QString documentInfoTitle() const; Q_SCRIPTABLE QString documentInfoAbstract() const; Q_SCRIPTABLE QString documentInfoKeywords() const; Q_SCRIPTABLE QString documentInfoSubject() const; Q_SCRIPTABLE QString documentInfoTelephone() const; Q_SCRIPTABLE QString documentInfoTelephoneWork() const; Q_SCRIPTABLE QString documentInfoTelephoneHome() const; Q_SCRIPTABLE QString documentInfoFax() const; Q_SCRIPTABLE QString documentInfoCountry() const; Q_SCRIPTABLE QString documentInfoPostalCode() const; Q_SCRIPTABLE QString documentInfoCity() const; Q_SCRIPTABLE QString documentInfoStreet() const; Q_SCRIPTABLE QString documentInfoInitial() const; Q_SCRIPTABLE QString documentInfoAuthorPostion() const; Q_SCRIPTABLE void setDocumentInfoAuthorName(const QString & text); Q_SCRIPTABLE void setDocumentInfoEmail(const QString &text); Q_SCRIPTABLE void setDocumentInfoCompanyName(const QString &text); Q_SCRIPTABLE void setDocumentInfoTelephone(const QString &text); Q_SCRIPTABLE void setDocumentInfoTelephoneWork(const QString &text); Q_SCRIPTABLE void setDocumentInfoTelephoneHome(const QString &text); Q_SCRIPTABLE void setDocumentInfoFax(const QString &text); Q_SCRIPTABLE void setDocumentInfoCountry(const QString &text); Q_SCRIPTABLE void setDocumentInfoTitle(const QString & text); Q_SCRIPTABLE void setDocumentInfoPostalCode(const QString &text); Q_SCRIPTABLE void setDocumentInfoCity(const QString & text); Q_SCRIPTABLE void setDocumentInfoStreet(const QString &text); Q_SCRIPTABLE void setDocumentInfoAbstract(const QString &text); Q_SCRIPTABLE void setDocumentInfoInitial(const QString & text); Q_SCRIPTABLE void setDocumentInfoKeywords(const QString & text); Q_SCRIPTABLE void setDocumentInfoSubject(const QString & text); Q_SCRIPTABLE void setDocumentInfoAuthorPosition(const QString & text); public: protected: KoPart* m_pDoc; }; #endif diff --git a/libs/main/KoViewAdaptor.h b/libs/main/KoViewAdaptor.h index 9406b3d3535..d64b0759fd6 100644 --- a/libs/main/KoViewAdaptor.h +++ b/libs/main/KoViewAdaptor.h @@ -1,53 +1,53 @@ /* This file is part of the KDE project Copyright (c) 2000 Simon Hausmann Copyright (C) 2006 Fredrik Edemar $Id: KoViewIface.h 539508 2006-05-10 20:01:40Z mlaurent $ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef __KoViewAdaptor_h__ #define __KoViewAdaptor_h__ #include #include -#include +#include class QString; class QStringList; #include "komain_export.h" class KoView; class KOMAIN_EXPORT KoViewAdaptor : public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.calligra.view") public: explicit KoViewAdaptor(KoView *view); virtual ~KoViewAdaptor(); public slots: // METHODS Q_SCRIPTABLE QStringList/*DCOPCStringList*/ actions(); protected: KoView *m_pView; }; #endif diff --git a/libs/odf/tests/TestKoElementReference.h b/libs/odf/tests/TestKoElementReference.h index 9c5686f1456..ebd8a8526f4 100644 --- a/libs/odf/tests/TestKoElementReference.h +++ b/libs/odf/tests/TestKoElementReference.h @@ -1,33 +1,33 @@ /* This file is part of the KDE project * Copyright (C) 2011 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef TESTKOELEMENTREFERENCE_H #define TESTKOELEMENTREFERENCE_H -#include +#include class TestKoElementReference : public QObject { Q_OBJECT private slots: void testElementReference(); }; #endif diff --git a/plan/libs/kernel/tests/CalendarTester.cpp b/plan/libs/kernel/tests/CalendarTester.cpp index 92e89a351ce..5e89becc185 100644 --- a/plan/libs/kernel/tests/CalendarTester.cpp +++ b/plan/libs/kernel/tests/CalendarTester.cpp @@ -1,353 +1,353 @@ /* This file is part of the KDE project Copyright (C) 2006-2007 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "CalendarTester.h" #include "DateTimeTester.h" #include #include #include #include #include "kptappointment.h" #include #include #include #include #include #include #include #include #include -#include +#include #include #include "debug.cpp" namespace KPlato { void CalendarTester::initTestCase() { QString kdehome = getenv("KDEHOME"); QDir d(kdehome); d.mkpath("calendartest"); d.cd("calendartest"); QString dataDir = d.path(); qDebug()<addInterval(TimeInterval(t1, length)); t.addDay(day); QVERIFY(t.findDay(wdate) == day); QVERIFY(t.hasInterval(after, DateTime( after.addDays(1))) == false); QVERIFY(t.hasInterval(before, DateTime(before.addDays(-1))) == false); QVERIFY(t.hasInterval(after, before) == false); QVERIFY(t.hasInterval(before, after)); QVERIFY((t.firstAvailableAfter(after, DateTime(after.addDays(10)))).isValid() == false); QVERIFY((t.firstAvailableBefore(before, DateTime(before.addDays(-10)))).isValid() == false); QCOMPARE(t.firstAvailableAfter(before,after), wdt1); QCOMPARE(t.firstAvailableBefore(after, before), wdt2); Duration e(0, 2, 0); QCOMPARE((t.effort(before, after)).toString(), e.toString()); } void CalendarTester::testWeekdays() { Calendar t("Test"); QDate wdate(2006,1,4); // wednesday DateTime before = DateTime(wdate.addDays(-2), QTime()); DateTime after = DateTime(wdate.addDays(2), QTime()); QTime t1(8,0,0); QTime t2(10,0,0); int length = t1.msecsTo( t2 ); CalendarDay *wd1 = t.weekday(Qt::Wednesday); QVERIFY(wd1 != 0); wd1->setState(CalendarDay::Working); wd1->addInterval(TimeInterval(t1, length)); QCOMPARE(t.firstAvailableAfter(before, after), DateTime(QDate(2006, 1, 4), QTime(8,0,0))); QCOMPARE((t.firstAvailableBefore(after, before)), DateTime(QDate(2006, 1, 4), QTime(10,0,0))); QCOMPARE(t.firstAvailableAfter(after, DateTime(QDate(QDate(2006,1,14)), QTime())), DateTime(QDate(2006, 1, 11), QTime(8,0,0))); QCOMPARE(t.firstAvailableBefore(before, DateTime(QDate(2005,12,25), QTime())), DateTime(QDate(2005, 12, 28), QTime(10,0,0))); } void CalendarTester::testCalendarWithParent() { Calendar p("Test 3 parent"); Calendar t("Test 3"); t.setParentCal(&p); QDate wdate(2006,1,2); DateTime before = DateTime(wdate.addDays(-1), QTime()); DateTime after = DateTime(wdate.addDays(1), QTime()); QTime t1(8,0,0); QTime t2(10,0,0); int length = t1.msecsTo( t2 ); DateTime wdt1(wdate, t1); DateTime wdt2(wdate, t2); CalendarDay *day = new CalendarDay(wdate, CalendarDay::Working); day->addInterval(TimeInterval(t1, length)); p.addDay(day); QVERIFY(p.findDay(wdate) == day); //same tests as in testSingleDay() QVERIFY(t.hasInterval(after, DateTime(after.addDays(1))) == false); QVERIFY(t.hasInterval(before, DateTime(before.addDays(-1))) == false); QVERIFY(t.hasInterval(after, before) == false); QVERIFY(t.hasInterval(before, after)); QVERIFY((t.firstAvailableAfter(after, DateTime(after.addDays(10)))).isValid() == false); QVERIFY((t.firstAvailableBefore(before, DateTime(before.addDays(-10)))).isValid() == false); QVERIFY(t.firstAvailableAfter(before, after).isValid()); QVERIFY(t.firstAvailableBefore(after, before).isValid()); QCOMPARE(t.firstAvailableAfter(before,after), wdt1); QCOMPARE(t.firstAvailableBefore(after, before), wdt2); Duration e(0, 2, 0); QCOMPARE((t.effort(before, after)).toString(), e.toString()); } void CalendarTester::testTimezone() { Calendar t("Test"); QDate wdate(2006,1,2); DateTime before = DateTime(wdate.addDays(-1), QTime()); DateTime after = DateTime(wdate.addDays(1), QTime()); QTime t1(8,0,0); QTime t2(10,0,0); DateTime wdt1(wdate, t1); DateTime wdt2(wdate, t2); int length = t1.msecsTo( t2 ); CalendarDay *day = new CalendarDay(wdate, CalendarDay::Working); day->addInterval(TimeInterval(t1, length)); t.addDay(day); Debug::print( &t, "Time zone testing" ); QVERIFY(t.findDay(wdate) == day); // local zone: Europe/Berlin ( 1 hours from London ) KTimeZone lo = KSystemTimeZones::zone("Europe/London"); QVERIFY( lo.isValid() ); KDateTime dt1 = KDateTime( wdate, t1, lo ).addSecs( -2 * 3600 ); KDateTime dt2 = KDateTime( wdate, t2, lo ).addSecs( 0 * 3600 ); qDebug()<addInterval( TimeInterval( t1, length ) ); t.addDay(day); QVERIFY(t.findDay(wdate) == day); AppointmentIntervalList lst = t.workIntervals( before, after, 100. ); QCOMPARE( lst.map().count(), 1 ); QCOMPARE( wdate, lst.map().values().first().startTime().date() ); QCOMPARE( t1, lst.map().values().first().startTime().time() ); QCOMPARE( wdate, lst.map().values().first().endTime().date() ); QCOMPARE( t2, lst.map().values().first().endTime().time() ); QCOMPARE( 100., lst.map().values().first().load() ); QTime t3( 12, 0, 0 ); day->addInterval( TimeInterval( t3, length ) ); lst = t.workIntervals( before, after, 100. ); Debug::print( lst ); QCOMPARE( lst.map().count(), 2 ); QCOMPARE( wdate, lst.map().values().first().startTime().date() ); QCOMPARE( t1, lst.map().values().first().startTime().time() ); QCOMPARE( wdate, lst.map().values().first().endTime().date() ); QCOMPARE( t2, lst.map().values().first().endTime().time() ); QCOMPARE( 100., lst.map().values().first().load() ); QCOMPARE( wdate, lst.map().values().at( 1 ).startTime().date() ); QCOMPARE( t3, lst.map().values().at( 1 ).startTime().time() ); QCOMPARE( wdate, lst.map().values().at( 1 ).endTime().date() ); QCOMPARE( t3.addMSecs( length ), lst.map().values().at( 1 ).endTime().time() ); QCOMPARE( 100., lst.map().values().at( 1 ).load() ); } void CalendarTester::workIntervalsFullDays() { Calendar t("Test"); QDate wdate(2006,1,2); DateTime before = DateTime(wdate.addDays(-1), QTime()); DateTime after = DateTime(wdate.addDays(10), QTime()); CalendarDay *day = new CalendarDay( wdate, CalendarDay::Working ); day->addInterval( TimeInterval( QTime( 0, 0, 0), 24*60*60*1000 ) ); t.addDay(day); QCOMPARE( day->numIntervals(), 1 ); QVERIFY( day->intervalAt( 0 )->endsMidnight() ); DateTime start = day->start(); DateTime end = day->end(); QCOMPARE( t.workIntervals( start, end, 100. ).map().count(), 1 ); QCOMPARE( t.workIntervals( before, after, 100. ).map().count(), 1 ); day = new CalendarDay( wdate.addDays( 1 ), CalendarDay::Working ); day->addInterval( TimeInterval( QTime( 0, 0, 0), 24*60*60*1000 ) ); t.addDay( day ); end = day->end(); QCOMPARE( t.workIntervals( start, end, 100. ).map().count(), 2 ); QCOMPARE( t.workIntervals( before, after, 100. ).map().count(), 2 ); day = new CalendarDay( wdate.addDays( 2 ), CalendarDay::Working ); day->addInterval( TimeInterval( QTime( 0, 0, 0), 24*60*60*1000 ) ); t.addDay( day ); end = day->end(); QCOMPARE( t.workIntervals( start, end, 100. ).map().count(), 3 ); QCOMPARE( t.workIntervals( before, after, 100. ).map().count(), 3 ); } } //namespace KPlato QTEST_KDEMAIN_CORE( KPlato::CalendarTester ) #include "CalendarTester.moc" diff --git a/plan/plugins/schedulers/rcps/tests/ProjectTester.cpp b/plan/plugins/schedulers/rcps/tests/ProjectTester.cpp index a37a3b0c604..29170bfafe6 100644 --- a/plan/plugins/schedulers/rcps/tests/ProjectTester.cpp +++ b/plan/plugins/schedulers/rcps/tests/ProjectTester.cpp @@ -1,724 +1,724 @@ /* This file is part of the KDE project Copyright (C) 2007 - 2011 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "ProjectTester.h" #include "KPlatoRCPSPlugin.h" #include "kptcommand.h" #include "kptcalendar.h" #include "kptdatetime.h" #include "kptresource.h" #include "kptnode.h" #include "kpttask.h" #include "kptschedule.h" #include #include #include #include #include #include #include #include #include -#include +#include #include #include #include "tests/DateTimeTester.h" #include "tests/debug.cpp" namespace KPlato { void ProjectTester::initTimezone() { QVERIFY( m_tmp.exists() ); QFile f; f.setFileName( m_tmp.name() + QLatin1String( "zone.tab" ) ); f.open(QIODevice::WriteOnly); QTextStream fStream(&f); fStream << "DE +5230+01322 Europe/Berlin\n" "EG +3003+03115 Africa/Cairo\n" "FR +4852+00220 Europe/Paris\n" "GB +512830-0001845 Europe/London Great Britain\n" "US +340308-1181434 America/Los_Angeles Pacific Time\n"; f.close(); QDir dir(m_tmp.name()); QVERIFY(dir.mkdir("Africa")); QFile::copy(QString::fromLatin1(KDESRCDIR) + QLatin1String("/Cairo"), m_tmp.name() + QLatin1String("Africa/Cairo")); QVERIFY(dir.mkdir("America")); QFile::copy(QString::fromLatin1(KDESRCDIR) + QLatin1String("/Los_Angeles"), m_tmp.name() + QLatin1String("America/Los_Angeles")); QVERIFY(dir.mkdir("Europe")); QFile::copy(QString::fromLatin1(KDESRCDIR) + QLatin1String("/Berlin"), m_tmp.name() + QLatin1String("Europe/Berlin")); QFile::copy(QString::fromLatin1(KDESRCDIR) + QLatin1String("/London"), m_tmp.name() + QLatin1String("Europe/London")); QFile::copy(QString::fromLatin1(KDESRCDIR) + QLatin1String("/Paris"), m_tmp.name() + QLatin1String("Europe/Paris")); // NOTE: QTEST_KDEMAIN_CORE puts the config file in QDir::homePath() + "/.kde-unit-test" // and hence, this is common to all unit tests KConfig config("ktimezonedrc"); KConfigGroup group(&config, "TimeZones"); group.writeEntry("ZoneinfoDir", m_tmp.name()); group.writeEntry("Zonetab", m_tmp.name() + QString::fromLatin1("zone.tab")); group.writeEntry("LocalZone", QString::fromLatin1("Europe/Berlin")); config.sync(); } void ProjectTester::cleanupTimezone() { } static ResourceGroup *createWorkResources( Project &p, int count ) { ResourceGroup *g = new ResourceGroup(); g->setName( "G1" ); p.addResourceGroup( g ); for ( int i = 0; i < count; ++i ) { Resource *r = new Resource(); r->setName( QString( "R%1" ).arg( i + 1 ) ); p.addResource( g, r ); } return g; } static void createRequest( Task *t, Resource *r ) { ResourceGroupRequest *gr = t->requests().find( r->parentGroup() ); if ( gr == 0 ) { gr = new ResourceGroupRequest( r->parentGroup() ); } t->addRequest( gr ); ResourceRequest *rr = new ResourceRequest( r, 100 ); gr->addResourceRequest( rr ); } static Calendar *createCalendar( Project &p ) { Calendar *c = new Calendar(); c->setDefault( true ); QTime t1( 9, 0, 0 ); QTime t2 ( 17, 0, 0 ); int length = t1.msecsTo( t2 ); for ( int i=1; i <= 7; ++i ) { CalendarDay *d = c->weekday( i ); d->setState( CalendarDay::Working ); d->addInterval( t1, length ); } p.addCalendar( c ); return c; } void ProjectTester::initTestCase() { initTimezone(); m_project = new Project(); m_project->setName( "P1" ); m_project->setId( m_project->uniqueNodeId() ); m_project->registerNodeId( m_project ); m_project->setConstraintStartTime( DateTime::fromString( "2012-02-01 00:00" ) ); m_project->setConstraintEndTime( m_project->constraintStartTime().addDays( 7 ) ); // standard worktime defines 8 hour day as default QVERIFY( m_project->standardWorktime() ); QCOMPARE( m_project->standardWorktime()->day(), 8.0 ); m_calendar = createCalendar( *m_project ); m_task = 0; qDebug()<<"Project:"<constraintStartTime()<constraintEndTime(); Debug::print( m_project, "Initiated to:" ); } void ProjectTester::cleanupTestCase() { qDebug()<createTask(); t->setName( "T1" ); m_project->addTask( t, m_project ); t->estimate()->setUnit( Duration::Unit_d ); t->estimate()->setExpectedEstimate( 1.0 ); t->estimate()->setType( Estimate::Type_Duration ); ScheduleManager *sm = m_project->createScheduleManager( "Test Plan" ); m_project->addScheduleManager( sm ); QString s = "Calculate forward, Task: Fixed duration ------------------------------"; qDebug()<startTime(), m_project->startTime() ); QCOMPARE( t->endTime(), DateTime(t->startTime().addDays( 1 )) ); s = "Calculate forward, Task: Length --------------------------------------"; qDebug()<estimate()->setCalendar( m_calendar ); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( *m_project, sm, true/*nothread*/ ); } Debug::print( m_calendar, s ); Debug::print( m_project, s, true ); QCOMPARE( t->startTime(), m_calendar->firstAvailableAfter( m_project->startTime(), m_project->endTime() ) ); QCOMPARE( t->endTime(), DateTime( t->startTime().addMSecs( length ) ) ); s = "Calculate forward, Task: Effort --------------------------------------"; qDebug()<addResourceGroup( g ); Resource *r = new Resource(); r->setAvailableFrom( QDateTime( yesterday, QTime() ) ); r->setCalendar( m_calendar ); m_project->addResource( g, r ); ResourceGroupRequest *gr = new ResourceGroupRequest( g ); t->addRequest( gr ); ResourceRequest *rr = new ResourceRequest( r, 100 ); gr->addResourceRequest( rr ); t->estimate()->setType( Estimate::Type_Effort ); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( *m_project, sm, true/*nothread*/ ); } Debug::print( t, s ); QCOMPARE( t->startTime(), m_calendar->firstAvailableAfter( m_project->startTime(), m_project->endTime() ) ); QCOMPARE( t->endTime(), DateTime( t->startTime().addMSecs( length ) ) ); s = "Calculate forward, Task: MustStartOn --------------------------------------"; qDebug()<setConstraint( Node::MustStartOn ); t->setConstraintStartTime( DateTime( tomorrow, t1 ) ); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( *m_project, sm, true/*nothread*/ ); } Debug::print( t, s ); QCOMPARE( t->startTime(), t->constraintStartTime() ); QCOMPARE( t->endTime(), t->startTime() + Duration( 0, 8, 0 ) ); s = "Calculate backward, Task: MustStartOn --------------------------------------"; qDebug()<setSchedulingDirection( true ); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( *m_project, sm, true/*nothread*/ ); } Debug::print( t, s ); Debug::printSchedulingLog( *sm, s ); QCOMPARE( t->startTime(), t->constraintStartTime() ); QCOMPARE( t->endTime(), t->startTime() + Duration( 0, 8, 0 ) ); s = "Calculate backward, Task: StartNotEarlier --------------------------------------"; qDebug()<setConstraint( Node::StartNotEarlier ); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( *m_project, sm, true/*nothread*/ ); } Debug::print( t, s ); QCOMPARE( t->startTime(), t->constraintStartTime() ); QCOMPARE( t->endTime(), t->startTime() + Duration( 0, 8, 0 ) ); s = "Calculate forward, Task: StartNotEarlier --------------------------------------"; qDebug()<setSchedulingDirection( false ); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( *m_project, sm, true/*nothread*/ ); } Debug::print( t, s ); QCOMPARE( t->startTime(), t->constraintStartTime() ); QCOMPARE( t->endTime(), t->startTime() + Duration( 0, 8, 0 ) ); s = "Calculate forward, Task: MustFinishOn --------------------------------------"; qDebug()<setConstraint( Node::MustFinishOn ); t->setConstraintEndTime( DateTime( tomorrow, t2 ) ); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( *m_project, sm, true/*nothread*/ ); } Debug::print( t, s ); QCOMPARE( t->endTime(), t->constraintEndTime() ); QCOMPARE( t->endTime(), t->startTime() + Duration( 0, 8, 0 ) ); s = "Calculate backward, Task: MustFinishOn --------------------------------------"; qDebug()<setSchedulingDirection( true ); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( *m_project, sm, true/*nothread*/ ); } Debug::print( t, s ); QCOMPARE( t->endTime(), t->constraintEndTime() ); QCOMPARE( t->endTime(), t->startTime() + Duration( 0, 8, 0 ) ); s = "Calculate backward, Task: FinishNotLater --------------------------------------"; qDebug()<setConstraint( Node::FinishNotLater ); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( *m_project, sm, true/*nothread*/ ); } Debug::print( t, s ); QCOMPARE( t->endTime(), t->constraintEndTime() ); QCOMPARE( t->endTime(), t->startTime() + Duration( 0, 8, 0 ) ); s = "Calculate forward, Task: FinishNotLater --------------------------------------"; qDebug()<setSchedulingDirection( false ); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( *m_project, sm, true/*nothread*/ ); } Debug::print( m_project, s, true ); QVERIFY( t->endTime() <= t->constraintEndTime() ); QCOMPARE( t->endTime(), t->startTime() + Duration( 0, 8, 0 ) ); s = "Calculate forward, Task: FixedInterval --------------------------------------"; qDebug()<setConstraint( Node ::FixedInterval ); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( *m_project, sm, true/*nothread*/ ); } Debug::print( t, s ); QCOMPARE( t->startTime(), t->constraintStartTime() ); QCOMPARE( t->endTime(), t->constraintEndTime() ); s = "Calculate backward, Task: FixedInterval --------------------------------------"; qDebug()<setSchedulingDirection( true ); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( *m_project, sm, true/*nothread*/ ); } Debug::print( t, s ); QCOMPARE( t->startTime(), t->constraintStartTime() ); QCOMPARE( t->endTime(), t->constraintEndTime() ); } void ProjectTester::team() { Project project; project.setName( "P1" ); project.setId( project.uniqueNodeId() ); project.registerNodeId( &project ); DateTime targetstart = DateTime( QDate( 2010, 5, 1 ), QTime(0,0,0) ); DateTime targetend = DateTime( targetstart.addDays( 7 ) ); project.setConstraintStartTime( targetstart ); project.setConstraintEndTime( targetend); Calendar *c = new Calendar("Test"); QTime t1(8,0,0); int length = 8*60*60*1000; // 8 hours for ( int i = 1; i <= 7; ++i ) { CalendarDay *wd1 = c->weekday(i); wd1->setState(CalendarDay::Working); wd1->addInterval(TimeInterval(t1, length)); } project.addCalendar( c ); Task *task1 = project.createTask(); task1->setName( "T1" ); project.addTask( task1, &project ); task1->estimate()->setUnit( Duration::Unit_d ); task1->estimate()->setExpectedEstimate( 2.0 ); task1->estimate()->setType( Estimate::Type_Effort ); QString s = "One team with one resource --------"; qDebug()<setName( "R1" ); r1->setCalendar( c ); project.addResource( g, r1 ); Resource *r2 = new Resource(); r2->setName( "Team member" ); r2->setCalendar( c ); project.addResource( g, r2 ); Resource *team = new Resource(); team->setType( Resource::Type_Team ); team->setName( "Team" ); team->addTeamMemberId( r2->id() ); project.addResource( g, team ); ResourceGroupRequest *gr = new ResourceGroupRequest( g ); task1->addRequest( gr ); ResourceRequest *tr = new ResourceRequest( team, 100 ); gr->addResourceRequest( tr ); ScheduleManager *sm = project.createScheduleManager( "Team" ); project.addScheduleManager( sm ); sm->createSchedules(); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( project, sm, true/*nothread*/ ); } // Debug::print( r1, s); // Debug::print( r2, s); Debug::print( team, s, false); Debug::print( &project, task1, s); // Debug::printSchedulingLog( *sm, s ); DateTime expectedEndTime = targetstart + Duration( 1, 16, 0 ); QCOMPARE( task1->endTime(), expectedEndTime ); s = "One team with one resource + one resource --------"; qDebug()<addResourceRequest( rr1 ); sm = project.createScheduleManager( "Team + Resource" ); project.addScheduleManager( sm ); sm->createSchedules(); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( project, sm, true/*nothread*/ ); } // Debug::print( r1, s); // Debug::print( r2, s); Debug::print( team, s, false); Debug::print( &project, task1, s); // Debug::printSchedulingLog( *sm, s ); expectedEndTime = targetstart + Duration( 0, 16, 0 ); QCOMPARE( task1->endTime(), expectedEndTime ); s = "One team with one resource + one resource, resource available too late --------"; qDebug()<setAvailableFrom( targetend ); r1->setAvailableUntil( targetend.addDays( 7 ) ); sm = project.createScheduleManager( "Team + Resource not available" ); project.addScheduleManager( sm ); sm->createSchedules(); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( project, sm, true/*nothread*/ ); } Debug::print( r1, s); // Debug::print( r2, s); Debug::print( team, s, false); Debug::print( &project, task1, s); Debug::printSchedulingLog( *sm, s ); expectedEndTime = targetstart + Duration( 1, 16, 0 ); QCOMPARE( task1->endTime(), expectedEndTime ); s = "One team with two resources --------"; qDebug()<removeRequests(); team->addTeamMemberId( r1->id() ); r1->setAvailableFrom( targetstart ); r1->setAvailableUntil( targetend ); sm = project.createScheduleManager( "Team with 2 resources" ); project.addScheduleManager( sm ); sm->createSchedules(); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( project, sm, true/*nothread*/ ); } // Debug::print( r1, s); // Debug::print( r2, s); Debug::print( team, s, false); Debug::print( &project, task1, s); Debug::printSchedulingLog( *sm, s ); expectedEndTime = targetstart + Duration( 0, 16, 0 ); QCOMPARE( task1->endTime(), expectedEndTime ); s = "One team with two resources, one resource unavailable --------"; qDebug()<setAvailableFrom( targetend ); r1->setAvailableUntil( targetend.addDays( 2 ) ); sm = project.createScheduleManager( "Team, one unavailable resource" ); project.addScheduleManager( sm ); sm->createSchedules(); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( project, sm, true/*nothread*/ ); } Debug::print( r1, s); // Debug::print( r2, s); Debug::print( team, s, false); Debug::print( &project, task1, s); Debug::printSchedulingLog( *sm, s ); expectedEndTime = targetstart + Duration( 1, 16, 0 ); QCOMPARE( task1->endTime(), expectedEndTime ); } void ProjectTester::mustStartOn() { return; Project project; project.setId( project.uniqueNodeId() ); project.registerNodeId( &project ); project.setConstraintStartTime( DateTime::fromString( "2011-01-01T00:00:00" ) ); project.setConstraintEndTime( DateTime::fromString( "2011-01-12T00:00:00" ) ); createCalendar( project ); ResourceGroup *g = createWorkResources( project, 1 ); Task *t = project.createTask(); t->setName( "T1" ); project.addTask( t, &project ); t->estimate()->setUnit( Duration::Unit_h ); t->estimate()->setExpectedEstimate( 1.0 ); t->estimate()->setType( Estimate::Type_Effort ); createRequest( t, g->resourceAt( 0 ) ); t->setConstraint( Node::MustStartOn ); t->setConstraintStartTime( DateTime::fromString( "2011-01-01T11:00:00" ) ); ScheduleManager *sm = project.createScheduleManager( "Test Plan" ); project.addScheduleManager( sm ); QString s = "Calculate forward, Task: MustStartOn ------------------------------"; qDebug()<startTime(), t->constraintStartTime() ); s = "Calculate forward, 2 Tasks ------------------------------"; qDebug()<setName( "T2" ); project.addTask( t2, &project ); t2->estimate()->setUnit( Duration::Unit_d ); t2->estimate()->setExpectedEstimate( 10.0 ); t2->estimate()->setType( Estimate::Type_Effort ); createRequest( t2, g->resourceAt( 0 ) ); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( project, sm, true/*nothread*/ ); } Debug::print( &project, s ); Debug::print( t, s ); Debug::print( t2, s ); QCOMPARE( t->startTime(), t->constraintStartTime() ); s = "Calculate backward, 2 Tasks ------------------------------"; qDebug()<setSchedulingDirection( true ); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( project, sm, true/*nothread*/ ); } Debug::print( &project, s ); Debug::print( t, s ); Debug::print( t2, s ); QCOMPARE( t->startTime(), t->constraintStartTime() ); } void ProjectTester::startNotEarlier() { Project project; project.setId( project.uniqueNodeId() ); project.registerNodeId( &project ); project.setConstraintStartTime( DateTime::fromString( "2011-01-01T00:00:00" ) ); project.setConstraintEndTime( DateTime::fromString( "2011-01-12T00:00:00" ) ); createCalendar( project ); ResourceGroup *g = createWorkResources( project, 1 ); Task *t = project.createTask(); t->setName( "T1" ); project.addTask( t, &project ); t->estimate()->setUnit( Duration::Unit_h ); t->estimate()->setExpectedEstimate( 1.0 ); t->estimate()->setType( Estimate::Type_Effort ); createRequest( t, g->resourceAt( 0 ) ); t->setConstraint( Node::StartNotEarlier ); t->setConstraintStartTime( DateTime::fromString( "2011-01-02T11:00:00" ) ); ScheduleManager *sm = project.createScheduleManager( "Test Plan" ); project.addScheduleManager( sm ); QString s = "Calculate forward, Task: StartNotEarlier ------------------------------"; qDebug()<startTime() >= t->constraintStartTime() ); QCOMPARE( t->endTime(), t->startTime() + Duration( 0, 1, 0 ) ); s = "Calculate forward, 2 Tasks ------------------------------"; qDebug()<setName( "T2" ); project.addTask( t2, &project ); t2->estimate()->setUnit( Duration::Unit_d ); t2->estimate()->setExpectedEstimate( 7.0 ); t2->estimate()->setType( Estimate::Type_Effort ); createRequest( t2, g->resourceAt( 0 ) ); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( project, sm, true/*nothread*/ ); } Debug::print( &project, s ); Debug::print( t, s ); Debug::print( t2, s ); QVERIFY( t->startTime() >= t->constraintStartTime() ); QCOMPARE( t->endTime(), t->startTime() + Duration( 0, 1, 0 ) ); s = "Calculate backward, 2 Tasks ------------------------------"; qDebug()<setSchedulingDirection( true ); { KPlatoRCPSPlugin rcps( 0, QVariantList() ); rcps.calculate( project, sm, true/*nothread*/ ); } Debug::print( &project, s ); Debug::print( t, s ); Debug::print( t2, s ); Debug::printSchedulingLog( *sm, s ); QVERIFY( t->startTime() >= t->constraintStartTime() ); QCOMPARE( t->endTime(), t->startTime() + Duration( 0, 1, 0 ) ); } } //namespace KPlato QTEST_KDEMAIN_CORE( KPlato::ProjectTester ) #include "ProjectTester.moc" diff --git a/plan/plugins/schedulers/tj/tests/SchedulerTester.cpp b/plan/plugins/schedulers/tj/tests/SchedulerTester.cpp index e956106d2f9..acea3b8ffc4 100644 --- a/plan/plugins/schedulers/tj/tests/SchedulerTester.cpp +++ b/plan/plugins/schedulers/tj/tests/SchedulerTester.cpp @@ -1,225 +1,225 @@ /* This file is part of the KDE project Copyright (C) 2007 - 2011 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "SchedulerTester.h" #include "PlanTJPlugin.h" #include "kptcommand.h" #include "kptcalendar.h" #include "kptdatetime.h" #include "kptresource.h" #include "kptnode.h" #include "kpttask.h" #include "kptschedule.h" #include "kptxmlloaderobject.h" #include #include #include #include #include #include #include #include #include -#include +#include #include #include #include "tests/DateTimeTester.h" #include "tests/debug.cpp" namespace KPlato { QStringList SchedulerTester::data() { return QStringList() << "test1.plan" << "startnotearlier.plan" ; } void SchedulerTester::initTimezone() { QString kdehome = getenv("KDEHOME"); QDir d(kdehome); d.mkpath("tjtest"); d.cd("tjtest"); QString dataDir = d.path(); qDebug()<calculationResult() == ScheduleManager::CalculationDone, s.toLatin1() ); long id1 = manager->scheduleId(); long id2 = sm->scheduleId(); s = QString( "%1: Compare project schedules:\n Expected: %2\n Result: %3" ) .arg( fname ) .arg( project.startTime( id1 ).toString( Qt::ISODate ) ) .arg( project.startTime( id2 ).toString( Qt::ISODate ) ); QVERIFY2( project.startTime( id1 ) == project.startTime( id2 ), s.toLatin1() ); foreach ( Node *n, project.allNodes() ) { compare( fname, n, id1, id2 ); } } void SchedulerTester::compare( const QString &fname, Node *n, long id1, long id2 ) { QString s = QString( "%1: '%2' Compare task schedules:\n Expected: %3\n Result: %4" ).arg( fname ).arg( n->name() ); QVERIFY2( n->startTime( id1 ) == n->startTime( id2 ), (s.arg(n->startTime( id1 ).toString(Qt::ISODate)).arg(n->startTime( id2 ).toString(Qt::ISODate))).toLatin1() ); QVERIFY2( n->endTime( id1 ) == n->endTime( id2 ), (s.arg(n->endTime( id1 ).toString(Qt::ISODate)).arg(n->endTime( id2 ).toString(Qt::ISODate))).toLatin1() ); } } //namespace KPlato QTEST_KDEMAIN_CORE( KPlato::SchedulerTester ) #include "SchedulerTester.moc" diff --git a/plan/plugins/schedulers/tj/tests/TaskJuggler.cpp b/plan/plugins/schedulers/tj/tests/TaskJuggler.cpp index 831e335430e..7f09a84c96c 100644 --- a/plan/plugins/schedulers/tj/tests/TaskJuggler.cpp +++ b/plan/plugins/schedulers/tj/tests/TaskJuggler.cpp @@ -1,1073 +1,1073 @@ /* This file is part of the KDE project Copyright (C) 2007 - 2011 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "TaskJuggler.h" #include "Allocation.h" #include "Project.h" #include "Interval.h" #include "Task.h" #include "Resource.h" #include "CoreAttributesList.h" #include "Interval.h" #include "Utility.h" #include "UsageLimits.h" #include "debug.h" #include "kptcommand.h" #include "kptcalendar.h" #include "kptdatetime.h" #include "kptresource.h" #include "kptnode.h" #include "kpttask.h" #include "kptschedule.h" #include #include #include #include #include #include #include #include #include -#include +#include #include #include #include "tests/DateTimeTester.h" #include "tests/debug.cpp" namespace KPlato { void TaskJuggler::initTimezone() { QVERIFY( m_tmp.exists() ); QFile f; f.setFileName( m_tmp.name() + QLatin1String( "zone.tab" ) ); f.open(QIODevice::WriteOnly); QTextStream fStream(&f); fStream << "DE +5230+01322 Europe/Berlin\n" "EG +3003+03115 Africa/Cairo\n" "FR +4852+00220 Europe/Paris\n" "GB +512830-0001845 Europe/London Great Britain\n" "US +340308-1181434 America/Los_Angeles Pacific Time\n"; f.close(); QDir dir(m_tmp.name()); QVERIFY(dir.mkdir("Africa")); QFile::copy(QString::fromLatin1(KDESRCDIR) + QLatin1String("/Cairo"), m_tmp.name() + QLatin1String("Africa/Cairo")); QVERIFY(dir.mkdir("America")); QFile::copy(QString::fromLatin1(KDESRCDIR) + QLatin1String("/Los_Angeles"), m_tmp.name() + QLatin1String("America/Los_Angeles")); QVERIFY(dir.mkdir("Europe")); QFile::copy(QString::fromLatin1(KDESRCDIR) + QLatin1String("/Berlin"), m_tmp.name() + QLatin1String("Europe/Berlin")); QFile::copy(QString::fromLatin1(KDESRCDIR) + QLatin1String("/London"), m_tmp.name() + QLatin1String("Europe/London")); QFile::copy(QString::fromLatin1(KDESRCDIR) + QLatin1String("/Paris"), m_tmp.name() + QLatin1String("Europe/Paris")); // NOTE: QTEST_KDEMAIN_CORE puts the config file in QDir::homePath() + "/.kde-unit-test" // and hence, this is common to all unit tests KConfig config("ktimezonedrc"); KConfigGroup group(&config, "TimeZones"); group.writeEntry("ZoneinfoDir", m_tmp.name()); group.writeEntry("Zonetab", m_tmp.name() + QString::fromLatin1("zone.tab")); group.writeEntry("LocalZone", QString::fromLatin1("Europe/Berlin")); config.sync(); } void TaskJuggler::cleanupTimezone() { } void TaskJuggler::initTestCase() { DebugCtrl.setDebugLevel(0); DebugCtrl.setDebugMode(0xffff); initTimezone(); qDebug()<<"Time zone initiated"; project = new TJ::Project(); qDebug()<<"Project created:"<setScheduleGranularity( TJ::ONEHOUR ); // seconds QDateTime dt = QDateTime::fromString( "2011-07-01 08:00:00", Qt::ISODate ); project->setStart( dt.toTime_t() ); project->setEnd( dt.addDays(7).addSecs( -1 ).toTime_t() ); qDebug()<getStart()<getEnd(); QList *lst; lst = project->getWorkingHours(0); QCOMPARE( lst->count(), 0 ); qDebug()<<"Sunday:"<getWorkingHours(1); QCOMPARE( lst->count(), 2 ); qDebug()<<"Monday:"<getWorkingHours(2); QCOMPARE( lst->count(), 2 ); qDebug()<<"Tuesday:"<getWorkingHours(3); QCOMPARE( lst->count(), 2 ); qDebug()<<"Wednesday:"<getWorkingHours(4); QCOMPARE( lst->count(), 2 ); qDebug()<<"Thursday:"<getWorkingHours(5); QCOMPARE( lst->count(), 2 ); qDebug()<<"Friday:"<getWorkingHours(6); QCOMPARE( lst->count(), 0 ); qDebug()<<"Saturday:"<getId(), QString("T1") ); QCOMPARE( t->getName(), QString("T1 name") ); qDebug()<<"finished"; int sc = project->getScenarioIndex( "plan" ); QCOMPARE( sc, 1 ); t->setDuration( sc-1, TJ::ONEHOUR ); QCOMPARE( t->getDuration( sc-1 ), (double)TJ::ONEHOUR ); QVERIFY( ! t->isMilestone() ); } void TaskJuggler::list() { TJ::CoreAttributesList lst; TJ::CoreAttributes *a = new TJ::CoreAttributes(project, "A1", "A1 name", 0); a->setSequenceNo(1); lst.inSort(a); a = new TJ::CoreAttributes(project, "A2", "A2 name", 0); a->setSequenceNo(3); lst.inSort(a); QCOMPARE( lst.count(), 2); QCOMPARE( lst.at(0)->getId(), QString( "A1" ) ); QCOMPARE( lst.at(1)->getId(), QString( "A2" ) ); a = new TJ::CoreAttributes(project, "A3", "A3 name", 0); a->setSequenceNo(2); lst.inSort(a); QCOMPARE( lst.at(0)->getId(), QString( "A1" ) ); QCOMPARE( lst.at(1)->getId(), QString( "A3" ) ); QCOMPARE( lst.at(2)->getId(), QString( "A2" ) ); lst.setSorting(TJ::CoreAttributesList::SequenceDown, 0); lst.setSorting(TJ::CoreAttributesList::SequenceDown, 1); lst.setSorting(TJ::CoreAttributesList::SequenceDown, 2); lst.sort(); QCOMPARE( lst.at(0)->getId(), QString( "A2" ) ); QCOMPARE( lst.at(1)->getId(), QString( "A3" ) ); QCOMPARE( lst.at(2)->getId(), QString( "A1" ) ); lst.setSorting(TJ::CoreAttributesList::IdDown, 0); lst.setSorting(TJ::CoreAttributesList::SequenceDown, 1); lst.setSorting(TJ::CoreAttributesList::SequenceDown, 2); lst.sort(); QStringList s; foreach(TJ::CoreAttributes *a, lst) s << a->getId(); qDebug()<getId(), QString( "A3" ) ); QCOMPARE( lst.at(1)->getId(), QString( "A2" ) ); QCOMPARE( lst.at(2)->getId(), QString( "A1" ) ); while ( ! lst.isEmpty() ) { delete lst.takeFirst(); } } void TaskJuggler::oneResource() { TJ::Resource *r = new TJ::Resource( project, "R1", "R1 name", 0 ); r->setEfficiency( 1.0 ); for (int day = 0; day < 7; ++day) { r->setWorkingHours( day, *(project->getWorkingHours(day)) ); foreach( TJ::Interval *i, *( r->getWorkingHours()[day] ) ) { qDebug()<resourceCount(), (uint)1 ); } void TaskJuggler::allocation() { TJ::Task *t = project->getTask( "T1" ); QVERIFY( t != 0 ); TJ::Resource *r = project->getResource( "R1" ); QVERIFY( r != 0 ); TJ::Allocation *a = new TJ::Allocation(); a->addCandidate( r ); QCOMPARE( a->getCandidates().count(), 1 ); t->addAllocation( a ); } void TaskJuggler::dependency() { int sc = project->getScenarioIndex( "plan" ); QCOMPARE( sc, 1); TJ::Task *m = new TJ::Task( project, "M1", "M1 name", 0, QString(), 0 ); m->setMilestone( true ); m->setSpecifiedStart( sc-1, project->getStart() ); TJ::Task *t = project->getTask( "T1" ); QVERIFY( t != 0 ); TJ::TaskDependency *d = t->addDepends( m->getId() ); QVERIFY( d != 0 ); } void TaskJuggler::scheduleResource() { QCOMPARE( project->getMaxScenarios(), 1 ); TJ::Task *t = project->getTask( "T1" ); QVERIFY( t != 0 ); t->setDuration( 0, 0.0 ); t->setEffort( 0, 5. ); QCOMPARE( t->getEffort( 0 ), 5. ); qDebug()<getId()<<"effort="<getEffort( 0 ); QVERIFY( project->pass2( true ) ); QVERIFY( project->scheduleAllScenarios() ); qDebug()<getStart( 0 ) )<getEnd( 0 ) ); } void TaskJuggler::scheduleDependencies() { QString s; QDateTime pstart = QDateTime::fromString( "2011-07-01 00:00:00", Qt::ISODate ); QDateTime pend = pstart.addDays(1); { s = "Test one ALAP milestone --------------------"; qDebug()<setScheduleGranularity( TJ::ONEHOUR ); // seconds proj->setStart( pstart.toTime_t() ); proj->setEnd( pend.toTime_t() ); TJ::Task *m = new TJ::Task(proj, "M1", "M1", 0, QString(), 0); m->setMilestone( true ); m->setScheduling( TJ::Task::ALAP ); m->setSpecifiedEnd( 0, proj->getEnd() - 1 ); QVERIFY( proj->pass2( true ) ); QVERIFY( proj->scheduleAllScenarios() ); QDateTime mstart = QDateTime::fromTime_t( m->getStart( 0 ) ); QDateTime mend = QDateTime::fromTime_t( m->getEnd( 0 ) ); QCOMPARE( mstart, pend ); QCOMPARE( mend, pend.addSecs( -1 ) ); delete proj; } { s = "Test one ALAP milestone + one ASAP task --------------------"; qDebug()<setScheduleGranularity( TJ::ONEHOUR ); // seconds proj->setStart( pstart.toTime_t() ); proj->setEnd( pend.toTime_t() ); TJ::Task *m = new TJ::Task(proj, "M1", "M1", 0, QString(), 0); m->setMilestone( true ); m->setScheduling( TJ::Task::ALAP ); m->setSpecifiedEnd( 0, proj->getEnd() - 1 ); TJ::Task *t = new TJ::Task(proj, "T1", "T1", 0, QString(), 0); t->setDuration( 0, (double)(TJ::ONEHOUR) / TJ::ONEDAY ); t->setSpecifiedStart( 0, proj->getStart() ); QVERIFY( proj->pass2( true ) ); QVERIFY( proj->scheduleAllScenarios() ); QDateTime tstart = QDateTime::fromTime_t( t->getStart( 0 ) ); QDateTime tend = QDateTime::fromTime_t( t->getEnd( 0 ) ); QCOMPARE( tstart, pstart ); QCOMPARE( tend, pstart.addSecs( TJ::ONEHOUR - 1 ) ); QDateTime mstart = QDateTime::fromTime_t( m->getStart( 0 ) ); QDateTime mend = QDateTime::fromTime_t( m->getEnd( 0 ) ); QCOMPARE( mstart, pend ); QCOMPARE( mend, pend.addSecs( -1 ) ); delete proj; } { s = "Test combination of ASAP/ALAP tasks and milestones --------------------"; qDebug()<setScheduleGranularity( 300 ); // seconds proj->setStart( pstart.toTime_t() ); proj->setEnd( pend.toTime_t() ); TJ::Task *t1 = new TJ::Task(proj, "T1", "T1", 0, QString(), 0); t1->setScheduling( TJ::Task::ASAP ); t1->setSpecifiedStart( 0, proj->getStart() ); t1->setDuration( 0, (double)(TJ::ONEHOUR) / TJ::ONEDAY ); TJ::Task *t2 = new TJ::Task(proj, "T2", "T2", 0, QString(), 0); t2->setScheduling( TJ::Task::ALAP ); t2->setDuration( 0, (double)(TJ::ONEHOUR) / TJ::ONEDAY ); t2->setSpecifiedEnd( 0, proj->getEnd() - 1 ); // m->addPrecedes( t->getId() ); TJ::Task *m1 = new TJ::Task(proj, "M1", "M1", 0, QString(), 0); m1->setMilestone( true ); m1->setScheduling( TJ::Task::ASAP ); m1->addDepends( t1->getId() ); m1->addPrecedes( t2->getId() ); TJ::Task *m2 = new TJ::Task(proj, "M2", "M2", 0, QString(), 0); m2->setMilestone( true ); m2->setScheduling( TJ::Task::ALAP ); m2->addDepends( t1->getId() ); m2->addPrecedes( t2->getId() ); TJ::Task *t3 = new TJ::Task(proj, "T3", "T3", 0, QString(), 0); t3->setDuration( 0, (double)(TJ::ONEHOUR) / TJ::ONEDAY ); t3->addPrecedes( m2->getId() ); t3->setScheduling( TJ::Task::ALAP ); // since t4 is ALAP, this must be ALAP too TJ::Task *t4 = new TJ::Task(proj, "T4", "T4", 0, QString(), 0); t4->setDuration( 0, (double)(TJ::ONEHOUR) / TJ::ONEDAY ); t4->addPrecedes( t3->getId() ); t4->setScheduling( TJ::Task::ALAP ); QVERIFY( proj->pass2( true ) ); QVERIFY( proj->scheduleAllScenarios() ); QDateTime t1end = QDateTime::fromTime_t( t1->getEnd( 0 ) ); QDateTime t2start = QDateTime::fromTime_t( t2->getStart( 0 ) ); QDateTime t3start = QDateTime::fromTime_t( t3->getStart( 0 ) ); QDateTime t3end = QDateTime::fromTime_t( t3->getEnd( 0 ) ); QDateTime t4end = QDateTime::fromTime_t( t4->getEnd( 0 ) ); QDateTime m1end = QDateTime::fromTime_t( m1->getEnd( 0 ) ); QDateTime m2start = QDateTime::fromTime_t( m2->getStart( 0 ) ); QDateTime m2end = QDateTime::fromTime_t( m2->getEnd( 0 ) ); QCOMPARE( m1end, t1end ); QCOMPARE( m2start, t2start ); QCOMPARE( m2end, t3end ); QCOMPARE( t3start, t4end.addSecs(1) ); delete proj; } { DebugCtrl.setDebugLevel(1000); DebugCtrl.setDebugMode(7); s = "Test sequeces of ASAP/ALAP milestones --------------------"; qDebug()<setScheduleGranularity( 300 ); // seconds proj->setStart( pstart.toTime_t() ); proj->setEnd( pend.toTime_t() ); // First milestone on project start TJ::Task *m1 = new TJ::Task(proj, "Start", "Start", 0, QString(), 0); m1->setMilestone( true ); m1->setScheduling( TJ::Task::ASAP ); m1->setSpecifiedStart( 0, proj->getStart() ); TJ::Task *m2 = new TJ::Task(proj, "M2-ASAP", "M2", 0, QString(), 0); m2->setMilestone( true ); m2->setScheduling( TJ::Task::ASAP ); TJ::Task *m3 = new TJ::Task(proj, "M3-ASAP", "M3", 0, QString(), 0); m3->setMilestone( true ); m3->setScheduling( TJ::Task::ASAP ); TJ::Task *m7 = new TJ::Task(proj, "M/-ASAP", "M7", 0, QString(), 0); m7->setMilestone( true ); m7->setScheduling( TJ::Task::ASAP ); TJ::Task *m4 = new TJ::Task(proj, "M4-ALAP", "M4", 0, QString(), 0); m4->setScheduling( TJ::Task::ALAP ); m4->setMilestone( true ); TJ::Task *m5 = new TJ::Task(proj, "M5-ALAP", "M5", 0, QString(), 0); m5->setScheduling( TJ::Task::ALAP ); m5->setMilestone( true ); TJ::Task *m8 = new TJ::Task(proj, "M8-ALAP", "M8", 0, QString(), 0); m8->setScheduling( TJ::Task::ALAP ); m8->setMilestone( true ); // ALAP milestone on project end TJ::Task *m6 = new TJ::Task(proj, "End", "End", 0, QString(), 0); m6->setMilestone( true ); m6->setScheduling( TJ::Task::ALAP ); m6->setSpecifiedEnd( 0, proj->getEnd() - 1 ); m2->addDepends( m1->getId() ); m3->addDepends( m2->getId() ); m7->addDepends( m3->getId() ); m6->addDepends( m7->getId() ); m1->addPrecedes( m4->getId() ); m4->addPrecedes( m5->getId() ); m5->addPrecedes( m8->getId() ); m8->addPrecedes( m6->getId() ); QVERIFY2( proj->pass2( true ), s.toLatin1() ); QVERIFY2( proj->scheduleAllScenarios(), s.toLatin1() ); qDebug()<"<"<"<"<"<"<"<"<getStart( 0 ) ); QDateTime m1end = QDateTime::fromTime_t( m1->getEnd( 0 ) ); QDateTime m2start = QDateTime::fromTime_t( m2->getStart( 0 ) ); QDateTime m2end = QDateTime::fromTime_t( m2->getEnd( 0 ) ); QDateTime m3start = QDateTime::fromTime_t( m3->getStart( 0 ) ); QDateTime m3end = QDateTime::fromTime_t( m3->getEnd( 0 ) ); QDateTime m4start = QDateTime::fromTime_t( m4->getStart( 0 ) ); QDateTime m4end = QDateTime::fromTime_t( m4->getEnd( 0 ) ); QDateTime m5start = QDateTime::fromTime_t( m5->getStart( 0 ) ); QDateTime m5end = QDateTime::fromTime_t( m5->getEnd( 0 ) ); QDateTime m6start = QDateTime::fromTime_t( m6->getStart( 0 ) ); QDateTime m6end = QDateTime::fromTime_t( m6->getEnd( 0 ) ); QDateTime m7start = QDateTime::fromTime_t( m7->getStart( 0 ) ); QDateTime m7end = QDateTime::fromTime_t( m7->getEnd( 0 ) ); QDateTime m8start = QDateTime::fromTime_t( m8->getStart( 0 ) ); QDateTime m8end = QDateTime::fromTime_t( m8->getEnd( 0 ) ); QCOMPARE( m1start, pstart ); QCOMPARE( m2start, m1start ); QCOMPARE( m3start, m2start ); QCOMPARE( m7start, m3start ); QCOMPARE( m6start, pend ); QCOMPARE( m8end, m6end ); QCOMPARE( m5end, m8end ); QCOMPARE( m4end, m5end ); delete proj; } { DebugCtrl.setDebugLevel(1000); DebugCtrl.setDebugMode(7); s = "Test sequeces of ASAP/ALAP milestones and tasks ----------------"; qDebug()<setScheduleGranularity( 300 ); // seconds proj->setStart( pstart.toTime_t() ); proj->setEnd( pend.toTime_t() ); // First milestone on project start TJ::Task *m1 = new TJ::Task(proj, "Start", "Start", 0, QString(), 0); m1->setMilestone( true ); m1->setScheduling( TJ::Task::ASAP ); m1->setSpecifiedStart( 0, proj->getStart() ); // ASAP milestone dependent on m1 TJ::Task *m2 = new TJ::Task(proj, "M2-ASAP", "M2", 0, QString(), 0); m2->setMilestone( true ); m2->setScheduling( TJ::Task::ASAP ); // ALAP milestone dependent on m1 TJ::Task *m3 = new TJ::Task(proj, "M3-ALAP", "M3", 0, QString(), 0); m3->setMilestone( true ); m3->setScheduling( TJ::Task::ALAP ); TJ::Task *t1 = new TJ::Task(proj, "T1-ASAP", "T1", 0, QString(), 0); t1->setScheduling( TJ::Task::ASAP ); t1->setDuration( 0, (double)(TJ::ONEHOUR) / TJ::ONEDAY ); TJ::Task *t2 = new TJ::Task(proj, "T2-ALAP", "T2", 0, QString(), 0); t2->setScheduling( TJ::Task::ALAP ); t2->setDuration( 0, (double)(TJ::ONEHOUR) / TJ::ONEDAY ); // ALAP milestone on project end TJ::Task *m4 = new TJ::Task(proj, "End", "End", 0, QString(), 0); m4->setMilestone( true ); m4->setScheduling( TJ::Task::ALAP ); m4->setSpecifiedEnd( 0, proj->getEnd() - 1 ); m1->addPrecedes( m2->getId() ); m2->addDepends( m1->getId() ); m2->addPrecedes( t2->getId() ); t2->addDepends( m2->getId() ); // t2 (ALAP) depends on ASAP milestone t2->addPrecedes( m4->getId() ); m4->addDepends( t2->getId() ); m1->addPrecedes( m3->getId() ); m3->addDepends( m1->getId() ); m3->addPrecedes( t1->getId() ); // m3 ALAP t1->addDepends( m3->getId() ); // t1 (ASAP) depends on ALAP milestone t1->addPrecedes( m4->getId() ); m4->addDepends( t1->getId() ); QVERIFY2( proj->pass2( true ), s.toLatin1() ); QVERIFY2( proj->scheduleAllScenarios(), s.toLatin1() ); qDebug()<getId()<<"->"<getId()<<"->"<getId()<<"->"<getId(); qDebug()<getId()<<"->"<getId()<<"->"<getId()<<"->"<getId(); QDateTime t1start = QDateTime::fromTime_t( t1->getStart( 0 ) ); QDateTime t1end = QDateTime::fromTime_t( t1->getEnd( 0 ) ); QDateTime t2start = QDateTime::fromTime_t( t2->getStart( 0 ) ); QDateTime t2end = QDateTime::fromTime_t( t2->getEnd( 0 ) ); QDateTime m1start = QDateTime::fromTime_t( m1->getStart( 0 ) ); QDateTime m1end = QDateTime::fromTime_t( m1->getEnd( 0 ) ); QDateTime m2start = QDateTime::fromTime_t( m2->getStart( 0 ) ); QDateTime m2end = QDateTime::fromTime_t( m2->getEnd( 0 ) ); QDateTime m3start = QDateTime::fromTime_t( m3->getStart( 0 ) ); QDateTime m3end = QDateTime::fromTime_t( m3->getEnd( 0 ) ); QDateTime m4start = QDateTime::fromTime_t( m4->getStart( 0 ) ); QDateTime m4end = QDateTime::fromTime_t( m4->getEnd( 0 ) ); QCOMPARE( m1start, pstart ); QCOMPARE( m2start, m1start ); QCOMPARE( m3start, t1start ); QCOMPARE( t2end, m4end ); QCOMPARE( m4start, pend ); delete proj; } { DebugCtrl.setDebugLevel(1000); DebugCtrl.setDebugMode(7); s = "Test backwards ----------------"; qDebug()<setScheduleGranularity( 300 ); // seconds proj->setStart( pstart.toTime_t() ); proj->setEnd( pend.toTime_t() ); // First an ASAP milestone on project start to precede m2 TJ::Task *m1 = new TJ::Task(proj, "Start", "Start", 0, QString(), 0); m1->setMilestone( true ); m1->setScheduling( TJ::Task::ASAP ); m1->setSpecifiedStart( 0, proj->getStart() ); // ALAP milestone dependent on m1 to simulate bacwards TJ::Task *m2 = new TJ::Task(proj, "M2-ALAP", "M2", 0, QString(), 0); m2->setMilestone( true ); m2->setScheduling( TJ::Task::ASAP ); // Then the "project" TJ::Task *m3 = new TJ::Task(proj, "M3-ASAP", "M3", 0, QString(), 0); m3->setMilestone( true ); m3->setScheduling( TJ::Task::ASAP ); TJ::Task *t1 = new TJ::Task(proj, "T1-ASAP", "T1", 0, QString(), 0); t1->setScheduling( TJ::Task::ASAP ); t1->setDuration( 0, (double)(TJ::ONEHOUR) / TJ::ONEDAY ); TJ::Task *t2 = new TJ::Task(proj, "T2-ALAP", "T2", 0, QString(), 0); t2->setScheduling( TJ::Task::ALAP ); t2->setDuration( 0, (double)(TJ::ONEHOUR) / TJ::ONEDAY ); // Then an ALAP milestone on project end TJ::Task *m4 = new TJ::Task(proj, "End", "End", 0, QString(), 0); m4->setMilestone( true ); m4->setScheduling( TJ::Task::ALAP ); m4->setSpecifiedEnd( 0, proj->getEnd() - 1 ); m1->addPrecedes( m2->getId() ); m2->addPrecedes( m3->getId() ); m3->addDepends( m2->getId() ); t1->addDepends( m3->getId() ); t1->addPrecedes( t2->getId() ); t2->addPrecedes( m4->getId() ); qDebug()<"<"<"<"<"<pass2( true ), s.toLatin1() ); QVERIFY2( proj->scheduleAllScenarios(), s.toLatin1() ); qDebug()<"<"<"<"<"<getStart( 0 ) ); QDateTime t1end = QDateTime::fromTime_t( t1->getEnd( 0 ) ); QDateTime t2start = QDateTime::fromTime_t( t2->getStart( 0 ) ); QDateTime t2end = QDateTime::fromTime_t( t2->getEnd( 0 ) ); QDateTime m1start = QDateTime::fromTime_t( m1->getStart( 0 ) ); QDateTime m1end = QDateTime::fromTime_t( m1->getEnd( 0 ) ); QDateTime m2start = QDateTime::fromTime_t( m2->getStart( 0 ) ); QDateTime m2end = QDateTime::fromTime_t( m2->getEnd( 0 ) ); QDateTime m3start = QDateTime::fromTime_t( m3->getStart( 0 ) ); QDateTime m3end = QDateTime::fromTime_t( m3->getEnd( 0 ) ); QDateTime m4start = QDateTime::fromTime_t( m4->getStart( 0 ) ); QDateTime m4end = QDateTime::fromTime_t( m4->getEnd( 0 ) ); QCOMPARE( m1start, pstart ); QCOMPARE( m2start, m3start ); QCOMPARE( m3start, t1start ); QCOMPARE( t2end, m4end ); QCOMPARE( m4start, pend ); delete proj; } } void TaskJuggler::scheduleConstraints() { DebugCtrl.setDebugMode( 0 ); DebugCtrl.setDebugLevel( 100 ); QString s; QDateTime pstart = QDateTime::fromString( "2011-07-01 09:00:00", Qt::ISODate ); QDateTime pend = pstart.addDays(1); { s = "Test MustStartOn --------------------"; qDebug()<setScheduleGranularity( TJ::ONEHOUR / 2 ); proj->setStart( pstart.toTime_t() ); proj->setEnd( pend.toTime_t() ); TJ::Resource *r = new TJ::Resource( proj, "R1", "R1", 0 ); r->setEfficiency( 1.0 ); for (int day = 0; day < 7; ++day) { r->setWorkingHours( day, *(proj->getWorkingHours(day)) ); } TJ::Task *m = new TJ::Task(proj, "M1", "M1", 0, QString(), 0); m->setMilestone( true ); m->setScheduling( TJ::Task::ASAP ); m->setSpecifiedStart( 0, proj->getStart() ); TJ::Task *t1 = new TJ::Task(proj, "T1", "T1", 0, QString(), 0); t1->setSpecifiedStart( 0, proj->getStart() + TJ::ONEHOUR ); t1->setEffort( 0, 1.0/24.0 ); TJ::Allocation *a = new TJ::Allocation(); a->addCandidate( r ); t1->addAllocation( a ); QVERIFY( proj->pass2( true ) ); QVERIFY( proj->scheduleAllScenarios() ); QDateTime mstart = QDateTime::fromTime_t( m->getStart( 0 ) ); QDateTime mend = QDateTime::fromTime_t( m->getEnd( 0 ) ); QDateTime t1start = QDateTime::fromTime_t( t1->getStart( 0 ) ); QDateTime t1end = QDateTime::fromTime_t( t1->getEnd( 0 ) ); QCOMPARE( mstart, pstart ); QCOMPARE( t1start, mstart.addSecs( TJ::ONEHOUR ) ); delete proj; } { s = "Test one MustStartOn + StartNotEarlier on same time -------------"; qDebug()<setScheduleGranularity( TJ::ONEHOUR / 2 ); proj->setStart( pstart.toTime_t() ); proj->setEnd( pend.toTime_t() ); TJ::Resource *r = new TJ::Resource( proj, "R1", "R1", 0 ); r->setEfficiency( 1.0 ); for (int day = 0; day < 7; ++day) { r->setWorkingHours( day, *(proj->getWorkingHours(day)) ); } TJ::Task *m = new TJ::Task(proj, "M1", "M1", 0, QString(), 0); m->setMilestone( true ); m->setScheduling( TJ::Task::ASAP ); m->setSpecifiedStart( 0, proj->getStart() ); TJ::Task *t1 = new TJ::Task(proj, "T1", "T1", 0, QString(), 0); t1->setPriority( 600 ); // high prio so it is likely it will be scheduled on time t1->setSpecifiedStart( 0, proj->getStart() + TJ::ONEHOUR ); t1->setEffort( 0, 1.0/24.0 ); TJ::Allocation *a = new TJ::Allocation(); a->addCandidate( r ); t1->addAllocation( a ); TJ::Task *t2 = new TJ::Task(proj, "T2", "T2", 0, QString(), 0); t2->setPriority( 500 ); // less than t1 t2->setSpecifiedStart( 0, proj->getStart() + TJ::ONEHOUR ); t2->setEffort( 0, 1.0/24.0 ); a = new TJ::Allocation(); a->addCandidate( r ); t2->addAllocation( a ); m->addPrecedes( t1->getId() ); t1->addDepends( m->getId() ); m->addPrecedes( t2->getId() ); t2->addDepends( m->getId() ); QVERIFY2( proj->pass2( true ), s.toLatin1() ); QVERIFY2( proj->scheduleAllScenarios(), s.toLatin1() ); QDateTime mstart = QDateTime::fromTime_t( m->getStart( 0 ) ); QDateTime mend = QDateTime::fromTime_t( m->getEnd( 0 ) ); QDateTime t1start = QDateTime::fromTime_t( t1->getStart( 0 ) ); QDateTime t1end = QDateTime::fromTime_t( t1->getEnd( 0 ) ); QDateTime t2start = QDateTime::fromTime_t( t2->getStart( 0 ) ); QDateTime t2end = QDateTime::fromTime_t( t2->getEnd( 0 ) ); QCOMPARE( mstart, pstart ); QCOMPARE( t1start, mstart.addSecs( TJ::ONEHOUR ) ); QCOMPARE( t2start, t1end.addSecs( 1 ) ); delete proj; } { s = "Test one MustStartOn + StartNotEarlier overlapping -------------"; qDebug()<setScheduleGranularity( TJ::ONEHOUR / 4 ); proj->setStart( pstart.toTime_t() ); proj->setEnd( pend.toTime_t() ); TJ::Resource *r = new TJ::Resource( proj, "R1", "R1", 0 ); r->setEfficiency( 1.0 ); for (int day = 0; day < 7; ++day) { r->setWorkingHours( day, *(proj->getWorkingHours(day)) ); } TJ::Task *m = new TJ::Task(proj, "M1", "M1", 0, QString(), 0); m->setMilestone( true ); m->setScheduling( TJ::Task::ASAP ); m->setSpecifiedStart( 0, proj->getStart() ); TJ::Task *t1 = new TJ::Task(proj, "T1", "T1", 0, QString(), 0); t1->setPriority( 600 ); // high prio so it is likely it will be scheduled on time t1->setSpecifiedStart( 0, proj->getStart() + TJ::ONEHOUR ); t1->setEffort( 0, 1.0 / proj->getDailyWorkingHours() ); TJ::Allocation *a = new TJ::Allocation(); a->addCandidate( r ); t1->addAllocation( a ); TJ::Task *t2 = new TJ::Task(proj, "T2", "T2", 0, QString(), 0); t2->setPriority( 500 ); // less than t1 t2->setSpecifiedStart( 0, proj->getStart() + TJ::ONEHOUR / 2 ); t2->setEffort( 0, 1.0 / proj->getDailyWorkingHours() ); a = new TJ::Allocation(); a->addCandidate( r ); t2->addAllocation( a ); m->addPrecedes( t1->getId() ); t1->addDepends( m->getId() ); m->addPrecedes( t2->getId() ); t2->addDepends( m->getId() ); QVERIFY2( proj->pass2( true ), s.toLatin1() ); QVERIFY2( proj->scheduleAllScenarios(), s.toLatin1() ); QDateTime mstart = QDateTime::fromTime_t( m->getStart( 0 ) ); QDateTime mend = QDateTime::fromTime_t( m->getEnd( 0 ) ); QDateTime t1start = QDateTime::fromTime_t( t1->getStart( 0 ) ); QDateTime t1end = QDateTime::fromTime_t( t1->getEnd( 0 ) ); QDateTime t2start = QDateTime::fromTime_t( t2->getStart( 0 ) ); QDateTime t2end = QDateTime::fromTime_t( t2->getEnd( 0 ) ); QCOMPARE( mstart, pstart ); QCOMPARE( t1start, mstart.addSecs( TJ::ONEHOUR ) ); QCOMPARE( t2start, mstart.addSecs( TJ::ONEHOUR / 2 ) ); QCOMPARE( t2end, t1end.addSecs( TJ::ONEHOUR / 2 ) ); delete proj; } { s = "Fixed interval with/without allocation-------------"; qDebug()<setScheduleGranularity( TJ::ONEHOUR / 4 ); proj->setStart( pstart.toTime_t() ); proj->setEnd( pend.toTime_t() ); TJ::Resource *r = new TJ::Resource( proj, "R1", "R1", 0 ); r->setEfficiency( 1.0 ); for (int day = 0; day < 7; ++day) { r->setWorkingHours( day, *(proj->getWorkingHours(day)) ); } TJ::Task *m = new TJ::Task(proj, "M1", "M1", 0, QString(), 0); m->setMilestone( true ); m->setScheduling( TJ::Task::ASAP ); m->setSpecifiedStart( 0, proj->getStart() ); TJ::Task *t1 = new TJ::Task(proj, "T1", "T1", 0, QString(), 0); t1->setPriority( 600 ); // high prio so it is likely it will be scheduled on time t1->setSpecifiedStart( 0, proj->getStart() + TJ::ONEHOUR ); t1->setSpecifiedEnd( 0, proj->getStart() + ( 2*TJ::ONEHOUR) -1 ); TJ::Allocation *a = new TJ::Allocation(); a->addCandidate( r ); t1->addAllocation( a ); TJ::Task *t2 = new TJ::Task(proj, "T2", "T2", 0, QString(), 0); t2->setPriority( 500 ); // less than t1 t2->setSpecifiedStart( 0, proj->getStart() + TJ::ONEHOUR ); t1->setSpecifiedEnd( 0, proj->getStart() + ( 2*TJ::ONEHOUR) -1 ); a = new TJ::Allocation(); a->addCandidate( r ); t2->addAllocation( a ); m->addPrecedes( t1->getId() ); t1->addDepends( m->getId() ); m->addPrecedes( t2->getId() ); t2->addDepends( m->getId() ); QVERIFY2( proj->pass2( true ), s.toLatin1() ); QVERIFY2( proj->scheduleAllScenarios(), s.toLatin1() ); QDateTime mstart = QDateTime::fromTime_t( m->getStart( 0 ) ); QDateTime mend = QDateTime::fromTime_t( m->getEnd( 0 ) ); QDateTime t1start = QDateTime::fromTime_t( t1->getStart( 0 ) ); QDateTime t1end = QDateTime::fromTime_t( t1->getEnd( 0 ) ); QDateTime t2start = QDateTime::fromTime_t( t2->getStart( 0 ) ); QDateTime t2end = QDateTime::fromTime_t( t2->getEnd( 0 ) ); QCOMPARE( mstart, pstart ); QCOMPARE( t1start, mstart.addSecs( TJ::ONEHOUR ) ); QCOMPARE( t2start, mstart.addSecs( TJ::ONEHOUR ) ); delete proj; } } void TaskJuggler::resourceConflict() { DebugCtrl.setDebugLevel( 0 ); DebugCtrl.setDebugMode( 0xffff ); QString s; QDateTime pstart = QDateTime::fromString( "2011-07-04 09:00:00", Qt::ISODate ); QDateTime pend = pstart.addDays(1); { s = "Test 2 tasks, allocate same resource --------------------"; qDebug()<setScheduleGranularity( TJ::ONEHOUR ); // seconds proj->setStart( pstart.toTime_t() ); proj->setEnd( pend.toTime_t() ); QCOMPARE( QDateTime::fromTime_t( proj->getStart() ), pstart ); TJ::Resource *r = new TJ::Resource( proj, "R1", "R1", 0 ); r->setEfficiency( 1.0 ); for (int day = 0; day < 7; ++day) { r->setWorkingHours( day, *(proj->getWorkingHours(day)) ); } TJ::Task *m = new TJ::Task(proj, "M1", "M1", 0, QString(), 0); m->setMilestone( true ); m->setScheduling( TJ::Task::ASAP ); m->setSpecifiedStart( 0, proj->getStart() ); TJ::Task *t1 = new TJ::Task(proj, "T1", "T1", 0, QString(), 0); t1->setPriority( 100 ); // this should be scheduled before t2 t1->setEffort( 0, 1.0/24.0 ); TJ::Allocation *a = new TJ::Allocation(); a->addCandidate( r ); t1->addAllocation( a ); TJ::Task *t2 = new TJ::Task(proj, "T2", "T2", 0, QString(), 0); t2->setPriority( 10 ); t2->setEffort( 0, 1.0/24.0 ); a = new TJ::Allocation(); a->addCandidate( r ); t2->addAllocation( a ); m->addPrecedes( t1->getId() ); t1->addDepends( m->getId() ); m->addPrecedes( t2->getId() ); t2->addDepends( m->getId() ); QVERIFY2( proj->pass2( true ), s.toLatin1() ); QVERIFY2( proj->scheduleAllScenarios(), s.toLatin1() ); QDateTime mstart = QDateTime::fromTime_t( m->getStart( 0 ) ); QDateTime mend = QDateTime::fromTime_t( m->getEnd( 0 ) ); QDateTime t1start = QDateTime::fromTime_t( t1->getStart( 0 ) ); QDateTime t1end = QDateTime::fromTime_t( t1->getEnd( 0 ) ); QDateTime t2start = QDateTime::fromTime_t( t2->getStart( 0 ) ); QDateTime t2end = QDateTime::fromTime_t( t2->getEnd( 0 ) ); QCOMPARE( mstart, pstart ); QCOMPARE( t1start, mstart ); QCOMPARE( t2start, t1end.addSecs( 1 ) ); delete proj; } } void TaskJuggler::units() { DebugCtrl.setDebugLevel( 1000 ); DebugCtrl.setDebugMode( TSDEBUG + RSDEBUG ); QString s; QDateTime pstart = QDateTime::fromString( "2011-07-04 09:00:00", Qt::ISODate ); QDateTime pend = pstart.addDays(3); { s = "Test one task, resource 50% using resource limit --------------------"; qDebug()<setScheduleGranularity( TJ::ONEHOUR ); proj->setStart( pstart.toTime_t() ); proj->setEnd( pend.toTime_t() ); QCOMPARE( QDateTime::fromTime_t( proj->getStart() ), pstart ); TJ::Resource *r = new TJ::Resource( proj, "R1", "R1", 0 ); TJ::UsageLimits *l = new TJ::UsageLimits(); l->setDailyUnits( 50 ); r->setLimits( l ); r->setEfficiency( 1.0 ); for (int day = 0; day < 7; ++day) { r->setWorkingHours( day, *(proj->getWorkingHours(day)) ); } TJ::Task *t1 = new TJ::Task(proj, "T1", "T1", 0, QString(), 0); t1->setSpecifiedStart( 0, proj->getStart() ); t1->setEffort( 0, 1.0 ); TJ::Allocation *a = new TJ::Allocation(); a->addCandidate( r ); t1->addAllocation( a ); QVERIFY2( proj->pass2( true ), s.toLatin1() ); QVERIFY2( proj->scheduleAllScenarios(), s.toLatin1() ); QDateTime t1start = QDateTime::fromTime_t( t1->getStart( 0 ) ); QDateTime t1end = QDateTime::fromTime_t( t1->getEnd( 0 ) ); // working hours: 09:00 - 12:00, 13:00 - 18:00 QCOMPARE( t1start, pstart ); QCOMPARE( t1end, t1start.addDays( 1 ).addSecs( 5 * TJ::ONEHOUR - 1) ); // remember lunch delete proj; } { s = "Test one task, resource 50% using resource efficiency --------------------"; qDebug()<setScheduleGranularity( TJ::ONEHOUR / 2 ); proj->setStart( pstart.toTime_t() ); proj->setEnd( pend.toTime_t() ); QCOMPARE( QDateTime::fromTime_t( proj->getStart() ), pstart ); TJ::Resource *r = new TJ::Resource( proj, "R1", "R1", 0 ); r->setEfficiency( 0.5 ); for (int day = 0; day < 7; ++day) { r->setWorkingHours( day, *(proj->getWorkingHours(day)) ); } TJ::Task *t1 = new TJ::Task(proj, "T1", "T1", 0, QString(), 0); t1->setSpecifiedStart( 0, proj->getStart() ); t1->setEffort( 0, 1.0 / proj->getDailyWorkingHours() ); TJ::Allocation *a = new TJ::Allocation(); a->addCandidate( r ); t1->addAllocation( a ); QVERIFY2( proj->pass2( true ), s.toLatin1() ); QVERIFY2( proj->scheduleAllScenarios(), s.toLatin1() ); QDateTime t1start = QDateTime::fromTime_t( t1->getStart( 0 ) ); QDateTime t1end = QDateTime::fromTime_t( t1->getEnd( 0 ) ); // working hours: 09:00 - 12:00, 13:00 - 18:00 QCOMPARE( t1start, pstart ); QCOMPARE( t1end, t1start.addSecs( 2 * TJ::ONEHOUR - 1) ); delete proj; } { s = "Test one task, allocation limit 50% per day --------------------"; qDebug()<setScheduleGranularity( TJ::ONEHOUR / 2 ); proj->setStart( pstart.toTime_t() ); proj->setEnd( pend.toTime_t() ); QCOMPARE( QDateTime::fromTime_t( proj->getStart() ), pstart ); TJ::Resource *r = new TJ::Resource( proj, "R1", "R1", 0 ); r->setEfficiency( 1.0 ); for (int day = 0; day < 7; ++day) { r->setWorkingHours( day, *(proj->getWorkingHours(day)) ); } TJ::Task *t1 = new TJ::Task(proj, "T1", "T1", 0, QString(), 0); t1->setSpecifiedStart( 0, proj->getStart() ); t1->setEffort( 0, 1.0 ); TJ::Allocation *a = new TJ::Allocation(); a->addCandidate( r ); TJ::UsageLimits *l = new TJ::UsageLimits(); l->setDailyUnits( 50 ); a->setLimits( l ); t1->addAllocation( a ); QVERIFY2( proj->pass2( true ), s.toLatin1() ); QVERIFY2( proj->scheduleAllScenarios(), s.toLatin1() ); QDateTime t1start = QDateTime::fromTime_t( t1->getStart( 0 ) ); QDateTime t1end = QDateTime::fromTime_t( t1->getEnd( 0 ) ); // working hours: 09:00 - 12:00, 13:00 - 18:00 QCOMPARE( t1start, pstart ); QCOMPARE( t1end, t1start.addDays( 1 ).addSecs( 5 * TJ::ONEHOUR - 1) ); // remember lunch delete proj; } } } //namespace KPlato QTEST_KDEMAIN_CORE( KPlato::TaskJuggler ) #include "TaskJuggler.moc" diff --git a/plan/workpackage/main.cpp b/plan/workpackage/main.cpp index a9b00d5aabc..8da25a8fd4e 100644 --- a/plan/workpackage/main.cpp +++ b/plan/workpackage/main.cpp @@ -1,53 +1,53 @@ /* This file is part of the KDE project Copyright (C) 2001 Thomas zander This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kplatowork_export.h" #include "aboutdata.h" #include "application.h" #include #include #include #include #include #include #include -#include +#include #include extern "C" KDE_EXPORT int kdemain( int argc, char **argv ) { KCmdLineArgs::init( argc, argv, KPlatoWork::newAboutData()); KCmdLineOptions options; options.add("+[file]", ki18n("File to open")); KCmdLineArgs::addCmdLineOptions( options ); if (!KUniqueApplication::start()) { fprintf(stderr, "PlanWork is already running!\n"); return 0; } KPlatoWork_Application app; fprintf(stderr, "app created\n"); app.exec(); return 0; } diff --git a/plugins/formulashape/tests/TestLayout.cpp b/plugins/formulashape/tests/TestLayout.cpp index 12f19589118..69e3f9b3885 100644 --- a/plugins/formulashape/tests/TestLayout.cpp +++ b/plugins/formulashape/tests/TestLayout.cpp @@ -1,115 +1,115 @@ /* This file is part of the KDE project Copyright 2007 Alfredo Beaumont Sainz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; only version 2 of the License. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "TestLayout.h" #include -#include +#include #include #include #include "AttributeManager.h" #include "IdentifierElement.h" #include "FencedElement.h" #include static QRectF layout(BasicElement* element, const QString& input) { KoXmlDocument doc; doc.setContent( input ); element->readMathML(doc.documentElement()); AttributeManager am; element->layout( &am ); return element->boundingRect(); } static void addRowInternal( const QString& input, const QString& text, const QFont& font ) { QFontMetrics fm( font ); QTest::newRow( "Layout" ) << input << QRectF( fm.boundingRect( text ) ); } static void addRow( const QString& input, const QString& text ) { QFont font; addRowInternal( input, text, font ); } static void addRow( const QString& input, const QString& text, double size ) { QFont font; font.setPointSizeF( size ); addRowInternal( input, text, font); } void TestLayout::identifierElement_data() { QTest::addColumn("input"); QTest::addColumn("output"); addRow( "x", "x"); addRow( "x", "x", 12); } void TestLayout::identifierElement() { QFETCH(QString, input); QFETCH(QRectF, output); IdentifierElement* element = new IdentifierElement; QCOMPARE(layout(element, input), output); delete element; } void TestLayout::fencedElement_data() { QTest::addColumn("input"); QTest::addColumn("output"); addRow( "", "()"); addRow( "x", "(x)"); addRow( "xy", "(x,y)"); addRow( "", "[)"); addRow( "", "[}"); addRow( "", "[}"); addRow( "xyz", "(x;y.z)"); } void TestLayout::fencedElement() { QFETCH(QString, input); QFETCH(QRectF, output); FencedElement* element = new FencedElement; QCOMPARE(layout(element, input), output); delete element; } QTEST_KDEMAIN(TestLayout, GUI) #include "TestLayout.moc" diff --git a/plugins/staging/threedshape/SceneObject.cpp b/plugins/staging/threedshape/SceneObject.cpp index e0de7bcdcde..566bf028c5b 100644 --- a/plugins/staging/threedshape/SceneObject.cpp +++ b/plugins/staging/threedshape/SceneObject.cpp @@ -1,240 +1,240 @@ /* This file is part of the KDE project * * Copyright (C) 2012 Inge Wallin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ // Own #include "SceneObject.h" // Qt #include #include #include -#include +#include // KDE #include // Calligra #include #include #include #include #include #include #include #include #include #include #include #include #include // 3D shape #include "Objects.h" SceneObject::SceneObject(Object3D *parent, bool topLevel) : Object3D(parent) #if IMPLEMENT_AS_SHAPECONTAINER , KoShapeContainer() #endif , m_topLevel(topLevel) , m_threeDParams(0) { } SceneObject::~SceneObject() { delete m_threeDParams; qDeleteAll(m_objects); } /// reimplemented from KoShapeContainer void SceneObject::paintComponent(QPainter &painter, const KoViewConverter &converter, KoShapePaintingContext &paintcontext) { Q_UNUSED(painter); Q_UNUSED(converter); Q_UNUSED(paintcontext); } void SceneObject::paint(QPainter &painter, const KoViewConverter &converter, KoShapePaintingContext &context) { Q_UNUSED(context); //painter.setPen(QPen(QColor(172, 196, 206))); painter.setPen(QPen(QColor(0, 0, 0))); #if 1 painter.drawRect(converter.documentToView(QRectF(QPoint(0, 0), size()))); #else QRectF rect = converter.documentToView(boundingRect()); QRectF rect = converter.documentToView(QRectF(QPoint(0, 0), size())); painter.drawRect(rect); #endif kDebug(31000) << "boundingRect: " << boundingRect(); kDebug(31000) << "outlineRect: " << outlineRect(); #if 0 // Taken from the vector shape QRectF rect(QPointF(0,0), m_size); painter.save(); // Draw a simple cross in a rectangle just to indicate that there is something here. painter.setPen(QPen(QColor(172, 196, 206))); painter.drawRect(rect); painter.drawLine(rect.topLeft(), rect.bottomRight()); painter.drawLine(rect.bottomLeft(), rect.topRight()); painter.restore(); #endif } void SceneObject::saveOdf(KoShapeSavingContext &context) const { if (m_topLevel) { saveObjectOdf(context); } } void SceneObject::saveObjectOdf(KoShapeSavingContext &context) const { KoXmlWriter &writer = context.xmlWriter(); writer.startElement("dr3d:scene"); if (m_topLevel) { saveOdfAttributes(context, (OdfAdditionalAttributes | OdfMandatories | OdfGeometry)); } else { saveOdfAttributes(context, (OdfAdditionalAttributes | OdfMandatories)); } if (m_topLevel && m_threeDParams) m_threeDParams->saveOdfAttributes(writer); // 2.1 Light sources if (m_topLevel && m_threeDParams) m_threeDParams->saveOdfChildren(writer); // 2.2 Objects in the scene foreach (const Object3D *object, m_objects) { object->saveObjectOdf(context); } writer.endElement(); // dr3d:scene } bool SceneObject::loadOdf(const KoXmlElement &sceneElement, KoShapeLoadingContext &context) { // Load style information. if (m_topLevel) { loadOdfAttributes(sceneElement, context, (OdfAdditionalAttributes | OdfMandatories | OdfGeometry)); } else { loadOdfAttributes(sceneElement, context, (OdfAdditionalAttributes | OdfMandatories)); } Object3D::loadOdf(sceneElement, context); // Load the view parameters. if (m_topLevel) { m_threeDParams = load3dScene(sceneElement); } // Load the child elements, i.e the scene itself. // From the ODF 1.1 spec section 9.4.1: // // The elements that may be contained in the element are: // * Title (short accessible name) – see section 9.2.20. // * Long description (in support of accessibility) – see section 9.2.20. // * Light – see section 9.4.2. (handled by Ko3DScene) // // * Scene – see section 9.4.1. [All of these can be 0 or more.] // * Cube – see section 9.4.3. // * Sphere – see section 9.4.4. // * Extrude – see section 9.4.5. // * Rotate – see section 9.4.6. // // The lights are skipped here, they are taken care of by the call // to load3dScene() above. KoXmlElement elem; forEachElement(elem, sceneElement) { if (elem.localName() == "scene" && elem.namespaceURI() == KoXmlNS::dr3d) { SceneObject *scene = new SceneObject(this, false); scene->loadOdf(elem, context); m_objects.append(scene); #if IMPLEMENT_AS_SHAPECONTAINER addShape(scene); #endif } else if (elem.localName() == "sphere" && elem.namespaceURI() == KoXmlNS::dr3d) { Sphere *sphere = new Sphere(this); sphere->loadOdf(elem, context); m_objects.append(sphere); #if IMPLEMENT_AS_SHAPECONTAINER addShape(sphere); #endif } else if (elem.localName() == "cube" && elem.namespaceURI() == KoXmlNS::dr3d) { Cube *cube = new Cube(this); cube->loadOdf(elem, context); m_objects.append(cube); #if IMPLEMENT_AS_SHAPECONTAINER addShape(cube); #endif } else if (elem.localName() == "extrude" && elem.namespaceURI() == KoXmlNS::dr3d) { Extrude *extrude = new Extrude(this); extrude->loadOdf(elem, context); m_objects.append(extrude); #if IMPLEMENT_AS_SHAPECONTAINER addShape(extrude); #endif } else if (elem.localName() == "rotate" && elem.namespaceURI() == KoXmlNS::dr3d) { Rotate *rotate = new Rotate(this); rotate->loadOdf(elem, context); m_objects.append(rotate); #if IMPLEMENT_AS_SHAPECONTAINER addShape(rotate); #endif } } kDebug(31000) << "Objects:" << m_objects.size(); #if IMPLEMENT_AS_SHAPECONTAINER kDebug(31000) << "Objects in shape container:" << shapeCount(); #endif return true; } void SceneObject::waitUntilReady(const KoViewConverter &converter, bool asynchronous) const { Q_UNUSED(converter); Q_UNUSED(asynchronous); } #include diff --git a/sheets/interfaces/MapAdaptor.h b/sheets/interfaces/MapAdaptor.h index 3236969d481..ced48c29c2d 100644 --- a/sheets/interfaces/MapAdaptor.h +++ b/sheets/interfaces/MapAdaptor.h @@ -1,70 +1,70 @@ /* This file is part of the KDE project Copyright 1999-2000 Torben Weis This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef CALLIGRA_SHEETS_MAP_ADAPTOR #define CALLIGRA_SHEETS_MAP_ADAPTOR #include -#include +#include #include "calligra_sheets_export.h" namespace Calligra { namespace Sheets { class Map; /** * The MapAdaptor class provides additional functionality to deal with sheets. */ class CALLIGRA_SHEETS_COMMON_EXPORT MapAdaptor : public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.calligra.spreadsheet.map") public: explicit MapAdaptor(Map*); // virtual bool processDynamic(const DCOPCString &fun, const QByteArray &data, // DCOPCString& replyType, QByteArray &replyData); public Q_SLOTS: // METHODS /** Return the objectName of the sheet with the defined sheet name. */ virtual QString sheet(const QString& name); /** Return the objectName of the sheet with the defined index. */ virtual QString sheetByIndex(int index); /** Return the number of available sheets. */ virtual int sheetCount() const; /** Return a list of available sheet names. */ virtual QStringList sheetNames() const; /** Return a list of available sheet objectName's. */ virtual QStringList sheets(); /** Insert a new sheet with the defined sheet name. */ virtual QString insertSheet(const QString& name); private: Map* m_map; }; } // namespace Sheets } // namespace Calligra #endif diff --git a/sheets/interfaces/SheetAdaptor.h b/sheets/interfaces/SheetAdaptor.h index 3ca28c71cb3..cf0ec69f975 100644 --- a/sheets/interfaces/SheetAdaptor.h +++ b/sheets/interfaces/SheetAdaptor.h @@ -1,193 +1,193 @@ /* This file is part of the KDE project Copyright 2006 Fredrik Edemar Copyright 2000, 2003 Laurent Montel Copyright 2002-2003 Joseph Wenninger Copyright 2002 Philipp Mueller Copyright 2002 Ariya Hidayat Copyright 2002 John Dailey Copyright 1999 Torben Weis This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef CALLIGRA_SHEETS_SHEET_ADAPTOR #define CALLIGRA_SHEETS_SHEET_ADAPTOR -#include +#include #include "calligra_sheets_export.h" #include namespace Calligra { namespace Sheets { class Damage; class Sheet; class CellProxy; class CALLIGRA_SHEETS_COMMON_EXPORT SheetAdaptor : public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.calligra.spreadsheet.sheet") public: explicit SheetAdaptor(Sheet*); ~SheetAdaptor(); public Q_SLOTS: // METHODS /** Return the cellname for x,y (where x is the row and y is the column). For example for x=5 and y=2 the string "B5" got returned. */ virtual QString cellName(int x, int y); /** Return the x,y-point for the cellname. */ virtual QPoint cellLocation(const QString& cellname); /** Return the row-number for the cellname. For example for the cellname "B5" the integer 5 got returned. */ virtual int cellRow(const QString& cellname); /** Return the column-number for the cellname. For example for the cellname "B5" the integer 2 got returned. */ virtual int cellColumn(const QString& cellname); /** Return the text for the row x and for the column y. */ virtual QString text(int x, int y); /** Return the text for a cellname. */ virtual QString text(const QString& cellname); /** Set the text of the cell with row x and column y. If the parse argument is true, the passed text got parsed (e.g. a text like "123" will be recognised as numeric value. */ virtual bool setText(int x, int y, const QString& text, bool parse = true); /** Set the text of the cell defined with cellname. */ virtual bool setText(const QString& cellname, const QString& text, bool parse = true); /** Return the value the cell at row x and column y has. The returned value is a variant and could be e.g. a number, a bool or a text depending on the format and the content the cell has. */ virtual QVariant value(int x, int y); /** Return the value for the cell defined with cellname. */ virtual QVariant value(const QString& cellname); /** Set the value in the cell at row x and column y. */ virtual bool setValue(int x, int y, const QVariant& value); /** Set the value in the cell defined with cellname. */ virtual bool setValue(const QString& cellname, const QVariant& value); /** Return the name of the sheet. */ virtual QString sheetName() const; /** Set the name of the sheet. */ virtual bool setSheetName(const QString & name); //virtual QString column( int _col ); //virtual QString row( int _row ); /** Return the position the last column on this sheet has. */ virtual int lastColumn() const; /** Return the position the last row on this sheet has. */ virtual int lastRow() const; /** Inserts nbCol number of new columns at the position col. All columns which are >= col are moved to the right. */ virtual void insertColumn(int col, int nbCol = 1); /** Inserts nbRow number of new rows at the position row. All rows which are >= row are moved down. */ virtual void insertRow(int row, int nbRow = 1); /** Remove nbCol number of columns from the position col. */ virtual void removeColumn(int col, int nbCol = 1); /** Remove nbRow number of columns from the position row. */ virtual void removeRow(int row, int nbRow = 1); /** Returns true if the sheet is hidden else false is returned. */ virtual bool isHidden() const; /** Hide the sheet if the argument hidden is true or show it if hidden is false. */ virtual void setHidden(bool hidden); //virtual bool showGrid() const; //virtual bool showFormula() const; //virtual bool lcMode() const; //virtual bool autoCalc() const; //virtual bool showColumnNumber() const; //virtual bool hideZero() const; //virtual bool firstLetterUpper() const; //virtual void setShowPageBorders( bool b ); /** Return the height the paper of the printer has. */ virtual float paperHeight() const; /** Set the height the paper of the printer has. */ virtual void setPrinterHeight(float height); /** Return the width the paper of the printer has. */ virtual float paperWidth() const; /** Set the width the paper of the printer has. */ virtual void setPaperWidth(float width); /** Return the left border the paper of the printer has. */ virtual float paperLeftBorder() const; /** Return the right border the paper of the printer has. */ virtual float paperRightBorder() const; /** Return the top border the paper of the printer has. */ virtual float paperTopBorder() const; /** Return the bottom border the paper of the printer has. */ virtual float paperBottomBorder() const; /** Return the name of the paper format (like "A4" or "Letter"). */ virtual QString paperFormat() const; /** Return the name of the paper orientation (like "Portrait" or "Landscape"). */ virtual QString paperOrientation() const; /** Set the left, top, right and bottom border as well as the page format and orientation the paper of the printer has. */ virtual void setPaperLayout(float leftBorder, float topBorder, float rightBorder, float bottomBoder, const QString& format, const QString& orientation); //QString printHeadLeft() const; //QString printHeadMid() const; //QString printHeadRight() const; //QString printFootLeft() const; //QString printFootMid() const; //QString printFootRight() const; //void setPrintHeaderLeft(const QString & text); //void setPrintHeaderMiddle(const QString & text); //void setPrintHeaderRight(const QString & text); //void setPrintFooterLeft(const QString & text); //void setPrintFooterMiddle(const QString & text); //void setPrintFooterRight(const QString & text); //NOTE: don't publish "QByteArray password()" cause that may introduce insecure situations... /** Return true if passwd is the correct password. */ virtual bool checkPassword(const QByteArray& passwd) const; /** Return true if the sheet/document is protected. */ virtual bool isProtected() const; /** Protect the document with the password passwd. */ virtual void setProtected(const QByteArray& passwd); Q_SIGNALS: /** This signal got emitted if the name of the sheet changed. */ void nameChanged(); /** This signal got emitted if the sheet got shown. */ void showChanged(); /** This signal got emitted if the sheet got hidden. */ void hideChanged(); private Q_SLOTS: /** * \ingroup Damages * Handles changes of the sheet name and visibility. */ void handleDamages(const QList& damages); private: Sheet* m_sheet; QByteArray ident; }; } // namespace Sheets } // namespace Calligra #endif // CALLIGRA_SHEETS_SHEET_ADAPTOR diff --git a/sheets/interfaces/ViewAdaptor.h b/sheets/interfaces/ViewAdaptor.h index 6f47a45c7ed..b5f33ab98bb 100644 --- a/sheets/interfaces/ViewAdaptor.h +++ b/sheets/interfaces/ViewAdaptor.h @@ -1,263 +1,263 @@ /* This file is part of the KDE project Copyright (C) 2006 Fredrik Edemar Copyright 2002-2003 Joseph Wenninger Copyright 2002 John Dailey Copyright 2001-2002 Laurent Montel Copyright 2000 Simon Hausmann Copyright 1999 Torben Weis This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef CALLIGRA_SHEETS_VIEW_ADAPTOR #define CALLIGRA_SHEETS_VIEW_ADAPTOR #include #include #include -#include +#include #include "calligra_sheets_export.h" namespace Calligra { namespace Sheets { class View; class CellProxy; /** * The ViewAdaptor class provides access to a view on a KSpread document. */ class CALLIGRA_SHEETS_COMMON_EXPORT ViewAdaptor : public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.calligra.spreadsheet.view") public: explicit ViewAdaptor(View*); ~ViewAdaptor(); public Q_SLOTS: // METHODS /** Return the name of the document the view looks on. */ virtual QString doc() const; /** Return the name of the map for the document. An map offers additional functionality to deal with the content of a document. */ virtual QString map() const; /** Return the name of the active sheet. */ virtual QString sheet() const; virtual void changeNbOfRecentFiles(int _nb); /** Hide the view. */ virtual void hide(); /** Show the view. */ virtual void show(); /** Set the range of cells that should be selected. */ virtual void setSelection(const QRect& selection); /** Return the range of cells that is selected. */ virtual QRect selection(); #if 0 // -> cell tool /** Display the find dialog to find something in the document. */ virtual void find(); /** Display the replace dialog to replace something in the document. */ virtual void replace(); /** Display the Conditional dialog that allows to set cell style based on certain conditions. */ virtual void conditional(); /** Display the Validity dialog that enables to set tests to confirm cell data is valid. */ virtual void validity(); /** Display the "Series" dialog that allows to insert series into cells. */ virtual void insertSeries(); /** Display the "Hyperlink" dialog that provides functionality to insert hyperlinks like URLs or E-Mails into a cell. */ virtual void insertHyperlink(); /** Display the "Go to..." dialog that enables to go to a defined cell. */ virtual void gotoCell(); /** Display the "Change Angle" dialog to offer to change the angle of a cell. */ virtual void changeAngle(); #endif virtual void preference(); /** Select the next sheet as active sheet. */ virtual void nextSheet(); /** Select the previous sheet as active sheet. */ virtual void previousSheet(); /** Select the sheet with name \p sheetName as active sheet. */ virtual bool showSheet(const QString& sheetName); #if 0 // -> cell tool /** Display the dialog to create a custom lists for sorting or autofill. */ virtual void sortList(); /** Set a name for a region of the spreadsheet. */ virtual void setAreaName(); /** Show the dialog that allows to edit or select named areas. */ virtual void showAreaName(); /** Merge the selected region. */ virtual void mergeCell(); /** Unmerge the selected region. */ virtual void dissociateCell(); /** Display the "Consolidate..." dialog. */ virtual void consolidate(); /** Delete a column from the sheet. */ virtual void deleteColumn(); /** Insert a new column into the sheet. */ virtual void insertColumn(); /** Delete a row from the sheet. */ virtual void deleteRow(); /** Insert a new row into the sheet. */ virtual void insertRow(); /** Hide a row in the sheet. */ virtual void hideRow(); /** Show a row in the sheet. */ virtual void showRow(); /** Hide a column in the sheet. */ virtual void hideColumn(); /** Show a column in the sheet. */ virtual void showColumn(); /** Convert all letters to upper case. */ virtual void upper(); /** Convert all letters to lower case. */ virtual void lower(); /** Equalize Column. */ virtual void equalizeColumn(); /** Equalize Row. */ virtual void equalizeRow(); /** Remove the contents of the current cell. */ virtual void clearTextSelection(); /** Remove comment from the selected cells. */ virtual void clearCommentSelection(); /** Remove the validity tests on this cell. */ virtual void clearValiditySelection(); /** Remove the conditional cell styles. */ virtual void clearConditionalSelection(); /** Displays the "Goal seek" dialog. */ virtual void goalSeek(); /** Calls the Insert/Database dialog. */ virtual void insertFromDatabase(); /** Calls the Insert/Textfile dialog. */ virtual void insertFromTextfile(); /** Calls the Insert/Clipboard dialog. */ virtual void insertFromClipboard(); /** Display the "Text to Columns..." dialog. */ virtual void textToColumns(); #endif /** Copy the content of the range of cells that is selected. */ virtual void copyAsText(); #if 0 // -> cell tool /** Set the cell formatting to look like your local currency. */ virtual void setSelectionMoneyFormat(bool b); /** Set the cell formatting to look like a percentage. */ virtual void setSelectionPercent(bool b); /** Make the cell text wrap onto multiple lines. */ virtual void setSelectionMultiRow(bool enable); /** Set the font size of the selected cells to the defined size. */ virtual void setSelectionSize(int size); /** Convert all letters to upper case. */ virtual void setSelectionUpper(); /** Convert all letters to lower case. */ virtual void setSelectionLower(); /** Convert First Letter to Upper Case. */ virtual void setSelectionFirstLetterUpper(); /** Print cell contents vertically. */ virtual void setSelectionVerticalText(bool enable); #endif /** Set the comment of all selected cells to the defined comment string. */ virtual void setSelectionComment(const QString& comment); #if 0 // -> cell tool /** Set the angle of all selected cells to the defined angle value. */ virtual void setSelectionAngle(int value); #endif /** Set the text color of all selected cells to the defined color value. */ virtual void setSelectionTextColor(const QColor& txtColor); /** Set the background color of all selected cells to the defined color value. */ virtual void setSelectionBgColor(const QColor& bgColor); /** Set the border color of all selected cells to the defined color value. */ virtual void setSelectionBorderColor(const QColor& bdColor); #if 0 // -> cell tool /** Delete content of the range of cells that is selected. */ virtual void deleteSelection(); /** Copy the content of the range of cells that is selected. */ virtual void copySelection(); /** Cut the content of the range of cells that is selected. */ virtual void cutSelection(); #endif /** Set the color of the left border. */ virtual void setLeftBorderColor(const QColor& color); /** Set the color of the top border. */ virtual void setTopBorderColor(const QColor& color); /** Set the color of the right border. */ virtual void setRightBorderColor(const QColor& color); /** Set the color of the bottom border. */ virtual void setBottomBorderColor(const QColor& color); /** Set the color of the all borders. */ virtual void setAllBorderColor(const QColor& color); /** Set the color of the outline border. */ virtual void setOutlineBorderColor(const QColor& color); #if 0 // -> cell tool /** Remove border. */ virtual void removeBorder(); /** Increase the indention. */ virtual void increaseIndent(); /** Decrease the indention. */ virtual void decreaseIndent(); /** Increase the precision. */ virtual void increasePrecision(); /** Decrease the precision. */ virtual void decreasePrecision(); /** Display the "Subtotals..." dialog. */ void subtotals(); /** Sort a group of cells in ascending (first to last) order. */ void sortInc(); /** Sort a group of cells in decreasing (last to first) order. */ void sortDec(); /** Display the "Layout..." dialog. */ void layoutDlg(); /** Increase the size of the font. */ void increaseFontSize(); /** Decrease the size of the font. */ void decreaseFontSize(); #endif Q_SIGNALS: /** This signal got emitted if this view got activated or deactivated. */ void activated(bool active); /** This signal got emitted if this view got selected or unselected. */ void selected(bool select); /** This signal got emitted if the selection changed. */ void selectionChanged(); private: View* m_view; CellProxy* m_proxy; }; } // namespace Sheets } // namespace Calligra #endif // CALLIGRA_SHEETS_VIEW_ADAPTOR diff --git a/sheets/part/Doc.cpp b/sheets/part/Doc.cpp index 8e563095b15..ca41249e86a 100644 --- a/sheets/part/Doc.cpp +++ b/sheets/part/Doc.cpp @@ -1,627 +1,627 @@ /* This file is part of the KDE project Copyright 2007 Stefan Nikolaus Copyright 2007 Thorsten Zachmann Copyright 2005-2006 Inge Wallin Copyright 2004 Ariya Hidayat Copyright 2002-2003 Norbert Andres Copyright 2000-2002 Laurent Montel Copyright 2002 John Dailey Copyright 2002 Phillip Mueller Copyright 2000 Werner Trobin Copyright 1999-2000 Simon Hausmann Copyright 1999 David Faure Copyright 1998-2000 Torben Weis This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // Local #include "Doc.h" #include "../DocBase_p.h" #include #include #include #include #include #include #include #include #include //Added by qt3to4: #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "BindingManager.h" #include "CalculationSettings.h" #include "Canvas.h" #include "CanvasItem.h" #include "DependencyManager.h" #include "Factory.h" #include "Formula.h" #include "Function.h" #include "FunctionModuleRegistry.h" #include "HeaderFooter.h" #include "LoadingInfo.h" #include "Localization.h" #include "Map.h" #include "NamedAreaManager.h" #include "PrintSettings.h" #include "RecalcManager.h" #include "Sheet.h" #include "SheetPrint.h" #include "StyleManager.h" #include "Util.h" #include "View.h" #include "SheetAccessModel.h" #include "BindingModel.h" // D-Bus #ifndef QT_NO_DBUS #include "interfaces/MapAdaptor.h" #include "interfaces/SheetAdaptor.h" -#include +#include #endif // chart shape #include "plugins/chartshape/ChartShape.h" #include "chart/ChartDialog.h" // ui #include "ui/Selection.h" #include "ui/SheetView.h" using namespace std; using namespace Calligra::Sheets; class Doc::Private { public: Map *map; static QList s_docs; static int s_docId; // document properties bool configLoadFromFile : 1; QStringList spellListIgnoreAll; SavedDocParts savedDocParts; SheetAccessModel *sheetAccessModel; KoDocumentResourceManager *resourceManager; }; // Make sure an appropriate DTD is available in www/calligra/DTD if changing this value static const char * CURRENT_DTD_VERSION = "1.2"; /***************************************************************************** * * Doc * *****************************************************************************/ QList Doc::Private::s_docs; int Doc::Private::s_docId = 0; Doc::Doc(KoPart *part) : DocBase(part) , dd(new Private) { connect(d->map, SIGNAL(sheetAdded(Sheet*)), this, SLOT(sheetAdded(Sheet*))); #ifndef QT_NO_DBUS new MapAdaptor(d->map); QDBusConnection::sessionBus().registerObject('/' + objectName() + '/' + d->map->objectName(), d->map); #endif // Init chart shape factory with KSpread's specific configuration panels. KoShapeFactoryBase *chartShape = KoShapeRegistry::instance()->value(ChartShapeId); if (chartShape) { QList panels = ChartDialog::panels(d->map); chartShape->setOptionPanels(panels); } connect(d->map, SIGNAL(commandAdded(KUndo2Command *)), this, SLOT(addCommand(KUndo2Command *))); // Load the function modules. FunctionModuleRegistry::instance()->loadFunctionModules(); } Doc::~Doc() { //don't save config when words is embedded into konqueror saveConfig(); delete dd; } void Doc::initEmpty() { KSharedConfigPtr config = Factory::global().config(); const int page = config->group("Parameters").readEntry("NbPage", 1); for (int i = 0; i < page; ++i) map()->addNewSheet(); resetURL(); initConfig(); map()->styleManager()->createBuiltinStyles(); KoDocument::initEmpty(); } void Doc::saveConfig() { KSharedConfigPtr config = Factory::global().config(); Q_UNUSED(config); } void Doc::initConfig() { KSharedConfigPtr config = Factory::global().config(); const int page = config->group("Tables Page Layout").readEntry("Default unit page", 0); setUnit(KoUnit::fromListForUi(page, KoUnit::HidePixel)); } int Doc::supportedSpecialFormats() const { return KoDocument::supportedSpecialFormats(); } bool Doc::completeSaving(KoStore* _store) { Q_UNUSED(_store); return true; } QDomDocument Doc::saveXML() { /* don't pull focus away from the editor if this is just a background autosave */ if (!isAutosaving()) {/* FIXME foreach(KoView* view, views()) static_cast(view)->selection()->emitCloseEditor(true); */ emit closeEditor(true); } QDomDocument doc = KoDocument::createDomDocument("tables", "spreadsheet", CURRENT_DTD_VERSION); QDomElement spread = doc.documentElement(); spread.setAttribute("editor", "Calligra Sheets"); spread.setAttribute("mime", "application/x-kspread"); spread.setAttribute("syntaxVersion", CURRENT_SYNTAX_VERSION); if (!d->spellListIgnoreAll.isEmpty()) { QDomElement spellCheckIgnore = doc.createElement("SPELLCHECKIGNORELIST"); spread.appendChild(spellCheckIgnore); for (QStringList::Iterator it = d->spellListIgnoreAll.begin(); it != d->spellListIgnoreAll.end(); ++it) { QDomElement spellElem = doc.createElement("SPELLCHECKIGNOREWORD"); spellCheckIgnore.appendChild(spellElem); spellElem.setAttribute("word", *it); } } SavedDocParts::const_iterator iter = d->savedDocParts.constBegin(); SavedDocParts::const_iterator end = d->savedDocParts.constEnd(); while (iter != end) { // save data we loaded in the beginning and which has no owner back to file spread.appendChild(iter.value().documentElement()); ++iter; } QDomElement e = map()->save(doc); /*FIXME // Save visual info for the first view, such as active sheet and active cell // It looks like a hack, but reopening a document creates only one view anyway (David) View *const view = static_cast(views().first()); Canvas *const canvas = view->canvasWidget(); e.setAttribute("activeTable", canvas->activeSheet()->sheetName()); e.setAttribute("markerColumn", view->selection()->marker().x()); e.setAttribute("markerRow", view->selection()->marker().y()); e.setAttribute("xOffset", canvas->xOffset()); e.setAttribute("yOffset", canvas->yOffset()); */ spread.appendChild(e); setModified(false); return doc; } bool Doc::loadChildren(KoStore* _store) { return map()->loadChildren(_store); } bool Doc::loadXML(const KoXmlDocument& doc, KoStore*) { QPointer updater; if (progressUpdater()) { updater = progressUpdater()->startSubtask(1, "KSpread::Doc::loadXML"); updater->setProgress(0); } d->spellListIgnoreAll.clear(); // KoXmlElement spread = doc.documentElement(); if (spread.attribute("mime") != "application/x-kspread" && spread.attribute("mime") != "application/vnd.kde.kspread") { setErrorMessage(i18n("Invalid document. Expected mimetype application/x-kspread or application/vnd.kde.kspread, got %1" , spread.attribute("mime"))); return false; } bool ok = false; int version = spread.attribute("syntaxVersion").toInt(&ok); map()->setSyntaxVersion(ok ? version : 0); if (map()->syntaxVersion() > CURRENT_SYNTAX_VERSION) { int ret = KMessageBox::warningContinueCancel( 0, i18n("This document was created with a newer version of Calligra Sheets (syntax version: %1)\n" "When you open it with this version of Calligra Sheets, some information may be lost.", map()->syntaxVersion()), i18n("File Format Mismatch"), KStandardGuiItem::cont()); if (ret == KMessageBox::Cancel) { setErrorMessage("USER_CANCELED"); return false; } } // KoXmlElement loc = spread.namedItem("locale").toElement(); if (!loc.isNull()) static_cast(map()->calculationSettings()->locale())->load(loc); if (updater) updater->setProgress(5); KoXmlElement defaults = spread.namedItem("defaults").toElement(); if (!defaults.isNull()) { double dim = defaults.attribute("row-height").toDouble(&ok); if (!ok) return false; map()->setDefaultRowHeight(dim); dim = defaults.attribute("col-width").toDouble(&ok); if (!ok) return false; map()->setDefaultColumnWidth(dim); } KoXmlElement ignoreAll = spread.namedItem("SPELLCHECKIGNORELIST").toElement(); if (!ignoreAll.isNull()) { KoXmlElement spellWord = spread.namedItem("SPELLCHECKIGNORELIST").toElement(); spellWord = spellWord.firstChild().toElement(); while (!spellWord.isNull()) { if (spellWord.tagName() == "SPELLCHECKIGNOREWORD") { d->spellListIgnoreAll.append(spellWord.attribute("word")); } spellWord = spellWord.nextSibling().toElement(); } } if (updater) updater->setProgress(40); // In case of reload (e.g. from konqueror) qDeleteAll(map()->sheetList()); map()->sheetList().clear(); KoXmlElement styles = spread.namedItem("styles").toElement(); if (!styles.isNull()) { if (!map()->styleManager()->loadXML(styles)) { setErrorMessage(i18n("Styles cannot be loaded.")); return false; } } // KoXmlElement mymap = spread.namedItem("map").toElement(); if (mymap.isNull()) { setErrorMessage(i18n("Invalid document. No map tag.")); return false; } if (!map()->loadXML(mymap)) { return false; } // named areas const KoXmlElement areaname = spread.namedItem("areaname").toElement(); if (!areaname.isNull()) map()->namedAreaManager()->loadXML(areaname); //Backwards compatibility with older versions for paper layout if (map()->syntaxVersion() < 1) { KoXmlElement paper = spread.namedItem("paper").toElement(); if (!paper.isNull()) { loadPaper(paper); } } if (updater) updater->setProgress(85); KoXmlElement element(spread.firstChild().toElement()); while (!element.isNull()) { QString tagName(element.tagName()); if (tagName != "locale" && tagName != "map" && tagName != "styles" && tagName != "SPELLCHECKIGNORELIST" && tagName != "areaname" && tagName != "paper") { // belongs to a plugin, load it and save it for later use QDomDocument doc; KoXml::asQDomElement(doc, element); d->savedDocParts[ tagName ] = doc; } element = element.nextSibling().toElement(); } if (updater) updater->setProgress(90); initConfig(); if (updater) updater->setProgress(100); return true; } void Doc::loadPaper(KoXmlElement const & paper) { KoPageLayout pageLayout; pageLayout.format = KoPageFormat::formatFromString(paper.attribute("format")); pageLayout.orientation = (paper.attribute("orientation") == "Portrait") ? KoPageFormat::Portrait : KoPageFormat::Landscape; // KoXmlElement borders = paper.namedItem("borders").toElement(); if (!borders.isNull()) { pageLayout.leftMargin = MM_TO_POINT(borders.attribute("left").toFloat()); pageLayout.rightMargin = MM_TO_POINT(borders.attribute("right").toFloat()); pageLayout.topMargin = MM_TO_POINT(borders.attribute("top").toFloat()); pageLayout.bottomMargin = MM_TO_POINT(borders.attribute("bottom").toFloat()); } //apply to all sheet foreach(Sheet* sheet, map()->sheetList()) { sheet->printSettings()->setPageLayout(pageLayout); } QString hleft, hright, hcenter; QString fleft, fright, fcenter; // KoXmlElement head = paper.namedItem("head").toElement(); if (!head.isNull()) { KoXmlElement left = head.namedItem("left").toElement(); if (!left.isNull()) hleft = left.text(); KoXmlElement center = head.namedItem("center").toElement(); if (!center.isNull()) hcenter = center.text(); KoXmlElement right = head.namedItem("right").toElement(); if (!right.isNull()) hright = right.text(); } // KoXmlElement foot = paper.namedItem("foot").toElement(); if (!foot.isNull()) { KoXmlElement left = foot.namedItem("left").toElement(); if (!left.isNull()) fleft = left.text(); KoXmlElement center = foot.namedItem("center").toElement(); if (!center.isNull()) fcenter = center.text(); KoXmlElement right = foot.namedItem("right").toElement(); if (!right.isNull()) fright = right.text(); } //The macro "" formerly was typed as "" hleft = hleft.replace("
", ""); hcenter = hcenter.replace("
", ""); hright = hright.replace("
", ""); fleft = fleft.replace("
", ""); fcenter = fcenter.replace("
", ""); fright = fright.replace("
", ""); foreach(Sheet* sheet, map()->sheetList()) { sheet->print()->headerFooter()->setHeadFootLine(hleft, hcenter, hright, fleft, fcenter, fright); } } bool Doc::completeLoading(KoStore* store) { kDebug(36001) << "------------------------ COMPLETING --------------------"; setModified(false); bool ok = map()->completeLoading(store); kDebug(36001) << "------------------------ COMPLETION DONE --------------------"; return ok; } bool Doc::docData(QString const & xmlTag, QDomDocument & data) { SavedDocParts::iterator iter = d->savedDocParts.find(xmlTag); if (iter == d->savedDocParts.end()) return false; data = iter.value(); d->savedDocParts.erase(iter); return true; } void Doc::addIgnoreWordAllList(const QStringList & _lst) { d->spellListIgnoreAll = _lst; } QStringList Doc::spellListIgnoreAll() const { return d->spellListIgnoreAll; } void Doc::paintContent(QPainter& painter, const QRect& rect) { paintContent(painter, rect, 0); } void Doc::paintContent(QPainter& painter, const QRect& rect, Sheet* _sheet) { if (rect.isEmpty()) { return; } Sheet *const sheet = _sheet ? _sheet : d->map->sheet(0); const KoPageLayout pageLayout = sheet->printSettings()->pageLayout(); QPixmap thumbnail(pageLayout.width, pageLayout.height); thumbnail.fill(Qt::white); SheetView sheetView(sheet); const qreal zoom = sheet->printSettings()->zoom(); KoZoomHandler zoomHandler; zoomHandler.setZoom(zoom); sheetView.setViewConverter(&zoomHandler); sheetView.setPaintCellRange(sheet->print()->cellRange(1)); // first page QPainter pixmapPainter(&thumbnail); pixmapPainter.setClipRect(QRect(QPoint(0, 0), thumbnail.size())); sheetView.paintCells(pixmapPainter, QRect(0, 0, pageLayout.width, pageLayout.height), QPointF(0,0)); // The pixmap gets scaled to fit the rectangle. painter.drawPixmap(rect & QRect(0, 0, 100, 100), thumbnail); } void Doc::updateAllViews() { emit updateView(); } void Doc::updateBorderButton() {/*FIXME foreach(KoView* view, views()) static_cast(view)->updateBorderButton();*/ emit updateBorderButton(); } void Doc::addIgnoreWordAll(const QString & word) { if (d->spellListIgnoreAll.indexOf(word) == -1) d->spellListIgnoreAll.append(word); } void Doc::clearIgnoreWordAll() { d->spellListIgnoreAll.clear(); } void Doc::loadConfigFromFile() { d->configLoadFromFile = true; } bool Doc::configLoadFromFile() const { return d->configLoadFromFile; } void Doc::sheetAdded(Sheet* sheet) { #ifndef QT_NO_DBUS new SheetAdaptor(sheet); QString dbusPath('/' + sheet->map()->objectName() + '/' + sheet->objectName()); if (sheet->parent() && !sheet->parent()->objectName().isEmpty()) { dbusPath.prepend('/' + sheet->parent()->objectName()); } QDBusConnection::sessionBus().registerObject(dbusPath, sheet); #endif } void Doc::saveOdfViewSettings(KoXmlWriter& settingsWriter) { /*FIXME // Save visual info for the first view, such as active sheet and active cell // It looks like a hack, but reopening a document creates only one view anyway (David) View *const view = static_cast(views().first()); // save current sheet selection before to save marker, otherwise current pos is not saved view->saveCurrentSheetSelection(); //Feuille1 if (Sheet *sheet = view->activeSheet()) { settingsWriter.addConfigItem("ActiveTable", sheet->sheetName()); } */ } void Doc::saveOdfViewSheetSettings(Sheet *sheet, KoXmlWriter &settingsWriter) { /*FIXME View *const view = static_cast(views().first()); QPoint marker = view->markerFromSheet(sheet); QPointF offset = view->offsetFromSheet(sheet); settingsWriter.addConfigItem("CursorPositionX", marker.x() - 1); settingsWriter.addConfigItem("CursorPositionY", marker.y() - 1); settingsWriter.addConfigItem("xOffset", offset.x()); settingsWriter.addConfigItem("yOffset", offset.y()); */ } bool Doc::saveOdfHelper(SavingContext &documentContext, SaveFlag saveFlag, QString *plainText) { /* don't pull focus away from the editor if this is just a background autosave */ if (!isAutosaving()) { /*FIXME foreach(KoView* view, views()) static_cast(view)->selection()->emitCloseEditor(true); */ emit closeEditor(true); } return DocBase::saveOdfHelper(documentContext, saveFlag, plainText); } #include "Doc.moc" diff --git a/sheets/part/View.cpp b/sheets/part/View.cpp index fa7bef5b857..e71faae3475 100644 --- a/sheets/part/View.cpp +++ b/sheets/part/View.cpp @@ -1,2154 +1,2154 @@ /* This file is part of the KDE project Copyright 2006-2007 Stefan Nikolaus Copyright 2005-2006 Raphael Langerhorst Copyright 2002-2005 Ariya Hidayat Copyright 1999-2003 Laurent Montel Copyright 2002-2003 Norbert Andres Copyright 2002-2003 Philipp Mueller Copyright 2002-2003 John Dailey Copyright 1999-2003 David Faure Copyright 1999-2001 Simon Hausmann Copyright 1998-2000 Torben Weis Copyright 2010 Boudewijn Rempt This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // Local #include "View.h" #include "TabBar.h" // standard C/C++ includes #include #include #include // Qt includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // KDE includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Calligra includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // KSpread includes #include "ApplicationSettings.h" #include "BindingManager.h" #include "CalculationSettings.h" #include "CanvasResources.h" #include "CellStorage.h" #include "Damages.h" #include "DependencyManager.h" #include "Doc.h" #include "Factory.h" #include "HeaderFooter.h" #include "LoadingInfo.h" #include "Canvas.h" #include "Global.h" #include "Headers.h" #include "HeaderWidgets.h" #include "Localization.h" #include "Map.h" #include "NamedAreaManager.h" #include "PrintSettings.h" #include "RecalcManager.h" #include "RowColumnFormat.h" #include "ShapeApplicationData.h" #include "Sheet.h" #include "SheetPrint.h" #include "Style.h" #include "StyleManager.h" #include "StyleStorage.h" #include "ToolRegistry.h" #include "Util.h" #include "ValueCalc.h" #include "ValueConverter.h" #include "PrintJob.h" // commands #include "commands/CopyCommand.h" #include "commands/DefinePrintRangeCommand.h" #include "commands/SheetCommands.h" // dialogs #include "dialogs/PageLayoutDialog.h" #include "dialogs/PreferenceDialog.h" #include "dialogs/ShowDialog.h" #include "dialogs/SheetPropertiesDialog.h" // ui #include "ui/CellView.h" #include "ui/MapViewModel.h" #include "ui/RightToLeftPaintingStrategy.h" #include "ui/Selection.h" #include "ui/SheetView.h" #include "ui/PixmapCachingSheetView.h" // D-Bus #ifndef QT_NO_DBUS #include "interfaces/ViewAdaptor.h" -#include +#include #endif using namespace Calligra::Sheets; class ViewActions; class View::Private { public: View* view; Doc* doc; // the active sheet, may be 0 // this is the sheet which has the input focus Sheet* activeSheet; MapViewModel* mapViewModel; QHash > sheetViews; // GUI elements QWidget *frame; Canvas *canvas; KoCanvasController* canvasController; KoZoomController* zoomController; KoZoomHandler* zoomHandler; RowHeaderWidget *rowHeader; ColumnHeaderWidget *columnHeader; SelectAllButtonWidget* selectAllButton; QScrollBar *horzScrollBar; QScrollBar *vertScrollBar; TabBar *tabBar; QLabel* calcLabel; QGridLayout* viewLayout; QGridLayout* tabScrollBarLayout; // all UI actions ViewActions* actions; // if true, kspread is still loading the document // don't try to refresh the view bool loading; // selection/marker Selection* selection; QMap savedAnchors; QMap savedMarkers; QMap savedOffsets; void initActions(); void adjustActions(bool mode); // On timeout this will execute the status bar operation (e.g. SUM). // This is delayed to speed up the selection. QTimer statusBarOpTimer; }; class ViewActions { public: // sheet/workbook operations QAction * sheetProperties; QAction * insertSheet; QAction * duplicateSheet; QAction * deleteSheet; QAction * renameSheet; QAction * hideSheet; QAction * showSheet; //Shape manipulation KAction * deleteShape; // page layout QAction * paperLayout; QAction * resetPrintRange; KToggleAction* showPageBorders; // recalculation KAction * recalcWorksheet; KAction * recalcWorkbook; // protection KToggleAction* protectSheet; KToggleAction* protectDoc; // navigation KAction * nextSheet; KAction * prevSheet; QAction * firstSheet; QAction * lastSheet; // misc QAction * createTemplate; KSelectAction* shapeAnchor; // settings KToggleAction* showColumnHeader; KToggleAction* showRowHeader; KToggleAction* showHorizontalScrollBar; KToggleAction* showVerticalScrollBar; KToggleAction* showStatusBar; KToggleAction* showTabBar; QAction * preference; // running calculation KToggleAction* calcNone; KToggleAction* calcMin; KToggleAction* calcMax; KToggleAction* calcAverage; KToggleAction* calcCount; KToggleAction* calcSum; KToggleAction* calcCountA; }; void View::Private::initActions() { actions = new ViewActions; KActionCollection* ac = view->actionCollection(); // -- sheet/workbook actions -- actions->sheetProperties = new KAction(i18n("Sheet Properties..."), view); ac->addAction("sheetProperties", actions->sheetProperties); connect(actions->sheetProperties, SIGNAL(triggered(bool)), view, SLOT(sheetProperties())); actions->sheetProperties->setToolTip(i18n("Modify current sheet's properties")); actions->insertSheet = new KAction(koIcon("insert-table"), i18n("Sheet"), view); actions->insertSheet->setIconText(i18n("Insert Sheet")); actions->insertSheet->setToolTip(i18n("Insert a new sheet")); ac->addAction("insertSheet", actions->insertSheet); connect(actions->insertSheet, SIGNAL(triggered(bool)), view, SLOT(insertSheet())); actions->duplicateSheet = new KAction(/*koIcon("inserttable"),*/ i18n("Duplicate Sheet"), view); actions->duplicateSheet->setToolTip(i18n("Duplicate the selected sheet")); ac->addAction("duplicateSheet", actions->duplicateSheet); connect(actions->duplicateSheet, SIGNAL(triggered(bool)), view, SLOT(duplicateSheet())); actions->deleteSheet = new KAction(koIcon("edit-delete"), i18n("Sheet"), view); actions->deleteSheet->setIconText(i18n("Remove Sheet")); actions->deleteSheet->setToolTip(i18n("Remove the active sheet")); ac->addAction("deleteSheet", actions->deleteSheet); connect(actions->deleteSheet, SIGNAL(triggered(bool)), view, SLOT(deleteSheet())); actions->renameSheet = new KAction(i18n("Rename Sheet..."), view); ac->addAction("renameSheet", actions->renameSheet); connect(actions->renameSheet, SIGNAL(triggered(bool)), view, SLOT(slotRename())); actions->renameSheet->setToolTip(i18n("Rename the active sheet")); actions->showSheet = new KAction(i18n("Show Sheet..."), view); ac->addAction("showSheet", actions->showSheet); connect(actions->showSheet, SIGNAL(triggered(bool)), view, SLOT(showSheet())); actions->showSheet->setToolTip(i18n("Show a hidden sheet")); actions->hideSheet = new KAction(i18n("Hide Sheet"), view); ac->addAction("hideSheet", actions->hideSheet); connect(actions->hideSheet, SIGNAL(triggered(bool)), view, SLOT(hideSheet())); actions->hideSheet->setToolTip(i18n("Hide the active sheet")); actions->paperLayout = new KAction(i18n("Page Layout..."), view); ac->addAction("paperLayout", actions->paperLayout); connect(actions->paperLayout, SIGNAL(triggered(bool)), view, SLOT(paperLayoutDlg())); actions->paperLayout->setToolTip(i18n("Specify the layout of the spreadsheet for a printout")); actions->resetPrintRange = new KAction(i18n("Reset Print Range"), view); ac->addAction("resetPrintRange", actions->resetPrintRange); connect(actions->resetPrintRange, SIGNAL(triggered(bool)), view, SLOT(resetPrintRange())); actions->resetPrintRange->setToolTip(i18n("Reset the print range in the current sheet")); actions->showPageBorders = new KToggleAction(i18n("Page Borders"), view); actions->showPageBorders->setToolTip(i18n("Show on the spreadsheet where the page borders will be")); ac->addAction("showPageBorders", actions->showPageBorders); connect(actions->showPageBorders, SIGNAL(toggled(bool)), view, SLOT(togglePageBorders(bool))); actions->recalcWorksheet = new KAction(i18n("Recalculate Sheet"), view); actions->recalcWorksheet->setIcon(koIcon("view-refresh")); actions->recalcWorksheet->setIconText(i18n("Recalculate")); ac->addAction("RecalcWorkSheet", actions->recalcWorksheet); actions->recalcWorksheet->setShortcut(QKeySequence(Qt::SHIFT + Qt::Key_F9)); connect(actions->recalcWorksheet, SIGNAL(triggered(bool)), view, SLOT(recalcWorkSheet())); actions->recalcWorksheet->setToolTip(i18n("Recalculate the value of every cell in the current worksheet")); actions->recalcWorkbook = new KAction(i18n("Recalculate Document"), view); actions->recalcWorkbook->setIcon(koIcon("view-refresh")); actions->recalcWorkbook->setIconText(i18n("Recalculate")); ac->addAction("RecalcWorkBook", actions->recalcWorkbook); actions->recalcWorkbook->setShortcut(QKeySequence(Qt::Key_F9)); connect(actions->recalcWorkbook, SIGNAL(triggered(bool)), view, SLOT(recalcWorkBook())); actions->recalcWorkbook->setToolTip(i18n("Recalculate the value of every cell in all worksheets")); actions->protectSheet = new KToggleAction(i18n("Protect &Sheet..."), view); ac->addAction("protectSheet", actions->protectSheet); actions->protectSheet->setToolTip(i18n("Protect the sheet from being modified")); connect(actions->protectSheet, SIGNAL(triggered(bool)), view, SLOT(toggleProtectSheet(bool))); actions->protectDoc = new KToggleAction(i18n("Protect &Document..."), view); ac->addAction("protectDoc", actions->protectDoc); actions->protectDoc->setToolTip(i18n("Protect the document from being modified")); connect(actions->protectDoc, SIGNAL(triggered(bool)), view, SLOT(toggleProtectDoc(bool))); // -- misc actions -- actions->createTemplate = new KAction(i18n("&Create Template From Document..."), view); ac->addAction("createTemplate", actions->createTemplate); connect(actions->createTemplate, SIGNAL(triggered(bool)), view, SLOT(createTemplate())); actions->shapeAnchor = new KSelectAction(i18n("Anchor"), view); actions->shapeAnchor->addAction(i18n("Cell")); actions->shapeAnchor->addAction(i18n("Page")); actions->shapeAnchor->setEnabled(false); actions->shapeAnchor->setToolTip(i18n("Switch shape anchoring")); ac->addAction("shapeAnchor", actions->shapeAnchor); connect(actions->shapeAnchor, SIGNAL(triggered(const QString&)), view, SLOT(setShapeAnchoring(const QString&))); // -- navigation actions -- actions->nextSheet = new KAction(koIcon("go-next"), i18n("Next Sheet"), view); actions->nextSheet->setIconText(i18n("Next")); actions->nextSheet->setToolTip(i18n("Move to the next sheet")); ac->addAction("go_next", actions->nextSheet); actions->nextSheet->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_PageDown)); connect(actions->nextSheet, SIGNAL(triggered(bool)), view, SLOT(nextSheet())); actions->prevSheet = new KAction(koIcon("go-previous"), i18n("Previous Sheet"), view); actions->prevSheet->setIconText(i18n("Previous")); actions->prevSheet->setToolTip(i18n("Move to the previous sheet")); ac->addAction("go_previous", actions->prevSheet); actions->prevSheet->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_PageUp)); connect(actions->prevSheet, SIGNAL(triggered(bool)), view, SLOT(previousSheet())); actions->firstSheet = new KAction(koIcon("go-first"), i18n("First Sheet"), view); actions->firstSheet->setIconText(i18n("First")); actions->firstSheet->setToolTip(i18n("Move to the first sheet")); ac->addAction("go_first", actions->firstSheet); connect(actions->firstSheet, SIGNAL(triggered(bool)), view, SLOT(firstSheet())); actions->lastSheet = new KAction(koIcon("go-last"), i18n("Last Sheet"), view); actions->lastSheet->setIconText(i18nc("Move to the last sheet", "Last")); actions->lastSheet->setToolTip(i18n("Move to the last sheet")); ac->addAction("go_last", actions->lastSheet); connect(actions->lastSheet, SIGNAL(triggered(bool)), view, SLOT(lastSheet())); // -- settings actions -- actions->showColumnHeader = new KToggleAction(i18n("Column Header"), view); actions->showColumnHeader->setToolTip(i18n("Show the column header")); ac->addAction("showColumnHeader", actions->showColumnHeader); connect(actions->showColumnHeader, SIGNAL(toggled(bool)), view, SLOT(showColumnHeader(bool))); actions->showRowHeader = new KToggleAction(i18n("Row Header"), view); actions->showRowHeader->setToolTip(i18n("Show the row header")); ac->addAction("showRowHeader", actions->showRowHeader); connect(actions->showRowHeader, SIGNAL(toggled(bool)), view, SLOT(showRowHeader(bool))); actions->showHorizontalScrollBar = new KToggleAction(i18n("Horizontal Scrollbar"), view); actions->showHorizontalScrollBar->setToolTip(i18n("Show the horizontal scrollbar")); ac->addAction("showHorizontalScrollBar", actions->showHorizontalScrollBar); connect(actions->showHorizontalScrollBar, SIGNAL(toggled(bool)), view, SLOT(showHorizontalScrollBar(bool))); actions->showVerticalScrollBar = new KToggleAction(i18n("Vertical Scrollbar"), view); actions->showVerticalScrollBar->setToolTip(i18n("Show the vertical scrollbar")); ac->addAction("showVerticalScrollBar", actions->showVerticalScrollBar); connect(actions->showVerticalScrollBar, SIGNAL(toggled(bool)), view, SLOT(showVerticalScrollBar(bool))); actions->showStatusBar = new KToggleAction(i18n("Status Bar"), view); actions->showStatusBar->setToolTip(i18n("Show the status bar")); ac->addAction("showStatusBar", actions->showStatusBar); connect(actions->showStatusBar, SIGNAL(toggled(bool)), view, SLOT(showStatusBar(bool))); actions->showTabBar = new KToggleAction(i18n("Tab Bar"), view); actions->showTabBar->setToolTip(i18n("Show the tab bar")); ac->addAction("showTabBar", actions->showTabBar); connect(actions->showTabBar, SIGNAL(toggled(bool)), view, SLOT(showTabBar(bool))); actions->preference = KStandardAction::preferences(view, SLOT(preference()), view); actions->preference->setToolTip(i18n("Set various Calligra Sheets options")); ac->addAction("preference", actions->preference); KAction *notifyAction = KStandardAction::configureNotifications(view, SLOT(optionsNotifications()), view); ac->addAction("configureNotifications", notifyAction); // -- calculation actions -- // QActionGroup* groupCalc = new QActionGroup(view); actions->calcNone = new KToggleAction(i18n("None"), view); ac->addAction("menu_none", actions->calcNone); connect(actions->calcNone, SIGNAL(toggled(bool)), view, SLOT(menuCalc(bool))); actions->calcNone->setToolTip(i18n("No calculation")); actions->calcNone->setActionGroup(groupCalc); actions->calcSum = new KToggleAction(i18n("Sum"), view); ac->addAction("menu_sum", actions->calcSum); connect(actions->calcSum, SIGNAL(toggled(bool)), view, SLOT(menuCalc(bool))); actions->calcSum->setToolTip(i18n("Calculate using sum")); actions->calcSum->setActionGroup(groupCalc); actions->calcMin = new KToggleAction(i18n("Min"), view); ac->addAction("menu_min", actions->calcMin); connect(actions->calcMin, SIGNAL(toggled(bool)), view, SLOT(menuCalc(bool))); actions->calcMin->setToolTip(i18n("Calculate using minimum")); actions->calcMin->setActionGroup(groupCalc); actions->calcMax = new KToggleAction(i18n("Max"), view); ac->addAction("menu_max", actions->calcMax); connect(actions->calcMax, SIGNAL(toggled(bool)), view, SLOT(menuCalc(bool))); actions->calcMax->setToolTip(i18n("Calculate using maximum")); actions->calcMax->setActionGroup(groupCalc); actions->calcAverage = new KToggleAction(i18n("Average"), view); ac->addAction("menu_average", actions->calcAverage); connect(actions->calcAverage, SIGNAL(toggled(bool)), view, SLOT(menuCalc(bool))); actions->calcAverage->setToolTip(i18n("Calculate using average")); actions->calcAverage->setActionGroup(groupCalc); actions->calcCount = new KToggleAction(i18n("Count"), view); ac->addAction("menu_count", actions->calcCount); connect(actions->calcCount, SIGNAL(toggled(bool)), view, SLOT(menuCalc(bool))); actions->calcCount->setToolTip(i18n("Calculate using the count")); actions->calcCount->setActionGroup(groupCalc); actions->calcCountA = new KToggleAction(i18n("CountA"), view); ac->addAction("menu_counta", actions->calcCountA); connect(actions->calcCountA, SIGNAL(toggled(bool)), view, SLOT(menuCalc(bool))); actions->calcCountA->setToolTip(i18n("Calculate using the countA")); actions->calcCountA->setActionGroup(groupCalc); //Shape actions actions->deleteShape = new KAction(koIcon("edit-delete"), i18n("Delete"), view); actions->deleteShape->setShortcut(QKeySequence("Del")); connect(actions->deleteShape, SIGNAL(triggered()), view, SLOT(editDeleteSelection())); connect(canvas->toolProxy(), SIGNAL(selectionChanged(bool)), actions->deleteShape, SLOT(setEnabled(bool))); ac->addAction("edit_delete", actions->deleteShape); // -- special action, only for developers -- // ac->addAssociatedWidget(view->canvasWidget()); foreach(QAction* action, ac->actions()) { action->setShortcutContext(Qt::WidgetWithChildrenShortcut); } } void View::Private::adjustActions(bool mode) { actions->recalcWorkbook->setEnabled(mode); actions->recalcWorksheet->setEnabled(mode); actions->paperLayout->setEnabled(mode); actions->resetPrintRange->setEnabled(mode); actions->deleteSheet->setEnabled(mode); actions->calcMin->setEnabled(mode); actions->calcMax->setEnabled(mode); actions->calcAverage->setEnabled(mode); actions->calcCount->setEnabled(mode); actions->calcCountA->setEnabled(mode); actions->calcSum->setEnabled(mode); actions->calcNone->setEnabled(mode); if (mode && !view->doc()->map()->isProtected()) actions->renameSheet->setEnabled(true); else actions->renameSheet->setEnabled(false); actions->showColumnHeader->setChecked(view->doc()->map()->settings()->showColumnHeader()); actions->showRowHeader->setChecked(view->doc()->map()->settings()->showRowHeader()); actions->showHorizontalScrollBar->setChecked(view->doc()->map()->settings()->showHorizontalScrollBar()); actions->showVerticalScrollBar->setChecked(view->doc()->map()->settings()->showVerticalScrollBar()); actions->showStatusBar->setChecked(view->doc()->map()->settings()->showStatusBar()); actions->showTabBar->setChecked(view->doc()->map()->settings()->showTabBar()); if (activeSheet) selection->update(); } /***************************************************************************** * * View * *****************************************************************************/ View::View(KoPart *part, QWidget *_parent, Doc *_doc) : KoView(part, _doc, _parent) , d(new Private) { ElapsedTime et("View constructor"); d->view = this; d->doc = _doc; d->activeSheet = 0; d->loading = true; setComponentData(Factory::global()); setXMLFile("sheets.rc"); // GUI Initializations initView(); d->initActions(); // Connect updateView() signal to View::update() in order to repaint its // child widgets: the column/row headers and the select all button. // Connect to Canvas::update() explicitly as it lives in the viewport // of the KoCanvasController. connect(doc(), SIGNAL(updateView()), this, SLOT(update())); connect(doc(), SIGNAL(updateView()), d->canvas, SLOT(update())); connect(doc()->map(), SIGNAL(sheetAdded(Sheet*)), this, SLOT(addSheet(Sheet*))); connect(doc()->map(), SIGNAL(sheetRemoved(Sheet*)), this, SLOT(removeSheet(Sheet*))); connect(doc()->map(), SIGNAL(sheetRevived(Sheet*)), this, SLOT(addSheet(Sheet*))); connect(doc()->map(), SIGNAL(damagesFlushed(const QList&)), this, SLOT(handleDamages(const QList&))); if (statusBar()) { connect(doc()->map(), SIGNAL(statusMessage(const QString&, int)), statusBar(), SLOT(showMessage(const QString&, int))); } connect(&d->statusBarOpTimer, SIGNAL(timeout()), this, SLOT(calcStatusBarOp())); // Delay the setting of the initial position, because we need to have // a sensible widget size, which is not always the case from the beginning // of the View's lifetime. // Therefore, initialPosition(), the last operation in the "View loading" // process, is called from resizeEvent(). The loading flag will be unset // at the end of initialPosition(). #ifndef QT_NO_DBUS new ViewAdaptor(this); #endif d->canvas->setFocus(); } View::~View() { selection()->emitCloseEditor(true); // save changes // if (d->calcLabel) disconnect(d->calcLabel,SIGNAL(pressed( int )),this,SLOT(statusBarClicked(int))); d->selection->emitCloseEditor(false); d->selection->endReferenceSelection(false); d->activeSheet = 0; // set the active sheet to 0 so that when during destruction // of embedded child documents possible repaints in Sheet are not // performed. The repains can happen if you delete an embedded document, // which leads to an regionInvalidated() signal emission in KoView, which calls // repaint, etc.etc. :-) (Simon) // delete the sheetView's after calling d->selection->emitCloseEditor cause the // emitCloseEditor may trigger over the Selection::emitChanged a Canvas::scrollToCell // which in turn needs the sheetview's to access the sheet itself. qDeleteAll(d->sheetViews.values()); delete d->selection; delete d->calcLabel; delete d->actions; delete d->zoomHandler; // NOTE sebsauer: first unregister the event-handler, then delete the canvas and then we are save to // call removeCanvasController without crashing. //d->canvasController->canvas()->canvasWidget()->removeEventFilter(d->canvasController); //delete d->canvasController->canvas(); // NOTE sebsauer: We need to remove the canvasController right before deleting it and // nothing needs to be done in between cause flake does first delete the TableTool // on removeCanvasController and the proxytool which points to that TableTool later // while the canvasController is destroyed. That means, that we will have a dangling // pointer in the KoToolProxy that points to the KoToolBase the time in between. KoToolManager::instance()->removeCanvasController(d->canvasController); // NOTE Stefan: Delete the Canvas explicitly, even if it has this view as // parent. Otherwise, it leads to crashes, because it tries to // access this View in some events (Bug #126492). // The KoCanvasController takes ownership of the Canvas and does the deletion. delete d->canvasController; delete d; } Doc* View::doc() const { return d->doc; } // should be called only once, from the constructor /* * Central part is the canvas, row header and vertical scrollbar. * Bottom part is the tab bar and horizontal scrollbar. * * Note that canvas must the one to be created, since other * widgets might depend on it. */ void View::initView() { d->viewLayout = new QGridLayout(this); d->viewLayout->setMargin(0); d->viewLayout->setSpacing(0); // Setup the Canvas and its controller. d->canvas = new Canvas(this); KoCanvasControllerWidget *canvasController = new KoCanvasControllerWidget(actionCollection(), this); d->canvasController = canvasController; d->canvasController->setCanvas(d->canvas); d->canvasController->setCanvasMode(KoCanvasController::Spreadsheet); canvasController->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); canvasController->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Setup the map model. d->mapViewModel = new MapViewModel(d->doc->map(), d->canvas, this); installEventFilter(d->mapViewModel); // listen to KParts::GUIActivateEvent connect(d->mapViewModel, SIGNAL(addCommandRequested(KUndo2Command*)), doc(), SLOT(addCommand(KUndo2Command*))); connect(d->mapViewModel, SIGNAL(activeSheetChanged(Sheet*)), this, SLOT(setActiveSheet(Sheet*))); // Setup the selection. d->selection = new Selection(d->canvas); connect(d->selection, SIGNAL(changed(const Region&)), this, SLOT(slotChangeSelection(const Region&))); connect(d->selection, SIGNAL(changed(const Region&)), this, SLOT(slotScrollChoice(const Region&))); connect(d->selection, SIGNAL(aboutToModify(const Region&)), this, SLOT(aboutToModify(const Region&))); connect(d->selection, SIGNAL(modified(const Region&)), this, SLOT(refreshSelection(const Region&))); connect(d->selection, SIGNAL(visibleSheetRequested(Sheet*)), this, SLOT(setActiveSheet(Sheet*))); connect(d->selection, SIGNAL(refreshSheetViews()), this, SLOT(refreshSheetViews())); connect(d->selection, SIGNAL(updateAccessedCellRange(Sheet*,QPoint)), this, SLOT(updateAccessedCellRange(Sheet*,QPoint))); connect(this, SIGNAL(documentReadWriteToggled(bool)), d->selection, SIGNAL(documentReadWriteToggled(bool))); connect(this, SIGNAL(sheetProtectionToggled(bool)), d->selection, SIGNAL(sheetProtectionToggled(bool))); // Let the selection pointer become a canvas resource. QVariant variant; variant.setValue(d->selection); d->canvas->resourceManager()->setResource(CanvasResource::Selection, variant); variant.setValue(doc()->map()->bindingManager()); // Load the KSpread Tools ToolRegistry::instance()->loadTools(); if (shell()) { KoToolManager::instance()->addController(d->canvasController); KoToolManager::instance()->registerTools(actionCollection(), d->canvasController); KoModeBoxFactory modeBoxFactory(canvasController, qApp->applicationName(), i18n("Tools")); shell()->createDockWidget(&modeBoxFactory); shell()->dockerManager()->removeToolOptionsDocker(); // Setup the tool options dock widget manager. //connect(canvasController, SIGNAL(toolOptionWidgetsChanged(const QList &)), // shell()->dockerManager(), SLOT(newOptionWidgets(const QList &))); } // Setup the zoom controller. d->zoomHandler = new KoZoomHandler(); d->zoomController = new KoZoomController(d->canvasController, d->zoomHandler, actionCollection(), 0, this); d->zoomController->zoomAction()->setZoomModes(KoZoomMode::ZOOM_CONSTANT); addStatusBarItem(d->zoomController->zoomAction()->createWidget(statusBar()), 0, true); connect(d->zoomController, SIGNAL(zoomChanged(KoZoomMode::Mode, qreal)), this, SLOT(viewZoom(KoZoomMode::Mode, qreal))); d->columnHeader = new ColumnHeaderWidget(this, d->canvas, this); d->rowHeader = new RowHeaderWidget(this, d->canvas , this); d->columnHeader->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); d->rowHeader->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); d->selectAllButton = new SelectAllButtonWidget(d->canvas); d->selectAllButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); d->canvas->setFocusPolicy(Qt::StrongFocus); QWidget::setFocusPolicy(Qt::StrongFocus); setFocusProxy(d->canvas); connect(this, SIGNAL(invalidated()), d->canvas, SLOT(update())); // Vert. Scroll Bar d->calcLabel = 0; d->vertScrollBar = new QScrollBar(this); canvasController->setVerticalScrollBar(d->vertScrollBar); connect(d->vertScrollBar, SIGNAL(valueChanged(int)), canvasController, SLOT(updateCanvasOffsetY())); d->vertScrollBar->setOrientation(Qt::Vertical); d->vertScrollBar->setSingleStep(60); //just random guess based on what feels okay d->vertScrollBar->setPageStep(60); //This should be controlled dynamically, depending on how many rows are shown QWidget* bottomPart = new QWidget(this); d->tabScrollBarLayout = new QGridLayout(bottomPart); d->tabScrollBarLayout->setMargin(0); d->tabScrollBarLayout->setSpacing(0); d->tabBar = new TabBar(0); d->tabScrollBarLayout->addWidget(d->tabBar, 0, 0); d->horzScrollBar = new QScrollBar(0); canvasController->setHorizontalScrollBar(d->horzScrollBar); connect(d->horzScrollBar, SIGNAL(valueChanged(int)), canvasController, SLOT(updateCanvasOffsetX())); d->tabScrollBarLayout->addWidget(d->horzScrollBar, 0, 1, 2, 1, Qt::AlignVCenter); d->horzScrollBar->setOrientation(Qt::Horizontal); d->horzScrollBar->setSingleStep(60); //just random guess based on what feels okay d->horzScrollBar->setPageStep(60); connect(d->tabBar, SIGNAL(tabChanged(const QString&)), this, SLOT(changeSheet(const QString&))); connect(d->tabBar, SIGNAL(tabMoved(unsigned, unsigned)), this, SLOT(moveSheet(unsigned, unsigned))); connect(d->tabBar, SIGNAL(contextMenu(const QPoint&)), this, SLOT(popupTabBarMenu(const QPoint&))); connect(d->tabBar, SIGNAL(doubleClicked()), this, SLOT(slotRename())); int extent = this->style()->pixelMetric(QStyle::PM_ScrollBarExtent); if (style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents)) { extent += style()->pixelMetric(QStyle::PM_DefaultFrameWidth) * 2; } d->viewLayout->setColumnStretch(1, 10); d->viewLayout->setRowStretch(2, 10); d->viewLayout->addWidget(d->selectAllButton, 1, 0); d->viewLayout->addWidget(d->columnHeader, 1, 1, 1, 1); d->viewLayout->addWidget(d->rowHeader, 2, 0); d->viewLayout->addWidget(canvasController, 2, 1); d->viewLayout->addWidget(d->vertScrollBar, 1, 2, 2, 1, Qt::AlignHCenter); d->viewLayout->addWidget(bottomPart, 3, 0, 1, 2); d->viewLayout->setColumnMinimumWidth(2, extent); d->viewLayout->setRowMinimumHeight(3, extent); KStatusBar * sb = statusBar(); d->calcLabel = sb ? new QLabel(sb) : 0; if (d->calcLabel) { d->calcLabel->setContextMenuPolicy(Qt::CustomContextMenu); addStatusBarItem(d->calcLabel, 0); connect(d->calcLabel , SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(statusBarClicked(QPoint))); } // signal slot connect(d->canvas, SIGNAL(documentSizeChanged(const QSize&)), d->canvasController->proxyObject, SLOT(updateDocumentSize(const QSize&))); connect(d->canvasController->proxyObject, SIGNAL(moveDocumentOffset(const QPoint&)), d->canvas, SLOT(setDocumentOffset(const QPoint&))); connect(d->canvas->shapeManager(), SIGNAL(selectionChanged()), this, SLOT(shapeSelectionChanged())); } Canvas* View::canvasWidget() const { return d->canvas; } KoZoomController *View::zoomController() const { return d->zoomController; } KoCanvasController* View::canvasController() const { return d->canvasController; } ColumnHeaderWidget* View::columnHeader()const { return d->columnHeader; } RowHeaderWidget* View::rowHeader()const { return d->rowHeader; } QScrollBar* View::horzScrollBar()const { return d->horzScrollBar; } QScrollBar* View::vertScrollBar()const { return d->vertScrollBar; } TabBar* View::tabBar() const { return d->tabBar; } KoZoomHandler* View::zoomHandler() const { return d->zoomHandler; } bool View::isLoading() const { return d->loading; } Selection* View::selection() const { return d->selection; } Sheet* View::activeSheet() const { return d->activeSheet; } void View::sheetDestroyed(QObject* obj) { if (Sheet *sheet = dynamic_cast(obj)) { Q_ASSERT(d->sheetViews.contains(sheet)); d->sheetViews.remove(sheet); // The SheetView will be proper destroyed already cause it's a QObject-child of the sheet. } } SheetView* View::sheetView(const Sheet* sheet) const { SheetView *sheetView = d->sheetViews.value(sheet); if (!sheetView) { kDebug(36004) << "View: Creating SheetView for" << sheet->sheetName(); sheetView = new SheetView(sheet); d->sheetViews.insert(sheet, sheetView); sheetView->setViewConverter(zoomHandler()); connect(sheetView, SIGNAL(visibleSizeChanged(const QSizeF&)), d->canvas, SLOT(setDocumentSize(const QSizeF&))); connect(sheetView, SIGNAL(visibleSizeChanged(const QSizeF&)), d->zoomController, SLOT(setDocumentSize(const QSizeF&))); connect(sheet, SIGNAL(visibleSizeChanged()), sheetView, SLOT(updateAccessedCellRange())); connect(sheet, SIGNAL(destroyed(QObject*)), this, SLOT(sheetDestroyed(QObject*))); } return sheetView; } void View::refreshSheetViews() { QList sheets = d->sheetViews.keys(); QList< QPointer > sheetViews = d->sheetViews.values(); foreach(const Sheet *sheet, d->sheetViews.keys()) { disconnect(sheet, SIGNAL(destroyed(QObject*)), this, SLOT(sheetDestroyed(QObject*))); } foreach (SheetView *sheetView, sheetViews) { disconnect(sheetView, SIGNAL(visibleSizeChanged(const QSizeF&)), d->canvas, SLOT(setDocumentSize(const QSizeF&))); disconnect(sheetView, SIGNAL(visibleSizeChanged(const QSizeF&)), d->zoomController, SLOT(setDocumentSize(const QSizeF&))); disconnect(sheetView->sheet(), SIGNAL(visibleSizeChanged()), sheetView, SLOT(updateAccessedCellRange())); } qDeleteAll(sheetViews); d->sheetViews.clear(); foreach(const Sheet *sheet, d->doc->map()->sheetList()) { sheet->cellStorage()->invalidateStyleCache(); } } void View::refreshSelection(const Region& region) { doc()->map()->addDamage(new CellDamage(activeSheet(), region, CellDamage::Appearance)); } void View::aboutToModify(const Region& region) { Q_UNUSED(region); selection()->emitCloseEditor(true); // save changes } void View::initConfig() { KSharedConfigPtr config = Factory::global().config(); const KConfigGroup parameterGroup = config->group("Parameters"); const bool configFromDoc = doc()->configLoadFromFile(); if (!configFromDoc) { doc()->map()->settings()->setShowHorizontalScrollBar(parameterGroup.readEntry("Horiz ScrollBar", true)); doc()->map()->settings()->setShowVerticalScrollBar(parameterGroup.readEntry("Vert ScrollBar", true)); } doc()->map()->settings()->setShowColumnHeader(parameterGroup.readEntry("Column Header", true)); doc()->map()->settings()->setShowRowHeader(parameterGroup.readEntry("Row Header", true)); if (!configFromDoc) doc()->map()->settings()->setCompletionMode((KGlobalSettings::Completion)parameterGroup.readEntry("Completion Mode", (int)(KGlobalSettings::CompletionAuto))); doc()->map()->settings()->setMoveToValue((Calligra::Sheets::MoveTo)parameterGroup.readEntry("Move", (int)(Bottom))); doc()->map()->settings()->setIndentValue(parameterGroup.readEntry("Indent", 10.0)); doc()->map()->settings()->setTypeOfCalc((MethodOfCalc)parameterGroup.readEntry("Method of Calc", (int)(SumOfNumber))); if (!configFromDoc) doc()->map()->settings()->setShowTabBar(parameterGroup.readEntry("Tabbar", true)); doc()->map()->settings()->setShowStatusBar(parameterGroup.readEntry("Status bar", true)); changeNbOfRecentFiles(parameterGroup.readEntry("NbRecentFile", 10)); //autosave value is stored as a minute. //but default value is stored as seconde. doc()->setAutoSave(parameterGroup.readEntry("AutoSave", KoDocument::defaultAutoSave() / 60)*60); doc()->setBackupFile(parameterGroup.readEntry("BackupFile", true)); const KConfigGroup colorGroup = config->group("KSpread Color"); doc()->map()->settings()->setGridColor(colorGroup.readEntry("GridColor", QColor(Qt::lightGray))); doc()->map()->settings()->changePageBorderColor(colorGroup.readEntry("PageBorderColor", QColor(Qt::red))); doc()->map()->settings()->setCaptureAllArrowKeys(config->group("Editor").readEntry("CaptureAllArrowKeys", true)); initCalcMenu(); calcStatusBarOp(); } void View::changeNbOfRecentFiles(int _nb) { if (shell()) shell()->setMaxRecentItems(_nb); } void View::initCalcMenu() { switch (doc()->map()->settings()->getTypeOfCalc()) { case SumOfNumber: d->actions->calcSum->setChecked(true); break; case Min: d->actions->calcMin->setChecked(true); break; case Max: d->actions->calcMax->setChecked(true); break; case Average: d->actions->calcAverage->setChecked(true); break; case Count: d->actions->calcCount->setChecked(true); break; case CountA: d->actions->calcCountA->setChecked(true); break; case NoneCalc: d->actions->calcNone->setChecked(true); break; default : d->actions->calcSum->setChecked(true); break; } } void View::recalcWorkBook() { doc()->map()->recalcManager()->recalcMap(); } void View::recalcWorkSheet() { if (!activeSheet()) return; doc()->map()->recalcManager()->recalcSheet(activeSheet()); } void View::shapeSelectionChanged() { const KoSelection* selection = d->canvas->shapeManager()->selection(); const QList shapes = selection->selectedShapes(KoFlake::StrippedSelection); if (shapes.isEmpty()) { d->actions->shapeAnchor->setEnabled(false); return; } d->actions->shapeAnchor->setEnabled(true); // start with the first shape const KoShape* shape = shapes[0]; const ShapeApplicationData* data = dynamic_cast(shape->applicationData()); if (!data) { // Container children do not have the application data set, deselect the anchoring action. d->actions->shapeAnchor->setCurrentAction(0); return; } bool anchoredToCell = data->isAnchoredToCell(); d->actions->shapeAnchor->setCurrentAction(anchoredToCell ? i18n("Cell") : i18n("Page")); // go on with the remaining shapes for (int i = 1; i < shapes.count(); ++i) { shape = shapes[i]; data = dynamic_cast(shape->applicationData()); Q_ASSERT(data); if (anchoredToCell != data->isAnchoredToCell()) { // If the anchoring differs between shapes, deselect the anchoring action and stop here. d->actions->shapeAnchor->setCurrentAction(0); break; } } } void View::editDeleteSelection() { d->canvas->toolProxy()->deleteSelection(); } void View::initialPosition() { // Loading completed, pick initial worksheet foreach(Sheet* sheet, doc()->map()->sheetList()) { addSheet(sheet); } // Set the initial X and Y offsets for the view (OpenDocument loading) const LoadingInfo* loadingInfo = doc()->map()->loadingInfo(); if (loadingInfo->fileFormat() == LoadingInfo::OpenDocument) { d->savedAnchors = loadingInfo->cursorPositions(); d->savedMarkers = loadingInfo->cursorPositions(); d->savedOffsets = loadingInfo->scrollingOffsets(); } Sheet* sheet = loadingInfo->initialActiveSheet(); if (!sheet) { //activate first table which is not hiding sheet = doc()->map()->visibleSheets().isEmpty() ? 0 : doc()->map()->findSheet(doc()->map()->visibleSheets().first()); if (!sheet) { sheet = doc()->map()->sheet(0); if (sheet) { sheet->setHidden(false); QString tabName = sheet->sheetName(); d->tabBar->addTab(tabName); } } } setActiveSheet(sheet); d->mapViewModel->setActiveSheet(sheet); // Set the initial X and Y offsets for the view (Native format loading) if (loadingInfo->fileFormat() == LoadingInfo::NativeFormat) { const QPoint offset = zoomHandler()->documentToView(loadingInfo->scrollingOffsets()[sheet]).toPoint(); d->canvas->setDocumentOffset(offset); d->horzScrollBar->setValue(offset.x()); d->vertScrollBar->setValue(offset.y()); // Set the initial position for the marker as stored in the XML file, // (1,1) otherwise const QPoint marker = loadingInfo->cursorPositions()[sheet]; d->selection->initialize((marker.x() <= 0 || marker.y() <= 0) ? QPoint(1, 1) : marker); } updateShowSheetMenu(); // Initialize shape anchoring action. shapeSelectionChanged(); initConfig(); d->canvas->setFocus(); QTimer::singleShot(50, this, SLOT(finishLoading())); } void View::finishLoading() { // finish the "View Loading" process d->loading = false; doc()->map()->deleteLoadingInfo(); setHeaderMinima(); // Activate the cell tool. if (shell()) KoToolManager::instance()->switchToolRequested("KSpreadCellToolId"); } void View::updateReadWrite(bool readwrite) { // inform the cell tool emit documentReadWriteToggled(readwrite); const QList actions = actionCollection()->actions(); for (int i = 0; i < actions.count(); ++i) { // The action collection contains also the flake tool actions. Skip them. if (actions[i]->parent() == this) actions[i]->setEnabled(readwrite); } if (!doc() || !doc()->map() || doc()->map()->isProtected()) { d->actions->showSheet->setEnabled(false); d->actions->hideSheet->setEnabled(false); } else { d->actions->showSheet->setEnabled(true); d->actions->hideSheet->setEnabled(true); } d->actions->showPageBorders->setEnabled(true); d->tabBar->setReadOnly(doc()->map()->isProtected()); } void View::createTemplate() { KoTemplateCreateDia::createTemplate("sheets_template", ".ots", Factory::global(), doc(), this); } void View::setActiveSheet(Sheet* sheet, bool updateSheet) { // It can happen that our tabBar->activeTab() is not in sync with our activeSheet() if // setActiveSheet() was previously called before the delayed View::initialPosition() // was called and had a change to proper TabBar::setTabs(). if (sheet == d->activeSheet && (!sheet || d->tabBar->activeTab() == sheet->sheetName())) return; if (d->activeSheet != 0 && !d->selection->referenceSelectionMode()) { selection()->emitCloseEditor(true); // save changes saveCurrentSheetSelection(); } const Sheet* oldSheet = d->activeSheet; d->activeSheet = sheet; if (d->activeSheet == 0) { return; } // flake // Change the active shape controller and its shapes. d->canvas->shapeController()->setShapeControllerBase(d->activeSheet); // and then update the toolmanager separately KoToolManager::instance()->updateShapeControllerBase(d->activeSheet, d->canvas->canvasController()); d->canvas->shapeManager()->setShapes(d->activeSheet->shapes()); // Tell the Canvas about the new visible sheet size. sheetView(d->activeSheet)->updateAccessedCellRange(); // If there was no sheet before or the layout directions differ. if (!oldSheet || oldSheet->layoutDirection() != d->activeSheet->layoutDirection()) { // Propagate the layout direction to the canvas and horz. scrollbar. const Qt::LayoutDirection direction = d->activeSheet->layoutDirection(); d->canvas->setLayoutDirection(direction); d->horzScrollBar->setLayoutDirection(direction); // Replace the painting strategy for painting shapes. KoShapeManager *const shapeManager = d->canvas->shapeManager(); KoShapeManagerPaintingStrategy *paintingStrategy = 0; if (direction == Qt::LeftToRight) { paintingStrategy = new KoShapeManagerPaintingStrategy(shapeManager); } else { paintingStrategy = new RightToLeftPaintingStrategy(shapeManager, d->canvas); } shapeManager->setPaintingStrategy(paintingStrategy); } // If there was no sheet before or the formula visibilities differ. if (!oldSheet || oldSheet->getShowFormula() != d->activeSheet->getShowFormula()) { const bool showFormulas = d->activeSheet->getShowFormula(); stateChanged("show_formulas", showFormulas ? StateNoReverse : StateReverse); } // Restore the old scrolling offset. QMap::Iterator it3 = d->savedOffsets.find(d->activeSheet); if (it3 != d->savedOffsets.end()) { const QPoint offset = zoomHandler()->documentToView(*it3).toPoint(); d->canvas->setDocumentOffset(offset); d->horzScrollBar->setValue(offset.x()); d->vertScrollBar->setValue(offset.y()); } // tell the resource manager of the newly active page d->canvas->resourceManager()->setResource(KoCanvasResourceManager::CurrentPage, QVariant(sheet->map()->indexOf(sheet) + 1)); // Always repaint the visible cells. d->canvas->update(); d->rowHeader->update(); d->columnHeader->update(); d->selectAllButton->update(); // Prevents an endless loop, if called by the TabBar. if (updateSheet) { d->tabBar->setActiveTab(d->activeSheet->sheetName()); } if (d->selection->referenceSelectionMode()) { d->selection->setActiveSheet(d->activeSheet); return; } /* see if there was a previous selection on this other sheet */ QMap::Iterator it = d->savedAnchors.find(d->activeSheet); QMap::Iterator it2 = d->savedMarkers.find(d->activeSheet); // restore the old anchor and marker const QPoint newAnchor = (it == d->savedAnchors.end()) ? QPoint(1, 1) : *it; const QPoint newMarker = (it2 == d->savedMarkers.end()) ? QPoint(1, 1) : *it2; d->selection->clear(); d->selection->setActiveSheet(d->activeSheet); d->selection->setOriginSheet(d->activeSheet); d->selection->initialize(QRect(newMarker, newAnchor)); d->actions->showPageBorders->blockSignals(true); d->actions->showPageBorders->setChecked(d->activeSheet->isShowPageBorders()); d->actions->showPageBorders->blockSignals(false); d->actions->protectSheet->blockSignals(true); d->actions->protectSheet->setChecked(d->activeSheet->isProtected()); d->actions->protectSheet->blockSignals(false); d->actions->protectDoc->blockSignals(true); d->actions->protectDoc->setChecked(doc()->map()->isProtected()); d->actions->protectDoc->blockSignals(false); d->adjustActions(!d->activeSheet->isProtected()); const bool protect = d->activeSheet->isProtected(); stateChanged("sheet_is_protected", protect ? StateNoReverse : StateReverse); // Auto calculation state for the INFO function. const bool autoCalc = d->activeSheet->isAutoCalculationEnabled(); d->doc->map()->calculationSettings()->setAutoCalculationEnabled(autoCalc); calcStatusBarOp(); } void View::changeSheet(const QString& _name) { if (activeSheet()->sheetName() == _name) return; Sheet *t = doc()->map()->findSheet(_name); if (!t) { kDebug() << "Unknown sheet" << _name; return; } setActiveSheet(t, false /* False: Endless loop because of setActiveTab() => do the visual area update manually*/); d->mapViewModel->setActiveSheet(t); } void View::moveSheet(unsigned sheet, unsigned target) { if (doc()->map()->isProtected()) return; QStringList vs = doc()->map()->visibleSheets(); if (target >= (uint) vs.count()) doc()->map()->moveSheet(vs[ sheet ], vs[ vs.count()-1 ], false); else doc()->map()->moveSheet(vs[ sheet ], vs[ target ], true); d->tabBar->moveTab(sheet, target); } void View::sheetProperties() { // sanity check, shouldn't happen if (doc()->map()->isProtected()) return; if (d->activeSheet->isProtected()) return; bool directionChanged = false; bool formulaVisibilityChanged = false; QPointer dlg = new SheetPropertiesDialog(this); dlg->setLayoutDirection(d->activeSheet->layoutDirection()); dlg->setAutoCalculationEnabled(d->activeSheet->isAutoCalculationEnabled()); dlg->setShowGrid(d->activeSheet->getShowGrid()); dlg->setShowPageBorders(d->activeSheet->isShowPageBorders()); dlg->setShowFormula(d->activeSheet->getShowFormula()); dlg->setHideZero(d->activeSheet->getHideZero()); dlg->setShowFormulaIndicator(d->activeSheet->getShowFormulaIndicator()); dlg->setShowCommentIndicator(d->activeSheet->getShowCommentIndicator()); dlg->setColumnAsNumber(d->activeSheet->getShowColumnNumber()); dlg->setLcMode(d->activeSheet->getLcMode()); dlg->setCapitalizeFirstLetter(d->activeSheet->getFirstLetterUpper()); if (dlg->exec()) { SheetPropertiesCommand* command = new SheetPropertiesCommand(d->activeSheet); if (d->activeSheet->layoutDirection() != dlg->layoutDirection()) directionChanged = true; if (d->activeSheet->getShowFormula() != dlg->showFormula()) { formulaVisibilityChanged = true; } command->setLayoutDirection(dlg->layoutDirection()); command->setAutoCalculationEnabled(dlg->autoCalc()); command->setShowGrid(dlg->showGrid()); command->setShowPageBorders(dlg->showPageBorders()); command->setShowFormula(dlg->showFormula()); command->setHideZero(dlg->hideZero()); command->setShowFormulaIndicator(dlg->showFormulaIndicator()); command->setShowCommentIndicator(dlg->showCommentIndicator()); command->setColumnAsNumber(dlg->columnAsNumber()); command->setLcMode(dlg->lcMode()); command->setCapitalizeFirstLetter(dlg->capitalizeFirstLetter()); doc()->addCommand(command); } delete dlg; if (directionChanged) { // the scrollbar and hborder remain reversed otherwise d->canvas->setLayoutDirection(d->activeSheet->layoutDirection()); // for scrolling d->horzScrollBar->setLayoutDirection(d->activeSheet->layoutDirection()); d->columnHeader->update(); // Replace the painting strategy for painting shapes. KoShapeManager *const shapeManager = d->canvas->shapeManager(); KoShapeManagerPaintingStrategy *paintingStrategy = 0; if (d->activeSheet->layoutDirection() == Qt::LeftToRight) { paintingStrategy = new KoShapeManagerPaintingStrategy(shapeManager); } else { paintingStrategy = new RightToLeftPaintingStrategy(shapeManager, d->canvas); } shapeManager->setPaintingStrategy(paintingStrategy); } if (formulaVisibilityChanged) { const bool showFormulas = d->activeSheet->getShowFormula(); stateChanged("show_formulas", showFormulas ? StateNoReverse : StateReverse); sheetView(d->activeSheet)->invalidate(); d->canvas->update(); } } void View::insertSheet() { if (doc()->map()->isProtected()) { KMessageBox::error(0, i18n("You cannot change a protected sheet.")); return; } selection()->emitCloseEditor(true); // save changes Sheet * t = doc()->map()->createSheet(); KUndo2Command* command = new AddSheetCommand(t); doc()->addCommand(command); setActiveSheet(t); if (doc()->map()->visibleSheets().count() > 1) { d->actions->deleteSheet->setEnabled(true); d->actions->hideSheet->setEnabled(true); } } void View::duplicateSheet() { if (doc()->map()->isProtected()) { KMessageBox::error(this, i18n("You cannot change a protected sheet.")); return; } DuplicateSheetCommand* command = new DuplicateSheetCommand(); command->setSheet(activeSheet()); doc()->addCommand(command); if (doc()->map()->visibleSheets().count() > 1) { d->actions->deleteSheet->setEnabled(true); d->actions->hideSheet->setEnabled(true); } } void View::hideSheet() { if (!d->activeSheet) return; if (doc()->map()->visibleSheets().count() == 1) { KMessageBox::error(this, i18n("You cannot hide the last visible sheet.")); return; } QStringList vs = doc()->map()->visibleSheets(); int i = vs.indexOf(d->activeSheet->sheetName()) - 1; if (i < 0) i = 1; QString sn = vs[i]; KUndo2Command* command = new HideSheetCommand(activeSheet()); doc()->addCommand(command); d->tabBar->removeTab(d->activeSheet->sheetName()); d->tabBar->setActiveTab(sn); } void View::showSheet() { if (!d->activeSheet) return; ShowDialog dialog(this, d->selection); dialog.exec(); } void View::copyAsText() { if (!d->activeSheet) return; QMimeData* mimeData = new QMimeData(); mimeData->setText(CopyCommand::saveAsPlainText(*selection())); QApplication::clipboard()->setMimeData(mimeData); } void View::setShapeAnchoring(const QString& mode) { const KoSelection* selection = d->canvas->shapeManager()->selection(); const QList shapes = selection->selectedShapes(KoFlake::StrippedSelection); for (int i = 0; i < shapes.count(); ++i) { const KoShape* shape = shapes[i]; ShapeApplicationData* data = dynamic_cast(shape->applicationData()); Q_ASSERT(data); data->setAnchoredToCell(mode == i18n("Cell")); } } void View::toggleProtectDoc(bool mode) { if (!doc() || !doc()->map()) return; bool success; if (mode) { success = doc()->map()->showPasswordDialog(this, ProtectableObject::Lock, i18n("Protect Document")); } else { success = doc()->map()->showPasswordDialog(this, ProtectableObject::Unlock, i18n("Unprotect Document")); } if (!success) { d->actions->protectDoc->setChecked(!mode); return; } doc()->setModified(true); stateChanged("map_is_protected", mode ? StateNoReverse : StateReverse); d->tabBar->setReadOnly(doc()->map()->isProtected()); } void View::toggleProtectSheet(bool mode) { if (!d->activeSheet) return; bool success; if (mode) { success = activeSheet()->showPasswordDialog(this, ProtectableObject::Lock, i18n("Protect Sheet")); } else { success = activeSheet()->showPasswordDialog(this, ProtectableObject::Unlock, i18n("Unprotect Sheet")); } if (!success) { d->actions->protectSheet->setChecked(!mode); return; } doc()->setModified(true); d->adjustActions(!mode); // The sheet protection change may hide/unhide some values or formulas, // so the cached visual data has become invalid. refreshSheetViews(); d->canvas->update(); // inform the cell tool emit sheetProtectionToggled(mode); } void View::togglePageBorders(bool mode) { if (!d->activeSheet) return; d->activeSheet->setShowPageBorders(mode); } void View::viewZoom(KoZoomMode::Mode mode, qreal zoom) { Q_UNUSED(zoom) #ifdef NDEBUG Q_UNUSED(mode); #endif Q_ASSERT(mode == KoZoomMode::ZOOM_CONSTANT); selection()->emitCloseEditor(true); // save changes setHeaderMinima(); d->canvas->update(); d->columnHeader->update(); d->rowHeader->update(); d->selectAllButton->update(); } void View::showColumnHeader(bool enable) { doc()->map()->settings()->setShowColumnHeader(enable); d->columnHeader->setVisible(enable); d->selectAllButton->setVisible(enable && d->rowHeader->isVisible()); } void View::showRowHeader(bool enable) { doc()->map()->settings()->setShowRowHeader(enable); d->rowHeader->setVisible(enable); d->selectAllButton->setVisible(enable && d->columnHeader->isVisible()); } void View::showHorizontalScrollBar(bool enable) { doc()->map()->settings()->setShowHorizontalScrollBar(enable); d->horzScrollBar->setVisible(enable); } void View::showVerticalScrollBar(bool enable) { doc()->map()->settings()->setShowVerticalScrollBar(enable); d->vertScrollBar->setVisible(enable); } void View::showStatusBar(bool enable) { doc()->map()->settings()->setShowStatusBar(enable); if (statusBar()) { statusBar()->setVisible(enable); } } void View::showTabBar(bool enable) { doc()->map()->settings()->setShowTabBar(enable); d->tabBar->setVisible(enable); } void View::optionsNotifications() { KNotifyConfigWidget::configure(this); } void View::preference() { PreferenceDialog dialog(this); dialog.exec(); } void View::nextSheet() { Sheet * t = doc()->map()->nextSheet(activeSheet()); if (!t) { kDebug(36001) << "Unknown sheet"; return; } selection()->emitCloseEditor(true); // save changes setActiveSheet(t); d->tabBar->setActiveTab(t->sheetName()); d->tabBar->ensureVisible(t->sheetName()); } void View::previousSheet() { Sheet * t = doc()->map()->previousSheet(activeSheet()); if (!t) { kDebug(36001) << "Unknown sheet"; return; } selection()->emitCloseEditor(true); // save changes setActiveSheet(t); d->tabBar->setActiveTab(t->sheetName()); d->tabBar->ensureVisible(t->sheetName()); } void View::firstSheet() { Sheet *t = doc()->map()->sheet(0); if (!t) { kDebug(36001) << "Unknown sheet"; return; } selection()->emitCloseEditor(true); // save changes setActiveSheet(t); d->tabBar->setActiveTab(t->sheetName()); d->tabBar->ensureVisible(t->sheetName()); } void View::lastSheet() { Sheet *t = doc()->map()->sheet(doc()->map()->count() - 1); if (!t) { kDebug(36001) << "Unknown sheet"; return; } selection()->emitCloseEditor(true); // save changes setActiveSheet(t); d->tabBar->setActiveTab(t->sheetName()); d->tabBar->ensureVisible(t->sheetName()); } void View::keyPressEvent(QKeyEvent *event) { #ifndef NDEBUG if ((event->modifiers() & Qt::ControlModifier) && (event->modifiers() & Qt::ShiftModifier)) { if (event->key() == Qt::Key_V) { // Ctrl+Shift+V to show debug (similar to Words) d->activeSheet->printDebug(); } } #endif QWidget::keyPressEvent(event); } int View::leftBorder() const { return (int)(((RowHeader*)d->rowHeader)->width()); } int View::rightBorder() const { return d->vertScrollBar->width(); } int View::topBorder() const { return (int)(((ColumnHeader*)d->columnHeader)->height()); } int View::bottomBorder() const { return d->horzScrollBar->height(); } void View::setHeaderMinima() { if (d->loading) // "View Loading" not finished yet return; QFont font(KoGlobal::defaultFont()); QFontMetricsF fm(font, 0); qreal h = fm.height() + 3; qreal w = fm.width(QString::fromLatin1("99999")) + 3; d->columnHeader->setMinimumHeight(qRound(h)); d->rowHeader->setMinimumWidth(qRound(w)); d->selectAllButton->setMinimumHeight(qRound(h)); d->selectAllButton->setMinimumWidth(qRound(w)); } void View::paperLayoutDlg() { selection()->emitCloseEditor(true); // save changes SheetPrint* print = d->activeSheet->print(); KoPageLayout pl = print->settings()->pageLayout(); /* const HeaderFooter *const headerFooter = print->headerFooter(); HeadFoot hf; hf.headLeft = headerFooter->localizeHeadFootLine(headerFooter->headLeft()); hf.headRight = headerFooter->localizeHeadFootLine(headerFooter->headRight()); hf.headMid = headerFooter->localizeHeadFootLine(headerFooter->headMid()); hf.footLeft = headerFooter->localizeHeadFootLine(headerFooter->footLeft()); hf.footRight = headerFooter->localizeHeadFootLine(headerFooter->footRight()); hf.footMid = headerFooter->localizeHeadFootLine(headerFooter->footMid()); */ PageLayoutDialog dialog(this, d->activeSheet); dialog.exec(); } void View::resetPrintRange() { DefinePrintRangeCommand* command = new DefinePrintRangeCommand(); command->setText(i18nc("(qtundo-format)", "Reset Print Range")); command->setSheet(activeSheet()); command->add(Region(QRect(QPoint(1, 1), QPoint(KS_colMax, KS_rowMax)), activeSheet())); doc()->addCommand(command); } void View::deleteSheet() { if (doc()->map()->count() <= 1 || (doc()->map()->visibleSheets().count() <= 1)) { KMessageBox::sorry(this, i18n("You cannot delete the only sheet."), i18n("Remove Sheet")); return; } int ret = KMessageBox::warningContinueCancel(this, i18n("You are about to remove the active sheet.\nDo you want to continue?"), i18n("Remove Sheet"), KGuiItem(i18n("&Delete"), koIconName("edit-delete"))); if (ret == KMessageBox::Continue) { selection()->emitCloseEditor(false); // discard changes doc()->setModified(true); Sheet * tbl = activeSheet(); KUndo2Command* command = new RemoveSheetCommand(tbl); doc()->addCommand(command); } } void View::slotRename() { Sheet * sheet = activeSheet(); if (sheet->isProtected()) { KMessageBox::error(0, i18n("You cannot change a protected sheet.")); return; } bool ok; QString activeName = sheet->sheetName(); QString newName = KInputDialog::getText(i18n("Rename Sheet"), i18n("Enter name:"), activeName, &ok, this); if (!ok) return; if ((newName.trimmed()).isEmpty()) { // Sheet name is empty. KMessageBox::information(this, i18n("Sheet name cannot be empty."), i18n("Change Sheet Name")); // Recursion slotRename(); } else if (newName != activeName) { // Sheet name changed. // Is the name already used if (doc()->map()->findSheet(newName)) { KMessageBox::information(this, i18n("This name is already used."), i18n("Change Sheet Name")); // Recursion slotRename(); return; } KUndo2Command* command = new RenameSheetCommand(sheet, newName); doc()->addCommand(command); doc()->setModified(true); } } //------------------------------------------------ // // Document signals // //------------------------------------------------ void View::slotChangeSelection(const Calligra::Sheets::Region& changedRegion) { if (!changedRegion.isValid()) return; if (d->selection->referenceSelectionMode()) { doc()->map()->addDamage(new SelectionDamage(changedRegion)); kDebug(36002) << "Choice:" << *selection(); return; } // delayed recalculation of the operation shown in the status bar d->statusBarOpTimer.setSingleShot(true); d->statusBarOpTimer.start(250); if (!d->loading && !doc()->map()->isLoading()) { doc()->map()->addDamage(new SelectionDamage(changedRegion)); } d->rowHeader->update(); d->columnHeader->update(); d->selectAllButton->update(); if (d->selection->isColumnSelected() || d->selection->isRowSelected()) { return; } d->canvas->validateSelection(); } void View::slotScrollChoice(const Calligra::Sheets::Region& changedRegion) { if (!selection()->referenceSelectionMode() || !changedRegion.isValid()) { return; } } void View::calcStatusBarOp() { Sheet * sheet = activeSheet(); ValueCalc* calc = doc()->map()->calc(); Value val; MethodOfCalc tmpMethod = doc()->map()->settings()->getTypeOfCalc(); if (sheet && tmpMethod != NoneCalc) { Value range = sheet->cellStorage()->valueRegion(*d->selection); switch (tmpMethod) { case SumOfNumber: val = calc->sum(range); break; case Average: val = calc->avg(range); break; case Min: val = calc->min(range); break; case Max: val = calc->max(range); break; case CountA: val = Value(calc->count(range)); break; case Count: val = Value(calc->count(range, false)); case NoneCalc: break; default: break; } } QString res = doc()->map()->converter()->asString(val).asString(); QString tmp; switch (tmpMethod) { case SumOfNumber: tmp = i18n("Sum: ") + res; break; case Average: tmp = i18n("Average: ") + res; break; case Min: tmp = i18n("Min: ") + res; break; case Max: tmp = i18n("Max: ") + res; break; case Count: tmp = i18n("Count: ") + res; break; case CountA: tmp = i18n("CountA: ") + res; break; case NoneCalc: tmp = ""; break; } if (d->calcLabel) d->calcLabel->setText(QString(' ') + tmp + ' '); } void View::statusBarClicked(const QPoint&) { QPoint mousepos = QCursor::pos(); if (factory()) if (QMenu* menu = dynamic_cast(factory()->container("calc_popup" , this))) menu->popup(mousepos); } void View::menuCalc(bool) { if (d->actions->calcMin->isChecked()) { doc()->map()->settings()->setTypeOfCalc(Min); } else if (d->actions->calcMax->isChecked()) { doc()->map()->settings()->setTypeOfCalc(Max); } else if (d->actions->calcCount->isChecked()) { doc()->map()->settings()->setTypeOfCalc(Count); } else if (d->actions->calcAverage->isChecked()) { doc()->map()->settings()->setTypeOfCalc(Average); } else if (d->actions->calcSum->isChecked()) { doc()->map()->settings()->setTypeOfCalc(SumOfNumber); } else if (d->actions->calcCountA->isChecked()) { doc()->map()->settings()->setTypeOfCalc(CountA); } else if (d->actions->calcNone->isChecked()) doc()->map()->settings()->setTypeOfCalc(NoneCalc); calcStatusBarOp(); } QWidget* View::canvas() const { return d->canvas; } void View::guiActivateEvent(KParts::GUIActivateEvent *ev) { // We need a width/height > 0 for setting the initial position properly. // This is not always the case from the beginning of the View's lifetime. if (ev->activated()) { initialPosition(); } if (d->activeSheet) { if (ev->activated()) { if (d->calcLabel) calcStatusBarOp(); } } KoView::guiActivateEvent(ev); } void View::popupTabBarMenu(const QPoint & _point) { if (!factory()) return; if (d->tabBar) { QMenu* const menu = static_cast(factory()->container("menupage_popup", this)); if (!menu) return; QAction* insertSheet = new KAction(koIcon("insert-table"), i18n("Insert Sheet"), this); insertSheet->setToolTip(i18n("Remove the active sheet")); connect(insertSheet, SIGNAL(triggered(bool)), this, SLOT(insertSheet())); menu->insertAction(d->actions->duplicateSheet, insertSheet); QAction* deleteSheet = new KAction(koIcon("delete_table"), i18n("Remove Sheet"), this); deleteSheet->setToolTip(i18n("Remove the active sheet")); connect(deleteSheet, SIGNAL(triggered(bool)), this, SLOT(deleteSheet())); menu->insertAction(d->actions->hideSheet, deleteSheet); bool state = (doc()->map()->visibleSheets().count() > 1); if (d->activeSheet && d->activeSheet->isProtected()) { deleteSheet->setEnabled(false); d->actions->hideSheet->setEnabled(false); d->actions->showSheet->setEnabled(false); } else { deleteSheet->setEnabled(state); d->actions->hideSheet->setEnabled(state); d->actions->showSheet->setEnabled(doc()->map()->hiddenSheets().count() > 0); } if (!doc() || !doc()->map() || doc()->map()->isProtected()) { insertSheet->setEnabled(false); deleteSheet->setEnabled(false); d->actions->renameSheet->setEnabled(false); d->actions->showSheet->setEnabled(false); d->actions->hideSheet->setEnabled(false); } menu->exec(_point); menu->removeAction(insertSheet); menu->removeAction(deleteSheet); delete insertSheet; delete deleteSheet; } } void View::updateBorderButton() { if (d->activeSheet) d->actions->showPageBorders->setChecked(d->activeSheet->isShowPageBorders()); } void View::addSheet(Sheet *sheet) { if (!sheet->isHidden()) { d->tabBar->addTab(sheet->sheetName()); } const bool state = (doc()->map()->visibleSheets().count() > 1); d->actions->deleteSheet->setEnabled(state); d->actions->hideSheet->setEnabled(state); // Connect some signals connect(sheet, SIGNAL(shapeAdded(Sheet *, KoShape *)), d->mapViewModel, SLOT(addShape(Sheet *, KoShape *))); connect(sheet, SIGNAL(shapeRemoved(Sheet *, KoShape *)), d->mapViewModel, SLOT(removeShape(Sheet *, KoShape *))); } void View::removeSheet(Sheet *sheet) { d->tabBar->removeTab(sheet->sheetName()); setActiveSheet(doc()->map()->sheet(0)); const bool state = (doc()->map()->visibleSheets().count() > 1); d->actions->deleteSheet->setEnabled(state); d->actions->hideSheet->setEnabled(state); // Disconnect signals. disconnect(sheet, 0, d->mapViewModel, 0); } QColor View::borderColor() const { return d->canvas->resourceManager()->foregroundColor().toQColor(); } void View::updateShowSheetMenu() { if (d->activeSheet) { if (d->activeSheet->map()->isProtected()) d->actions->showSheet->setEnabled(false); else d->actions->showSheet->setEnabled(doc()->map()->hiddenSheets().count() > 0); } } QPoint View::markerFromSheet(Sheet* sheet) const { QMap::Iterator it = d->savedMarkers.find(sheet); QPoint newMarker = (it == d->savedMarkers.end()) ? QPoint(1, 1) : *it; return newMarker; } QPointF View::offsetFromSheet(Sheet* sheet) const { QMap::Iterator it = d->savedOffsets.find(sheet); QPointF offset = (it == d->savedOffsets.end()) ? QPointF() : *it; return offset; } void View::saveCurrentSheetSelection() { /* save the current selection on this sheet */ if (d->activeSheet != 0) { d->savedAnchors.remove(d->activeSheet); d->savedAnchors.insert(d->activeSheet, d->selection->anchor()); kDebug(36005) << " Current scrollbar vert value:" << d->vertScrollBar->value(); kDebug(36005) << "Saving marker pos:" << d->selection->marker(); d->savedMarkers.remove(d->activeSheet); d->savedMarkers.insert(d->activeSheet, d->selection->marker()); d->savedOffsets.remove(d->activeSheet); d->savedOffsets.insert(d->activeSheet, QPointF(d->canvas->xOffset(), d->canvas->yOffset())); } } void View::handleDamages(const QList& damages) { QRegion paintRegion; enum { Nothing, Everything, Clipped } paintMode = Nothing; QList::ConstIterator end(damages.end()); for (QList::ConstIterator it = damages.begin(); it != end; ++it) { Damage* damage = *it; if (!damage) continue; if (damage->type() == Damage::Cell) { CellDamage* cellDamage = static_cast(damage); kDebug(36007) << "Processing\t" << *cellDamage; Sheet* const damagedSheet = cellDamage->sheet(); if (cellDamage->changes() & CellDamage::Appearance) { const Region& region = cellDamage->region(); sheetView(damagedSheet)->invalidateRegion(region); paintMode = Everything; } continue; } if (damage->type() == Damage::Sheet) { SheetDamage* sheetDamage = static_cast(damage); kDebug(36007) << *sheetDamage; const SheetDamage::Changes changes = sheetDamage->changes(); if (changes & (SheetDamage::Name | SheetDamage::Shown)) { d->tabBar->setTabs(doc()->map()->visibleSheets()); paintMode = Everything; } if (changes & (SheetDamage::Shown | SheetDamage::Hidden)) { updateShowSheetMenu(); paintMode = Everything; } // The following changes only affect the active sheet. if (sheetDamage->sheet() != d->activeSheet) { continue; } if (changes.testFlag(SheetDamage::ContentChanged)) { update(); paintMode = Everything; } if (changes.testFlag(SheetDamage::PropertiesChanged)) { sheetView(d->activeSheet)->invalidate(); paintMode = Everything; } if (sheetDamage->changes() & SheetDamage::ColumnsChanged) columnHeader()->update(); if (sheetDamage->changes() & SheetDamage::RowsChanged) rowHeader()->update(); continue; } if (damage->type() == Damage::Selection) { SelectionDamage* selectionDamage = static_cast(damage); kDebug(36007) << "Processing\t" << *selectionDamage; const Region region = selectionDamage->region(); if (paintMode == Clipped) { const QRectF rect = canvasWidget()->cellCoordinatesToView(region.boundingRect()); paintRegion += rect.toRect().adjusted(-3, -3, 4, 4); } else { paintMode = Everything; } continue; } kDebug(36007) << "Unhandled\t" << *damage; } // At last repaint the dirty cells. if (paintMode == Clipped) { canvas()->update(paintRegion); } else if (paintMode == Everything) { canvas()->update(); } } KoPrintJob * View::createPrintJob() { if (!activeSheet()) return 0; // About to print; close the editor. selection()->emitCloseEditor(true); // save changes return new PrintJob(this); } void View::updateAccessedCellRange(Sheet* sheet, const QPoint &location) { sheetView(sheet)->updateAccessedCellRange(location); } #include "View.moc" diff --git a/stage/part/KPrPresentationToolAdaptor.h b/stage/part/KPrPresentationToolAdaptor.h index e0f8def6a44..0c88a3349cd 100644 --- a/stage/part/KPrPresentationToolAdaptor.h +++ b/stage/part/KPrPresentationToolAdaptor.h @@ -1,78 +1,78 @@ /* This file is part of the KDE project * Copyright (C) 2010 Gopalakrishna Bhat A * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPRPRESENTATIONTOOLADAPTOR_H #define KPRPRESENTATIONTOOLADAPTOR_H #include "KPrPresentationTool.h" -#include +#include class KPrViewModePresentation; class KPrPresentationTool; class KPrPresentationToolAdaptor : public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.calligra.presentation.tool") public: explicit KPrPresentationToolAdaptor(KPrPresentationTool *tool); virtual ~KPrPresentationToolAdaptor(); public slots: // METHODS /** * Blank the presentation. */ void blankPresentation(); /** * Highlight the presentation. */ Q_NOREPLY void highlightPresentation(int pointx, int pointy); /** * Draw on presentation. * @color can take the color values as a string. Eg: red, green, black. */ void startDrawPresentation(int pointx, int pointy, int penSize, QString color); /** * Start drawing on presentation tool. * The parameters pointx and pointy specify a point in the path. */ Q_NOREPLY void drawOnPresentation(int pointx,int pointy); /** * Stop drawing path. The current path is stopped. */ void stopDrawPresentation(); /** * Normal presentation mode. */ void normalPresentation(); private: KPrPresentationTool *m_tool; KPrViewModePresentation &m_viewModePresentation; }; #endif /* KPRPRESENTATIONTOOLADAPTOR_H */ diff --git a/stage/part/ui/KPrHtmlExportDialog.h b/stage/part/ui/KPrHtmlExportDialog.h index cec63559394..7e0b1802847 100644 --- a/stage/part/ui/KPrHtmlExportDialog.h +++ b/stage/part/ui/KPrHtmlExportDialog.h @@ -1,75 +1,75 @@ /* This file is part of the KDE project * Copyright (C) 2009 Yannick Motta * Copyright (C) 2009-2010 Benjamin Port * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPRHTMLEXPORTDIALOG_H #define KPRHTMLEXPORTDIALOG_H #include "ui_KPrHtmlExport.h" -#include +#include #include class KPrHtmlExportDialog : public KDialog { Q_OBJECT public: KPrHtmlExportDialog(const QList &slides, const QString &title, const QString &author, QWidget *parent=0); QList checkedSlides(); QStringList slidesNames(); KUrl templateUrl(); QString title(); QString author(); bool openBrowser(); private slots: void checkAllItems(); void uncheckAllItems(); void renderPreview(); void favoriteAction(); void updateFavoriteButton(); void generateNext(); void generatePrevious(); void generatePreview(int item=-1); void browserAction(); private: void generateSlidesNames(const QList &slides); void loadTemplatesList(); bool selectedTemplateIsFavorite(); bool selectedTemplateIsSystemFavorite(); bool verifyZipFile(const QString &zipLocalPath); void addSelectedTemplateToFavorite(); void delSelectedTemplateFromFavorite(); QList m_allSlides; QString m_title; Ui::KPrHtmlExport ui; QWebPage preview; int frameToRender; }; #endif // KPRHTMLEXPORTDIALOG_H diff --git a/tools/okularodpgenerator/OkularOdpGenerator.cpp b/tools/okularodpgenerator/OkularOdpGenerator.cpp index d7aea9e1ade..10d7fae8e22 100644 --- a/tools/okularodpgenerator/OkularOdpGenerator.cpp +++ b/tools/okularodpgenerator/OkularOdpGenerator.cpp @@ -1,140 +1,140 @@ /* This file is part of the KDE project Copyright (C) 2010 KO GmbH Copyright (C) 2010 Sven Langkamp This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include static KAboutData createAboutData() { KAboutData aboutData( "okular_odp", "okular_odp", ki18n( "ODP Backend" ), "0.1", ki18n( "ODP file renderer" ), KAboutData::License_GPL, ki18n( "© 2010 Sven Langkamp" ) ); // fill the about data return aboutData; } OKULAR_EXPORT_PLUGIN(OkularOdpGenerator, createAboutData()) OkularOdpGenerator::OkularOdpGenerator( QObject *parent, const QVariantList &args ) : Okular::Generator( parent, args ) { m_doc = 0; } OkularOdpGenerator::~OkularOdpGenerator() { } bool OkularOdpGenerator::loadDocument( const QString &fileName, QVector &pages ) { KComponentData cd("OkularOdpGenerator", QByteArray(), KComponentData::SkipMainComponentRegistration); const QString mimetype = KMimeType::findByPath(fileName)->name(); QString error; KoPart *part = KMimeTypeTrader::self()->createInstanceFromQuery( mimetype, QLatin1String("CalligraPart"), 0, QString(), QVariantList(), &error ); if (!error.isEmpty()) { qWarning() << "Error creating document" << mimetype << error; return 0; } KoPADocument* doc = qobject_cast(part->document()); m_doc = doc; KUrl url; url.setPath(fileName); doc->setCheckAutoSaveFile(false); doc->setAutoErrorHandlingEnabled(false); // show error dialogs if (!doc->openUrl(url)) { return false; } doc->setReadWrite(false); doc->setAutoSave(0); int pageCount = m_doc->pageCount(); for(int i = 0; i < pageCount; i++) { KoPAPageBase* kprpage = m_doc->pages().value(i); if (!kprpage) { continue; } QSize size = kprpage->size().toSize(); Okular::Page * page = new Okular::Page( i, size.width(), size.height(), Okular::Rotation0 ); pages.append(page); } return true; } bool OkularOdpGenerator::doCloseDocument() { delete m_doc; return true; } bool OkularOdpGenerator::canGeneratePixmap() const { return true; } void OkularOdpGenerator::generatePixmap( Okular::PixmapRequest *request ) { QPixmap* pix; if (!m_doc) { pix = new QPixmap(request->width(), request->height()); QPainter painter(pix); painter.fillRect(0 ,0 , request->width(), request->height(), Qt::white); } else { KoPAPageBase* page = m_doc->pages().value(request->pageNumber()); pix = new QPixmap(page->thumbnail(QSize(request->width(), request->height()))); } request->page()->setPixmap( request->id(), pix ); signalPixmapRequestDone( request ); } diff --git a/tools/slidecompare/combinedview.cpp b/tools/slidecompare/combinedview.cpp index ba85c165a79..a0634a9a713 100644 --- a/tools/slidecompare/combinedview.cpp +++ b/tools/slidecompare/combinedview.cpp @@ -1,189 +1,189 @@ /* This file is part of the KDE project Copyright (C) 2010 KO GmbH This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "combinedview.h" #include "dirslideloader.h" #include "kpresenterslideloader.h" #include "slideview.h" #include "oothread.h" #include #include #include #include -#include -#include +#include +#include CombinedView::CombinedView(QWidget* parent) :QWidget(parent), ooodploader(new DirSlideLoader(this)), koodploader(new KPresenterSlideLoader(this)), oopptloader(new DirSlideLoader(this)), kopptloader(new KPresenterSlideLoader(this)), ooodpview(new SlideView(ooodploader, this)), koodpview(new SlideView(koodploader, this)), oopptview(new SlideView(oopptloader, this)), kopptview(new SlideView(kopptloader, this)), oothread(new OoThread(this)), layout(new QGridLayout(this)) { ooodploader->setSlideNamePattern("img%1.png"); oopptloader->setSlideNamePattern("img%1.png"); addSlideView(ooodpview); addSlideView(koodpview); addSlideView(oopptview); addSlideView(kopptview); layout->addWidget(ooodpview, 0, 0); layout->addWidget(koodpview, 0, 1); layout->addWidget(oopptview, 1, 0); layout->addWidget(kopptview, 1, 1); layout->setColumnStretch(0, 1); layout->setColumnStretch(1, 1); layout->setRowStretch(0, 1); layout->setRowStretch(1, 1); layout->setSpacing(0); layout->setContentsMargins(0, 0, 0, 0); setLayout(layout); connect(oothread, SIGNAL(toOdpDone(QString)), this, SLOT(slotHandleOoOdp(QString))); connect(oothread, SIGNAL(toPngDone(QString)), this, SLOT(slotHandleOoPng(QString))); setAcceptDrops(true); } CombinedView::~CombinedView() { oothread->stop(); oothread->wait(); } void CombinedView::slotSetView(qreal zoomFactor, int h, int v) { for (int i=0; isetView(zoomFactor, h, v); } } void CombinedView::addSlideView(SlideView* slideview) { slideViews.push_back(slideview); connect(slideview, SIGNAL(viewChanged(qreal,int,int)), this, SLOT(slotSetView(qreal,int,int))); } QString koppttoodp(const QString& from) { QDir d(QDir::temp().filePath("slidecompare-" + QDir::home().dirName())); QString dirpath = d.absolutePath(); d.mkpath(dirpath); QString to = dirpath + QDir::separator() + QFileInfo(from).baseName() + ".odp"; QFile::remove(to); PptToOdp ppttoodp(0, 0); ppttoodp.convert(from, to, KoStore::Zip); return to; } void CombinedView::openFile(const QString& path) { bool odp = path.toLower().endsWith(".odp"); oopptview->setVisible(!odp); kopptview->setVisible(!odp); layout->setRowStretch(1, (odp)?0:1); // update view now for more pleasing user experience, later renderings // may be slow qApp->processEvents(); oopptloader->setSlideDir(""); kopptloader->close(); if (!QFileInfo(path).exists()) { KMessageBox::error(this, QString("File %1 does not exist.").arg(path)); return; } if (!odp) { nextodpfile = koppttoodp(path); if (!QFileInfo(nextodpfile).exists()) { KMessageBox::error(this, QString( "File %1 cannot be converted by PptToOdp.").arg(path)); return; } koodploader->open(nextodpfile); } else { nextodpfile = ""; koodploader->open(path); } quint32 nslides = koodploader->numberOfSlides(); if (nslides == 0) { return; } ooodploader->setSlideSize(koodploader->slideSize()); ooodploader->setNumberOfSlides(nslides); if (!odp) { // start conversion to odp ooodpresult = oothread->toOdp(path); oopptloader->setSlideSize(koodploader->slideSize()); oopptloader->setNumberOfSlides(nslides); } else { oopptloader->setNumberOfSlides(0); } QString dir = oothread->toPng(path, koodploader->slideSize().width()); ooodploader->setSlideDir(dir); // if ppt, convert to odp with calligra and put in queue for conversion to // png // adapt zoom level to number of slides qreal zoomlevel = (nslides > 3 || nslides == 0) ?0.25 :1.0/nslides; ooodpview->setView(zoomlevel, 0, 0); koodpview->setView(zoomlevel, 0, 0); oopptview->setView(zoomlevel, 0, 0); kopptview->setView(zoomlevel, 0, 0); } void CombinedView::slotHandleOoOdp(const QString& path) { if (path == ooodpresult) { kopptloader->open(path); } } void CombinedView::slotHandleOoPng(const QString& /*path*/) { if (!nextodpfile.isEmpty()) { QString dir = oothread->toPng(nextodpfile, koodploader->slideSize().width()); oopptloader->setSlideDir(dir); nextodpfile = ""; } } void CombinedView::dragEnterEvent(QDragEnterEvent *event) { foreach (const QUrl& url, event->mimeData()->urls()) { const QString path(url.toLocalFile()); if (path.isEmpty()) { // url is not local event->acceptProposedAction(); } else { QString mimetype = KMimeType::findByUrl(url)->name(); if (mimetype == "application/vnd.oasis.opendocument.presentation" || mimetype == "application/vnd.ms-powerpoint") { event->acceptProposedAction(); } } } } void CombinedView::dropEvent(QDropEvent *event) { if (event->mimeData()->urls().size()) { openFile(event->mimeData()->urls().first().toLocalFile()); } } diff --git a/tools/slidecompare/kpresenterslideloader.cpp b/tools/slidecompare/kpresenterslideloader.cpp index fa4a8e7ae6f..208e7b05274 100644 --- a/tools/slidecompare/kpresenterslideloader.cpp +++ b/tools/slidecompare/kpresenterslideloader.cpp @@ -1,86 +1,86 @@ /* This file is part of the KDE project Copyright (C) 2010 KO GmbH This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kpresenterslideloader.h" #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include KPresenterSlideLoader::KPresenterSlideLoader(QObject* parent) :SlideLoader(parent) { m_doc = 0; version = 0; } KPresenterSlideLoader::~KPresenterSlideLoader() { close(); } void KPresenterSlideLoader::close() { delete m_doc; m_doc = 0; version++; emit slidesChanged(); } void KPresenterSlideLoader::open(const QString& path) { close(); KComponentData cd("KPresenterSlideLoader", QByteArray(), KComponentData::SkipMainComponentRegistration); KPluginFactory *factory = KPluginLoader("calligrastagepart", cd).factory(); if (!factory) { qDebug() << "could not load calligrastagepart"; close(); return; } KoPADocument* doc = factory->create(); m_doc = doc; KUrl url; url.setPath(path); doc->setCheckAutoSaveFile(false); doc->setAutoErrorHandlingEnabled(true); // show error dialogs if (!doc->openUrl(url)) { qDebug() << "could not open " << path; close(); return; } doc->setReadWrite(false); doc->setAutoSave(0); emit slidesChanged(); } int KPresenterSlideLoader::numberOfSlides() { return (m_doc) ?m_doc->pageCount() :0; } QSize KPresenterSlideLoader::slideSize() { if (!m_doc) return QSize(); KoPAPageBase* page = m_doc->pages().value(0); if (!page) return QSize(); return page->size().toSize(); } QPixmap KPresenterSlideLoader::loadSlide(int number, const QSize& maxsize) { if (!m_doc) return QPixmap(); KoPAPageBase* page = m_doc->pages().value(number); if (!page) return QPixmap(); return page->thumbnail(maxsize); } diff --git a/tools/slidecompare/slideview.cpp b/tools/slidecompare/slideview.cpp index e8283769247..3dd23394976 100644 --- a/tools/slidecompare/slideview.cpp +++ b/tools/slidecompare/slideview.cpp @@ -1,284 +1,284 @@ /* This file is part of the KDE project Copyright (C) 2010 KO GmbH This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "slideview.h" #include "slideloader.h" #include #include #include #include #include #include #include #include #include #include -#include +#include #include class GraphicsSlideItem : public QGraphicsItem { public: #ifdef QT46 class Cache { private: QPixmapCache::Key key; public: bool find(QPixmap& pixmap) const { return QPixmapCache::find(key, &pixmap); } void clear() const { QPixmapCache::remove(key); } void add(const QPixmap& pixmap) { clear(); key = QPixmapCache::insert(pixmap); } }; #else class Cache { private: const QString key; public: Cache() :key(QString("%1 GraphicsSlideItem").arg((qlonglong)this)) {} bool find(QPixmap& pixmap) const { return QPixmapCache::find(key, pixmap); } void clear() const { QPixmapCache::remove(key); } void add(const QPixmap& pixmap) { clear(); QPixmapCache::insert(key, pixmap); } }; #endif Cache cache; QRectF rect; QPainterPath path; SlideView* const view; int position; int slideVersion; explicit GraphicsSlideItem(int pos, SlideView* v) :QGraphicsItem(), view(v), position(pos) { slideVersion = -1; } void setPosition(int pos) { if (position != pos) { position = pos; slideVersion = -1; } if (view->loader->slideVersion(position) != slideVersion) { update(rect); } } void paint(QPainter* painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/ = 0) { QPixmap pixmap; if (slideVersion != view->loader->slideVersion(position) || !cache.find(pixmap)) { slideVersion = view->loader->slideVersion(position); pixmap = view->loader->loadSlide(position, rect.size().toSize()); cache.add(pixmap); } if (pixmap.isNull()) { painter->fillRect(rect, Qt::gray); } else { painter->drawPixmap(rect.topLeft(), pixmap); } } QRectF boundingRect() const { return rect; } QPainterPath opaqueArea() const { return path; } void setBoundingRect(const QRectF& newrect) { if (rect != newrect) { if (rect.size() != newrect.size()) { cache.clear(); } prepareGeometryChange(); rect = newrect; path = QPainterPath(); path.addRect(rect); } } void mouseDoubleClickEvent(QGraphicsSceneMouseEvent * /*event*/) { view->toggleSlideZoom(this); } }; SlideView::SlideView(SlideLoader* l, QWidget* parent) :QWidget(parent), loader(l), zoomfactor(0.25), sendingChange(false) { // use opengl canvas view.setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); // listen to resize and wheel events view.viewport()->installEventFilter(this); connect(loader, SIGNAL(slidesChanged()), this, SLOT(slotUpdateSlides())); connect(view.verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(slotViewChanged())); connect(view.horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(slotViewChanged())); QVBoxLayout *layout = new QVBoxLayout(); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); layout->addWidget(&view); layout->addWidget(&progressBar); setLayout(layout); progressBar.setVisible(false); scene.setBackgroundBrush(Qt::Dense4Pattern); view.setScene(&scene); slotUpdateSlides(); } void SlideView::slotUpdateSlides() { int numberOfSlides = loader->numberOfSlides(); QList items = scene.items(); if (items.size() > numberOfSlides) { // remove surplus items for (int i = numberOfSlides; i < items.size(); ++i) { scene.removeItem(items[i]); } } else if (numberOfSlides > items.size()) { // add new items for (int i=items.size(); isetVisible(true); scene.addItem(item); } } items = scene.items(); for (int i=0; i(items[i])->setPosition(i); } layout(); } void SlideView::layout() { const qreal spacing = 2; QSizeF slidesize = loader->slideSize(); int slidesPerRow = (zoomfactor > 1) ?1 :1/zoomfactor; if (zoomfactor <= 1) { view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); } else { view.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); } qreal viewwidth = view.viewport()->width(); qreal x = 0; qreal y = 0; qreal screenslidewidth = zoomfactor * viewwidth; qreal w, h, viewscale; if (screenslidewidth > slidesize.width()) { viewscale = screenslidewidth / slidesize.width(); w = slidesize.width(); h = slidesize.height(); } else { viewscale = 1; qreal slidescale = screenslidewidth / slidesize.width(); w = slidesize.width() * slidescale; h = slidesize.height() * slidescale; } QTransform transform; transform.scale(viewscale, viewscale); view.setTransform(transform); const QList items = scene.items(); qreal dx = w + spacing; qreal dy = h + spacing; for (int i=0; i < items.size(); ++i) { GraphicsSlideItem* item = static_cast(items[i]); item->setBoundingRect(QRectF(x, y, w, h)); if ((i+1) % slidesPerRow) { x += dx; } else { x = 0; y += dy; } } if (x == 0) { scene.setSceneRect(0, 0, slidesPerRow*dx, y); } else { scene.setSceneRect(0, 0, slidesPerRow*dx, y + dy); } } bool SlideView::eventFilter(QObject * obj, QEvent *event) { if (obj != view.viewport()) return false; if (event->type() == QEvent::Wheel) { const QWheelEvent* e = static_cast(event); if (e->modifiers() == Qt::ControlModifier) { zoomfactor *= pow(1.1, e->delta()/120.0); layout(); slotViewChanged(); return true; } } else if (event->type() == QEvent::Resize) { layout(); slotViewChanged(); } return false; } void SlideView::setView(qreal zoomfactor, int h, int v) { if (sendingChange) return; this->zoomfactor = zoomfactor; if (scene.items().size()) layout(); view.horizontalScrollBar()->setValue(h); view.verticalScrollBar()->setValue(v); } void SlideView::slotViewChanged() { sendingChange = true; int h = view.horizontalScrollBar()->value(); int v = view.verticalScrollBar()->value(); emit viewChanged(zoomfactor, h, v); sendingChange = false; } void SlideView::toggleSlideZoom(const GraphicsSlideItem* item) { // zoom to zoomfactor 1 with clicked slide on the top, unless that slide // is already active, then zoom to level 0.25 in the range of the clicked // slide // this function does not work well, the behavior of the scrollbar is a // mystery, but the magic dance seems to work ok so far QScrollBar* sb = view.verticalScrollBar(); int offset = 2; qreal y = item->boundingRect().top(); qDebug() << y << " " << sb->value(); if (zoomfactor == 1 && (qAbs(y - sb->value()) <= offset+1 || sb->value()+1 >= sb->maximum())) { zoomfactor = 0.25; } else { zoomfactor = 1; } layout(); // magic dance layout(); view.mapToScene(0, 0).y(); // end of magic dance y = item->boundingRect().top(); view.verticalScrollBar()->setValue(y - offset); // small offset looks nice } void SlideView::SlideGraphicsScene::dragEnterEvent( QGraphicsSceneDragDropEvent *event) { event->ignore(); }