diff options
Diffstat (limited to 'src-qt5')
27 files changed, 1926 insertions, 191 deletions
diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Grav.json b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Grav.json new file mode 100644 index 00000000..8d75d399 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Grav.json @@ -0,0 +1,25 @@ +{ + "name" : { + "default" : "Grav" + }, + "description" : { + "default" : "Simulates a solar system, with a single star and planets erratically orbiting that star" + }, + "author" : { + "name" : "Zackary Welch", + "email" : "zwelch@ixsystems.com", + "website" : "https://github.com/ZackaryWelch", + "company" : "iXsystems", + "company_website" : "http://ixsystems.com" + }, + "meta" : { + "license" : "3-clause BSD", + "license_url" : "https://github.com/trueos/lumina/blob/master/LICENSE", + "copyright" : "Copyright (c) 2017, Ken Moore (ken@ixsystems.com)", + "date_created" : "20171101", + "version" : "1.0" + }, + "qml" : { + "exec" : "qml_scripts/Grav.qml" + } +} diff --git a/src-qt5/core/lumina-desktop-unified/global-includes.h b/src-qt5/core/lumina-desktop-unified/global-includes.h index 40987ad4..fbc3c4f7 100644 --- a/src-qt5/core/lumina-desktop-unified/global-includes.h +++ b/src-qt5/core/lumina-desktop-unified/global-includes.h @@ -59,10 +59,6 @@ #include <QQmlEngine> #include <QQuickImageProvider> -// C++ Backend classes for QML interface -#include <RootDesktopObject.h> -#include <ScreenObject.h> - // libLumina includes #include <LuminaX11.h> #include <LuminaXDG.h> @@ -80,6 +76,9 @@ #include <LIconCache.h> #include <LFileInfo.h> +// C++ Backend classes for QML interface +#include <RootDesktopObject.h> +#include <ScreenObject.h> //Setup any global defines (no classes or global objects: use "global-objects.h" for that) diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.cpp new file mode 100644 index 00000000..471da58f --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.cpp @@ -0,0 +1,44 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "PanelObject.h" +#include <QQmlEngine> +#include <QDebug> + +PanelObject::PanelObject(QString id, QObject *parent) : QObject(parent){ + panel_id = id; +} + +void PanelObject::RegisterType(){ + static bool done = false; + if(done){ return; } + done=true; + qmlRegisterType<PanelObject>("Lumina.Backend.PanelObject",2,0, "PanelObject"); +} + +QString PanelObject::name(){ return panel_id; } +QString PanelObject::background(){ + if(bg.isEmpty()){ return "transparent"; } + return bg; +} +int PanelObject::x(){ return geom.x(); } +int PanelObject::y(){ return geom.y(); } +int PanelObject::width(){ return geom.width(); } +int PanelObject::height(){ return geom.height(); } + +void PanelObject::setBackground(QString fileOrColor){ + if(bg!=fileOrColor){ + bg = fileOrColor; + emit backgroundChanged(); + } +} + +void PanelObject::setGeometry( QRect newgeom ){ + if(geom!=newgeom){ + geom = newgeom; + emit geomChanged(); + } +} diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.h new file mode 100644 index 00000000..a788fa07 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.h @@ -0,0 +1,49 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is the base C++ object that is used to pass Panel info to the QML classes +//=========================================== +#ifndef _LUMINA_DESKTOP_PANEL_OBJECT_H +#define _LUMINA_DESKTOP_PANEL_OBJECT_H +#include <QObject> +#include <QString> +#include <QScreen> + +class PanelObject : public QObject { + Q_OBJECT + Q_PROPERTY( QString name READ name ) + Q_PROPERTY( QString background READ background NOTIFY backgroundChanged) + Q_PROPERTY( int x READ x NOTIFY geomChanged) + Q_PROPERTY( int y READ y NOTIFY geomChanged) + Q_PROPERTY( int width READ width NOTIFY geomChanged) + Q_PROPERTY( int height READ height NOTIFY geomChanged) + +private: + QString panel_id, bg; + QRect geom; + +public: + PanelObject(QString id = "", QObject *parent = 0); + + static void RegisterType(); + + Q_INVOKABLE QString name(); + Q_INVOKABLE QString background(); + Q_INVOKABLE int x(); + Q_INVOKABLE int y(); + Q_INVOKABLE int width(); + Q_INVOKABLE int height(); + +public slots: + void setBackground(QString fileOrColor); + void setGeometry(QRect newgeom); + +signals: + void backgroundChanged(); + void geomChanged(); +}; + +#endif diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp index 60cf56c3..5750ac2d 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp @@ -21,6 +21,9 @@ RootDesktopObject::~RootDesktopObject(){ } void RootDesktopObject::RegisterType(){ + static bool done = false; + if(done){ return; } + done=true; qmlRegisterType<RootDesktopObject>("Lumina.Backend.RootDesktopObject", 2, 0, "RootDesktopObject"); //Also register any types that are needed by this class ScreenObject::RegisterType(); @@ -47,6 +50,47 @@ ScreenObject* RootDesktopObject::screen(QString id){ return 0; } +QStringList RootDesktopObject::panels(){ + //qDebug() << "Request Panels:" << panel_objects.length(); + QStringList names; + for(int i=0; i<panel_objects.length(); i++){ names << panel_objects[i]->name(); } + return names; +} + +PanelObject* RootDesktopObject::panel(QString id){ + //qDebug() << "Got Panel Request:" << id; + for(int i=0; i<panel_objects.length(); i++){ + if(panel_objects[i]->name()==id){ return panel_objects[i]; } + } + return 0; +} + +QStringList RootDesktopObject::windows(){ + //qDebug() << "Request Panels:" << panel_objects.length(); + QStringList names; + for(int i=0; i<window_objects.length(); i++){ names << QString::number(window_objects[i]->id()); } + return names; +} + +NativeWindow* RootDesktopObject::window(QString id){ + //qDebug() << "Got Panel Request:" << id; + WId chk = id.toInt(); //numerical ID's in this case + for(int i=0; i<window_objects.length(); i++){ + if(window_objects[i]->id()==chk){ return window_objects[i]; } + } + return 0; +} + +void RootDesktopObject::setPanels(QList<PanelObject*> list){ + panel_objects = list; + emit panelsChanged(); +} + +void RootDesktopObject::setWindows(QList<NativeWindow*> list){ + window_objects = list; + emit windowsChanged(); +} + void RootDesktopObject::logout(){ emit startLogout(); } @@ -85,4 +129,5 @@ void RootDesktopObject::ChangeWallpaper(QString screen, QString value){ } } + // === PRIVATE === diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h index ba586701..838b5f7d 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h @@ -10,6 +10,7 @@ #define _LUMINA_DESKTOP_QML_BACKEND_ROOT_DESKTOP_OBJECT_H #include <QObject> #include <QList> +#include <global-includes.h> #include "ScreenObject.h" @@ -17,6 +18,8 @@ class RootDesktopObject : public QObject{ Q_OBJECT //Define all the QML Properties here (interface between QML and the C++ methods below) Q_PROPERTY( QStringList screens READ screens NOTIFY screensChanged) + Q_PROPERTY( QStringList panels READ panels NOTIFY panelsChanged) + Q_PROPERTY( QStringList windows READ windows NOTIFY windowsChanged); public: //main contructor/destructor @@ -29,15 +32,25 @@ public: static RootDesktopObject* instance(); //QML Read Functions - QStringList screens(); + Q_INVOKABLE QStringList screens(); Q_INVOKABLE ScreenObject* screen(QString id); + Q_INVOKABLE QStringList panels(); + Q_INVOKABLE PanelObject* panel(QString id); + Q_INVOKABLE QStringList windows(); + Q_INVOKABLE NativeWindow* window(QString id); + + void setPanels(QList<PanelObject*> list); + void setWindows(QList<NativeWindow*> list); //QML Access Functions Q_INVOKABLE void logout(); Q_INVOKABLE void lockscreen(); Q_INVOKABLE void mousePositionChanged(); + private: QList<ScreenObject*> s_objects; + QList<PanelObject*> panel_objects; + QList<NativeWindow*> window_objects; public slots: void updateScreens(); //rescan/update screen objects @@ -47,6 +60,9 @@ private slots: signals: void screensChanged(); + void panelsChanged(); + void windowsChanged(); + void startLogout(); void mouseMoved(); void lockScreen(); diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.cpp index 4c1d6189..82622403 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.cpp @@ -13,7 +13,12 @@ ScreenObject::ScreenObject(QScreen *scrn, QObject *parent) : QObject(parent){ } void ScreenObject::RegisterType(){ + static bool done = false; + if(done){ return; } + done=true; qmlRegisterType<ScreenObject>("Lumina.Backend.ScreenObject",2,0, "ScreenObject"); + //Also register any types that are needed by this class + PanelObject::RegisterType(); } QString ScreenObject::name(){ return bg_screen->name(); } @@ -29,3 +34,24 @@ void ScreenObject::setBackground(QString fileOrColor){ emit backgroundChanged(); } } + +void ScreenObject::setPanels(QList<PanelObject*> list){ + panel_objects = list; + emit panelsChanged(); +} + +//QML Read Functions +QStringList ScreenObject::panels(){ + //qDebug() << "Request Panels:" << panel_objects.length(); + QStringList names; + for(int i=0; i<panel_objects.length(); i++){ names << panel_objects[i]->name(); } + return names; +} + +PanelObject* ScreenObject::panel(QString id){ + //qDebug() << "Got Panel Request:" << id; + for(int i=0; i<panel_objects.length(); i++){ + if(panel_objects[i]->name()==id){ return panel_objects[i]; } + } + return 0; +} diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.h index 8076f1ae..1afff6d2 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.h +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.h @@ -12,6 +12,8 @@ #include <QString> #include <QScreen> +#include "PanelObject.h" + class ScreenObject : public QObject { Q_OBJECT Q_PROPERTY( QString name READ name ) @@ -20,10 +22,12 @@ class ScreenObject : public QObject { Q_PROPERTY( int y READ y NOTIFY geomChanged) Q_PROPERTY( int width READ width NOTIFY geomChanged) Q_PROPERTY( int height READ height NOTIFY geomChanged) + Q_PROPERTY( QStringList panels READ panels NOTIFY panelsChanged) private: QScreen *bg_screen; QString bg; + QList<PanelObject*> panel_objects; public: ScreenObject(QScreen *scrn = 0, QObject *parent = 0); @@ -36,6 +40,10 @@ public: Q_INVOKABLE int y(); Q_INVOKABLE int width(); Q_INVOKABLE int height(); + Q_INVOKABLE QStringList panels(); + Q_INVOKABLE PanelObject* panel(QString id); + + void setPanels(QList<PanelObject*> list); public slots: void setBackground(QString fileOrColor); @@ -43,6 +51,7 @@ public slots: signals: void backgroundChanged(); void geomChanged(); + void panelsChanged(); }; #endif diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/src-cpp.pri b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/src-cpp.pri index 33b699da..899f4968 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/src-cpp.pri +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/src-cpp.pri @@ -1,8 +1,9 @@ SOURCES *= $${PWD}/RootDesktopObject.cpp \ - $${PWD}/ScreenObject.cpp + $${PWD}/ScreenObject.cpp \ + $${PWD}/PanelObject.cpp HEADERS *= $${PWD}/RootDesktopObject.h \ - $${PWD}/ScreenObject.h + $${PWD}/ScreenObject.h \ + $${PWD}/PanelObject.h INCLUDEPATH *= $${PWD} - diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Panel.qml b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Panel.qml new file mode 100644 index 00000000..846b5b55 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Panel.qml @@ -0,0 +1,26 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +import QtQuick 2.2 +import QtQuick.Window 2.2 +import QtQuick.Controls 1 + +import Lumina.Backend.PanelObject 2.0 + +AnimatedImage { + //C++ backend object + property string screen_id + property PanelObject object + + //Normal geometries/placements + asynchronous: true + clip: true + source: object.background + x: object.x + y: object.y + width: object.width + height: object.height + } diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/RootDesktop.qml b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/RootDesktop.qml index e0381e23..c564ee42 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/RootDesktop.qml +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/RootDesktop.qml @@ -46,11 +46,12 @@ Rectangle { //Create the context menu itself QML.ContextMenu { id: contextMenu } - //Setup the wallpapers + //Setup the screens/wallpapers Repeater{ model: RootObject.screens - QML.WallpaperImage{ + QML.Screen{ screen_id: modelData + object: RootObject.screen(modelData) z: 0+index } } diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/WallpaperImage.qml b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Screen.qml index 1b44963f..3b83653a 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/WallpaperImage.qml +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Screen.qml @@ -13,7 +13,7 @@ import Lumina.Backend.ScreenObject 2.0 AnimatedImage { //C++ backend object property string screen_id - property ScreenObject object: RootObject.screen(screen_id) + property ScreenObject object //Normal geometries/placements asynchronous: true diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.pri b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.pri index fed18e02..ad07902a 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.pri +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.pri @@ -2,7 +2,8 @@ lupdate_only{ SOURCES *= $${PWD}/RootDesktop.qml \ $${PWD}/ContextMenu.qml \ - $${PWD}/WallpaperImage.qml + $${PWD}/Screen.qml \ + $${PWD}/Panel.qml } RESOURCES *= $${PWD}/src-qml.qrc diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.qrc b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.qrc index ebdcc606..b0c66e20 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.qrc +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.qrc @@ -2,6 +2,7 @@ <qresource prefix="qml"> <file>RootDesktop.qml</file> <file>ContextMenu.qml</file> - <file>WallpaperImage.qml</file> + <file>Screen.qml</file> + <file>Panel.qml</file> </qresource> </RCC> diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.cpp index 670e1c9c..e581b016 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.cpp +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.cpp @@ -43,7 +43,7 @@ lthemeenginePlatformTheme::lthemeenginePlatformTheme(){ #endif QGuiApplication::setFont(m_generalFont); } - qCDebug(llthemeengine) << "using lthemeengine plugin"; + //qCDebug(llthemeengine) << "using lthemeengine plugin"; #ifdef QT_WIDGETS_LIB if(!QStyleFactory::keys().contains("lthemeengine-style")) qCCritical(llthemeengine) << "unable to find lthemeengine proxy style"; @@ -60,7 +60,7 @@ QPlatformMenuBar *lthemeenginePlatformTheme::createPlatformMenuBar() const{ if(m_checkDBusGlobalMenu){ QDBusConnection conn = QDBusConnection::sessionBus(); m_dbusGlobalMenuAvailable = conn.interface()->isServiceRegistered("com.canonical.AppMenu.Registrar"); - qCDebug(llthemeengine) << "D-Bus global menu:" << (m_dbusGlobalMenuAvailable ? "yes" : "no"); + //qCDebug(llthemeengine) << "D-Bus global menu:" << (m_dbusGlobalMenuAvailable ? "yes" : "no"); } return (m_dbusGlobalMenuAvailable ? new QDBusMenuBar() : nullptr); } diff --git a/src-qt5/desktop-utils/lumina-pdf/CM_PrintPreviewWidget.h b/src-qt5/desktop-utils/lumina-pdf/CM_PrintPreviewWidget.h deleted file mode 100644 index ac457a10..00000000 --- a/src-qt5/desktop-utils/lumina-pdf/CM_PrintPreviewWidget.h +++ /dev/null @@ -1,34 +0,0 @@ -//=========================================== -// Lumina Desktop source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -// Simple subclass of QPrintPreviewWidget to provide -// notification when a context menu is requested -//=========================================== -#ifndef _CONTEXT_MENU_PRINT_PREVIEW_WIDGET_H -#define _CONTEXT_MENU_PRINT_PREVIEW_WIDGET_H - -#include <QPrintPreviewWidget> -#include <QMouseEvent> -#include <QDebug> - -class CM_PrintPreviewWidget : public QPrintPreviewWidget{ - Q_OBJECT -signals: - void customContextMenuRequested(const QPoint&); - -public: - CM_PrintPreviewWidget(QPrinter * printer = 0, QWidget *parent = 0) : QPrintPreviewWidget(printer, parent){ - this->setMouseTracking(true); - QList<QWidget*> children = this->findChildren<QWidget*>("",Qt::FindChildrenRecursively); - for(int i=0; i<children.length(); i++){ - children[i]->setContextMenuPolicy(Qt::CustomContextMenu); - connect(children[i], SIGNAL(customContextMenuRequested(const QPoint&)), this, SIGNAL(customContextMenuRequested(const QPoint&)) ); - } - } - -}; - -#endif diff --git a/src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp b/src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp new file mode 100644 index 00000000..7a25357a --- /dev/null +++ b/src-qt5/desktop-utils/lumina-pdf/PrintWidget.cpp @@ -0,0 +1,290 @@ +#include "PrintWidget.h" + +PrintWidget::PrintWidget(QPrinter* printer, QWidget *parent) : QGraphicsView(parent), scene(0), curPage(1), + viewMode(SinglePageView), zoomMode(FitInView), zoomFactor(1), initialized(false), fitting(true) { + + this->printer = printer; + this->setMouseTracking(true); + QList<QWidget*> children = this->findChildren<QWidget*>("",Qt::FindChildrenRecursively); + for(int i=0; i<children.length(); i++){ + children[i]->setContextMenuPolicy(Qt::CustomContextMenu); + connect(children[i], SIGNAL(customContextMenuRequested(const QPoint&)), this, SIGNAL(customContextMenuRequested(const QPoint&)) ); + } + this->setInteractive(false); + this->setDragMode(QGraphicsView::ScrollHandDrag); + this->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); + this->setFocusPolicy(Qt::NoFocus); + QObject::connect(this->verticalScrollBar(), SIGNAL(valueChanged(int)), + this, SLOT(updateCurrentPage())); + QObject::connect(this, SIGNAL(resized()), this, SLOT(fit())); + + scene = new QGraphicsScene(this); + scene->setBackgroundBrush(Qt::gray); + this->setScene(scene); + + /*QVBoxLayout *layout = new QVBoxLayout; + setLayout(layout); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(this);*/ +} + +PrintWidget::~PrintWidget() { + //delete scene; + //delete items in pages(?) +} + +//Public Slots + +void PrintWidget::fitView() { + setZoomMode(FitInView); +} + +void PrintWidget::fitToWidth() { + setZoomMode(FitToWidth); +} + +void PrintWidget::setZoomMode(ZoomMode mode) { + zoomMode = mode; + fitting = true; + fit(true); +} + +void PrintWidget::setAllPagesViewMode() { + setViewMode(AllPagesView); +} + +void PrintWidget::setSinglePageViewMode() { + setViewMode(SinglePageView); +} + +void PrintWidget::setFacingPagesViewMode() { + setViewMode(FacingPagesView); +} + +void PrintWidget::setViewMode(ViewMode mode) { + viewMode = mode; + layoutPages(); + if (viewMode == AllPagesView) { + this->fitInView(scene->itemsBoundingRect(), Qt::KeepAspectRatio); + fitting = false; + zoomMode = CustomZoom; + zoomFactor = this->transform().m11() * (double(printer->logicalDpiY()) / logicalDpiY()); + } else { + fitting = true; + fit(); + } +} + +void PrintWidget::zoomIn(double factor) { + fitting = false; + zoomMode = CustomZoom; + zoomFactor *= factor; + this->scale(factor, factor); +} + +void PrintWidget::zoomOut(double factor) { + fitting = false; + zoomMode = CustomZoom; + zoomFactor *= factor; + this->scale(1/factor, 1/factor); +} + +void PrintWidget::updatePreview() { + initialized = true; + generatePreview(); + this->updateGeometry(); +} + +void PrintWidget::setVisible(bool visible) { + if(visible and !initialized) + updatePreview(); + QGraphicsView::setVisible(visible); +} + +void PrintWidget::setCurrentPage(int pageNumber) { + if(pageNumber < 1 || pageNumber > pages.count()) + return; + + int lastPage = curPage; + curPage = pageNumber; + + if (lastPage != curPage && lastPage > 0 && lastPage <= pages.count()) { + if (zoomMode != FitInView) { + QScrollBar *hsc = this->horizontalScrollBar(); + QScrollBar *vsc = this->verticalScrollBar(); + QPointF pt = this->transform().map(pages.at(curPage-1)->pos()); + vsc->setValue(int(pt.y()) - 10); + hsc->setValue(int(pt.x()) - 10); + } else { + this->centerOn(pages.at(curPage-1)); + } + } +} + +//Private functions + +void PrintWidget::generatePreview() { + qDebug() << "generating preview"; + if(!previewEngine) + previewEngine = new QPreviewPaintEngine(); + if(!pdfEngine) + pdfEngine = new QPdfPrintEngine(QPrinter::HighResolution); + + printer->setEngines(previewEngine, previewEngine); + previewEngine->setProxyEngines(pdfEngine, pdfEngine); + + emit paintRequested(printer); + + printer->setEngines(pdfEngine, pdfEngine); + + qDebug() << "Populating Scene"; + populateScene(); // i.e. setPreviewPrintedPictures() e.l. + layoutPages(); + curPage = qBound(1, curPage, pages.count()); + if (fitting) + fit(); +} + +void PrintWidget::layoutPages() { + int numPages = pages.count(); + if (numPages < 1) + return; + + int numPagePlaces = numPages; + int cols = 1; // singleMode and default + if (viewMode == AllPagesView) { + if (printer->orientation() == QPrinter::Portrait) + cols = qCeil(qSqrt(numPages)); + else + cols = qFloor(qSqrt(numPages)); + cols += cols % 2; // Nicer with an even number of cols + } + else if (viewMode == FacingPagesView) { + cols = 2; + numPagePlaces += 1; + } + int rows = qCeil(double(numPagePlaces) / cols); + + double itemWidth = pages.at(0)->boundingRect().width(); + double itemHeight = pages.at(0)->boundingRect().height(); + int pageNum = 1; for (int i = 0; i < rows && pageNum <= numPages; i++) { + for (int j = 0; j < cols && pageNum <= numPages; j++) { + if (!i && !j && viewMode == FacingPagesView) { + continue; + } else { + pages.at(pageNum-1)->setPos(QPointF(j*itemWidth, i*itemHeight)); + pageNum++; + } + } + } + scene->setSceneRect(scene->itemsBoundingRect()); +} + +void PrintWidget::populateScene() +{ + for (int i = 0; i < pages.size(); i++) + scene->removeItem(pages.at(i)); + qDeleteAll(pages); + pages.clear(); + qDebug() << "Pages cleared"; + + int numPages = pictures->count(); + QSize paperSize = printer->pageLayout().fullRectPixels(printer->resolution()).size(); + QRect pageRect = printer->pageLayout().paintRectPixels(printer->resolution()); + qDebug() << "Fields set"; + + for (int i = 0; i < numPages; i++) { + PageItem* item = new PageItem(i+1, (*pictures)[i], paperSize, pageRect); + scene->addItem(item); + pages.append(item); + } +} + + +//Private Slots +void PrintWidget::updateCurrentPage() { + if (viewMode == AllPagesView) + return; + + int newPage = calcCurrentPage(); + if (newPage != curPage) { + curPage = newPage; + } +} + +int PrintWidget::calcCurrentPage() { + int maxArea = 0; + int newPage = curPage; + QRect viewRect = this->viewport()->rect(); + QList<QGraphicsItem*> items = this->items(viewRect); + for (int i=0; i<items.size(); ++i) { + PageItem* pg = static_cast<PageItem*>(items.at(i)); + QRect overlap = this->mapFromScene(pg->sceneBoundingRect()).boundingRect() & viewRect; + int area = overlap.width() * overlap.height(); + if (area > maxArea) { + maxArea = area; + newPage = pg->pageNumber(); + } else if (area == maxArea && pg->pageNumber() < newPage) { + newPage = pg->pageNumber(); + } + } + return newPage; +} + +void PrintWidget::fit(bool doFitting) { + if (curPage < 1 || curPage > pages.count()) + return; + if (!doFitting && !fitting) + return; + + if (doFitting && fitting) { + QRect viewRect = this->viewport()->rect(); + if (zoomMode == FitInView) { + QList<QGraphicsItem*> containedItems = this->items(viewRect, Qt::ContainsItemBoundingRect); + foreach(QGraphicsItem* item, containedItems) { + PageItem* pg = static_cast<PageItem*>(item); + if (pg->pageNumber() == curPage) + return; + } + } + + int newPage = calcCurrentPage(); + if (newPage != curPage) + curPage = newPage; + } + + QRectF target = pages.at(curPage-1)->sceneBoundingRect(); + if (viewMode == FacingPagesView) { + if (curPage % 2) + target.setLeft(target.left() - target.width()); + else + target.setRight(target.right() + target.width()); + } else if (viewMode == AllPagesView) { + target = scene->itemsBoundingRect(); + } + + if (zoomMode == FitToWidth) { + QTransform t; + qreal scale = this->viewport()->width() / target.width(); + t.scale(scale, scale); + this->setTransform(t); + if (doFitting && fitting) { + QRectF viewSceneRect = this->viewportTransform().mapRect(this->viewport()->rect()); + viewSceneRect.moveTop(target.top()); + this->ensureVisible(viewSceneRect); // Nah... + } + } else { + this->fitInView(target, Qt::KeepAspectRatio); + if (zoomMode == FitInView) { + int step = qRound(this->matrix().mapRect(target).height()); + this->verticalScrollBar()->setSingleStep(step); + this->verticalScrollBar()->setPageStep(step); + } + } + + zoomFactor = this->transform().m11() * (float(printer->logicalDpiY()) / this->logicalDpiY()); +} + +void PrintWidget::setPictures(QHash<int, QImage> *hash) { + pictures = hash; +} diff --git a/src-qt5/desktop-utils/lumina-pdf/PrintWidget.h b/src-qt5/desktop-utils/lumina-pdf/PrintWidget.h new file mode 100644 index 00000000..81e4e794 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-pdf/PrintWidget.h @@ -0,0 +1,171 @@ +//=========================================== +// Lumina Desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// Simple subclass of QPrintPreviewWidget to provide +// notification when a context menu is requested +//=========================================== +#ifndef _PRINT_GRAPHICS_H +#define _PRINT_GRAPHICS_H + +#include <QMouseEvent> +#include <QDebug> +#include <QGraphicsView> +#include <QGraphicsItem> +#include <QBoxLayout> +#include <QScrollBar> +#include <QStyleOptionGraphicsItem> +#include <QtMath> +#include <QPrinter> +namespace { +class PageItem : public QGraphicsItem +{ +public: + PageItem(int _pageNum, const QImage _pagePicture, QSize _paperSize, QRect _pageRect) + : pageNum(_pageNum), pagePicture(_pagePicture), + paperSize(_paperSize), pageRect(_pageRect) + { + qreal border = qMax(paperSize.height(), paperSize.width()) / 25; + brect = QRectF(QPointF(-border, -border), + QSizeF(paperSize)+QSizeF(2*border, 2*border)); + setCacheMode(DeviceCoordinateCache); + } + + QRectF boundingRect() const Q_DECL_OVERRIDE + { return brect; } + + inline int pageNumber() const + { return pageNum; } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) Q_DECL_OVERRIDE; + +private: + int pageNum; + const QImage pagePicture; + QSize paperSize; + QRect pageRect; + QRectF brect; +}; + +void PageItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(widget); + QRectF paperRect(0,0, paperSize.width(), paperSize.height()); + + // Draw shadow + painter->setClipRect(option->exposedRect); + qreal shWidth = paperRect.width()/100; + QRectF rshadow(paperRect.topRight() + QPointF(0, shWidth), + paperRect.bottomRight() + QPointF(shWidth, 0)); + QLinearGradient rgrad(rshadow.topLeft(), rshadow.topRight()); + rgrad.setColorAt(0.0, QColor(0,0,0,255)); + rgrad.setColorAt(1.0, QColor(0,0,0,0)); + painter->fillRect(rshadow, QBrush(rgrad)); + QRectF bshadow(paperRect.bottomLeft() + QPointF(shWidth, 0), + paperRect.bottomRight() + QPointF(0, shWidth)); + QLinearGradient bgrad(bshadow.topLeft(), bshadow.bottomLeft()); + bgrad.setColorAt(0.0, QColor(0,0,0,255)); + bgrad.setColorAt(1.0, QColor(0,0,0,0)); + painter->fillRect(bshadow, QBrush(bgrad)); + QRectF cshadow(paperRect.bottomRight(), + paperRect.bottomRight() + QPointF(shWidth, shWidth)); + QRadialGradient cgrad(cshadow.topLeft(), shWidth, cshadow.topLeft()); + cgrad.setColorAt(0.0, QColor(0,0,0,255)); + cgrad.setColorAt(1.0, QColor(0,0,0,0)); + painter->fillRect(cshadow, QBrush(cgrad)); + + painter->setClipRect(paperRect & option->exposedRect); + painter->fillRect(paperRect, Qt::white); + if (pagePicture.isNull()) + return; + painter->drawImage(pageRect.topLeft(), pagePicture); + + // Effect: make anything drawn in the margins look washed out. + QPainterPath path; + path.addRect(paperRect); + path.addRect(pageRect); + painter->setPen(QPen(Qt::NoPen)); + painter->setBrush(QColor(255, 255, 255, 180)); + painter->drawPath(path); +} +} + +class PrintWidget : public QGraphicsView +{ + Q_OBJECT +public: + PrintWidget(QPrinter *printer, QWidget *parent = 0); + ~PrintWidget(); + enum ViewMode { + SinglePageView, + FacingPagesView, + AllPagesView + }; + + enum ZoomMode { + CustomZoom, + FitToWidth, + FitInView + }; + + double getZoomFactor() const { return this->zoomFactor; }; + ZoomMode getZoomMode() const { return this->zoomMode; }; + int currentPage() const { return curPage; }; + void setPictures(QHash<int, QImage>*); + +signals: + void resized(); + void customContextMenuRequested(const QPoint&); + void paintRequested(QPrinter*); +public slots: + void zoomIn(double factor=1.2); + void zoomOut(double factor=1.2); + void setCurrentPage(int); + void setVisible(bool) Q_DECL_OVERRIDE; + + void fitView(); + void fitToWidth(); + void setAllPagesViewMode(); + void setSinglePageViewMode(); + void setFacingPagesViewMode(); + + void updateCurrentPage(); + int calcCurrentPage(); + void fit(bool doFitting=false); + void updatePreview(); +protected: + void resizeEvent(QResizeEvent* e) Q_DECL_OVERRIDE { + /*{ + const QSignalBlocker blocker(verticalScrollBar()); // Don't change page, QTBUG-14517 + QGraphicsView::resizeEvent(e); + }*/ + QGraphicsView::resizeEvent(e); + emit resized(); + } + + void showEvent(QShowEvent* e) Q_DECL_OVERRIDE { + QGraphicsView::showEvent(e); + emit resized(); + } +private: + void generatePreview(); + void layoutPages(); + void populateScene(); + void setViewMode(ViewMode); + void setZoomMode(ZoomMode); + QGraphicsScene *scene; + QPrinter *printer; + QPreviewPaintEngine *previewEngine; + QPdfPrintEngine *pdfEngine; + + int curPage; + ViewMode viewMode; + ZoomMode zoomMode; + double zoomFactor; + bool initialized, fitting; + QList<QGraphicsItem *> pages; + QHash<int, QImage> *pictures; +}; +#endif diff --git a/src-qt5/desktop-utils/lumina-pdf/lumina-pdf.pro b/src-qt5/desktop-utils/lumina-pdf/lumina-pdf.pro index 894d21f2..8ee67d06 100644 --- a/src-qt5/desktop-utils/lumina-pdf/lumina-pdf.pro +++ b/src-qt5/desktop-utils/lumina-pdf/lumina-pdf.pro @@ -18,13 +18,17 @@ include(../../core/libLumina/LuminaXDG.pri) message("Qt Modules Needed: $${QT}") SOURCES += main.cpp \ - mainUI.cpp + mainUI.cpp \ + propDialog.cpp \ + PrintWidget.cpp HEADERS += mainUI.h \ - CM_PrintPreviewWidget.h \ - PresentationLabel.h + PrintWidget.h \ + PresentationLabel.h \ + PropDialog.h -FORMS += mainUI.ui +FORMS += mainUI.ui \ + propDialog.ui LIBS += -lpoppler-qt5 diff --git a/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp b/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp index ce2707c9..4e65a766 100644 --- a/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp +++ b/src-qt5/desktop-utils/lumina-pdf/mainUI.cpp @@ -16,23 +16,24 @@ #include <QApplication> #include <QScreen> #include <QTimer> +#include <iostream> #include <QtConcurrent> #include <LuminaXDG.h> -#include "CM_PrintPreviewWidget.h" +#include "PrintWidget.h" MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI()){ ui->setupUi(this); this->setWindowTitle(tr("Lumina PDF Viewer")); this->setWindowIcon( LXDG::findIcon("application-pdf","unknown")); + this->highlight = false; presentationLabel = 0; - CurrentPage = 0; - ccw = 0; + CurrentPage = 1; lastdir = QDir::homePath(); Printer = new QPrinter(); //Create the interface widgets - WIDGET = new CM_PrintPreviewWidget(Printer,this); + WIDGET = new PrintWidget(Printer, this); clockTimer = new QTimer(this); clockTimer->setInterval(1000); //1-second updates to clock connect(clockTimer, SIGNAL(timeout()), this, SLOT(updateClock()) ); @@ -45,16 +46,20 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI()){ contextMenu = new QMenu(this); connect(contextMenu, SIGNAL(aboutToShow()), this, SLOT(updateContextMenu())); //Now put the widgets into the UI + ui->bookmarksFrame->setParent(WIDGET); + ui->findGroup->setParent(WIDGET); + qDebug() << "Setting central widget"; this->setCentralWidget(WIDGET); WIDGET->setContextMenuPolicy(Qt::CustomContextMenu); connect(WIDGET, SIGNAL(customContextMenuRequested(const QPoint&)),this, SLOT(showContextMenu(const QPoint&)) ); - connect(WIDGET, SIGNAL(paintRequested(QPrinter*)), this, SLOT(paintOnWidget(QPrinter*)) ); + connect(WIDGET, &PrintWidget::paintRequested, this, + [=](QPrinter *printer) { this->paintOnWidget(printer, this->highlight); }); DOC = 0; connect(this, SIGNAL(PageLoaded(int)), this, SLOT(slotPageLoaded(int)) ); PrintDLG = new QPrintDialog(this); - connect(PrintDLG, SIGNAL(accepted(QPrinter*)), this, SLOT(paintToPrinter(QPrinter*)) ); - connect(ui->menuStart_Presentation, SIGNAL(triggered(QAction*)), this, SLOT(slotStartPresentation(QAction*)) ); + //connect(PrintDLG, SIGNAL(accepted(QPrinter*)), this, SLOT(paintToPrinter(QPrinter*)) ); + //connect(ui->menuStart_Presentation, SIGNAL(triggered(QAction*)), this, SLOT(slotStartPresentation(QAction*)) ); //Create the other interface widgets progress = new QProgressBar(this); @@ -79,20 +84,66 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI()){ tmp->addAction(ui->actionAll_Pages); ui->actionSingle_Page->setChecked(true); + qDebug() << "Starting connections"; + //Connect up the buttons connect(ui->actionClose, SIGNAL(triggered()), this, SLOT(close()) ); connect(ui->actionPrint, SIGNAL(triggered()), PrintDLG, SLOT(open()) ); connect(ui->actionFit_Width, SIGNAL(triggered()), WIDGET, SLOT(fitToWidth()) ); - connect(ui->actionFit_Page, SIGNAL(triggered()), WIDGET, SLOT(fitInView()) ); + connect(ui->actionFit_Page, SIGNAL(triggered()), WIDGET, SLOT(fitView()) ); connect(ui->actionOpen_PDF, SIGNAL(triggered()), this, SLOT(OpenNewFile()) ); connect(ui->actionSingle_Page, SIGNAL(triggered()), WIDGET, SLOT(setSinglePageViewMode()) ); connect(ui->actionDual_Pages, SIGNAL(triggered()), WIDGET, SLOT(setFacingPagesViewMode()) ); connect(ui->actionAll_Pages, SIGNAL(triggered()), WIDGET, SLOT(setAllPagesViewMode()) ); - connect(ui->actionScroll_Mode, SIGNAL(toggled(bool)), this, SLOT(setScroll(bool)) ); + //connect(ui->actionScroll_Mode, &QAction::triggered, this, [&] { this->setScroll(true); }); + //connect(ui->actionSelect_Mode, &QAction::triggered, this, [&] { this->setScroll(false); }); connect(ui->actionZoom_In, &QAction::triggered, WIDGET, [&] { WIDGET->zoomIn(1.2); }); connect(ui->actionZoom_Out, &QAction::triggered, WIDGET, [&] { WIDGET->zoomOut(1.2); }); - connect(ui->actionRotate_Counterclockwise, &QAction::triggered, this, [&] { this->rotate(Printer, true); }); - connect(ui->actionRotate_Clockwise, &QAction::triggered, this, [&] { this->rotate(Printer, false); }); + connect(ui->actionRotate_Counterclockwise, &QAction::triggered, this, [&] { this->rotate(true); }); + connect(ui->actionRotate_Clockwise, &QAction::triggered, this, [&] { this->rotate(false); }); + connect(ui->actionZoom_In_2, &QAction::triggered, WIDGET, [&] { WIDGET->zoomIn(1.2); }); + connect(ui->actionZoom_Out_2, &QAction::triggered, WIDGET, [&] { WIDGET->zoomOut(1.2); }); + connect(ui->actionFirst_Page, SIGNAL(triggered()), this, SLOT(firstPage()) ); + connect(ui->actionPrevious_Page, SIGNAL(triggered()), this, SLOT(prevPage()) ); + connect(ui->actionNext_Page, SIGNAL(triggered()), this, SLOT(nextPage()) ); + connect(ui->actionLast_Page, SIGNAL(triggered()), this, SLOT(lastPage()) ); + connect(ui->actionProperties, SIGNAL(triggered()), this, SLOT(showInformation())); + connect(ui->actionFind, SIGNAL(triggered()), this, SLOT(enableFind())); + connect(ui->actionFind_Next, &QAction::triggered, this, + [&] { find(ui->textEdit->text(), true); }); + connect(ui->actionFind_Previous, &QAction::triggered, this, + [&] { find(ui->textEdit->text(), false); }); + connect(ui->findNextB, &QPushButton::clicked, this, + [&] { find(ui->textEdit->text(), true); }); + connect(ui->findPrevB, &QPushButton::clicked, this, + [&] { find(ui->textEdit->text(), false); }); + connect(ui->matchCase, &QPushButton::clicked, this, + [&] (bool value) { this->matchCase = value; }); + connect(ui->closeFind, &QPushButton::clicked, this, + [&] { ui->findGroup->setVisible(false); this->setFocus(); }); + connect(ui->actionClearHighlights, &QAction::triggered, WIDGET, + [&] { WIDGET->updatePreview(); }); + connect(ui->actionBookmarks, SIGNAL(triggered()), this, SLOT(showBookmarks())); + + qDebug() << "Finished connctions"; + + //int curP = WIDGET->currentPage()-1; //currentPage reports pages starting at 1 + //int lastP = numPages-1; + ui->actionFirst_Page->setText(tr("First Page")); + ui->actionPrevious_Page->setText(tr("Previous Page")); + ui->actionNext_Page->setText(tr("Next Page")); + ui->actionLast_Page->setText(tr("Last Page")); + /*ui->actionFirst_Page->setEnabled(curP!=0); + ui->actionPrevious_Page->setEnabled(curP>0); + ui->actionNext_Page->setEnabled(curP<lastP); + ui->actionLast_Page->setEnabled(curP!=lastP);*/ + + ui->actionStart_Here->setText(tr("Start Presentation (current slide)")); + connect(ui->actionStart_Here, SIGNAL(triggered()), this, SLOT(startPresentationHere()) ); + ui->actionStart_Begin->setText(tr("Start Presentation (at beginning)")); + connect(ui->actionStart_Begin, SIGNAL(triggered()), this, SLOT(startPresentationBeginning()) ); + ui->actionStop_Presentation->setText(tr("Stop Presentation")); + connect(ui->actionStop_Presentation, SIGNAL(triggered()), this, SLOT(closePresentation()) ); //Setup all the icons ui->actionPrint->setIcon( LXDG::findIcon("document-print","")); @@ -104,14 +155,40 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI()){ ui->actionDual_Pages->setIcon(LXDG::findIcon("format-view-grid-small","")); ui->actionAll_Pages->setIcon(LXDG::findIcon("format-view-grid-large","")); ui->actionScroll_Mode->setIcon(LXDG::findIcon("cursor-pointer","")); + ui->actionSelect_Mode->setIcon(LXDG::findIcon("cursor-text","")); ui->actionZoom_In->setIcon(LXDG::findIcon("zoom-in","")); ui->actionZoom_Out->setIcon(LXDG::findIcon("zoom-out","")); + ui->actionZoom_In_2->setIcon(LXDG::findIcon("zoom-in","")); + ui->actionZoom_Out_2->setIcon(LXDG::findIcon("zoom-out","")); ui->actionRotate_Counterclockwise->setIcon(LXDG::findIcon("object-rotate-left","")); ui->actionRotate_Clockwise->setIcon(LXDG::findIcon("object-rotate-right","")); + ui->actionFirst_Page->setIcon(LXDG::findIcon("go-first","")); + ui->actionPrevious_Page->setIcon(LXDG::findIcon("go-previous","")); + ui->actionNext_Page->setIcon(LXDG::findIcon("go-next","")); + ui->actionLast_Page->setIcon(LXDG::findIcon("go-last","")); + ui->actionStart_Here->setIcon(LXDG::findIcon("media-playback-start-circled","")); + ui->actionStart_Begin->setIcon(LXDG::findIcon("presentation-play","")); + ui->actionStop_Presentation->setIcon(LXDG::findIcon("media-playback-stop-circled","")); + ui->actionBookmarks->setIcon(LXDG::findIcon("bookmark-new","")); + ui->actionFind->setIcon(LXDG::findIcon("edit-find","")); + ui->actionFind_Next->setIcon(LXDG::findIcon("edit-find-next","")); + ui->actionFind_Previous->setIcon(LXDG::findIcon("edit-find-prev","")); + ui->actionProperties->setIcon(LXDG::findIcon("dialog-information","")); + ui->actionSettings->setIcon(LXDG::findIcon("document-properties","")); + ui->findNextB->setIcon(LXDG::findIcon("go-down-search")); + ui->findPrevB->setIcon(LXDG::findIcon("go-up-search")); + ui->matchCase->setIcon(LXDG::findIcon("format-text-italic")); + ui->closeFind->setIcon(LXDG::findIcon("dialog-close")); + + qDebug() << "Finished setting icons"; //Now set the default state of the menu's and actions - ui->menuStart_Presentation->setEnabled(false); ui->actionStop_Presentation->setEnabled(false); + ui->actionStart_Here->setEnabled(false); + ui->actionStart_Begin->setEnabled(false); + + ui->findGroup->setVisible(false); + ui->bookmarksFrame->setVisible(false); } MainUI::~MainUI(){ @@ -141,7 +218,7 @@ void MainUI::loadFile(QString path){ delete DOC; DOC=0; } - loadingHash.clear(); //clear out this hash + //loadingHash.clear(); //clear out this hash numPages = -1; DOC = TDOC; //Save this for later qDebug() << "Opening File:" << path; @@ -157,14 +234,15 @@ void MainUI::loadFile(QString path){ Printer->setPageSize( QPageSize(PAGE->pageSize(), QPageSize::Point) ); Printer->setPageMargins(QMarginsF(0,0,0,0), QPageLayout::Point); switch(PAGE->orientation()){ - case Poppler::Page::Landscape: - Printer->setOrientation(QPrinter::Landscape); break; - default: - Printer->setOrientation(QPrinter::Portrait); + case Poppler::Page::Landscape: + Printer->setOrientation(QPrinter::Landscape); break; + default: + Printer->setOrientation(QPrinter::Portrait); } delete PAGE; qDebug() << " - Document Setup : start loading pages now"; - QTimer::singleShot(10, WIDGET, SLOT(updatePreview())); //start loading the file preview + startLoadingPages(Printer); + //QTimer::singleShot(10, WIDGET, SLOT(updatePreview())); //start loading the file preview } } @@ -175,7 +253,7 @@ void MainUI::loadPage(int num, Poppler::Document *doc, MainUI *obj, QSize dpi, Q // Using Qt to scale the image (adjust page value) smooths out the image quite a bit without a lot of performance loss (but cannot scale up without pixelization) // The best approach seams to be to increase the DPI a bit, but match that with the same scaling on the page size (smoothing) - //qDebug() << " - Render Page:" << num; + qDebug() << " - Render Page:" << num; Poppler::Page *PAGE = doc->page(num); if(PAGE!=0){ //qDebug() << "DPI:" << dpi << "Size:" << page << "Page Size (pt):" << PAGE->pageSize(); @@ -256,7 +334,8 @@ void MainUI::startPresentation(bool atStart){ presentationLabel->showFullScreen(); ui->actionStop_Presentation->setEnabled(true); - ui->menuStart_Presentation->setEnabled(false); + ui->actionStart_Here->setEnabled(false); + ui->actionStart_Begin->setEnabled(false); updateClock(); clockAct->setVisible(true); clockTimer->start(); @@ -273,7 +352,7 @@ void MainUI::ShowPage(int page){ endPresentation(); return; //invalid - no document loaded or invalid page specified } - WIDGET->setCurrentPage(page+1); //page numbers start at 1 for this widget + WIDGET->setCurrentPage(page); //page numbers start at 1 for this widget //Stop here if no presentation currently running if(presentationLabel == 0 || !presentationLabel->isVisible()){ return; } CurrentPage = page; @@ -296,7 +375,8 @@ void MainUI::endPresentation(){ if(presentationLabel==0 || !presentationLabel->isVisible()){ return; } //not in presentation mode presentationLabel->hide(); //just hide this (no need to re-create the label for future presentations) ui->actionStop_Presentation->setEnabled(false); - ui->menuStart_Presentation->setEnabled(true); + ui->actionStart_Here->setEnabled(true); + ui->actionStart_Begin->setEnabled(true); clockTimer->stop(); clockAct->setVisible(false); this->releaseKeyboard(); @@ -304,15 +384,13 @@ void MainUI::endPresentation(){ void MainUI::startLoadingPages(QPrinter *printer){ if(numPages>0){ return; } //currently loaded[ing] - //qDebug() << " - Start Loading Pages"; + qDebug() << " - Start Loading Pages"; numPages = DOC->numPages(); //qDebug() << "numPages:" << numPages; progress->setRange(0,numPages); progress->setValue(0); progAct->setVisible(true); QRectF pageSize = printer->pageRect(QPrinter::DevicePixel); - printer->setPageSize(QPageSize(QSize(pageSize.width()*2, pageSize.height()*2))); - qDebug() << "Starting size" << pageSize.size(); QSize DPI(printer->resolution(),printer->resolution()); /*qDebug() << "Screen Resolutions:"; QList<QScreen*> screens = QApplication::screens(); @@ -320,50 +398,78 @@ void MainUI::startLoadingPages(QPrinter *printer){ qDebug() << screens[i]->name() << screens[i]->logicalDotsPerInchX() << screens[i]->logicalDotsPerInchY(); }*/ for(int i=0; i<numPages; i++){ - //qDebug() << " - Kickoff page load:" << i; - this->ccw = 0; + qDebug() << " - Kickoff page load:" << i; + //this->ccw = 0; QtConcurrent::run(this, &MainUI::loadPage, i, DOC, this, DPI, pageSize.size()); } } void MainUI::slotPageLoaded(int page){ + Q_UNUSED(page); //qDebug() << "Page Loaded:" << page; int finished = loadingHash.keys().length(); if(finished == numPages){ progAct->setVisible(false); - QTimer::singleShot(0, WIDGET, SLOT(updatePreview())); - qDebug() << "Updating"; + qDebug() << "Setting Pictures"; + WIDGET->setPictures(&loadingHash); + QTimer::singleShot(10, WIDGET, SLOT(updatePreview())); + //qDebug() << "Updating"; ui->actionStop_Presentation->setEnabled(false); - ui->menuStart_Presentation->setEnabled(true); + ui->actionStart_Here->setEnabled(true); + ui->actionStart_Begin->setEnabled(true); }else{ progress->setValue(finished); } } -void MainUI::slotStartPresentation(QAction *act){ +/*void MainUI::slotStartPresentation(QAction *act){ startPresentation(act == ui->actionAt_Beginning); -} +}*/ -void MainUI::paintOnWidget(QPrinter *PRINTER){ +void MainUI::paintOnWidget(QPrinter *PRINTER, bool highlight){ + static bool first = true; + static bool shrunk = false; if(DOC==0){ return; } - //this->show(); - qDebug() << "Painting"; - qDebug() << numPages << loadingHash.keys().length(); if(loadingHash.keys().length() != numPages){ startLoadingPages(PRINTER); return; } - + //Increase the resolution of the page to match the image to prevent downscaling + if(first) + PRINTER->setPageSize(QPageSize(PRINTER->pageRect().size()*2)); + qDebug() << PRINTER->pageRect().size() << loadingHash[0].size() << WIDGET->size(); QPainter painter(PRINTER); + painter.setPen(Qt::NoPen); + if(ui->findGroup->isVisible()) { + QSize size = PRINTER->pageRect().size(); + size = QSize(size.width(), size.height()-ui->findGroup->height()); + PRINTER->setPageSize(QPageSize(size)); + shrunk = true; + }else if(shrunk){ + QSize size = PRINTER->pageRect().size(); + size = QSize(size.width(), size.height()+ui->findGroup->height()); + PRINTER->setPageSize(QPageSize(size)); + shrunk = false; + } + if(highlight) { + Poppler::TextBox *currentText = results.keys()[currentHighlight]; + int pageNum = results.value(currentText), i; + + for(i = 0; i <= pageNum; i++) + if(i != 0){ PRINTER->newPage(); } + + qDebug() << pageNum << i; + this->highlight=false; + }else { for(int i=0; i<numPages; i++){ if(i != 0){ PRINTER->newPage(); } //this is the start of the next page (not needed for first) - if(loadingHash.contains(i)){ painter.drawImage(0,0, loadingHash[i].scaled(PRINTER->pageRect().size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); qDebug() << PRINTER->pageRect().size();} - else{ painter.drawImage(0,0, QImage()); } - if(ccw != 0) { - QTransform transform; - transform.rotate((ccw-1) ? 270 : 90); - painter.setTransform(transform); - //painter.rotate((ccw-1) ? 270 : 90); + if(loadingHash.contains(i)){ + painter.drawImage(0,0, loadingHash[i].scaled(PRINTER->pageRect().size(), + Qt::KeepAspectRatio, Qt::SmoothTransformation)); } + else{ painter.drawImage(0,0, QImage()); } } - WIDGET->setContextMenuPolicy(Qt::CustomContextMenu); + WIDGET->setContextMenuPolicy(Qt::CustomContextMenu); + //loadingHash.clear(); + first = false; + } } void MainUI::paintToPrinter(QPrinter *PRINTER){ @@ -403,7 +509,6 @@ void MainUI::paintToPrinter(QPrinter *PRINTER){ } } //qDebug() << "Final Page Range:" << pageCount; - //return; //Generate the sizing information for the printer QSize sz(PRINTER->pageRect().width(), PRINTER->pageRect().height()); bool landscape = PRINTER->orientation()==QPrinter::Landscape; @@ -443,32 +548,173 @@ void MainUI::setScroll(bool tog) { }else{ QApplication::setOverrideCursor(Qt::IBeamCursor); } - //WIDGET-> } -void MainUI::rotate(QPrinter *printer, bool ccw) { - QRectF pageSize = printer->pageRect(QPrinter::DevicePixel); - QSize dpi(printer->resolution(),printer->resolution()); - this->ccw = ccw+1; - for(int i=0; i < numPages; i++) - QtConcurrent::run(this, &MainUI::loadPage, i, DOC, this, dpi, pageSize.size()); +void MainUI::rotate(bool ccw) { + for(int i = 0; i < numPages; i++) { + QImage image = loadingHash[i]; + qDebug() << "Page rotating: " << i; + //Setup a rotation matrix that rotates 90 degrees clockwise or counterclockwise + QMatrix matrix = (ccw) ? QMatrix(0, -1, 1, 0, 0, 0) : QMatrix(0, 1, -1, 0, 0, 0); + image = image.transformed(matrix, Qt::SmoothTransformation); + //Updates the image in the hash + loadingHash.insert(i, image); + } + //Rotates the page as well as the image + Printer->setOrientation((Printer->orientation() == QPrinter::Landscape) ? + QPrinter::Portrait : QPrinter::Landscape); + + QTimer::singleShot(0, WIDGET, SLOT(updatePreview())); } void MainUI::updateContextMenu(){ contextMenu->clear(); - int curP = WIDGET->currentPage()-1; //currentPage reports pages starting at 1 - int lastP = numPages-1; - contextMenu->addSection( QString(tr("Page %1 of %2")).arg(QString::number(curP+1), QString::number(lastP+1) ) ); - contextMenu->addAction(tr("Next Page"), this, SLOT(nextPage()))->setEnabled(curP<lastP); - contextMenu->addAction(tr("Previous Page"), this, SLOT(prevPage()))->setEnabled( curP>0 ); + contextMenu->addSection( QString(tr("Page %1 of %2")).arg(QString::number(WIDGET->currentPage()), + QString::number(numPages) ) ); + contextMenu->addAction(ui->actionPrevious_Page); + contextMenu->addAction(ui->actionNext_Page); contextMenu->addSeparator(); - contextMenu->addAction(tr("First Page"), this, SLOT(firstPage()))->setEnabled(curP!=0); - contextMenu->addAction(tr("Last Page"), this, SLOT(lastPage()))->setEnabled(curP!=lastP); + contextMenu->addAction(ui->actionFirst_Page); + contextMenu->addAction(ui->actionLast_Page); contextMenu->addSeparator(); if(presentationLabel==0 || !presentationLabel->isVisible()){ - contextMenu->addAction(tr("Start Presentation (current slide)"), this, SLOT(startPresentationHere()) ); - contextMenu->addAction(tr("Start Presentation (at beginning)"), this, SLOT(startPresentationBeginning()) ); + contextMenu->addAction(ui->actionStart_Begin); + contextMenu->addAction(ui->actionStart_Here); }else{ - contextMenu->addAction(tr("Stop Presentation"), this, SLOT(closePresentation()) ); + contextMenu->addAction(ui->actionStop_Presentation); } } + +void MainUI::keyPressEvent(QKeyEvent *event){ + //See if this is one of the special hotkeys and act appropriately + bool inPresentation = (presentationLabel!=0); + if( event->key()==Qt::Key_Escape || event->key()==Qt::Key_Backspace){ + if(inPresentation){ endPresentation(); } + }else if(event->key()==Qt::Key_Right || event->key()==Qt::Key_Space || + event->key()==Qt::Key_PageDown){ + nextPage(); + }else if(event->key()==Qt::Key_Left || event->key()==Qt::Key_PageUp){ + prevPage(); + }else if(event->key()==Qt::Key_Home){ + firstPage(); + }else if(event->key()==Qt::Key_End){ + lastPage(); + }else if(event->key()==Qt::Key_F11){ + if(inPresentation){ endPresentation(); } + else{ startPresentationHere(); } + }else if(event->key() == Qt::Key_Up) { + //Scroll the widget up + }else if(event->key() == Qt::Key_Down) { + //Scroll the widget down + /*qDebug() << "Send Wheel Event"; + QWheelEvent wEvent( WIDGET->mapFromGlobal(QCursor::pos()), QCursor::pos(),QPoint(0,0), QPoint(0,30), 0, Qt::Vertical, Qt::LeftButton, Qt::NoModifier); + QApplication::sendEvent(WIDGET, &wEvent);*/ + }else{ + QMainWindow::keyPressEvent(event); + } +} + +void MainUI::wheelEvent(QWheelEvent *event) { + //Scroll the window according to the mouse wheel + QMainWindow::wheelEvent(event); +} + +void MainUI::showInformation() { + PROPDIALOG = new PropDialog(DOC); + PROPDIALOG->show(); +} + +void MainUI::find(QString text, bool forward) { + if(!text.isEmpty()) { + qDebug() << "Finding Text"; + bool newText = results.empty(); + bool research = false; + if(!newText) + research = !results.keys()[0]->text().contains(text); + //Clear results if the user gives a new search string + if(research) + results.clear(); + + if(research or newText) { + for(int i = 0; i < numPages; i++) { + QList<Poppler::TextBox*> textList = DOC->page(i)->textList(); + for(int j = 0; j < textList.size(); j++) { + if(textList[j]->text().contains(text, (matchCase) + ? Qt::CaseSensitive : Qt::CaseInsensitive)) { + results.insert(textList[j], i); + } + } + } + currentHighlight = (forward) ? -1 : results.size(); + } + + qDebug() << "Jumping to next result"; + if(!results.empty()) { + //Jump to the location of the next or previous textbox and highlight + if(forward) { + currentHighlight = (currentHighlight + 1) % results.size(); + }else{ + currentHighlight--; + //Ensure currentHighlight will be between 0 and results.size() - 1 + if(currentHighlight < 0) + currentHighlight = results.size() - 1; + } + + qDebug() << "Jump to location: " << currentHighlight; + + Poppler::TextBox *currentText = results.keys()[currentHighlight]; + WIDGET->setCurrentPage(results.value(currentText)); + + QTimer::singleShot(0, WIDGET, SLOT(updatePreview())); + this->highlight = true; + }else{ + //Print "No results found" + } + } +} + +void MainUI::enableFind() { + if(ui->findGroup->isVisible()) { + qDebug() << "Disabling Find"; + ui->findGroup->setVisible(false); + WIDGET->setGeometry(QRect(WIDGET->pos(), + QSize(WIDGET->width(), WIDGET->height()+ui->findGroup->height()))); + QTimer::singleShot(0, WIDGET, SLOT(updatePreview())); + this->setFocus(); + }else{ + qDebug() << "Enabling Find"; + ui->findGroup->setGeometry(QRect(QPoint(0, WIDGET->height()-ui->findGroup->height()), + QSize(WIDGET->width()-12, ui->findGroup->height()))); + ui->findGroup->setVisible(true); + WIDGET->setGeometry(QRect(WIDGET->pos(), + QSize(WIDGET->width(), WIDGET->height()-ui->findGroup->height()))); + + QTimer::singleShot(0, WIDGET, SLOT(updatePreview())); + ui->findGroup->setFocus(); + } +} + +void MainUI::showBookmarks() { + ui->bookmarksFrame->setVisible(true); +} + +void MainUI::resizeEvent(QResizeEvent *event) { + if(ui->findGroup->isVisible()) { + ui->findGroup->setGeometry(QRect(QPoint(0, WIDGET->height()-ui->findGroup->height()), + QSize(WIDGET->width()-10, ui->findGroup->height()))); + } + QMainWindow::resizeEvent(event); +} + +void MainUI::highlightText(QPrinter *PRINTER) { + Poppler::TextBox *currentText = results.keys()[currentHighlight]; + QPainter painter(PRINTER); + painter.setPen(Qt::NoPen); + int pageNum = results.value(currentText), i; + + for(i = 0; i <= pageNum; i++) + if(i != 0){ PRINTER->newPage(); } + + qDebug() << pageNum << i; + this->highlight=false; +} diff --git a/src-qt5/desktop-utils/lumina-pdf/mainUI.h b/src-qt5/desktop-utils/lumina-pdf/mainUI.h index 527bcb2a..b3ad38f1 100644 --- a/src-qt5/desktop-utils/lumina-pdf/mainUI.h +++ b/src-qt5/desktop-utils/lumina-pdf/mainUI.h @@ -21,6 +21,8 @@ #include <poppler/qt5/poppler-qt5.h> #include "PresentationLabel.h" +#include "propDialog.h" +#include "PrintWidget.h" namespace Ui{ class MainUI; @@ -34,17 +36,17 @@ public: void loadFile(QString path); - private: Poppler::Document *DOC; - QPrintPreviewWidget *WIDGET; + PrintWidget *WIDGET; Ui::MainUI *ui; + PropDialog *PROPDIALOG; QPrinter* Printer; QPrintDialog *PrintDLG; - - int ccw; - QString lastdir; + bool matchCase, highlight; + QMap<Poppler::TextBox*, int> results; + int currentHighlight; //Other Interface elements QProgressBar *progress; @@ -60,6 +62,7 @@ private: int numPages; void loadPage(int num, Poppler::Document *doc, MainUI *obj, QSize dpi, QSizeF page); + void highlightText(QPrinter *PRINTER); //Functions/variables for the presentation mode PresentationLabel *presentationLabel; @@ -72,7 +75,7 @@ private: private slots: void startLoadingPages(QPrinter *printer); void slotPageLoaded(int); - void slotStartPresentation(QAction *act); + //void slotStartPresentation(QAction *act); //Simplification routines void nextPage(){ ShowPage( WIDGET->currentPage() ); } //currentPage() starts at 1 rather than 0 @@ -82,9 +85,12 @@ private slots: void startPresentationHere(){ startPresentation(false); } void startPresentationBeginning(){ startPresentation(true); } void closePresentation(){ endPresentation(); } + void showInformation(); + void find(QString text, bool forward); + void enableFind(); + void showBookmarks(); - - void paintOnWidget(QPrinter *PRINTER); + void paintOnWidget(QPrinter*, bool); void paintToPrinter(QPrinter *PRINTER); //Button Slots @@ -96,51 +102,14 @@ private slots: void updateContextMenu(); void setScroll(bool); - void rotate(QPrinter*, bool); + void rotate(bool); signals: void PageLoaded(int); protected: - void keyPressEvent(QKeyEvent *event){ - //See if this is one of the special hotkeys and act appropriately - //qDebug() << "Got Key Press:"; - bool inPresentation = (presentationLabel!=0); - if(!inPresentation){ - //Alternate functionality when **not** in presentation mode - /*if(event->key()==Qt::Key_Down){ - qDebug() << "Send Wheel Event"; - QWheelEvent event( WIDGET->mapFromGlobal(QCursor::pos()), QCursor::pos(),QPoint(0,0), QPoint(0,30), 0, Qt::Vertical, Qt::LeftButton, Qt::NoModifier); - QApplication::sendEvent(WIDGET, &event); - //WIDGET->scrollDown(); - return; - }else if(event->key()==Qt::Key_Up){ - return; - }*/ - } - - if( event->key()==Qt::Key_Escape || event->key()==Qt::Key_Backspace){ - //qDebug() << " - Escape/Backspace"; - if(inPresentation){ endPresentation(); } - }else if(event->key()==Qt::Key_Right || event->key()==Qt::Key_Down || event->key()==Qt::Key_Space || event->key()==Qt::Key_PageDown){ - //qDebug() << " - Right/Down/Spacebar" << inPresentation; - nextPage(); - }else if(event->key()==Qt::Key_Left || event->key()==Qt::Key_Up || event->key()==Qt::Key_PageUp){ - //qDebug() << " - Left/Up"; - prevPage(); - }else if(event->key()==Qt::Key_Home){ - //qDebug() << " - Home"; - firstPage(); - }else if(event->key()==Qt::Key_End){ - //qDebug() << " - End"; - lastPage(); - }else if(event->key()==Qt::Key_F11){ - //qDebug() << " - F11"; - if(inPresentation){ endPresentation(); } - else{ startPresentationHere(); } - }else{ - QMainWindow::keyPressEvent(event); - } - } + void keyPressEvent(QKeyEvent*); + void wheelEvent(QWheelEvent*); + void resizeEvent(QResizeEvent*); }; #endif diff --git a/src-qt5/desktop-utils/lumina-pdf/mainUI.ui b/src-qt5/desktop-utils/lumina-pdf/mainUI.ui index 20a79cf2..8f6fff27 100644 --- a/src-qt5/desktop-utils/lumina-pdf/mainUI.ui +++ b/src-qt5/desktop-utils/lumina-pdf/mainUI.ui @@ -6,20 +6,119 @@ <rect> <x>0</x> <y>0</y> - <width>660</width> - <height>588</height> + <width>697</width> + <height>694</height> </rect> </property> <property name="windowTitle"> <string>MainWindow</string> </property> - <widget class="QWidget" name="centralwidget"/> + <widget class="QWidget" name="centralwidget"> + <widget class="QFrame" name="findGroup"> + <property name="geometry"> + <rect> + <x>0</x> + <y>560</y> + <width>691</width> + <height>61</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="closeFind"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="textEdit"/> + </item> + <item> + <widget class="QPushButton" name="findPrevB"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="findNextB"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="matchCase"> + <property name="text"> + <string/> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Find...</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QFrame" name="bookmarksFrame"> + <property name="geometry"> + <rect> + <x>0</x> + <y>9</y> + <width>81</width> + <height>601</height> + </rect> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <widget class="QLabel" name="label_2"> + <property name="geometry"> + <rect> + <x>10</x> + <y>0</y> + <width>71</width> + <height>16</height> + </rect> + </property> + <property name="text"> + <string>Bookmarks</string> + </property> + </widget> + </widget> + </widget> <widget class="QMenuBar" name="menubar"> <property name="geometry"> <rect> <x>0</x> <y>0</y> - <width>660</width> + <width>697</width> <height>21</height> </rect> </property> @@ -33,19 +132,14 @@ <addaction name="separator"/> <addaction name="actionClose"/> <addaction name="separator"/> - <addaction name="actionPDF_Info"/> + <addaction name="actionProperties"/> </widget> <widget class="QMenu" name="menuPresentation"> <property name="title"> <string>&Presentation</string> </property> - <widget class="QMenu" name="menuStart_Presentation"> - <property name="title"> - <string>Start Presentation</string> - </property> - <addaction name="actionAt_Beginning"/> - </widget> - <addaction name="menuStart_Presentation"/> + <addaction name="actionStart_Begin"/> + <addaction name="actionStart_Here"/> <addaction name="actionStop_Presentation"/> </widget> <widget class="QMenu" name="menuSettings"> @@ -55,10 +149,13 @@ <addaction name="actionFind"/> <addaction name="actionFind_Next"/> <addaction name="actionFind_Previous"/> + <addaction name="actionClearHighlights"/> <addaction name="separator"/> <addaction name="actionSettings"/> <addaction name="separator"/> <addaction name="actionScroll_Mode"/> + <addaction name="actionSelect_Mode"/> + <addaction name="separator"/> </widget> <widget class="QMenu" name="menuView"> <property name="title"> @@ -105,6 +202,9 @@ <addaction name="actionSingle_Page"/> <addaction name="actionDual_Pages"/> <addaction name="actionAll_Pages"/> + <addaction name="separator"/> + <addaction name="actionZoom_In_2"/> + <addaction name="actionZoom_Out_2"/> </widget> <action name="actionOpen_PDF"> <property name="text"> @@ -170,9 +270,9 @@ <string>All Pages</string> </property> </action> - <action name="actionAt_Beginning"> + <action name="actionStart_Begin"> <property name="text"> - <string>At Beginning</string> + <string>Start Presentation (at beginning)</string> </property> </action> <action name="actionStop_Presentation"> @@ -230,9 +330,9 @@ <string>Last Page</string> </property> </action> - <action name="actionPDF_Info"> + <action name="actionProperties"> <property name="text"> - <string>PDF Info</string> + <string>Properties</string> </property> </action> <action name="actionBookmarks"> @@ -250,29 +350,46 @@ <string>Rotate Clockwise</string> </property> </action> - <action name="actionSelect_Mode"> + <action name="actionScroll_Mode"> <property name="checkable"> - <bool>true</bool> + <bool>false</bool> </property> <property name="checked"> + <bool>false</bool> + </property> + <property name="enabled"> <bool>true</bool> </property> <property name="text"> - <string>Select Mode</string> + <string>Scroll Mode</string> </property> </action> - <action name="actionScroll_Mode"> - <property name="checkable"> - <bool>true</bool> + <action name="actionZoom_Out_2"> + <property name="text"> + <string/> </property> - <property name="checked"> + </action> + <action name="actionZoom_In_2"> + <property name="text"> + <string/> + </property> + </action> + <action name="actionStart_Here"> + <property name="text"> + <string>Start Presentation (current slide)</string> + </property> + </action> + <action name="actionSelect_Mode"> + <property name="checkable"> <bool>false</bool> </property> - <property name="enabled"> - <bool>true</bool> + <property name="text"> + <string>Select Mode</string> </property> + </action> + <action name="actionClearHighlights"> <property name="text"> - <string>Scroll Mode</string> + <string>Clear Highlights</string> </property> </action> </widget> diff --git a/src-qt5/desktop-utils/lumina-pdf/propDialog.cpp b/src-qt5/desktop-utils/lumina-pdf/propDialog.cpp new file mode 100644 index 00000000..0c26af74 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-pdf/propDialog.cpp @@ -0,0 +1,56 @@ +//=========================================== +// Lumina Desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== + +#include "propDialog.h" +#include "ui_propDialog.h" + +#include <LuminaXDG.h> + +PropDialog::PropDialog(Poppler::Document *DOC) : QDialog(), ui(new Ui::PropDialog()){ + this->setWindowTitle(tr("PDF Information")); + this->setWindowIcon( LXDG::findIcon("dialog-information","unknown")); + int verMa, verMi; + QString version; + QSize size = DOC->page(0)->pageSize(); + + //Grab the version + DOC->getPdfVersion(&verMa, &verMi); + version = QString::number(verMa)+"."+QString::number(verMi); + + ui->setupUi(this); + + connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(close())); + + //Setup translations + ui->titleL->setText(tr("Title:")); + ui->subjectL->setText(tr("Subject:")); + ui->authorL->setText(tr("Author:")); + ui->creatorL->setText(tr("Creator:")); + ui->producerL->setText(tr("Producer:")); + ui->keywordsL->setText(tr("Keywords:")); + ui->createdL->setText(tr("Created:")); + ui->modifiedL->setText(tr("Modified:")); + ui->versionL->setText(tr("PDF Version:")); + ui->sizeL->setText(tr("Page Size:")); + ui->numberL->setText(tr("Number of Pages:")); + ui->saveButton->setText(tr("Save")); + ui->closeButton->setText(tr("Close")); + + //Fill the text boxes with information from the document + ui->titleE->setText(DOC->title()); + ui->subjectE->setText(DOC->subject()); + ui->authorE->setText(DOC->author()); + ui->creatorE->setText(DOC->creator()); + ui->producerE->setText(DOC->producer()); + ui->keywordE->setText(DOC->keywords()); + ui->createdEntry->setText(DOC->creationDate().toString(Qt::TextDate)); + ui->modifiedEntry->setText(DOC->modificationDate().toString(Qt::TextDate)); + ui->versionL->setText(ui->versionL->text()+version); + ui->sizeL->setText(ui->sizeL->text()+QString::number(size.height())+ + ", "+QString::number(size.width())); + ui->numberL->setText(ui->numberL->text()+QString::number(DOC->numPages())); +} diff --git a/src-qt5/desktop-utils/lumina-pdf/propDialog.h b/src-qt5/desktop-utils/lumina-pdf/propDialog.h new file mode 100644 index 00000000..be67ebd3 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-pdf/propDialog.h @@ -0,0 +1,25 @@ +//=========================================== +// Lumina Desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#ifndef _LUMINA_PDF_VIEWER_PROP_DIALOG_H +#define _LUMINA_PDF_VIEWER_PROP_DIALOG_H + +#include <QDialog> +#include <poppler/qt5/poppler-qt5.h> + +namespace Ui{ + class PropDialog; +}; + +class PropDialog : public QDialog { + Q_OBJECT + public: + PropDialog(Poppler::Document*); + + private: + Ui::PropDialog *ui; +}; +#endif diff --git a/src-qt5/desktop-utils/lumina-pdf/propDialog.ui b/src-qt5/desktop-utils/lumina-pdf/propDialog.ui new file mode 100644 index 00000000..6806f81a --- /dev/null +++ b/src-qt5/desktop-utils/lumina-pdf/propDialog.ui @@ -0,0 +1,477 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PropDialog</class> + <widget class="QDialog" name="PropDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>PDF Information</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="titleL"> + <property name="text"> + <string>Title:</string> + </property> + </widget> + </item> + <item row="0" column="1" colspan="2"> + <widget class="QTextEdit" name="titleE"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>256</width> + <height>16</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>512</width> + <height>16</height> + </size> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> + </property> + <property name="readOnly"> + <bool>false</bool> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="subjectL"> + <property name="text"> + <string>Subject:</string> + </property> + </widget> + </item> + <item row="1" column="1" colspan="2"> + <widget class="QTextEdit" name="subjectE"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>256</width> + <height>16</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>512</width> + <height>16</height> + </size> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> + </property> + <property name="readOnly"> + <bool>false</bool> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="authorL"> + <property name="text"> + <string>Author:</string> + </property> + </widget> + </item> + <item row="2" column="1" colspan="2"> + <widget class="QTextEdit" name="authorE"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>256</width> + <height>16</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>512</width> + <height>16</height> + </size> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> + </property> + <property name="readOnly"> + <bool>false</bool> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="creatorL"> + <property name="text"> + <string>Creator:</string> + </property> + </widget> + </item> + <item row="3" column="1" colspan="2"> + <widget class="QTextEdit" name="creatorE"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>256</width> + <height>16</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>512</width> + <height>16</height> + </size> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> + </property> + <property name="readOnly"> + <bool>false</bool> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="producerL"> + <property name="text"> + <string>Producer:</string> + </property> + </widget> + </item> + <item row="4" column="1" colspan="2"> + <widget class="QTextEdit" name="producerE"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>256</width> + <height>16</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>512</width> + <height>16</height> + </size> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> + </property> + <property name="readOnly"> + <bool>false</bool> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="keywordsL"> + <property name="text"> + <string>Keywords:</string> + </property> + </widget> + </item> + <item row="5" column="1" colspan="2"> + <widget class="QTextEdit" name="keywordE"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>256</width> + <height>16</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>512</width> + <height>16</height> + </size> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> + </property> + <property name="readOnly"> + <bool>false</bool> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="createdL"> + <property name="text"> + <string>Created: </string> + </property> + </widget> + </item> + <item row="6" column="1" colspan="2"> + <widget class="QTextEdit" name="createdEntry"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>256</width> + <height>16</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>512</width> + <height>16</height> + </size> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="7" column="0"> + <widget class="QLabel" name="modifiedL"> + <property name="text"> + <string>Modified: </string> + </property> + </widget> + </item> + <item row="7" column="1" colspan="2"> + <widget class="QTextEdit" name="modifiedEntry"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>256</width> + <height>16</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>512</width> + <height>16</height> + </size> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContents</enum> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="8" column="0" colspan="3"> + <widget class="QLabel" name="versionL"> + <property name="text"> + <string>PDF Version:</string> + </property> + </widget> + </item> + <item row="9" column="0" colspan="3"> + <widget class="QLabel" name="sizeL"> + <property name="text"> + <string>Page Size:</string> + </property> + </widget> + </item> + <item row="10" column="0" colspan="3"> + <widget class="QLabel" name="numberL"> + <property name="text"> + <string>Number of Pages:</string> + </property> + </widget> + </item> + <item row="11" column="1"> + <widget class="QPushButton" name="saveButton"> + <property name="text"> + <string>Save</string> + </property> + </widget> + </item> + <item row="11" column="2"> + <widget class="QPushButton" name="closeButton"> + <property name="text"> + <string>Close</string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + <property name="default"> + <bool>true</bool> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src-qt5/src-qml/test/Grav.qml b/src-qt5/src-qml/test/Grav.qml new file mode 100644 index 00000000..d7404a56 --- /dev/null +++ b/src-qt5/src-qml/test/Grav.qml @@ -0,0 +1,164 @@ +import QtQuick 2.7 +import QtQuick.Window 2.2 +import QtGraphicalEffects 1.0 + +Rectangle { + id : canvas + anchors.fill: parent + width: Screen.width + height: Screen.height + color: "black" + + //TODO Add orbital trails option + //TODO Fix jitteryness and start position + //TODO Make orbits more extreme + + //Between 5 and 15 planets, read from settings + property int planets: Math.round(( Math.random() * 10 ) + 5 ) + property int cx: Math.round(width/2) + property int cy: Math.round(height/2) + + //Create planets + Repeater { + id: planetRepeater + model: planets + + Rectangle { + id : index + parent: canvas + + //Creates random distance for elipse + property double c: Math.random() * 250 + property double b: Math.random() * 150 + c + property double a: Math.sqrt(b*b+c*c) + //Random angle of rotation + property double th: Math.random() * Math.PI + property var pathX: createPathX() + property var pathY: createPathY() + property var testArray: createTest() + + //Calculates starting position + x: Math.round(cx + a * Math.cos(th)) + y: Math.round(cy + b * Math.sin(th)) + + //Planet size between 14 and 32 pixels + width: Math.round(1.75 * (((Math.random() * 10) + 8 ))) + height: width + + //Make each rectangle look circular + radius: width / 2 + + //Give each planet a random color, semi-transparent + color: Qt.rgba(Math.random(), Math.random(), Math.random(), 0.5) + + PathAnimation on x{ + loops: Animation.Infinite + duration: 200 + path: Path { + startX: x + startY: y + PathCurve { x: pathX; y: pathY } + } + } + + NumberAnimation { + + } + + function createTest() { + var test = [] + for(var i = 1; i <= 200; i++) { + test.push(PathCurve { x: pathX[i]; y: pathY[i] }) + } + return test + } + + function createPathX() { + var pathX = [] + for(var i = 1; i <= 200; i++) { + pathX.push(cx+a*Math.cos(2*Math.PI*(i/200.0))*Math.cos(th) - b*Math.sin(2*Math.PI*(i/200.0))*Math.sin(th)) + } + return pathX + } + + function createPathY() { + var pathY = [] + for(var i = 1; i <= 200; i++) { + pathY.push(cy+a*Math.cos(2*Math.PI*(i/200.0))*Math.sin(th) + b*Math.sin(2*Math.PI*(i/200.0))*Math.cos(th)) + } + return pathY + } + + /*Timer { + //Each planet updates between 1ms and 51ms (smaller times=faster) + interval: Math.round(Math.random() * 50 ) + 1 + repeat: true + running: true + property int time: 0 + + onTriggered: { + //Parametric equation that calculates the position of the general ellipse. Completes a loop ever 314 cycles. Credit to + x = cx+a*Math.cos(2*Math.PI*(time/314.0))*Math.cos(th) - b*Math.sin(2*Math.PI*(time/314.0))*Math.sin(th) + y = cy+a*Math.cos(2*Math.PI*(time/314.0))*Math.sin(th) + b*Math.sin(2*Math.PI*(time/314.0))*Math.cos(th) + time++; + + //Move a planet 80 pixels away from the sun if the planet is too close + if(x > cx && Math.abs(cx-x) < 80) { + x+=80 + }else if(x < cx && Math.abs(cx-x) < 80) { + x-=80 + } + + if(y > cy && Math.abs(cy-y) < 80) { + y+=80 + }else if(y < cy && Math.abs(cy-y) < 80) { + y-=80 + } + } + }*/ + } + } + + //Create the star + Rectangle{ + id: star + parent: canvas + + //Centers in star in the center of the canvas, with an offset to center the animation + x: cx - 30 + y: cy - 30 + + width: 60 + height: width + + //Create the wobble animation + SequentialAnimation on height { + loops: Animation.Infinite + PropertyAnimation { duration: 2000; to: 90 } + PropertyAnimation { duration: 2000; to: 60 } + } + + SequentialAnimation on width { + loops: Animation.Infinite + PropertyAnimation { duration: 2000; to: 90 } + PropertyAnimation { duration: 2000; to: 60 } + } + + color: "black" + radius: width / 2 + + //Creates a radial gradient to make the star look cool + RadialGradient { + anchors.fill: parent + gradient: Gradient { + GradientStop { position:0 ;color: Qt.rgba(0,0,0,0)} + GradientStop { position:0.18 ;color: Qt.rgba(0,0,0,0)} + GradientStop { position:0.2 ;color: Qt.rgba(0.32,0.47,0.30,0.13)} + GradientStop { position:0.3 ;color: Qt.rgba(0.62,0.92,0.58,0.25)} + GradientStop { position:0.4 ;color: Qt.rgba(1.00,0.93,0.59,0.51)} + GradientStop { position:0.5 ;color: Qt.rgba(0,0,0,0)} + } + } + + } +} diff --git a/src-qt5/src-qml/test/Test.qml b/src-qt5/src-qml/test/Test.qml new file mode 100644 index 00000000..a2407b6c --- /dev/null +++ b/src-qt5/src-qml/test/Test.qml @@ -0,0 +1,7 @@ +import QtQuick 2.7 + +Rectangle { + id : canvas + anchors.fill: parent + color: "black" +} |