├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake ├── BuildSailfishSDK.txt ├── FindBooster.cmake ├── FindPoppler.cmake ├── FindQtSparql.cmake ├── FindSilica.cmake ├── QtTranslationWithID.cmake ├── sailfish_armv7hl.cmake └── sailfish_i486.cmake ├── config.h.in ├── dbusadaptor.cpp ├── dbusadaptor.h ├── images └── CMakeLists.txt ├── main.cpp ├── models ├── documentlistmodel.cpp ├── documentlistmodel.h ├── documentprovider.cpp ├── documentprovider.h ├── filtermodel.cpp ├── filtermodel.h ├── trackerdocumentprovider.cpp └── trackerdocumentprovider.h ├── pdf ├── CMakeLists.txt ├── pdfannotation.cpp ├── pdfannotation.h ├── pdfcanvas.cpp ├── pdfcanvas.h ├── pdfdocument.cpp ├── pdfdocument.h ├── pdfjob.cpp ├── pdfjob.h ├── pdflinkarea.cpp ├── pdflinkarea.h ├── pdfrenderthread.cpp ├── pdfrenderthread.h ├── pdfsearchmodel.cpp ├── pdfsearchmodel.h ├── pdfselection.cpp ├── pdfselection.h ├── pdftocmodel.cpp ├── pdftocmodel.h ├── qmldir ├── sailfishofficepdfplugin.cpp └── sailfishofficepdfplugin.h ├── plugin ├── CMakeLists.txt ├── CalligraDocumentPage.qml ├── ContextMenuHook.qml ├── ControllerFlickable.qml ├── DeleteButton.qml ├── DetailsPage.qml ├── DocumentFlickable.qml ├── DocumentHeader.qml ├── DocumentPage.qml ├── FullscreenError.qml ├── IndexButton.qml ├── OverlayToolbar.qml ├── PDFAnnotationEdit.qml ├── PDFAnnotationNew.qml ├── PDFContextMenuHighlight.qml ├── PDFContextMenuLinks.qml ├── PDFContextMenuText.qml ├── PDFDetailsPage.qml ├── PDFDocumentPage.qml ├── PDFDocumentToCPage.qml ├── PDFSelectionDrag.qml ├── PDFSelectionHandle.qml ├── PDFSelectionView.qml ├── PDFStorage.js ├── PDFView.qml ├── PlainTextDocumentPage.qml ├── PresentationDetailsPage.qml ├── PresentationPage.qml ├── PresentationThumbnailPage.qml ├── SearchBarItem.qml ├── ShareButton.qml ├── SpreadsheetDetailsPage.qml ├── SpreadsheetListPage.qml ├── SpreadsheetPage.qml ├── TextDetailsPage.qml ├── TextDocumentPage.qml ├── TextDocumentToCPage.qml ├── ToolBar.qml ├── plaintextmodel.cpp ├── plaintextmodel.h ├── qmldir ├── sailfishofficeplugin.cpp └── sailfishofficeplugin.h ├── qml ├── CoverFileItem.qml ├── CoverPage.qml ├── FileListPage.qml ├── Main.qml ├── SortTypeSelectionPage.qml └── translations │ └── StoreDescription.qml ├── rpm └── sailfish-office.spec ├── sailfish-office.desktop ├── sailfish-office.privileges └── tests ├── 00-introduction.txt ├── 00-start-application.txt ├── 01-odf-loading.txt ├── 02-pdf-loading.txt ├── 03-msoffice-loading.txt ├── 04-msooxml-loading.txt └── 05-contents-listing.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .* 3 | *.kdev* 4 | *build* 5 | *.o 6 | *.so 7 | *.cmake 8 | Makefile 9 | moc_* 10 | mocs_* 11 | *.moc 12 | CMakeFiles 13 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(sailfish-office) 2 | 3 | cmake_minimum_required(VERSION 3.10) 4 | 5 | include(GNUInstallDirs) 6 | 7 | set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) 8 | set(CMAKE_AUTOMOC TRUE) 9 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 10 | 11 | find_package(Qt5Core REQUIRED) 12 | find_package(Qt5Quick REQUIRED) 13 | find_package(Qt5Gui REQUIRED) 14 | find_package(Qt5DBus REQUIRED) 15 | find_package(Qt5LinguistTools REQUIRED) 16 | find_package(QtSparql REQUIRED) 17 | find_package(Booster REQUIRED) 18 | 19 | include(cmake/QtTranslationWithID.cmake) 20 | 21 | include_directories( 22 | ${CMAKE_SOURCE_DIR} 23 | ${CMAKE_BINARY_DIR} 24 | ${QT_INCLUDES} 25 | ${BOOSTER_INCLUDE_DIR} 26 | ${QTSPARQL_INCLUDE_DIR} 27 | ) 28 | 29 | set(CALLIGRA_QML_PLUGIN_DIR ${CMAKE_INSTALL_LIBDIR}/calligra CACHE PATH "The location of the Calligra QtQuick Components") 30 | configure_file(config.h.in config.h) 31 | 32 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -fPIC -pie -rdynamic -Wall") 33 | 34 | add_subdirectory(plugin) 35 | add_subdirectory(pdf) 36 | 37 | set(sailfishoffice_SRCS 38 | main.cpp 39 | dbusadaptor.cpp 40 | models/filtermodel.cpp 41 | models/documentlistmodel.cpp 42 | models/documentprovider.cpp 43 | models/trackerdocumentprovider.cpp 44 | ) 45 | 46 | set(sailfishoffice_QML_SRCS 47 | qml/CoverPage.qml 48 | qml/FileListPage.qml 49 | qml/Main.qml 50 | qml/CoverFileItem.qml 51 | qml/SortTypeSelectionPage.qml 52 | ) 53 | 54 | file(GLOB plugin_QML_SRCS plugin/*.qml) 55 | 56 | set(sailfishoffice_TS_SRCS 57 | ${sailfishoffice_SRCS} 58 | ${sailfishoffice_QML_SRCS} 59 | ${plugin_QML_SRCS} 60 | qml/translations/StoreDescription.qml 61 | ) 62 | 63 | create_translation(engen_qm_file ${CMAKE_BINARY_DIR}/sailfish-office.ts ${sailfishoffice_TS_SRCS}) 64 | 65 | add_executable(sailfish-office ${sailfishoffice_SRCS} ${engen_qm_file}) 66 | qt5_use_modules(sailfish-office Widgets Quick DBus) 67 | target_link_libraries(sailfish-office stdc++ ${QT_LIBRARIES} ${BOOSTER_LIBRARY} ${QTSPARQL_LIBRARY}) 68 | 69 | install(TARGETS sailfish-office DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) 70 | install(FILES 71 | sailfish-office.desktop 72 | DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) 73 | install(FILES ${sailfishoffice_QML_SRCS} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/sailfish-office 74 | ) 75 | install(FILES ${engen_qm_file} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/translations) 76 | install(FILES ${CMAKE_BINARY_DIR}/sailfish-office.ts DESTINATION ${CMAKE_INSTALL_PREFIX}/share/translations/source) 77 | install(FILES sailfish-office.privileges DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mapplauncherd/privileges.d) 78 | 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | sailfish-office 2 | =============== 3 | Sailfish Office is a document viewer for Sailfish OS. Sailfish Office uses 4 | Sailfish Silica components for the user interface, as well as poppler for PDF 5 | rendering. Office is based on the open source Calligra project. 6 | 7 | License 8 | ------- 9 | Office is licensed under the GPLv2 (https://www.gnu.org/licenses/gpl-2.0.html). 10 | -------------------------------------------------------------------------------- /cmake/BuildSailfishSDK.txt: -------------------------------------------------------------------------------- 1 | mkdir build 2 | cd build 3 | cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/sailfish_i486.cmake .. 4 | make 5 | make deploy 6 | make run -------------------------------------------------------------------------------- /cmake/FindBooster.cmake: -------------------------------------------------------------------------------- 1 | find_path(BOOSTER_INCLUDE_DIR 2 | MDeclarativeCache 3 | PATH_SUFFIXES 4 | applauncherd 5 | mdeclarativecache5 6 | ) 7 | 8 | find_library(BOOSTER_LIBRARY 9 | NAMES mdeclarativecache5 10 | ) 11 | 12 | include(FindPackageHandleStandardArgs) 13 | find_package_handle_standard_args(Booster DEFAULT_MSG BOOSTER_INCLUDE_DIR BOOSTER_LIBRARY) 14 | 15 | mark_as_advanced(BOOSTER_INCLUDE_DIR BOOSTER_LIBRARY) 16 | 17 | -------------------------------------------------------------------------------- /cmake/FindPoppler.cmake: -------------------------------------------------------------------------------- 1 | find_path(POPPLER_INCLUDE_DIR 2 | poppler-version.h 3 | PATH_SUFFIXES 4 | poppler/cpp 5 | ) 6 | 7 | find_path(POPPLER_QT5_INCLUDE_DIR 8 | poppler-qt5.h 9 | PATH_SUFFIXES 10 | poppler/qt5 11 | ) 12 | 13 | find_library(POPPLER_LIBRARY 14 | NAMES libpoppler.so 15 | ) 16 | 17 | find_library(POPPLER_QT5_LIBRARY 18 | NAMES libpoppler-qt5.so 19 | ) 20 | 21 | include(FindPackageHandleStandardArgs) 22 | find_package_handle_standard_args(Poppler DEFAULT_MSG POPPLER_INCLUDE_DIR POPPLER_QT5_INCLUDE_DIR POPPLER_LIBRARY POPPLER_QT5_LIBRARY) 23 | 24 | mark_as_advanced(POPPLER_INCLUDE_DIR POPPLER_QT5_INCLUDE_DIR POPPLER_LIBRARY POPPLER_QT5_LIBRARY) 25 | 26 | -------------------------------------------------------------------------------- /cmake/FindQtSparql.cmake: -------------------------------------------------------------------------------- 1 | find_path(QTSPARQL_INCLUDE_DIR 2 | QtSparql 3 | PATH_SUFFIXES 4 | Qt5Sparql 5 | ) 6 | 7 | find_library(QTSPARQL_LIBRARY 8 | Qt5Sparql 9 | ) 10 | 11 | include(FindPackageHandleStandardArgs) 12 | find_package_handle_standard_args(QtSparql DEFAULT_MSG QTSPARQL_INCLUDE_DIR QTSPARQL_LIBRARY) 13 | 14 | mark_as_advanced(QTSPARQL_INCLUDE_DIR QTSPARQL_LIBRARY) 15 | -------------------------------------------------------------------------------- /cmake/FindSilica.cmake: -------------------------------------------------------------------------------- 1 | find_path(SILICA_IMPORTS_DIR 2 | ApplicationWindow.qml 3 | PATHS 4 | /usr/lib/qt4/imports/Sailfish/Silica 5 | ) 6 | 7 | include(FindPackageHandleStandardArgs) 8 | find_package_handle_standard_args(Silica DEFAULT_MSG SILICA_IMPORTS_DIR) 9 | 10 | mark_as_advanced(SILICA_IMPORTS_DIR) 11 | 12 | -------------------------------------------------------------------------------- /cmake/QtTranslationWithID.cmake: -------------------------------------------------------------------------------- 1 | macro(ADD_TRANSLATION _qm_files) 2 | foreach (_current_FILE ${ARGN}) 3 | get_filename_component(_abs_FILE ${_current_FILE} ABSOLUTE) 4 | get_filename_component(qm ${_abs_FILE} NAME_WE) 5 | get_source_file_property(output_location ${_abs_FILE} OUTPUT_LOCATION) 6 | if(output_location) 7 | file(MAKE_DIRECTORY "${output_location}") 8 | set(qm "${output_location}/${qm}_eng_en.qm") 9 | else() 10 | set(qm "${CMAKE_CURRENT_BINARY_DIR}/${qm}_eng_en.qm") 11 | endif() 12 | 13 | add_custom_command(OUTPUT ${qm} 14 | COMMAND ${Qt5_LRELEASE_EXECUTABLE} 15 | ARGS -idbased ${_abs_FILE} -qm ${qm} 16 | DEPENDS ${_abs_FILE} VERBATIM 17 | ) 18 | list(APPEND ${_qm_files} ${qm}) 19 | endforeach () 20 | set(${_qm_files} ${${_qm_files}} PARENT_SCOPE) 21 | endmacro() 22 | 23 | function(CREATE_TRANSLATION _qm_files) 24 | set(options) 25 | set(oneValueArgs) 26 | set(multiValueArgs OPTIONS) 27 | 28 | cmake_parse_arguments(_LUPDATE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 29 | set(_lupdate_files ${_LUPDATE_UNPARSED_ARGUMENTS}) 30 | set(_lupdate_options ${_LUPDATE_OPTIONS}) 31 | 32 | set(_my_sources) 33 | set(_my_tsfiles) 34 | foreach(_file ${_lupdate_files}) 35 | get_filename_component(_ext ${_file} EXT) 36 | get_filename_component(_abs_FILE ${_file} ABSOLUTE) 37 | if(_ext MATCHES "ts") 38 | list(APPEND _my_tsfiles ${_abs_FILE}) 39 | else() 40 | list(APPEND _my_sources ${_abs_FILE}) 41 | endif() 42 | endforeach() 43 | foreach(_ts_file ${_my_tsfiles}) 44 | if(_my_sources) 45 | # make a list file to call lupdate on, so we don't make our commands too 46 | # long for some systems 47 | get_filename_component(_ts_name ${_ts_file} NAME_WE) 48 | set(_ts_lst_file "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_ts_name}_lst_file") 49 | set(_lst_file_srcs) 50 | foreach(_lst_file_src ${_my_sources}) 51 | set(_lst_file_srcs "${_lst_file_src}\n${_lst_file_srcs}") 52 | endforeach() 53 | 54 | get_directory_property(_inc_DIRS INCLUDE_DIRECTORIES) 55 | foreach(_pro_include ${_inc_DIRS}) 56 | get_filename_component(_abs_include "${_pro_include}" ABSOLUTE) 57 | set(_lst_file_srcs "-I${_pro_include}\n${_lst_file_srcs}") 58 | endforeach() 59 | 60 | file(WRITE ${_ts_lst_file} "${_lst_file_srcs}") 61 | endif() 62 | add_custom_command(OUTPUT ${_ts_file} 63 | COMMAND ${Qt5_LUPDATE_EXECUTABLE} 64 | ARGS ${_lupdate_options} "@${_ts_lst_file}" -ts ${_ts_file} 65 | DEPENDS ${_my_sources} ${_ts_lst_file} VERBATIM) 66 | endforeach() 67 | add_translation(${_qm_files} ${_my_tsfiles}) 68 | set(${_qm_files} ${${_qm_files}} PARENT_SCOPE) 69 | endfunction() 70 | -------------------------------------------------------------------------------- /cmake/sailfish_armv7hl.cmake: -------------------------------------------------------------------------------- 1 | set(SAILFISH_SCRATCHBOX 1) 2 | 3 | set(CMAKE_SYSTEM_NAME Linux) 4 | set(CMAKE_SYSTEM_VERSION 1) 5 | 6 | set(CMAKE_C_COMPILER /opt/cross/bin/armv7hl-meego-linux-gnueabi-gcc) 7 | #$ENV{HOME}/SailfishOS/share/qtcreator/MerProject/mer-sdk-tools/MerSDK/SailfishOS-i486-x86/gcc) 8 | set(CMAKE_CXX_COMPILER /opt/cross/bin/armv7hl-meego-linux-gnueabi-g++) 9 | #$ENV{HOME}/SailfishOS/share/qtcreator/MerProject/mer-sdk-tools/MerSDK/SailfishOS-i486-x86/gcc) 10 | 11 | set(CMAKE_FIND_ROOT_PATH $ENV{HOME}/SailfishOS/mersdk/targets/SailfishOS-armv7hl/) 12 | 13 | set(QT_QMAKE_EXECUTABLE $ENV{HOME}/SailfishOS/mersdk/targets/SailfishOS-armv7hl/usr/bin/qmake) 14 | 15 | add_custom_target(deploy COMMENT "Deploying to emulator...") 16 | add_custom_command(TARGET deploy POST_BUILD COMMAND mkdir ARGS -p deploy) 17 | add_custom_command(TARGET deploy POST_BUILD COMMAND make ARGS DESTDIR=deploy install) 18 | add_custom_command(TARGET deploy POST_BUILD COMMAND scp ARGS -r -P 2223 -i $ENV{HOME}/.ssh/mer-qt-creator-rsa deploy/* root@localhost:/) 19 | add_custom_command(TARGET deploy POST_BUILD COMMAND rm ARGS -rf deploy) 20 | add_dependencies(deploy all) 21 | 22 | add_custom_target(run COMMENT "Running application...") 23 | add_custom_command(TARGET run POST_BUILD COMMAND ssh ARGS -p 2223 -i $ENV{HOME}/.ssh/mer-qt-creator-rsa root@localhost "DISPLAY=:0 /usr/bin/invoker --type=j -s /opt/sdk/bin/documents") 24 | add_dependencies(run deploy) 25 | -------------------------------------------------------------------------------- /cmake/sailfish_i486.cmake: -------------------------------------------------------------------------------- 1 | set(SAILFISH_SCRATCHBOX 1) 2 | 3 | set(CMAKE_SYSTEM_NAME Linux) 4 | set(CMAKE_SYSTEM_VERSION 1) 5 | 6 | set(CMAKE_C_COMPILER $ENV{HOME}/.config/SailfishAlpha/mer-sdk-tools/MerSDK/SailfishOS-i486-x86/gcc) 7 | set(CMAKE_CXX_COMPILER $ENV{HOME}/.config/SailfishAlpha/mer-sdk-tools/MerSDK/SailfishOS-i486-x86/gcc) 8 | 9 | set(CMAKE_FIND_ROOT_PATH $ENV{HOME}/SailfishOS/mersdk/targets/SailfishOS-i486-x86/) 10 | 11 | set(QT_QMAKE_EXECUTABLE $ENV{HOME}/.config/SailfishAlpha/mer-sdk-tools/MerSDK/SailfishOS-i486-x86/qmake) 12 | 13 | add_custom_target(deploy COMMENT "Deploying to emulator...") 14 | add_custom_command(TARGET deploy POST_BUILD COMMAND mkdir ARGS -p deploy) 15 | add_custom_command(TARGET deploy POST_BUILD COMMAND make ARGS DESTDIR=deploy install) 16 | add_custom_command(TARGET deploy POST_BUILD COMMAND scp ARGS -r -P 2223 -i $ENV{HOME}/SailfishOS/vmshare/ssh/private_keys/1/root deploy/* root@localhost:/) 17 | add_custom_command(TARGET deploy POST_BUILD COMMAND rm ARGS -rf deploy) 18 | add_dependencies(deploy all) 19 | 20 | add_custom_target(run COMMENT "Running application...") 21 | add_custom_command(TARGET run POST_BUILD COMMAND ssh ARGS -p 2223 -i $ENV{HOME}/SailfishOS/vmshare/ssh/private_keys/1/nemo nemo@localhost "/usr/bin/invoker --type=j -s /usr/bin/sailfish-office") 22 | add_dependencies(run deploy) 23 | 24 | add_custom_target(debug COMMENT "Debugging application...") 25 | add_custom_command(TARGET debug POST_BUILD COMMAND ssh ARGS -p 2223 -i $ENV{HOME}/SailfishOS/vmshare/ssh/private_keys/1/nemo nemo@localhost 'gdb -ex "run" /usr/bin/sailfish-office') 26 | add_dependencies(debug deploy) 27 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_H 2 | #define CONFIG_H 3 | 4 | #define QML_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/sailfish-office/" 5 | #define TRANSLATION_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/translations/" 6 | 7 | #endif //CONFIG_H 8 | -------------------------------------------------------------------------------- /dbusadaptor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 - 2022 Jolla Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; version 2 only. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 | */ 17 | 18 | #include "dbusadaptor.h" 19 | 20 | #include 21 | #include 22 | 23 | DBusAdaptor::DBusAdaptor(QQuickView *view) 24 | : QDBusAbstractAdaptor(view) 25 | , m_view(view) 26 | { 27 | } 28 | 29 | DBusAdaptor::~DBusAdaptor() 30 | { 31 | } 32 | 33 | void DBusAdaptor::Open(const QStringList &uris, const QVariantMap &platformData) 34 | { 35 | if (!uris.isEmpty()) { 36 | QMetaObject::invokeMethod(m_view->rootObject(), "openFile", Q_ARG(QVariant, uris.at(0))); 37 | } else { 38 | Activate(platformData); 39 | } 40 | } 41 | 42 | void DBusAdaptor::Activate(const QVariantMap &platformData) 43 | { 44 | Q_UNUSED(platformData) 45 | QMetaObject::invokeMethod(m_view->rootObject(), "activate"); 46 | } 47 | -------------------------------------------------------------------------------- /dbusadaptor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 - 2022 Jolla Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; version 2 only. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 | */ 17 | 18 | #ifndef DBUSADAPTOR_H 19 | #define DBUSADAPTOR_H 20 | 21 | #include 22 | #include 23 | 24 | class QQuickView; 25 | class DBusAdaptor : public QDBusAbstractAdaptor 26 | { 27 | Q_OBJECT 28 | Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Application") 29 | 30 | public: 31 | DBusAdaptor(QQuickView *view); 32 | ~DBusAdaptor(); 33 | 34 | public Q_SLOTS: 35 | Q_NOREPLY void Open(const QStringList &uris, const QVariantMap &platformData); 36 | Q_NOREPLY void Activate(const QVariantMap &platformData); 37 | 38 | private: 39 | QQuickView *m_view; 40 | }; 41 | 42 | #endif // DBUSADAPTOR_H 43 | -------------------------------------------------------------------------------- /images/CMakeLists.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sailfishos/sailfish-office/b87cb88f3d6ffed19273b59b0455f4257d50be95/images/CMakeLists.txt -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 - 2022 Jolla Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; version 2 only. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | #include "config.h" 35 | #include "models/filtermodel.h" 36 | #include "models/documentlistmodel.h" 37 | #include "models/trackerdocumentprovider.h" 38 | #include "models/documentprovider.h" 39 | #include "dbusadaptor.h" 40 | 41 | namespace { 42 | QSharedPointer createApplication(int &argc, char **argv) 43 | { 44 | auto app = QSharedPointer(new QApplication(argc, argv)); 45 | //FIXME: We should be able to use a pure QGuiApplication but currently too much of 46 | //Calligra depends on QApplication. 47 | //QSharedPointer(MDeclarativeCache::qApplication(argc, argv)); 48 | 49 | QTranslator *engineeringEnglish = new QTranslator(app.data()); 50 | if (!engineeringEnglish->load("sailfish-office_eng_en", TRANSLATION_INSTALL_DIR)) 51 | qWarning("Could not load engineering english translation file!"); 52 | QCoreApplication::installTranslator(engineeringEnglish); 53 | 54 | QTranslator *translator = new QTranslator(app.data()); 55 | if (!translator->load(QLocale::system(), "sailfish-office", "-", TRANSLATION_INSTALL_DIR)) 56 | qWarning() << "Could not load translations for" << QLocale::system().name().toLatin1(); 57 | QCoreApplication::installTranslator(translator); 58 | 59 | return app; 60 | } 61 | 62 | QSharedPointer createView(const QString &file) 63 | { 64 | qmlRegisterType("Sailfish.Office.Files", 1, 0, "DocumentListModel"); 65 | qmlRegisterType("Sailfish.Office.Files", 1, 0, "TrackerDocumentProvider"); 66 | qmlRegisterType("Sailfish.Office.Files", 1, 0, "FilterModel"); 67 | qmlRegisterInterface("DocumentProvider"); 68 | 69 | QSharedPointer view(MDeclarativeCache::qQuickView()); 70 | view->setSource(QUrl::fromLocalFile(QML_INSTALL_DIR + file)); 71 | 72 | new DBusAdaptor(view.data()); 73 | 74 | if (!QDBusConnection::sessionBus().registerObject("/org/sailfishos/Office", view.data())) 75 | qWarning() << "Could not register /org/sailfishos/Office D-Bus object."; 76 | 77 | if (!QDBusConnection::sessionBus().registerService("org.sailfishos.Office")) 78 | qWarning() << "Could not register org.sailfishos.Office D-Bus service."; 79 | 80 | return view; 81 | } 82 | } 83 | 84 | 85 | Q_DECL_EXPORT int main(int argc, char *argv[]) 86 | { 87 | // TODO: start using Silica booster 88 | QQuickWindow::setDefaultAlphaBuffer(true); 89 | 90 | if (!qgetenv("QML_DEBUGGING_ENABLED").isEmpty()) { 91 | QQmlDebuggingEnabler qmlDebuggingEnabler; 92 | } 93 | 94 | auto app = createApplication(argc, argv); 95 | // Note, these must be said now, otherwise some plugins using QSettings 96 | // will get terribly confused when they fail to load properly. 97 | app->setOrganizationName("org.sailfishos"); 98 | app->setApplicationName("Office"); 99 | 100 | auto view = createView("Main.qml"); 101 | 102 | //% "Documents" 103 | Q_UNUSED(QT_TRID_NOOP("sailfish-office-ap-name")) 104 | 105 | bool preStart = false; 106 | bool debug = false; 107 | QString fileName; 108 | 109 | for (int i = 1; i < argc; ++i) { 110 | QString parameter(argv[i]); 111 | if (parameter == QStringLiteral("-prestart")) { 112 | preStart = true; 113 | } else if (parameter == QStringLiteral("-d")) { 114 | debug = true; 115 | } else if (fileName.isEmpty()) { 116 | fileName = parameter; 117 | } 118 | } 119 | 120 | if (!debug) { 121 | // calligra is quite noisy by default 122 | QLoggingCategory::setFilterRules("calligra.*.debug=false"); 123 | } 124 | 125 | int retn = 1; 126 | if (view->errors().count() == 0) { 127 | if (!fileName.isEmpty()) { 128 | QVariant fileNameParameter(fileName); 129 | QMetaObject::invokeMethod(view->rootObject(), "openFile", Q_ARG(QVariant, fileNameParameter)); 130 | } else if (!preStart) { 131 | view->showFullScreen(); 132 | } 133 | 134 | retn = app->exec(); 135 | } 136 | 137 | return retn; 138 | } 139 | -------------------------------------------------------------------------------- /models/documentlistmodel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Open Mobile Platform LLC 3 | * Copyright (C) 2013-2014 Jolla Ltd. 4 | * Contact: Robin Burchell 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License 8 | * as published by the Free Software Foundation; version 2 only. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef DOCUMENTLISTMODEL_H 21 | #define DOCUMENTLISTMODEL_H 22 | 23 | #include 24 | #include 25 | 26 | class DocumentListModelPrivate; 27 | 28 | class DocumentListModel : public QAbstractListModel 29 | { 30 | Q_OBJECT 31 | public: 32 | enum DocumentClass { 33 | UnknownDocument, 34 | TextDocument, 35 | PlainTextDocument, 36 | SpreadSheetDocument, 37 | PresentationDocument, 38 | PDFDocument 39 | }; 40 | Q_ENUMS(DocumentClass) 41 | 42 | enum Roles { 43 | FileNameRole = Qt::UserRole + 1, 44 | FilePathRole, 45 | FileTypeRole, 46 | FileSizeRole, 47 | FileDateRole, 48 | FileMimeTypeRole, 49 | FileDocumentClass, 50 | FileTypeAndNameRole 51 | }; 52 | 53 | DocumentListModel(QObject *parent = 0); 54 | ~DocumentListModel(); 55 | 56 | DocumentListModel(const DocumentListModel&) = delete; 57 | DocumentListModel& operator=(const DocumentListModel&) = delete; 58 | 59 | virtual QVariant data(const QModelIndex &index, int role) const; 60 | virtual int rowCount(const QModelIndex &parent) const; 61 | virtual QHash roleNames() const; 62 | 63 | void setAllItemsDirty(bool status); 64 | void addItem(const QString &name, const QString &path, const QString &type, int size, QDateTime date, 65 | const QString &mimeType); 66 | void removeItemsDirty(); 67 | void removeAt(int index); 68 | void clear(); 69 | 70 | Q_INVOKABLE int mimeTypeToDocumentClass(QString mimeType) const; 71 | 72 | private: 73 | class Private; 74 | const QScopedPointer d; 75 | }; 76 | 77 | #endif // DOCUMENTLISTMODEL_H 78 | -------------------------------------------------------------------------------- /models/documentprovider.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #include "documentprovider.h" 20 | 21 | class DocumentProvider::Private { 22 | public: 23 | Private() {} 24 | }; 25 | 26 | DocumentProvider::DocumentProvider(QObject *parent) 27 | : QObject(parent) 28 | , d(new Private) 29 | { 30 | } 31 | 32 | DocumentProvider::~DocumentProvider() 33 | { 34 | delete d; 35 | } 36 | 37 | void DocumentProvider::deleteFile(const QUrl &file) 38 | { 39 | Q_UNUSED(file); 40 | qWarning("Provider does not implement file deletion."); 41 | } 42 | -------------------------------------------------------------------------------- /models/documentprovider.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef DOCUMENTPROVIDER_H 20 | #define DOCUMENTPROVIDER_H 21 | 22 | #include 23 | #include 24 | 25 | class DocumentProvider : public QObject 26 | { 27 | Q_OBJECT 28 | Q_PROPERTY(int count READ count NOTIFY countChanged) 29 | Q_PROPERTY(QObject *model READ model NOTIFY modelChanged) 30 | Q_PROPERTY(bool ready READ isReady NOTIFY readyChanged) 31 | Q_PROPERTY(bool error READ error NOTIFY errorChanged) 32 | 33 | public: 34 | DocumentProvider(QObject *parent = 0); 35 | virtual ~DocumentProvider(); 36 | 37 | virtual int count() const = 0; 38 | virtual QObject *model() const = 0; 39 | virtual bool isReady() const = 0; 40 | virtual bool error() const = 0; 41 | 42 | Q_INVOKABLE virtual void deleteFile(const QUrl &file); 43 | 44 | signals: 45 | void countChanged(); 46 | void modelChanged(); 47 | void readyChanged(); 48 | void errorChanged(); 49 | 50 | private: 51 | class Private; 52 | Private *d; 53 | }; 54 | 55 | Q_DECLARE_INTERFACE(DocumentProvider, "DocumentProviderInterface/1.0") 56 | 57 | #endif // DOCUMENTPROVIDER_H 58 | -------------------------------------------------------------------------------- /models/filtermodel.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Open Mobile Platform LLC 3 | * Copyright (C) 2015 Caliste Damien. 4 | * Contact: Damien Caliste 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License 8 | * as published by the Free Software Foundation; version 2 only. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "filtermodel.h" 21 | 22 | #include "documentlistmodel.h" 23 | 24 | FilterModel::FilterModel(QObject *parent) 25 | : QSortFilterProxyModel(parent) 26 | { 27 | this->setFilterRole(DocumentListModel::Roles::FileNameRole); 28 | setSortParameter(SortParameter::Date); 29 | setSortCaseSensitivity(Qt::CaseInsensitive); 30 | } 31 | 32 | FilterModel::~FilterModel() 33 | { 34 | } 35 | 36 | void FilterModel::setSourceModel(DocumentListModel *model) 37 | { 38 | QSortFilterProxyModel::setSourceModel(static_cast(model)); 39 | } 40 | 41 | int FilterModel::sortParameter() const 42 | { 43 | return m_sortParameter; 44 | } 45 | 46 | void FilterModel::setSortParameter(int sortParameter) 47 | { 48 | if (m_sortParameter == sortParameter) { 49 | return; 50 | } 51 | 52 | m_sortParameter = sortParameter; 53 | Qt::SortOrder order = Qt::AscendingOrder; 54 | 55 | switch (m_sortParameter) { 56 | case Name: 57 | setSortRole(DocumentListModel::Roles::FileNameRole); 58 | break; 59 | case Type: 60 | setSortRole(DocumentListModel::Roles::FileTypeAndNameRole); 61 | break; 62 | case Date: 63 | setSortRole(DocumentListModel::Roles::FileDateRole); 64 | order = Qt::DescendingOrder; 65 | break; 66 | default: 67 | break; 68 | } 69 | 70 | emit sortParameterChanged(); 71 | 72 | sort(0, order); 73 | } 74 | 75 | DocumentListModel* FilterModel::sourceModel() const 76 | { 77 | return static_cast(QSortFilterProxyModel::sourceModel()); 78 | } 79 | -------------------------------------------------------------------------------- /models/filtermodel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Open Mobile Platform LLC 3 | * Copyright (C) 2015 Caliste Damien. 4 | * Contact: Damien Caliste 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License 8 | * as published by the Free Software Foundation; version 2 only. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef FILTERMODEL_H 21 | #define FILTERMODEL_H 22 | 23 | #include 24 | 25 | #include "documentlistmodel.h" 26 | 27 | class FilterModel : public QSortFilterProxyModel 28 | { 29 | Q_OBJECT 30 | Q_PROPERTY(DocumentListModel *sourceModel READ sourceModel WRITE setSourceModel NOTIFY sourceModelChanged) 31 | Q_PROPERTY(int sortParameter READ sortParameter WRITE setSortParameter NOTIFY sortParameterChanged) 32 | public: 33 | FilterModel(QObject *parent = 0); 34 | ~FilterModel(); 35 | 36 | enum SortParameter { 37 | None, 38 | Name, 39 | Type, 40 | Date 41 | }; 42 | 43 | Q_ENUM(SortParameter) 44 | 45 | public: 46 | DocumentListModel* sourceModel() const; 47 | 48 | int sortParameter() const; 49 | void setSortParameter(int sortParameter); 50 | 51 | public Q_SLOTS: 52 | void setSourceModel(DocumentListModel *model); 53 | 54 | private: 55 | int m_sortParameter; 56 | 57 | Q_SIGNALS: 58 | void sourceModelChanged(); 59 | void sortParameterChanged(); 60 | }; 61 | 62 | #endif // FILTERMODEL_H 63 | -------------------------------------------------------------------------------- /models/trackerdocumentprovider.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Open Mobile Platform LLC 3 | * Copyright (C) 2013-2014 Jolla Ltd. 4 | * Contact: Robin Burchell 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License 8 | * as published by the Free Software Foundation; version 2 only. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "trackerdocumentprovider.h" 21 | #include "documentlistmodel.h" 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include "config.h" 33 | 34 | //The Tracker driver to use. direct = libtracker-sparql based 35 | static const QString trackerDriver{"QTRACKER_DIRECT"}; 36 | 37 | //The query to run to get files out of Tracker. 38 | static const QString documentQuery{ 39 | "SELECT ?name ?path ?size ?lastModified ?mimeType " 40 | "WHERE {" 41 | " GRAPH tracker:Documents {" 42 | " SELECT nfo:fileName(?path1) AS ?name" 43 | " nfo:fileSize(?path1) AS ?size" 44 | " nfo:fileLastModified(?path1) AS ?lastModified" 45 | " ?path1 AS ?path " 46 | " ?mimeType1 AS ?mimeType" 47 | " WHERE {" 48 | " ?u nie:isStoredAs ?path1 ." 49 | " ?path1 nie:dataSource/tracker:available true . " 50 | " ?u nie:mimeType ?mimeType1 ." 51 | " { ?u a nfo:PaginatedTextDocument . }" 52 | " UNION { ?u nie:mimeType 'text/plain' FILTER(fn:ends-with(nfo:fileName(nie:isStoredAs(?u)),'.txt')) }" 53 | " }" 54 | " }" 55 | "}" 56 | }; 57 | 58 | static const QString documentGraph("http://tracker.api.gnome.org/ontology/v3/tracker#Documents"); 59 | 60 | class TrackerDocumentProvider::Private { 61 | public: 62 | Private() 63 | : model(new DocumentListModel) 64 | , connection{nullptr} 65 | , ready(false) 66 | , error(false) 67 | { 68 | model->setObjectName("TrackerDocumentList"); 69 | } 70 | 71 | ~Private() 72 | { 73 | model->deleteLater(); 74 | } 75 | 76 | DocumentListModel *model; 77 | QSparqlConnection *connection; 78 | bool ready; 79 | bool error; 80 | }; 81 | 82 | TrackerDocumentProvider::TrackerDocumentProvider(QObject *parent) 83 | : DocumentProvider(parent) 84 | , d(new Private) 85 | { 86 | } 87 | 88 | TrackerDocumentProvider::~TrackerDocumentProvider() 89 | { 90 | delete d->connection; 91 | delete d; 92 | } 93 | 94 | void TrackerDocumentProvider::classBegin() 95 | { 96 | } 97 | 98 | void TrackerDocumentProvider::componentComplete() 99 | { 100 | d->connection = new QSparqlConnection(trackerDriver); 101 | if (!d->connection->isValid()) { 102 | qWarning() << "No valid QSparqlConnection on TrackerDocumentProvider"; 103 | } else { 104 | startSearch(); 105 | d->connection->subscribeToGraph(documentGraph); 106 | connect(d->connection, &QSparqlConnection::graphUpdated, 107 | this, &TrackerDocumentProvider::trackerGraphChanged); 108 | } 109 | } 110 | 111 | void TrackerDocumentProvider::startSearch() 112 | { 113 | QSparqlQuery q(documentQuery); 114 | QSparqlResult *result = d->connection->exec(q); 115 | if (result->hasError()) { 116 | qWarning() << "Error executing sparql query:" << result->lastError(); 117 | delete result; 118 | } else { 119 | connect(result, SIGNAL(finished()), this, SLOT(searchFinished())); 120 | } 121 | } 122 | 123 | void TrackerDocumentProvider::stopSearch() 124 | { 125 | } 126 | 127 | void TrackerDocumentProvider::searchFinished() 128 | { 129 | QSparqlResult *r = qobject_cast(sender()); 130 | bool wasError = d->error; 131 | d->error = r->hasError(); 132 | 133 | if (!d->error) { 134 | // d->model->clear(); 135 | // Mark all current entries in the model dirty. 136 | d->model->setAllItemsDirty(true); 137 | while (r->next()) { 138 | // This will remove the dirty flag for already 139 | // existing entries. 140 | d->model->addItem( 141 | r->binding(0).value().toString(), 142 | r->binding(1).value().toString(), 143 | r->binding(1).value().toString().split('.').last(), 144 | r->binding(2).value().toInt(), 145 | r->binding(3).value().toDateTime(), 146 | r->binding(4).value().toString() 147 | ); 148 | } 149 | // Remove all entries with the dirty mark. 150 | d->model->removeItemsDirty(); 151 | if (!d->ready) { 152 | d->ready = true; 153 | emit readyChanged(); 154 | } 155 | } 156 | 157 | delete r; 158 | 159 | if (wasError != d->error) { 160 | emit errorChanged(); 161 | } 162 | 163 | emit countChanged(); 164 | } 165 | 166 | int TrackerDocumentProvider::count() const 167 | { 168 | // TODO lolnope 169 | return d->model->rowCount(QModelIndex()); 170 | } 171 | 172 | bool TrackerDocumentProvider::isReady() const 173 | { 174 | return d->ready; 175 | } 176 | 177 | bool TrackerDocumentProvider::error() const 178 | { 179 | return d->error; 180 | } 181 | 182 | QObject* TrackerDocumentProvider::model() const 183 | { 184 | return d->model; 185 | } 186 | 187 | void TrackerDocumentProvider::deleteFile(const QUrl &file) 188 | { 189 | if (QFile::exists(file.toLocalFile())) { 190 | QFile::remove(file.toLocalFile()); 191 | 192 | const int count = d->model->rowCount(QModelIndex()); 193 | for (int i = 0; i < count; ++i) { 194 | if (d->model->data(d->model->index(i, 0), DocumentListModel::FilePathRole).toUrl() == file) { 195 | d->model->removeAt(i); 196 | break; 197 | } 198 | } 199 | } 200 | } 201 | 202 | void TrackerDocumentProvider::trackerGraphChanged(const QString &graphName) 203 | { 204 | if (graphName == documentGraph) { 205 | startSearch(); 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /models/trackerdocumentprovider.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef TRACKERDOCUMENTPROVIDER_H 20 | #define TRACKERDOCUMENTPROVIDER_H 21 | 22 | #include "documentprovider.h" 23 | 24 | #include 25 | 26 | class DocumentListModel; 27 | class TrackerDocumentProvider : public DocumentProvider, public QQmlParserStatus 28 | { 29 | Q_OBJECT 30 | Q_INTERFACES(DocumentProvider QQmlParserStatus) 31 | 32 | public: 33 | enum DocumentType { 34 | TextDocumentType, 35 | SpreadsheetType, 36 | PresentationType 37 | }; 38 | TrackerDocumentProvider(QObject *parent = 0); 39 | ~TrackerDocumentProvider(); 40 | 41 | virtual int count() const; 42 | virtual QObject *model() const; 43 | virtual bool isReady() const; 44 | virtual bool error() const; 45 | 46 | virtual void classBegin(); 47 | virtual void componentComplete(); 48 | 49 | virtual void deleteFile(const QUrl &file) Q_DECL_OVERRIDE; 50 | 51 | public Q_SLOTS: 52 | void startSearch(); 53 | void stopSearch(); 54 | 55 | private Q_SLOTS: 56 | void searchFinished(); 57 | void trackerGraphChanged(const QString &graphName); 58 | 59 | private: 60 | class Private; 61 | Private *d; 62 | }; 63 | 64 | #endif // TRACKERDOCUMENTPROVIDER_H 65 | -------------------------------------------------------------------------------- /pdf/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(Poppler REQUIRED) 2 | find_package(Qt5Sql REQUIRED) 3 | 4 | include_directories(${POPPLER_INCLUDE_DIR} ${POPPLER_QT5_INCLUDE_DIR}) 5 | 6 | set(pdfplugin_SRCS 7 | sailfishofficepdfplugin.cpp 8 | pdfdocument.cpp 9 | pdfrenderthread.cpp 10 | pdfjob.cpp 11 | pdftocmodel.cpp 12 | pdfcanvas.cpp 13 | pdflinkarea.cpp 14 | pdfsearchmodel.cpp 15 | pdfselection.cpp 16 | pdfannotation.cpp 17 | ) 18 | 19 | add_library(sailfishofficepdfplugin MODULE ${pdfplugin_SRCS}) 20 | qt5_use_modules(sailfishofficepdfplugin Quick) 21 | qt5_use_modules(sailfishofficepdfplugin Sql) 22 | target_link_libraries(sailfishofficepdfplugin stdc++ ${QT_LIBRARIES} ${POPPLER_LIBRARY} ${POPPLER_QT5_LIBRARY}) 23 | 24 | install(TARGETS sailfishofficepdfplugin DESTINATION ${CMAKE_INSTALL_LIBDIR}/qt5/qml/Sailfish/Office/PDF) 25 | install(FILES qmldir DESTINATION ${CMAKE_INSTALL_LIBDIR}/qt5/qml/Sailfish/Office/PDF) 26 | -------------------------------------------------------------------------------- /pdf/pdfannotation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Caliste Damien. 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef PDFANNOTATION_H 20 | #define PDFANNOTATION_H 21 | 22 | #include 23 | 24 | #include "pdfdocument.h" 25 | #include "pdfselection.h" 26 | 27 | class PDFTextAnnotation; 28 | class PDFHighlightAnnotation; 29 | 30 | class PDFAnnotation : public QObject 31 | { 32 | Q_OBJECT 33 | 34 | Q_ENUMS(SubType) 35 | 36 | Q_PROPERTY(PDFDocument* document READ document NOTIFY attached) 37 | Q_PROPERTY(int page READ page NOTIFY attached) 38 | Q_PROPERTY(QRectF boundary READ boundary NOTIFY attached) 39 | 40 | Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged) 41 | Q_PROPERTY(QString contents READ contents WRITE setContents NOTIFY contentsChanged) 42 | Q_PROPERTY(QDateTime creationDate READ creationDate CONSTANT) 43 | Q_PROPERTY(QDateTime modificationDate READ modificationDate NOTIFY modificationDateChanged) 44 | Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) 45 | Q_PROPERTY(SubType type READ type CONSTANT) 46 | 47 | public: 48 | enum SubType { 49 | Base, 50 | Text, 51 | Line, 52 | GeometricFigure, 53 | Highlight, 54 | Stamp, 55 | InkPath, 56 | Link, 57 | Caret, 58 | FileAttachment, 59 | Sound, 60 | Movie, 61 | Screen, 62 | Widget 63 | }; 64 | 65 | PDFAnnotation(QObject *parent = 0); 66 | PDFAnnotation(Poppler::Annotation *annotation, QObject *parent = 0); 67 | PDFAnnotation(Poppler::Annotation *annotation, 68 | PDFDocument *document, int ipage, QObject *parent = 0); 69 | ~PDFAnnotation(); 70 | 71 | SubType type() const; 72 | 73 | PDFDocument* document() const; 74 | int page() const; 75 | QRectF boundary() const; 76 | Q_INVOKABLE void attach(PDFDocument *document, PDFSelection *selection); 77 | Q_INVOKABLE void remove(); 78 | 79 | QString author() const; 80 | void setAuthor(const QString &value); 81 | 82 | QString contents() const; 83 | void setContents(const QString &value); 84 | 85 | QDateTime creationDate() const; 86 | 87 | QDateTime modificationDate() const; 88 | 89 | QColor color() const; 90 | void setColor(const QColor &value); 91 | 92 | Q_SIGNALS: 93 | void attached(); 94 | void authorChanged(); 95 | void contentsChanged(); 96 | void creationDateChanged(); 97 | void modificationDateChanged(); 98 | void colorChanged(); 99 | 100 | protected: 101 | class Private; 102 | Private *d; 103 | 104 | void attachOnce(PDFDocument *document, int page); 105 | }; 106 | 107 | class PDFTextAnnotation : public PDFAnnotation 108 | { 109 | Q_OBJECT 110 | 111 | Q_ENUMS(IconType) 112 | 113 | Q_PROPERTY(IconType icon READ icon WRITE setIcon NOTIFY iconChanged) 114 | 115 | public: 116 | enum IconType { 117 | Note, 118 | Comment, 119 | Key, 120 | Help, 121 | NewParagraph, 122 | Paragraph, 123 | Insert, 124 | Cross, 125 | Circle 126 | }; 127 | 128 | PDFTextAnnotation(QObject *parent = 0); 129 | PDFTextAnnotation(Poppler::TextAnnotation *annotation, 130 | PDFDocument *document, int ipage, QObject *parent = 0); 131 | ~PDFTextAnnotation(); 132 | 133 | Q_INVOKABLE void attach(PDFDocument *document, PDFSelection *selection); 134 | Q_INVOKABLE void attachAt(PDFDocument *document, 135 | unsigned int page, qreal x, qreal y); 136 | 137 | IconType icon() const; 138 | void setIcon(IconType value); 139 | 140 | Q_SIGNALS: 141 | void iconChanged(); 142 | }; 143 | 144 | class PDFCaretAnnotation : public PDFAnnotation 145 | { 146 | Q_OBJECT 147 | 148 | public: 149 | PDFCaretAnnotation(QObject *parent = 0); 150 | PDFCaretAnnotation(Poppler::CaretAnnotation *annotation, 151 | PDFDocument *document, int ipage, QObject *parent = 0); 152 | ~PDFCaretAnnotation(); 153 | }; 154 | 155 | class PDFHighlightAnnotation : public PDFAnnotation 156 | { 157 | Q_OBJECT 158 | 159 | Q_ENUMS(HighlightType) 160 | 161 | Q_PROPERTY(HighlightType style READ style WRITE setStyle NOTIFY styleChanged) 162 | 163 | public: 164 | enum HighlightType { 165 | Highlight, 166 | Squiggly, 167 | Underline, 168 | StrikeOut 169 | }; 170 | 171 | PDFHighlightAnnotation(QObject *parent = 0); 172 | PDFHighlightAnnotation(Poppler::HighlightAnnotation *annotation, 173 | PDFDocument *document, int ipage, QObject *parent = 0); 174 | ~PDFHighlightAnnotation(); 175 | 176 | Q_INVOKABLE void attach(PDFDocument *document, PDFSelection *selection); 177 | 178 | HighlightType style() const; 179 | void setStyle(HighlightType value); 180 | 181 | Q_SIGNALS: 182 | void styleChanged(); 183 | }; 184 | 185 | #endif // PDFANNOTATION_H 186 | -------------------------------------------------------------------------------- /pdf/pdfcanvas.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef PDFCANVAS_H 20 | #define PDFCANVAS_H 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | class PDFDocument; 28 | 29 | class PDFCanvas : public QQuickItem 30 | { 31 | Q_OBJECT 32 | Q_PROPERTY(PDFDocument* document READ document WRITE setDocument NOTIFY documentChanged) 33 | Q_PROPERTY(QQuickItem* flickable READ flickable WRITE setFlickable NOTIFY flickableChanged) 34 | Q_PROPERTY(float spacing READ spacing WRITE setSpacing NOTIFY spacingChanged) 35 | Q_PROPERTY(QColor linkColor READ linkColor WRITE setLinkColor NOTIFY linkColorChanged) 36 | Q_PROPERTY(QColor pagePlaceholderColor READ pagePlaceholderColor WRITE setPagePlaceholderColor NOTIFY pagePlaceholderColorChanged) 37 | Q_PROPERTY(int currentPage READ currentPage NOTIFY currentPageChanged) 38 | Q_PROPERTY(float linkWiggle READ linkWiggle WRITE setLinkWiggle NOTIFY linkWiggleChanged) 39 | 40 | public: 41 | PDFCanvas(QQuickItem *parent = 0); 42 | ~PDFCanvas(); 43 | 44 | typedef QPair ReducedBox; 45 | 46 | Q_INVOKABLE QRectF pageRectangle(int index) const; 47 | 48 | QQuickItem *flickable() const; 49 | void setFlickable(QQuickItem *f); 50 | 51 | PDFDocument* document() const; 52 | void setDocument(PDFDocument *doc); 53 | 54 | /** 55 | * Getter for property #spacing. 56 | */ 57 | float spacing() const; 58 | /** 59 | * Setter for property #spacing. 60 | */ 61 | void setSpacing(float newValue); 62 | 63 | float linkWiggle() const; 64 | void setLinkWiggle(float newValue); 65 | 66 | /** 67 | * Getter for property #linkColor. 68 | */ 69 | QColor linkColor() const; 70 | /** 71 | * Setter for property #linkColor. 72 | */ 73 | void setLinkColor(const QColor &color); 74 | /** 75 | * Getter for property #pagePlaceholderColor. 76 | */ 77 | QColor pagePlaceholderColor() const; 78 | /** 79 | * Setter for property #pagePlaceholderColor. 80 | */ 81 | void setPagePlaceholderColor(const QColor &color); 82 | 83 | /** 84 | * Getter for property #currentPage. 85 | */ 86 | int currentPage() const; 87 | 88 | void layout(); 89 | 90 | /** 91 | * \return The url of the link at point or an empty url if there is no link at point. 92 | */ 93 | QPair urlAtPoint(const QPointF &point) const; 94 | QPair pageAtPoint(const QPointF &point) const; 95 | QPair annotationAtPoint(const QPointF &point) const; 96 | /** 97 | * \return A rectangle in the canvas coordinates from a rectangle 98 | * in page coordinates. Index is the index of the page. 99 | */ 100 | Q_INVOKABLE QRectF fromPageToItem(int index, const QRectF &rect) const; 101 | Q_INVOKABLE QPointF fromPageToItem(int index, const QPointF &point) const; 102 | /** 103 | * Provide a distance measure from @point to a rectangle given by @reducedCoordRect. 104 | * @point is given in PDFCanvas coordinates, while @reducedCoordRect is in 105 | * reduced coordinates and will be converted to PDFCanvas coordinates thanks 106 | * to @pageRect. @pageRect can be obtained by calling pageAtPoint(). 107 | */ 108 | qreal squaredDistanceFromRect(const QRectF &pageRect, 109 | const QRectF &reducedCoordRect, 110 | const QPointF &point) const; 111 | 112 | Q_SIGNALS: 113 | void documentChanged(); 114 | void flickableChanged(); 115 | void spacingChanged(); 116 | void linkColorChanged(); 117 | void pagePlaceholderColorChanged(); 118 | void currentPageChanged(); 119 | void pageLayoutChanged(); 120 | void linkWiggleChanged(); 121 | 122 | protected: 123 | virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); 124 | virtual QSGNode* updatePaintNode(QSGNode *node, UpdatePaintNodeData*); 125 | 126 | void updatePolish() override; 127 | void itemChange(ItemChange change, const ItemChangeData &data) override; 128 | 129 | private Q_SLOTS: 130 | void linksFinished(int id, const QList > &links); 131 | void pageModified(int id, const QRectF &subpart); 132 | void pageFinished(int id, int pageRenderWidth, 133 | QRect subpart, const QImage &image, int extraData); 134 | void documentLoaded(); 135 | void resizeTimeout(); 136 | void pageSizesFinished(const QList &sizes); 137 | void invalidateSceneGraph(); 138 | void schedulePolish() { polish(); } 139 | 140 | private: 141 | class Private; 142 | Private * const d; 143 | }; 144 | 145 | Q_DECLARE_METATYPE(PDFCanvas*) 146 | 147 | #endif // PDFCANVAS_H 148 | -------------------------------------------------------------------------------- /pdf/pdfdocument.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef PDFDOCUMENT_H 20 | #define PDFDOCUMENT_H 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | class PDFJob; 32 | 33 | class PDFDocument : public QObject, public QQmlParserStatus 34 | { 35 | Q_OBJECT 36 | Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged) 37 | Q_PROPERTY(QString autoSavePath READ autoSavePath WRITE setAutoSavePath NOTIFY autoSavePathChanged) 38 | Q_PROPERTY(int pageCount READ pageCount NOTIFY pageCountChanged) 39 | Q_PROPERTY(QObject* tocModel READ tocModel NOTIFY tocModelChanged) 40 | Q_PROPERTY(bool loaded READ isLoaded NOTIFY documentLoadedChanged) 41 | Q_PROPERTY(bool passwordProtected READ isPasswordProtected NOTIFY documentLoadedChanged) 42 | Q_PROPERTY(bool failure READ isFailed NOTIFY documentFailedChanged) 43 | Q_PROPERTY(bool locked READ isLocked NOTIFY documentLockedChanged) 44 | Q_PROPERTY(bool modified READ isModified NOTIFY documentModifiedChanged) 45 | Q_PROPERTY(bool searching READ searching NOTIFY searchingChanged) 46 | Q_PROPERTY(QObject* searchModel READ searchModel NOTIFY searchModelChanged) 47 | Q_PROPERTY(QString password READ password NOTIFY passwordChanged) 48 | 49 | Q_INTERFACES(QQmlParserStatus) 50 | 51 | public: 52 | PDFDocument(QObject *parent = 0); 53 | ~PDFDocument(); 54 | 55 | public: 56 | typedef QList > LinkList; 57 | typedef QList > TextList; 58 | 59 | QString source() const; 60 | QString autoSavePath() const; 61 | int pageCount() const; 62 | QObject* tocModel() const; 63 | bool searching() const; 64 | QObject* searchModel() const; 65 | QString password() const; 66 | 67 | TextList textBoxesAtPage(int page); 68 | 69 | bool isLoaded() const; 70 | bool isPasswordProtected() const; 71 | bool isFailed() const; 72 | bool isLocked() const; 73 | bool isModified() const; 74 | 75 | void addAnnotation(Poppler::Annotation *annotation, int pageIndex, 76 | bool normalizeSize = false); 77 | QList annotations(int page) const; 78 | void removeAnnotation(Poppler::Annotation *annotation, int pageIndex); 79 | 80 | void setDocumentModified(); 81 | 82 | Q_INVOKABLE void clearCachedPassword() const; 83 | 84 | int requestPage(int index, int size, 85 | QRect subpart = QRect(), int extraData = 0); 86 | 87 | virtual void classBegin(); 88 | virtual void componentComplete(); 89 | 90 | public Q_SLOTS: 91 | void setSource(const QString &source); 92 | void setAutoSavePath(const QString &filename); 93 | void requestUnLock(const QString &password, bool store = false); 94 | void requestLinksAtPage(int page); 95 | 96 | void prioritizeRequest(int index, int size, QRect subpart = QRect()); 97 | bool cancelPageRequest(int index); 98 | void requestPageSizes(); 99 | void search(const QString &search, uint startPage = 0); 100 | void cancelSearch(bool resetModel = true); 101 | void onSearchFinished(); 102 | void onSearchProgress(float fraction, const QList> &matches); 103 | void loadFinished(); 104 | void jobFinished(PDFJob *job); 105 | void onPageModified(int page, const QRectF &subpart); 106 | 107 | Q_SIGNALS: 108 | void sourceChanged(); 109 | void autoSavePathChanged(); 110 | void pageCountChanged(); 111 | void tocModelChanged(); 112 | void searchingChanged(); 113 | void searchModelChanged(); 114 | void passwordChanged(); 115 | void pageModified(int index, const QRectF &subpart); 116 | 117 | void documentLoadedChanged(); 118 | void documentFailedChanged(); 119 | void documentLockedChanged(); 120 | void documentModifiedChanged(); 121 | void linksFinished(int page, const LinkList &links); 122 | void pageFinished(int requestId, int resolution, QRect subpart, 123 | const QImage &page, int extraData); 124 | void pageSizesFinished(const QList &heights); 125 | 126 | private: 127 | class Private; 128 | Private * const d; 129 | }; 130 | 131 | #endif // PDFDOCUMENT_H 132 | -------------------------------------------------------------------------------- /pdf/pdfjob.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef PDFJOB_H 20 | #define PDFJOB_H 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | namespace Poppler 28 | { 29 | class Document; 30 | } 31 | 32 | class PDFJob : public QObject 33 | { 34 | Q_OBJECT 35 | public: 36 | enum JobType { 37 | LoadDocumentJob, 38 | ClearSecretJob, 39 | UnLockDocumentJob, 40 | LinksJob, 41 | RenderPageJob, 42 | PageSizesJob, 43 | SearchDocumentJob, 44 | }; 45 | 46 | PDFJob(JobType type) : m_document(nullptr), m_type(type) { } 47 | virtual ~PDFJob() { } 48 | 49 | virtual void run() = 0; 50 | 51 | JobType type() const { return m_type; } 52 | 53 | protected: 54 | friend class PDFRenderThreadQueue; 55 | Poppler::Document *m_document; 56 | 57 | private: 58 | JobType m_type; 59 | }; 60 | 61 | class LoadDocumentJob : public PDFJob 62 | { 63 | Q_OBJECT 64 | public: 65 | LoadDocumentJob(const QString &source); 66 | 67 | virtual void run(); 68 | QString source() const; 69 | 70 | private: 71 | QString m_source; 72 | }; 73 | 74 | class ClearSecretJob : public PDFJob 75 | { 76 | Q_OBJECT 77 | public: 78 | ClearSecretJob(const QString &storeKey); 79 | 80 | virtual void run(); // Default run action is clear(). 81 | 82 | private: 83 | QString m_storeKey; 84 | }; 85 | 86 | class UnLockDocumentJob : public PDFJob 87 | { 88 | Q_OBJECT 89 | public: 90 | UnLockDocumentJob(const QString &password, const QString &storeKey = QString()); 91 | 92 | virtual void run(); 93 | QString password() const; 94 | 95 | private: 96 | QString m_password; 97 | QString m_storeKey; 98 | }; 99 | 100 | class LinksJob : public PDFJob 101 | { 102 | Q_OBJECT 103 | public: 104 | LinksJob(int page); 105 | 106 | virtual void run(); 107 | 108 | int m_page; 109 | QList > m_links; 110 | }; 111 | 112 | class RenderPageJob : public PDFJob 113 | { 114 | Q_OBJECT 115 | public: 116 | RenderPageJob(int requestId, int index, uint width, 117 | QRect subpart = QRect(), int extraData = 0); 118 | 119 | virtual void run(); 120 | 121 | int m_requestId; 122 | int m_index; 123 | QRect m_subpart; 124 | QImage m_page; 125 | int m_extraData; 126 | 127 | int renderWidth() const { return m_width; } 128 | void changeRenderWidth(int width) { m_width = width; } 129 | 130 | private: 131 | uint m_width; 132 | }; 133 | 134 | class PageSizesJob : public PDFJob 135 | { 136 | Q_OBJECT 137 | public: 138 | PageSizesJob() : PDFJob(PDFJob::PageSizesJob) { } 139 | 140 | virtual void run(); 141 | 142 | QList m_pageSizes; 143 | }; 144 | 145 | 146 | #endif // PDFJOB_H 147 | -------------------------------------------------------------------------------- /pdf/pdflinkarea.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef LINKLAYER_H 20 | #define LINKLAYER_H 21 | 22 | #include 23 | #include "pdfannotation.h" 24 | 25 | class PDFCanvas; 26 | class PDFSelection; 27 | 28 | class PDFLinkArea : public QQuickItem 29 | { 30 | Q_OBJECT 31 | Q_PROPERTY(PDFCanvas* canvas READ canvas WRITE setCanvas NOTIFY canvasChanged) 32 | Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged) 33 | Q_PROPERTY(QRectF clickedBox READ clickedBox NOTIFY clickedBoxChanged) 34 | Q_PROPERTY(PDFSelection* selection READ selection WRITE setSelection NOTIFY selectionChanged) 35 | 36 | public: 37 | PDFLinkArea(QQuickItem *parent = 0); 38 | virtual ~PDFLinkArea(); 39 | 40 | PDFCanvas* canvas() const; 41 | bool pressed() const; 42 | QRectF clickedBox() const; 43 | void setCanvas(PDFCanvas *newCanvas); 44 | PDFSelection* selection() const; 45 | void setSelection(PDFSelection *newSelection); 46 | 47 | Q_SIGNALS: 48 | void pressedChanged(); 49 | void clickedBoxChanged(); 50 | void positionChanged(QPointF at); 51 | void released(); 52 | void clicked(QPointF clickAt); 53 | void doubleClicked(); 54 | void linkClicked(QUrl linkTarget); 55 | void gotoClicked(int page, qreal top, qreal left); 56 | void selectionClicked(); 57 | void annotationClicked(PDFAnnotation *annotation); 58 | void annotationLongPress(PDFAnnotation *annotation); 59 | void longPress(QPointF pressAt); 60 | 61 | void canvasChanged(); 62 | void selectionChanged(); 63 | 64 | protected: 65 | virtual void mousePressEvent(QMouseEvent *event); 66 | virtual void mouseMoveEvent(QMouseEvent *event); 67 | virtual void mouseReleaseEvent(QMouseEvent *event); 68 | virtual void mouseDoubleClickEvent(QMouseEvent *event); 69 | virtual void mouseUngrabEvent(); 70 | 71 | private Q_SLOTS: 72 | void pressTimeout(); 73 | void onPageLayoutChanged(); 74 | 75 | private: 76 | class Private; 77 | Private *d; 78 | 79 | PDFAnnotation* newProxyForAnnotation(); 80 | }; 81 | 82 | #endif // LINKLAYER_H 83 | -------------------------------------------------------------------------------- /pdf/pdfrenderthread.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef PDFRENDERTHREAD_H 20 | #define PDFRENDERTHREAD_H 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | class QSize; 30 | class PDFJob; 31 | class PDFRenderThreadPrivate; 32 | 33 | class PDFRenderThread : public QObject 34 | { 35 | Q_OBJECT 36 | public: 37 | PDFRenderThread(QObject *parent = 0); 38 | ~PDFRenderThread(); 39 | 40 | int pageCount() const; 41 | QObject* tocModel() const; 42 | bool isLoaded() const; 43 | bool isPasswordProtected() const; 44 | bool isFailed() const; 45 | bool isLocked() const; 46 | QMultiMap > linkTargets() const; 47 | QList > textBoxesAtPage(int page); 48 | void search(const QString &search, uint startPage); 49 | void cancelSearch(); 50 | 51 | void addAnnotation(Poppler::Annotation *annotation, int pageIndex, 52 | bool normalizeSize); 53 | QList annotations(int pageIndex) const; 54 | void removeAnnotation(Poppler::Annotation *annotation, int pageIndex); 55 | 56 | void setAutoSaveName(const QString &filename); 57 | 58 | QString cachedPassword() const; 59 | 60 | void queueJob(PDFJob *job); 61 | bool cancelRenderJob(int index); 62 | void prioritizeRenderJob(int index, int size, QRect subpart); 63 | 64 | Q_SIGNALS: 65 | void loadFinished(); 66 | void pageModified(int page, const QRectF &subpart); 67 | void jobFinished(PDFJob *job); 68 | void searchFinished(); 69 | void searchProgress(float fraction, const QList> &newMatches); 70 | 71 | private Q_SLOTS: 72 | void onSearchProgress(float fraction, uint beginIndex, uint nNewMatches); 73 | 74 | private: 75 | friend class PDFRenderThreadPrivate; 76 | 77 | PDFRenderThreadPrivate * const d; 78 | }; 79 | 80 | #endif // PDFRENDERTHREAD_H 81 | -------------------------------------------------------------------------------- /pdf/pdfsearchmodel.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Caliste Damien. 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #include "pdfsearchmodel.h" 20 | 21 | #include 22 | 23 | class PDFSearchModel::Private 24 | { 25 | public: 26 | Private() 27 | : m_fraction(0.f) 28 | { 29 | roles.insert(Page, "page"); 30 | roles.insert(Rect, "rect"); 31 | } 32 | QList > m_matches; 33 | QHash roles; 34 | float m_fraction; 35 | }; 36 | 37 | PDFSearchModel::PDFSearchModel(QObject *parent) 38 | : QAbstractListModel(parent), d(new Private) 39 | { 40 | } 41 | 42 | PDFSearchModel::~PDFSearchModel() 43 | { 44 | } 45 | 46 | QHash PDFSearchModel::roleNames() const 47 | { 48 | return d->roles; 49 | } 50 | 51 | QVariant PDFSearchModel::data(const QModelIndex& index, int role) const 52 | { 53 | QVariant result; 54 | if (index.isValid()) { 55 | int row = index.row(); 56 | if (row > -1 && row < d->m_matches.count()) { 57 | const QPair &match = d->m_matches.at(row); 58 | switch(role) 59 | { 60 | case Page: 61 | result.setValue(match.first); 62 | break; 63 | case Rect: 64 | result.setValue(match.second); 65 | break; 66 | default: 67 | result.setValue(QString("Unknown role: %1").arg(role)); 68 | break; 69 | } 70 | } 71 | } 72 | return result; 73 | } 74 | 75 | int PDFSearchModel::rowCount(const QModelIndex& parent) const 76 | { 77 | if (parent.isValid()) 78 | return 0; 79 | return d->m_matches.count(); 80 | } 81 | 82 | int PDFSearchModel::count() const 83 | { 84 | return d->m_matches.count(); 85 | } 86 | 87 | float PDFSearchModel::fraction() const 88 | { 89 | return d->m_fraction; 90 | } 91 | 92 | void PDFSearchModel::addMatches(float fraction, const QList > &matches) 93 | { 94 | if (!matches.empty()) { 95 | beginInsertRows(QModelIndex(), d->m_matches.count(), 96 | d->m_matches.count() + matches.count() - 1); 97 | d->m_matches.append(matches); 98 | endInsertRows(); 99 | emit countChanged(); 100 | } 101 | 102 | d->m_fraction = fraction; 103 | emit fractionChanged(); 104 | } 105 | -------------------------------------------------------------------------------- /pdf/pdfsearchmodel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Caliste Damien. 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef PDFSEARCHMODEL_H 20 | #define PDFSEARCHMODEL_H 21 | 22 | #include 23 | 24 | class PDFSearchModel : public QAbstractListModel 25 | { 26 | Q_OBJECT 27 | Q_PROPERTY(int count READ count NOTIFY countChanged) 28 | Q_PROPERTY(float fraction READ fraction NOTIFY fractionChanged) 29 | 30 | public: 31 | enum PDFSearchModelRoles { 32 | Page = Qt::UserRole + 1, 33 | Rect 34 | }; 35 | explicit PDFSearchModel(QObject *parent = 0); 36 | virtual ~PDFSearchModel(); 37 | 38 | virtual QVariant data(const QModelIndex &index, int role) const; 39 | virtual int rowCount(const QModelIndex &parent) const; 40 | virtual QHash roleNames() const; 41 | 42 | int count() const; 43 | float fraction() const; 44 | void addMatches(float fraction, const QList > &matches); 45 | 46 | Q_SIGNALS: 47 | void countChanged(); 48 | void fractionChanged(); 49 | 50 | private: 51 | class Private; 52 | const QScopedPointer d; 53 | }; 54 | 55 | #endif // PDFSEARCHMODEL_H 56 | -------------------------------------------------------------------------------- /pdf/pdfselection.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Caliste Damien. 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef PDFSELECTION_H 20 | #define PDFSELECTION_H 21 | 22 | #include 23 | 24 | #include "pdfcanvas.h" 25 | 26 | class PDFSelection : public QAbstractListModel 27 | { 28 | Q_OBJECT 29 | Q_PROPERTY(int count READ count NOTIFY countChanged) 30 | Q_PROPERTY(PDFCanvas* canvas READ canvas WRITE setCanvas NOTIFY canvasChanged) 31 | Q_PROPERTY(QPointF handle1 READ handle1 WRITE setHandle1 NOTIFY handle1Changed) 32 | Q_PROPERTY(QPointF handle2 READ handle2 WRITE setHandle2 NOTIFY handle2Changed) 33 | Q_PROPERTY(float handle1Height READ handle1Height NOTIFY handle1Changed) 34 | Q_PROPERTY(float handle2Height READ handle2Height NOTIFY handle2Changed) 35 | Q_PROPERTY(QString text READ text NOTIFY textChanged) 36 | Q_PROPERTY(float wiggle READ wiggle WRITE setWiggle NOTIFY wiggleChanged) 37 | 38 | public: 39 | enum PDFSelectionRoles { 40 | Rect = Qt::UserRole + 1, 41 | Text 42 | }; 43 | explicit PDFSelection(QObject *parent = 0); 44 | virtual ~PDFSelection(); 45 | 46 | virtual QVariant data(const QModelIndex &index, int role) const; 47 | virtual int rowCount(const QModelIndex &parent) const; 48 | virtual QHash roleNames() const; 49 | 50 | QPair rectAt(int index) const; 51 | 52 | int count() const; 53 | PDFCanvas* canvas() const; 54 | void setCanvas(PDFCanvas *newCanvas); 55 | float wiggle() const; 56 | void setWiggle(float newValue); 57 | 58 | /** 59 | * Change current selection to match the word that is at point in canvas coordinates. 60 | * If there is no word at point, the selection is invalidated (ie. count is set to 61 | * zero). 62 | */ 63 | Q_INVOKABLE bool selectAt(const QPointF &point); 64 | Q_INVOKABLE void unselect(); 65 | 66 | /** 67 | * Check if point is inside selection. 68 | */ 69 | bool selectionAtPoint(const QPointF &point) const; 70 | 71 | /** 72 | * Return a point for the start handle of the selection in canvas coordinates. 73 | * This handle can be dragged later and become the stop handle. 74 | */ 75 | QPointF handle1() const; 76 | float handle1Height() const; 77 | /** 78 | * Change the start/stop of the selection to the start/end of the word at point. 79 | * point is given in canvas coordinates. If there is no word at point, 80 | * the selection is left unchanged. 81 | */ 82 | void setHandle1(const QPointF &point); 83 | 84 | /** 85 | * Return a point for the stop handle of the selection in canvas coordinates. 86 | * This handle can later be dragged to become the start handle. 87 | */ 88 | QPointF handle2() const; 89 | float handle2Height() const; 90 | /** 91 | * Change the stop of the selection to the end of the word at point. 92 | * point is given in canvas coordinates. If there is no word at point, 93 | * the selection is left unchanged. 94 | */ 95 | void setHandle2(const QPointF &point); 96 | 97 | QString text() const; 98 | 99 | Q_SIGNALS: 100 | void countChanged(); 101 | void canvasChanged(); 102 | void handle1Changed(); 103 | void handle2Changed(); 104 | void textChanged(); 105 | void wiggleChanged(); 106 | 107 | private: 108 | class Private; 109 | Private * const d; 110 | 111 | void setStart(const QPointF &point); 112 | void setStop(const QPointF &point); 113 | 114 | void onLayoutChanged(); 115 | }; 116 | 117 | #endif // PDFSELECTION_H 118 | -------------------------------------------------------------------------------- /pdf/pdftocmodel.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #include "pdftocmodel.h" 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | struct PDFTocEntry 26 | { 27 | PDFTocEntry() 28 | : level(0) 29 | , pageNumber(0) 30 | {} 31 | QString title; 32 | int level; 33 | int pageNumber; 34 | }; 35 | 36 | class TocThread: public QThread 37 | { 38 | Q_OBJECT 39 | public: 40 | TocThread(Poppler::Document *document, QObject *parent = 0) 41 | : QThread(parent), m_document(document) 42 | { 43 | } 44 | ~TocThread() 45 | { 46 | wait(); 47 | qDeleteAll(entries); 48 | } 49 | 50 | QList entries; 51 | 52 | void run() 53 | { 54 | QDomDocument *toc = m_document->toc(); 55 | addSynopsisChildren(toc, 0); 56 | delete toc; 57 | emit tocAvailable(); 58 | } 59 | 60 | void addSynopsisChildren(QDomNode *parent, int level) 61 | { 62 | if (!parent || parent->isNull()) 63 | return; 64 | 65 | // keep track of the current listViewItem 66 | QDomNode n = parent->firstChild(); 67 | while (!n.isNull()) { 68 | PDFTocEntry *tocEntry = new PDFTocEntry; 69 | tocEntry->level = level; 70 | // convert the node to an element (sure it is) 71 | QDomElement e = n.toElement(); 72 | tocEntry->title = e.tagName(); 73 | 74 | // Apparently we can have external links in the ToC. 75 | // Not doing this for now, but leave it in here as a note to self 76 | // if (!e.attribute("ExternalFileName").isNull()) item.setAttribute("ExternalFileName", e.attribute("ExternalFileName")); 77 | if (!e.attribute("DestinationName").isNull()) { 78 | Poppler::LinkDestination *dest = m_document->linkDestination(e.attribute("DestinationName")); 79 | if (dest) { 80 | tocEntry->pageNumber = dest->pageNumber(); 81 | delete dest; 82 | } 83 | //item.setAttribute("ViewportName", e.attribute("DestinationName")); 84 | } 85 | if (!e.attribute("Destination").isNull()) { 86 | //fillViewportFromLinkDestination( vp, Poppler::LinkDestination(e.attribute("Destination")) ); 87 | //item.setAttribute( "Viewport", vp.toString() ); 88 | Poppler::LinkDestination dest(e.attribute("Destination")); 89 | tocEntry->pageNumber = dest.pageNumber(); 90 | } 91 | // if (!e.attribute("Open").isNull()) item.setAttribute("Open", e.attribute("Open")); 92 | // if (!e.attribute("DestinationURI").isNull()) item.setAttribute("URL", e.attribute("DestinationURI")); 93 | 94 | // Add the entry to the list of ToC entries 95 | entries.append(tocEntry); 96 | // descend recursively and advance to the next node 97 | ++level; 98 | if (e.hasChildNodes()) 99 | addSynopsisChildren(&n, level); 100 | --level; 101 | n = n.nextSibling(); 102 | } 103 | } 104 | 105 | signals: 106 | void tocAvailable(); 107 | 108 | private: 109 | Poppler::Document *m_document; 110 | }; 111 | 112 | class PDFTocModel::Private 113 | { 114 | public: 115 | Private(Poppler::Document *doc) 116 | : document(doc) 117 | , tocReady(false) 118 | , tocThread(nullptr) 119 | {} 120 | ~Private() { delete tocThread; } 121 | 122 | Poppler::Document *document; 123 | bool tocReady; 124 | TocThread *tocThread; 125 | }; 126 | 127 | PDFTocModel::PDFTocModel(Poppler::Document *document, QObject *parent) 128 | : QAbstractListModel(parent) 129 | , d(new Private(document)) 130 | { 131 | } 132 | 133 | PDFTocModel::~PDFTocModel() 134 | { 135 | delete d; 136 | } 137 | 138 | QHash PDFTocModel::roleNames() const 139 | { 140 | QHash names; 141 | names[Title] = "title"; 142 | names[Level] = "level"; 143 | names[PageNumber] = "pageNumber"; 144 | return names; 145 | } 146 | 147 | QVariant PDFTocModel::data(const QModelIndex &index, int role) const 148 | { 149 | QVariant result; 150 | if (index.isValid() && d->tocReady) { 151 | int row = index.row(); 152 | if (row > -1 && row < d->tocThread->entries.count()) { 153 | const PDFTocEntry *entry = d->tocThread->entries.at(row); 154 | switch(role) 155 | { 156 | case Title: 157 | result.setValue(entry->title); 158 | break; 159 | case Level: 160 | result.setValue(entry->level); 161 | break; 162 | case PageNumber: 163 | result.setValue(entry->pageNumber); 164 | break; 165 | default: 166 | result.setValue(QString("Unknown role: %1").arg(role)); 167 | break; 168 | } 169 | } 170 | } 171 | return result; 172 | } 173 | 174 | int PDFTocModel::rowCount(const QModelIndex &parent) const 175 | { 176 | if (parent.isValid() || !d->tocReady) 177 | return 0; 178 | return d->tocThread->entries.count(); 179 | } 180 | 181 | int PDFTocModel::count() const 182 | { 183 | return (d->tocReady) ? d->tocThread->entries.count() : 0; 184 | } 185 | 186 | bool PDFTocModel::ready() const 187 | { 188 | return d->tocReady; 189 | } 190 | 191 | void PDFTocModel::requestToc() 192 | { 193 | if (d->tocThread) 194 | return; 195 | 196 | d->tocThread = new TocThread(d->document); 197 | d->tocThread->start(); 198 | connect(d->tocThread, &TocThread::tocAvailable, 199 | this, &PDFTocModel::onTocAvailable); 200 | } 201 | 202 | void PDFTocModel::onTocAvailable() 203 | { 204 | d->tocReady = true; 205 | emit readyChanged(); 206 | 207 | beginInsertRows(QModelIndex(), 0, d->tocThread->entries.count() - 1); 208 | endInsertRows(); 209 | emit countChanged(); 210 | } 211 | 212 | #include "pdftocmodel.moc" 213 | -------------------------------------------------------------------------------- /pdf/pdftocmodel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef PDFTOCMODEL_H 20 | #define PDFTOCMODEL_H 21 | 22 | #include 23 | 24 | namespace Poppler { class Document; } 25 | 26 | class PDFTocModel : public QAbstractListModel 27 | { 28 | Q_OBJECT 29 | Q_PROPERTY(int count READ count NOTIFY countChanged) 30 | Q_PROPERTY(bool ready READ ready NOTIFY readyChanged) 31 | 32 | public: 33 | enum PDFTocModelRoles { 34 | Title = Qt::UserRole + 1, 35 | Level, 36 | PageNumber 37 | }; 38 | explicit PDFTocModel(Poppler::Document *document, QObject *parent = 0); 39 | virtual ~PDFTocModel(); 40 | 41 | virtual QVariant data(const QModelIndex &index, int role) const; 42 | virtual int rowCount(const QModelIndex &parent) const; 43 | virtual QHash roleNames() const; 44 | 45 | int count() const; 46 | bool ready() const; 47 | 48 | Q_INVOKABLE void requestToc(); 49 | 50 | Q_SIGNALS: 51 | void countChanged(); 52 | void readyChanged(); 53 | 54 | private Q_SLOTS: 55 | void onTocAvailable(); 56 | 57 | private: 58 | class Private; 59 | Private * const d; 60 | }; 61 | 62 | #endif // PDFTOCMODEL_H 63 | -------------------------------------------------------------------------------- /pdf/qmldir: -------------------------------------------------------------------------------- 1 | module Sailfish.Office.PDF 2 | plugin sailfishofficepdfplugin 3 | -------------------------------------------------------------------------------- /pdf/sailfishofficepdfplugin.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #include "sailfishofficepdfplugin.h" 20 | 21 | #include "pdfdocument.h" 22 | #include "pdfcanvas.h" 23 | #include "pdflinkarea.h" 24 | #include "pdfselection.h" 25 | #include "pdfannotation.h" 26 | 27 | SailfishOfficePDFPlugin::SailfishOfficePDFPlugin(QObject *parent) 28 | : QQmlExtensionPlugin(parent) 29 | { 30 | } 31 | 32 | void SailfishOfficePDFPlugin::registerTypes(const char *uri) 33 | { 34 | Q_ASSERT(uri == QLatin1String("Sailfish.Office.PDF")); 35 | qmlRegisterType(uri, 1, 0, "Document"); 36 | qmlRegisterType(uri, 1, 0, "Canvas"); 37 | qmlRegisterType(uri, 1, 0, "LinkArea"); 38 | qmlRegisterType(uri, 1, 0, "Selection"); 39 | qmlRegisterType(uri, 1, 0, "Annotation"); 40 | qmlRegisterType(uri, 1, 0, "TextAnnotation"); 41 | qmlRegisterType(uri, 1, 0, "CaretAnnotation"); 42 | qmlRegisterType(uri, 1, 0, "HighlightAnnotation"); 43 | } 44 | -------------------------------------------------------------------------------- /pdf/sailfishofficepdfplugin.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef SAILFISHOFFICEPDFPLUGIN_H 20 | #define SAILFISHOFFICEPDFPLUGIN_H 21 | 22 | #include 23 | 24 | class SailfishOfficePDFPlugin : public QQmlExtensionPlugin 25 | { 26 | Q_OBJECT 27 | 28 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") 29 | 30 | public: 31 | explicit SailfishOfficePDFPlugin(QObject *parent = 0); 32 | 33 | virtual void registerTypes(const char *uri); 34 | }; 35 | 36 | #endif // SAILFISHOFFICEPDFPLUGIN_H 37 | -------------------------------------------------------------------------------- /plugin/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(PkgConfig REQUIRED) 2 | pkg_check_modules(SAILFISHSILICA sailfishsilica REQUIRED) 3 | pkg_check_modules(ICU icu-i18n REQUIRED) 4 | 5 | include_directories( 6 | ${SAILFISHSILICA_INCLUDE_DIRS} 7 | ${ICU_INCLUDE_DIRS} 8 | ) 9 | 10 | set(plugin_SRCS 11 | plaintextmodel.cpp 12 | sailfishofficeplugin.cpp 13 | ) 14 | 15 | add_library(sailfishofficeplugin MODULE ${plugin_SRCS}) 16 | qt5_use_modules(sailfishofficeplugin Widgets Quick) 17 | target_link_libraries(sailfishofficeplugin stdc++ ${QT_LIBRARIES} ${SAILFISHSILICA_LIBRARIES} ${ICU_LIBRARIES}) 18 | 19 | install(TARGETS sailfishofficeplugin DESTINATION ${CMAKE_INSTALL_LIBDIR}/qt5/qml/Sailfish/Office) 20 | 21 | install(FILES 22 | qmldir 23 | CalligraDocumentPage.qml 24 | ContextMenuHook.qml 25 | ControllerFlickable.qml 26 | DeleteButton.qml 27 | DetailsPage.qml 28 | DocumentFlickable.qml 29 | DocumentHeader.qml 30 | DocumentPage.qml 31 | FullscreenError.qml 32 | IndexButton.qml 33 | OverlayToolbar.qml 34 | PDFAnnotationEdit.qml 35 | PDFAnnotationNew.qml 36 | PDFContextMenuHighlight.qml 37 | PDFContextMenuLinks.qml 38 | PDFContextMenuText.qml 39 | PDFDetailsPage.qml 40 | PDFDocumentPage.qml 41 | PDFDocumentToCPage.qml 42 | PDFSelectionDrag.qml 43 | PDFSelectionHandle.qml 44 | PDFSelectionView.qml 45 | PDFStorage.js 46 | PDFView.qml 47 | PlainTextDocumentPage.qml 48 | PresentationPage.qml 49 | PresentationDetailsPage.qml 50 | PresentationThumbnailPage.qml 51 | SearchBarItem.qml 52 | ShareButton.qml 53 | SpreadsheetListPage.qml 54 | SpreadsheetPage.qml 55 | SpreadsheetDetailsPage.qml 56 | TextDetailsPage.qml 57 | TextDocumentPage.qml 58 | TextDocumentToCPage.qml 59 | ToolBar.qml 60 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/qt5/qml/Sailfish/Office 61 | ) 62 | -------------------------------------------------------------------------------- /plugin/CalligraDocumentPage.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 - 2019 Jolla Ltd. 3 | * Copyright (c) 2020 Open Mobile Platform LLC. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | import Sailfish.Silica.private 1.0 22 | import org.kde.calligra 1.0 as Calligra 23 | 24 | DocumentPage { 25 | id: page 26 | 27 | property alias document: doc 28 | property alias contents: contentsModel 29 | property int coverAlignment: Qt.AlignLeft | Qt.AlignTop 30 | property int coverFillMode: Image.PreserveAspectCrop 31 | 32 | function currentIndex() { 33 | // This is a function which can be shadowed because the currentIndex property doesn't 34 | // notify reliably and nothing needs to bind to it. 35 | return doc.currentIndex 36 | } 37 | 38 | backNavigation: !busy // During loading the UI is unresponsive, don't show page indicator as back-stepping is not possible 39 | busyIndicator._forceAnimation: busy // Start animation before the main thread gets blocked by loading 40 | icon: "image://theme/icon-m-file-formatted" 41 | busy: doc.status !== Calligra.DocumentStatus.Loaded 42 | && doc.status !== Calligra.DocumentStatus.Failed 43 | 44 | Timer { 45 | interval: 1 46 | running: status === PageStatus.Active 47 | // Delay loading the document until the page has been activated 48 | onTriggered: document.source = page.source 49 | } 50 | 51 | Timer { 52 | id: previewDelay 53 | 54 | interval: 100 55 | running: doc.status === Calligra.DocumentStatus.Loaded 56 | // We're not using a binding for the preview because calligra is sensitive to the order 57 | // of evaluation and by binding directly to the document status it's possible to attempt 58 | // to get a thumbnail from the contents model after the document has loaded but before the 59 | // model is populated. 60 | onTriggered: page.preview = previewComponent 61 | } 62 | 63 | Component { 64 | id: previewComponent 65 | 66 | Rectangle { 67 | id: preview 68 | 69 | color: page.backgroundColor 70 | 71 | Calligra.ImageDataItem { 72 | x: { 73 | if (page.coverAlignment & Qt.AlignHCenter) { 74 | return (preview.width - width) / 2 75 | } else if (page.coverAlignment & Qt.AlignRight) { 76 | return preview.width - width 77 | } else { 78 | return 0 79 | } 80 | } 81 | 82 | y: { 83 | if (page.coverAlignment & Qt.AlignVCenter) { 84 | return (preview.height - height) / 2 85 | } else if (page.coverAlignment & Qt.AlignBottom) { 86 | return preview.height - height 87 | } else { 88 | return 0 89 | } 90 | } 91 | 92 | width: { 93 | if (implicitHeight > 0 && page.coverFillMode === Image.PreserveAspectCrop) { 94 | return Math.max( 95 | preview.width, 96 | Math.round(implicitWidth * preview.height / implicitHeight)) 97 | } else if (implicitHeight > 0 && page.coverFillMode === Image.PreserveAspectFit) { 98 | return Math.min( 99 | preview.width, 100 | Math.round(implicitWidth * preview.height / implicitHeight)) 101 | } else { 102 | return preview.width 103 | } 104 | } 105 | 106 | height: implicitWidth > 0 107 | ? Math.round(implicitHeight * width / implicitWidth) 108 | : preview.height 109 | 110 | Component.onCompleted: { 111 | data = contentsModel.thumbnail(page.currentIndex(), preview.height) 112 | } 113 | } 114 | } 115 | } 116 | 117 | Calligra.ContentsModel { 118 | id: contentsModel 119 | 120 | document: doc 121 | thumbnailSize: Theme.coverSizeLarge 122 | } 123 | 124 | Calligra.Document { 125 | id: doc 126 | 127 | readonly property bool failure: status === Calligra.DocumentStatus.Failed 128 | readOnly: true 129 | onStatusChanged: { 130 | if (status === Calligra.DocumentStatus.Failed) { 131 | errorLoader.setSource(Qt.resolvedUrl("FullscreenError.qml"), { error: lastError }) 132 | } 133 | } 134 | } 135 | 136 | Loader { 137 | id: errorLoader 138 | anchors.fill: parent 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /plugin/ContextMenuHook.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Caliste Damien. 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | 22 | Item { 23 | id: hook 24 | 25 | property bool active: _menu ? _menu.active : false 26 | property alias backgroundColor: background.color 27 | property alias backgroundOpacity: background.opacity 28 | 29 | property real _flickableContentHeight 30 | property real _flickableContentYAtOpen 31 | property bool _opened: _menu ? _menu._open : false 32 | 33 | property int _hookHeight 34 | property var _menu 35 | 36 | // Used to emulate the MouseArea that trigger a ContextMenu 37 | property bool pressed: true 38 | property bool preventStealing 39 | signal positionChanged(point mouse) 40 | signal released(bool mouse) 41 | 42 | function setTarget(targetY, targetHeight) { 43 | y = targetY 44 | _hookHeight = targetHeight 45 | } 46 | 47 | function showMenu(menu) { 48 | _menu = menu 49 | menu.open(hook) 50 | _flickableContentHeight = _menu._flickable.contentHeight 51 | } 52 | 53 | // Ensure that flickable position is restored after context menu 54 | // has been closed. We cannot trust the value that will be restored 55 | // automatically when the state of the menu changes because the 56 | // contentHeight of the flickable may have changed in-between due to 57 | // device rotation for instance. 58 | on_OpenedChanged: { 59 | if (!_opened) { 60 | // Limit the flickable going back to previous y position 61 | // if the device has been rotated and the link would be sent 62 | // out of screen. 63 | _menu._flickable.contentY = 64 | Math.max(_flickableContentYAtOpen, 65 | hook.y + _hookHeight + Theme.paddingSmall - _menu._flickable.height) 66 | // Reset menu flickable after menu is closed to avoid initialisation 67 | // issues next time showMenu() is called. 68 | _menu._flickable = null 69 | } else { 70 | _flickableContentYAtOpen = _menu._flickable.contentY 71 | } 72 | } 73 | Connections { 74 | target: _menu && _menu._flickable ? _menu._flickable : null 75 | onContentHeightChanged: { 76 | // Update the initial opening position with the zoom factor 77 | // if the contentHeight is changed while menu was displayed. 78 | _flickableContentYAtOpen *= _menu._flickable.contentHeight / _flickableContentHeight 79 | _flickableContentHeight = _menu._flickable.contentHeight 80 | } 81 | } 82 | 83 | width: _menu && _menu._flickable ? _menu._flickable.width : 0 84 | x: _menu && _menu._flickable ? _menu._flickable.contentX : 0 85 | height: _hookHeight + (_menu ? Theme.paddingSmall + _menu.height : 0.) 86 | 87 | Rectangle { 88 | id: background 89 | 90 | parent: _menu ? _menu : null 91 | anchors.fill: parent ? parent : undefined 92 | color: Theme.highlightDimmerColor 93 | opacity: 0.91 94 | z: -1 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /plugin/ControllerFlickable.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Jolla Ltd. 3 | * Contact: Joona Petrell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | 22 | DocumentFlickable { 23 | id: flickable 24 | 25 | property QtObject controller 26 | 27 | pinchArea.onPinchUpdated: { 28 | var oldWidth = contentWidth 29 | var oldHeight = contentHeight 30 | var oldZoom = controller.zoom 31 | controller.zoomAroundPoint(controller.zoom * (pinch.scale - pinch.previousScale), 0, 0) 32 | 33 | if (controller.zoom === oldZoom) return 34 | 35 | var multiplier = (1.0 + pinch.scale - pinch.previousScale) 36 | var newWidth = multiplier * oldWidth 37 | var newHeight = multiplier * oldHeight 38 | 39 | contentX += pinch.previousCenter.x - pinch.center.x 40 | contentY += pinch.previousCenter.y - pinch.center.y 41 | 42 | // zoom about center 43 | if (newWidth > width) 44 | contentX -= (oldWidth - newWidth)/(oldWidth/pinch.previousCenter.x) 45 | if (newHeight > height) 46 | contentY -= (oldHeight - newHeight)/(oldHeight/pinch.previousCenter.y) 47 | } 48 | 49 | function zoomOut() { 50 | var scale = controller.zoom / controller.minimumZoom 51 | zoomOutContentYAnimation.to = Math.max(-topMargin, 52 | Math.min(flickable.contentHeight - flickable.height, 53 | (flickable.contentY + flickable.height/2) / scale - flickable.height/2)) 54 | zoomOutAnimation.start() 55 | } 56 | 57 | ParallelAnimation { 58 | id: zoomOutAnimation 59 | 60 | onStopped: flickable.returnToBounds() 61 | NumberAnimation { 62 | target: controller 63 | property: "zoom" 64 | to: controller.minimumZoom 65 | easing.type: Easing.InOutQuad 66 | duration: 200 67 | } 68 | NumberAnimation { 69 | target: flickable 70 | properties: "contentX" 71 | to: 0 72 | easing.type: Easing.InOutQuad 73 | duration: 200 74 | } 75 | NumberAnimation { 76 | id: zoomOutContentYAnimation 77 | 78 | target: flickable 79 | properties: "contentY" 80 | easing.type: Easing.InOutQuad 81 | duration: 200 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /plugin/DeleteButton.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Jolla Ltd. 3 | * Contact: Joona Petrell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | 22 | IconButton { 23 | property DocumentPage page 24 | readonly property url source: page.source 25 | 26 | onClicked: window._mainPage.deleteSource(page.source) 27 | 28 | icon.source: "image://theme/icon-m-delete" 29 | anchors.verticalCenter: parent.verticalCenter 30 | visible: page.source != "" 31 | } 32 | -------------------------------------------------------------------------------- /plugin/DetailsPage.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | import Sailfish.Office 1.0 22 | import Nemo.FileManager 1.0 23 | 24 | Page { 25 | id: page 26 | 27 | property QtObject document 28 | property url source 29 | property string mimeType 30 | default property alias children: contentColumn.data 31 | 32 | FileInfo { 33 | id: info 34 | url: page.source 35 | } 36 | 37 | SilicaFlickable { 38 | id: flickable 39 | 40 | anchors.fill: parent 41 | contentHeight: contentColumn.height + Theme.paddingLarge 42 | 43 | Column { 44 | id: contentColumn 45 | 46 | width: parent.width 47 | 48 | PageHeader { 49 | //: Details page title 50 | //% "Details" 51 | title: qsTrId("sailfish-office-he-details") 52 | } 53 | 54 | DetailItem { 55 | //: File path detail of the document 56 | //% "File path" 57 | label: qsTrId("sailfish-office-la-filepath") 58 | value: info.file 59 | alignment: Qt.AlignLeft 60 | } 61 | 62 | DetailItem { 63 | //: File size detail of the document 64 | //% "Size" 65 | label: qsTrId("sailfish-office-la-filesize") 66 | value: Format.formatFileSize(info.size) 67 | alignment: Qt.AlignLeft 68 | } 69 | 70 | DetailItem { 71 | //: File type detail of the document 72 | //% "Type" 73 | label: qsTrId("sailfish-office-la-filetype") 74 | value: info.mimeTypeComment 75 | alignment: Qt.AlignLeft 76 | } 77 | 78 | DetailItem { 79 | //: Last modified date of the document 80 | //% "Last modified" 81 | label: qsTrId("sailfish-office-la-lastmodified") 82 | value: Format.formatDate(info.lastModified, Format.DateFull) 83 | alignment: Qt.AlignLeft 84 | } 85 | } 86 | 87 | VerticalScrollDecorator {} 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /plugin/DocumentFlickable.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Jolla Ltd. 3 | * Contact: Joona Petrell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | import Sailfish.Silica.private 1.0 22 | 23 | SilicaFlickable { 24 | id: flickable 25 | 26 | readonly property bool zoomed: contentWidth > width 27 | property alias pinchArea: pinchArea 28 | default property alias foreground: pinchArea.data 29 | 30 | // Make sure that _noGrabbing will be reset back to false (JB#42531) 31 | Component.onDestruction: if (!visible) pageStack._noGrabbing = false 32 | 33 | // Override SilicaFlickable's pressDelay because otherwise it will 34 | // block touch events going to PinchArea in certain cases. 35 | pressDelay: 0 36 | interactive: !dragDetector.horizontalDragUnused 37 | ScrollDecorator { color: Theme.highlightDimmerColor } 38 | 39 | Binding { // Allow page navigation when panning the document near the top or bottom edge 40 | target: pageStack 41 | when: flickable.visible 42 | property: "_noGrabbing" 43 | value: dragDetector.horizontalDragUnused 44 | } 45 | 46 | Connections { 47 | target: pageStack 48 | onDragInProgressChanged: { 49 | if (pageStack.dragInProgress && pageStack._noGrabbing) { 50 | pageStack._grabMouse() 51 | } 52 | } 53 | } 54 | 55 | DragDetectorItem { 56 | id: dragDetector 57 | 58 | flickable: flickable 59 | anchors.fill: parent 60 | PinchArea { 61 | id: pinchArea 62 | 63 | onPinchFinished: flickable.returnToBounds() 64 | anchors.fill: parent 65 | enabled: !pageStack.dragInProgress 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /plugin/DocumentHeader.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Jolla Ltd. 3 | * Contact: Joona Petrell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | 22 | MouseArea { 23 | property string detailsPage: "DetailsPage.qml" 24 | property int indexCount 25 | property DocumentPage page 26 | property color color: Theme.primaryColor 27 | readonly property bool down: pressed && containsMouse 28 | 29 | onClicked: pageStack.animatorPush(Qt.resolvedUrl(detailsPage), { 30 | document: page.document, 31 | source: page.source, 32 | mimeType: page.mimeType 33 | }) 34 | 35 | width: parent.width 36 | height: pageHeader.height 37 | enabled: !page.busy && !page.error 38 | 39 | PageHeader { 40 | id: pageHeader 41 | 42 | title: page.title 43 | titleColor: parent.down ? Theme.highlightColor : parent.color 44 | rightMargin: Theme.horizontalPageMargin + detailsImage.width + Theme.paddingMedium 45 | } 46 | 47 | HighlightImage { 48 | id: detailsImage 49 | 50 | color: parent.color 51 | source: "image://theme/icon-m-about" 52 | highlighted: parent.down 53 | Behavior on opacity { FadeAnimator {}} 54 | opacity: parent.enabled ? 1.0 : Theme.opacityHigh 55 | anchors { 56 | right: parent.right 57 | rightMargin: Theme.horizontalPageMargin 58 | } 59 | y: pageHeader.topMargin + pageHeader.titleHeight / 2 - height / 2 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /plugin/DocumentPage.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | 22 | Page { 23 | id: page 24 | 25 | property string title 26 | property url source 27 | property bool error 28 | property string mimeType 29 | property alias busy: busyIndicator.running 30 | property QtObject document 31 | property QtObject provider 32 | property Component preview: defaultPreview 33 | property alias placeholderPreview: defaultPreview 34 | property url icon: "image://theme/icon-m-file-other" 35 | property alias busyIndicator: busyIndicator 36 | 37 | allowedOrientations: Orientation.All 38 | clip: status !== PageStatus.Active || pageStack.dragInProgress 39 | 40 | PageBusyIndicator { 41 | id: busyIndicator 42 | z: 101 43 | } 44 | 45 | Component { 46 | id: defaultPreview 47 | 48 | CoverPlaceholder { 49 | icon.source: page.icon 50 | text: page.title 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /plugin/FullscreenError.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Jolla Ltd. 3 | * Contact: Pekka Vuorela 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.6 20 | import Sailfish.Silica 1.0 21 | 22 | TouchBlocker { 23 | id: root 24 | 25 | property string error 26 | property string localizedError: { 27 | // Match hard-coded error string from calligra / KoDocument.cpp 28 | // Ideally there would be Calligra localization available, but it 29 | // a) is stored in separate kde subversion repository together with all kinds of kde things 30 | // b) weights some 2-3MB per language 31 | // So since this is should be the only place really showing Calligra strings, let's just 32 | // hack a separate translation for the few known cases. Likely even out of these many won't be 33 | // ever shown to the user. 34 | var re = new RegExp("Could not open file://(.*)\\.\\nReason: (.*)\\.\\n(.*)") 35 | var matches = re.exec(error) 36 | if (matches && matches.length == 4) { 37 | //% "Could not open file:" 38 | return qsTrId("sailfish-calligra_open_error") + "\n" + matches[1] 39 | + "\n\n" + localizeOpenError(matches[2]) 40 | } else { 41 | console.log("Unable to parse Calligra error string", error) 42 | return error 43 | } 44 | } 45 | 46 | anchors.fill: parent 47 | 48 | function localizeOpenError(error) { 49 | switch(error) { 50 | case "Could not create the filter plugin": 51 | //% "Could not create the filter plugin" 52 | return qsTrId("office_calligra_error-could_not_create_filter_plugin") 53 | case "Could not create the output document": 54 | //% "Could not create the output document" 55 | return qsTrId("office_calligra_error-could_not_create_output_document") 56 | case "File not found": 57 | //% "File not found" 58 | return qsTrId("office_calligra_error-file_not_found") 59 | case "Cannot create storage": 60 | //% "Cannot create storage" 61 | return qsTrId("office_calligra_error-cannot_create_storage") 62 | case "Bad MIME type": 63 | //% "Bad MIME type" 64 | return qsTrId("office_calligra_error-bad_mime_type") 65 | case "Error in embedded document": 66 | //% "Error in embedded document" 67 | return qsTrId("office_calligra_error-error_in_embedded_document") 68 | case "Format not recognized": 69 | //% "Format not recognized" 70 | return qsTrId("office_calligra_error-format_not_recognized") 71 | case "Not implemented": 72 | //% "Not implemented" 73 | return qsTrId("office_calligra_error-not_implemented") 74 | case "Parsing error": 75 | //% "Parsing error" 76 | return qsTrId("office_calligra_error-parsing_error") 77 | case "Document is password protected": 78 | //% "Document is password protected" 79 | return qsTrId("office_calligra_error-password_protected_file") 80 | case "Invalid file format": 81 | //% "Invalid file format" 82 | return qsTrId("office_calligra_error-invalid_file_format") 83 | case "Internal error": 84 | //% "Internal error" 85 | return qsTrId("office_calligra_error-internal_error") 86 | case "Out of memory": 87 | //% "Out of memory" 88 | return qsTrId("office_calligra_error-out_of_memory") 89 | case "Empty Filter Plugin": 90 | //% "Empty Filter Plugin" 91 | return qsTrId("office_calligra_error-empty_filter_plugin") 92 | case "Trying to load into the wrong kind of document": 93 | //% "Trying to load into the wrong kind of document" 94 | return qsTrId("office_calligra_error-wrong_kind_of_document") 95 | case "Failed to download remote file": 96 | //% "Failed to download remote file" 97 | return qsTrId("office_calligra_error-faile_to_download_remote_file") 98 | case "Unknown error": 99 | //% "Unknown error" 100 | return qsTrId("office_calligra_error-unknown") 101 | } 102 | 103 | return error 104 | } 105 | 106 | Rectangle { 107 | anchors.fill: parent 108 | opacity: Theme.opacityLow 109 | color: Theme.highlightDimmerColor 110 | } 111 | 112 | Column { 113 | x: Theme.horizontalPageMargin 114 | width: parent.width - 2*x 115 | spacing: Theme.paddingMedium 116 | anchors.verticalCenter: parent.verticalCenter 117 | 118 | HighlightImage { 119 | id: warningIcon 120 | 121 | anchors.horizontalCenter: parent.horizontalCenter 122 | source: "image://theme/icon-l-attention" 123 | highlighted: true 124 | } 125 | 126 | Label { 127 | width: parent.width 128 | text: localizedError 129 | wrapMode: Text.Wrap 130 | color: Theme.highlightColor 131 | horizontalAlignment: Text.AlignHCenter 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /plugin/IndexButton.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Jolla Ltd. 3 | * Contact: Joona Petrell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | 22 | MouseArea { 23 | id: root 24 | 25 | property bool allowed: true 26 | property color color: Theme.primaryColor 27 | property int index 28 | property int count 29 | readonly property bool highlighted: pressed && containsMouse 30 | 31 | enabled: count > 1 && allowed 32 | opacity: count > 0 && allowed ? (count > 1 ? 1.0 : Theme.opacityHigh) : 0.0 33 | width: Math.min(Theme.itemSizeMedium, label.implicitWidth + Theme.paddingSmall) 34 | height: parent.height 35 | 36 | Label { 37 | id: label 38 | 39 | anchors.centerIn: parent 40 | width: parent.width - Theme.paddingSmall 41 | fontSizeMode: Text.HorizontalFit 42 | color: root.highlighted ? Theme.highlightColor : parent.color 43 | text: index + " | " + count 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /plugin/OverlayToolbar.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Jolla Ltd. 3 | * Contact: Joona Petrell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | import Sailfish.Silica.private 1.0 22 | 23 | FadeGradient { 24 | default property alias buttons: row.data 25 | 26 | height: row.height + 2 * row.anchors.bottomMargin 27 | width: parent.width 28 | anchors.bottom: parent.bottom 29 | 30 | Row { 31 | id: row 32 | 33 | anchors { 34 | bottom: parent.bottom 35 | bottomMargin: Theme.paddingLarge 36 | horizontalCenter: parent.horizontalCenter 37 | } 38 | spacing: Theme.paddingLarge 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /plugin/PDFAnnotationEdit.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Caliste Damien. 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | import Sailfish.Office.PDF 1.0 as PDF 22 | 23 | Page { 24 | id: root 25 | 26 | property variant annotation 27 | 28 | property bool _isText: annotation && (annotation.type == PDF.Annotation.Text 29 | || annotation.type == PDF.Annotation.Caret) 30 | 31 | signal remove() 32 | 33 | SilicaFlickable { 34 | id: flickable 35 | 36 | anchors.fill: parent 37 | contentHeight: content.height 38 | 39 | PullDownMenu { 40 | MenuItem { 41 | //% "Delete" 42 | text: qsTrId("sailfish-office-mi-delete-annotation") 43 | onClicked: root.remove() 44 | } 45 | } 46 | 47 | Column { 48 | id: content 49 | 50 | width: parent.width 51 | PageHeader { 52 | id: pageHeader 53 | 54 | title: annotation && annotation.author != "" 55 | ? annotation.author 56 | : (_isText 57 | //% "Note" 58 | ? qsTrId("sailfish-office-hd-text-annotation") 59 | //% "Comment" 60 | : qsTrId("sailfish-office-hd-comment-annotation")) 61 | } 62 | TextArea { 63 | width: parent.width 64 | height: Math.max(flickable.height - pageHeader.height, implicitHeight) 65 | background: null 66 | focus: false 67 | text: annotation ? annotation.contents : "" 68 | placeholderText: _isText 69 | ? //% "Write a note…" 70 | qsTrId("sailfish-office-ta-text-annotation-edit") 71 | : //% "Write a comment…" 72 | qsTrId("sailfish-office-ta-comment-annotation-edit") 73 | onTextChanged: { 74 | if (annotation) { 75 | annotation.contents = text 76 | } 77 | } 78 | } 79 | } 80 | VerticalScrollDecorator { flickable: flickable } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /plugin/PDFAnnotationNew.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Caliste Damien. 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | 22 | Dialog { 23 | id: root 24 | 25 | property alias text: areaContents.text 26 | property bool isTextAnnotation 27 | 28 | SilicaFlickable { 29 | id: flickable 30 | 31 | anchors.fill: parent 32 | contentHeight: content.height 33 | 34 | Column { 35 | id: content 36 | 37 | width: parent.width 38 | DialogHeader { 39 | id: dialogHeader 40 | 41 | //% "Save" 42 | acceptText: qsTrId("sailfish-office-he-txt-anno-save") 43 | //% "Cancel" 44 | cancelText: qsTrId("sailfish-office-he-txt-anno-cancel") 45 | } 46 | TextArea { 47 | id: areaContents 48 | 49 | width: parent.width 50 | height: Math.max(flickable.height - dialogHeader.height, implicitHeight) 51 | placeholderText: isTextAnnotation 52 | ? //% "Write a note…" 53 | qsTrId("sailfish-office-ta-text-annotation") 54 | : //% "Write a comment…" 55 | qsTrId("sailfish-office-ta-comment-annotation") 56 | background: null 57 | focus: true 58 | } 59 | } 60 | VerticalScrollDecorator { flickable: flickable } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /plugin/PDFContextMenuHighlight.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Caliste Damien. 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | import Sailfish.Office.PDF 1.0 22 | 23 | ContextMenu { 24 | id: contextMenuHighlight 25 | 26 | property Annotation annotation 27 | 28 | InfoLabel { 29 | id: infoContents 30 | 31 | visible: infoContents.text != "" 32 | width: parent.width 33 | height: implicitHeight + 2 * Theme.paddingSmall 34 | font.pixelSize: Theme.fontSizeSmall 35 | verticalAlignment: Text.AlignVCenter 36 | wrapMode: Text.Wrap 37 | elide: Text.ElideRight 38 | maximumLineCount: 2 39 | color: Theme.highlightColor 40 | opacity: .6 41 | text: { 42 | if (contextMenuHighlight.annotation 43 | && contextMenuHighlight.annotation.contents != "") { 44 | return (contextMenuHighlight.annotation.author != "" 45 | ? "(" + contextMenuHighlight.annotation.author + ") " : "") 46 | + contextMenuHighlight.annotation.contents 47 | } 48 | 49 | return "" 50 | } 51 | } 52 | Row { 53 | height: Theme.itemSizeExtraSmall 54 | Repeater { 55 | id: colors 56 | 57 | model: ["#db431c", "#ffff00", "#8afa72", "#00ffff", 58 | "#3828f9", "#a328c7", "#ffffff", "#989898", 59 | "#000000"] 60 | delegate: Rectangle { 61 | width: contextMenuHighlight.width / colors.model.length 62 | height: parent.height 63 | color: modelData 64 | MouseArea { 65 | anchors.fill: parent 66 | onClicked: { 67 | contextMenuHighlight.close() 68 | contextMenuHighlight.annotation.color = color 69 | highlightColorConfig.value = modelData 70 | } 71 | } 72 | } 73 | } 74 | } 75 | Row { 76 | height: Theme.itemSizeExtraSmall 77 | Repeater { 78 | id: styles 79 | model: [{"style": HighlightAnnotation.Highlight, 80 | "label": "abc"}, 81 | {"style": HighlightAnnotation.Squiggly, 82 | "label": "a̰b̰c̰"}, 83 | {"style": HighlightAnnotation.Underline, 84 | "label": "abc"}, 85 | {"style": HighlightAnnotation.StrikeOut, 86 | "label": "abc"}] 87 | delegate: BackgroundItem { 88 | id: bgStyle 89 | 90 | width: contextMenuHighlight.width / styles.model.length 91 | height: parent.height 92 | onClicked: { 93 | contextMenuHighlight.close() 94 | contextMenuHighlight.annotation.style = modelData["style"] 95 | highlightStyleConfig.value = highlightStyleConfig.fromEnum(modelData["style"]) 96 | } 97 | Label { 98 | anchors.centerIn: parent 99 | text: modelData["label"] 100 | textFormat: Text.RichText 101 | color: bgStyle.highlighted 102 | || (contextMenuHighlight.annotation 103 | && contextMenuHighlight.annotation.style == modelData["style"]) 104 | ? Theme.highlightColor : Theme.primaryColor 105 | Rectangle { 106 | visible: modelData["style"] == HighlightAnnotation.Highlight 107 | anchors.fill: parent 108 | color: bgStyle.highlighted ? Theme.highlightColor : Theme.primaryColor 109 | opacity: Theme.opacityLow 110 | z: -1 111 | } 112 | } 113 | } 114 | } 115 | } 116 | MenuItem { 117 | visible: contextMenuHighlight.annotation 118 | text: contextMenuHighlight.annotation 119 | && contextMenuHighlight.annotation.contents == "" 120 | //% "Add a comment" 121 | ? qsTrId("sailfish-office-me-pdf-hl-anno-comment") 122 | //% "Edit the comment" 123 | : qsTrId("sailfish-office-me-pdf-hl-anno-comment-edit") 124 | onClicked: { 125 | if (contextMenuHighlight.annotation.contents == "") { 126 | doc.create(contextMenuHighlight.annotation) 127 | } else { 128 | doc.edit(contextMenuHighlight.annotation) 129 | } 130 | } 131 | } 132 | MenuItem { 133 | //% "Clear" 134 | text: qsTrId("sailfish-office-me-pdf-hl-anno-clear") 135 | onClicked: contextMenuHighlight.annotation.remove() 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /plugin/PDFContextMenuLinks.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Caliste Damien. 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | 22 | ContextMenu { 23 | id: contextMenuLinks 24 | 25 | property alias url: linkTarget.text 26 | 27 | InfoLabel { 28 | id: linkTarget 29 | font.pixelSize: Theme.fontSizeSmall 30 | wrapMode: Text.Wrap 31 | elide: Text.ElideRight 32 | maximumLineCount: 4 33 | color: Theme.highlightColor 34 | opacity: .6 35 | } 36 | MenuItem { 37 | text: (contextMenuLinks.url.indexOf("http:") === 0 38 | || contextMenuLinks.url.indexOf("https:") === 0) 39 | //% "Open in browser" 40 | ? qsTrId("sailfish-office-me-pdf-open-browser") 41 | //% "Open in external application" 42 | : qsTrId("sailfish-office-me-pdf-open-external") 43 | onClicked: Qt.openUrlExternally(contextMenuLinks.url) 44 | } 45 | MenuItem { 46 | //% "Copy to clipboard" 47 | text: qsTrId("sailfish-office-me-pdf-copy-link") 48 | onClicked: Clipboard.text = contextMenuLinks.url 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /plugin/PDFContextMenuText.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Caliste Damien. 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | import Sailfish.Office.PDF 1.0 22 | 23 | ContextMenu { 24 | id: contextMenuText 25 | 26 | property Annotation annotation 27 | property point at 28 | 29 | MenuItem { 30 | visible: !contextMenuText.annotation 31 | //% "Add note" 32 | text: qsTrId("sailfish-office-me-pdf-txt-anno-add") 33 | onClicked: { 34 | var annotation = textComponent.createObject(contextMenuText) 35 | annotation.color = "#202020" 36 | doc.create(annotation, 37 | function() { 38 | var at = view.getPositionAt(contextMenuText.at) 39 | annotation.attachAt(doc, at[0], at[2], at[1]) 40 | }) 41 | } 42 | Component { 43 | id: textComponent 44 | TextAnnotation { } 45 | } 46 | } 47 | MenuItem { 48 | visible: contextMenuText.annotation 49 | //% "Edit" 50 | text: qsTrId("sailfish-office-me-pdf-txt-anno-edit") 51 | onClicked: doc.edit(contextMenuText.annotation) 52 | } 53 | MenuItem { 54 | visible: contextMenuText.annotation 55 | //% "Delete" 56 | text: qsTrId("sailfish-office-me-pdf-txt-anno-clear") 57 | onClicked: contextMenuText.annotation.remove() 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /plugin/PDFDetailsPage.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2024 Damien Caliste 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | import Sailfish.Office 1.0 22 | 23 | DetailsPage { 24 | readonly property bool storePassword: document.password.length > 0 25 | 26 | DetailItem { 27 | //: Page count of the PDF document 28 | //% "Page Count" 29 | label: qsTrId("sailfish-office-la-pdf-pagecount") 30 | value: document.pageCount 31 | alignment: Qt.AlignLeft 32 | visible: !document.locked 33 | } 34 | SectionHeader { 35 | visible: document.passwordProtected 36 | //% "Read protection" 37 | text: qsTrId("sailfish-office-la-pdf-readprotection") 38 | } 39 | Label { 40 | visible: document.passwordProtected 41 | width: parent.width - 2*x 42 | x: Theme.horizontalPageMargin 43 | //% "This document is protected by a password" 44 | text: qsTrId("sailfish-office-la-pdf-passwordprotected") 45 | color: palette.secondaryHighlightColor 46 | font.pixelSize: Theme.fontSizeSmall 47 | textFormat: Text.PlainText 48 | wrapMode: Text.Wrap 49 | } 50 | Item { 51 | visible: storePassword 52 | width: parent.width 53 | height: Theme.paddingLarge 54 | } 55 | PasswordField { 56 | opacity: storePassword ? 1 : 0 57 | Behavior on opacity {FadeAnimator {}} 58 | x: Theme.horizontalPageMargin 59 | width: parent.width - 2*x 60 | text: document.password 61 | readOnly: true 62 | } 63 | Item { 64 | visible: storePassword 65 | width: parent.width 66 | height: Theme.paddingLarge 67 | } 68 | Button { 69 | opacity: storePassword ? 1 : 0 70 | Behavior on opacity {FadeAnimator {}} 71 | anchors.horizontalCenter: parent.horizontalCenter 72 | //% "Clear stored password" 73 | text: qsTrId("sailfish-office-la-pdf-clearpassword") 74 | onClicked: document.clearCachedPassword() 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /plugin/PDFDocumentToCPage.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | 22 | Page { 23 | id: page 24 | 25 | property int pageCount 26 | property alias tocModel: tocListView.model 27 | 28 | signal pageSelected(int pageNumber) 29 | 30 | allowedOrientations: Orientation.All 31 | 32 | onTocModelChanged: tocModel.requestToc() 33 | 34 | SilicaListView { 35 | id: tocListView 36 | 37 | width: parent.width 38 | height: parent.height - gotoPage.height 39 | clip: true 40 | 41 | //: Page with PDF index 42 | //% "Index" 43 | header: PageHeader { title: qsTrId("sailfish-office-he-pdf_index") } 44 | 45 | ViewPlaceholder { 46 | id: placeholder 47 | enabled: tocListView.model 48 | && tocListView.model.ready 49 | && tocListView.model.count == 0 50 | //% "Document has no table of content" 51 | text: qsTrId("sailfish-office-me-no-toc") 52 | } 53 | PageBusyIndicator { 54 | running: !tocListView.model || !tocListView.model.ready 55 | z: 1 56 | } 57 | 58 | delegate: BackgroundItem { 59 | id: bg 60 | 61 | Label { 62 | anchors { 63 | left: parent.left 64 | leftMargin: Theme.horizontalPageMargin + (Theme.paddingLarge * model.level) 65 | right: pageNumberLabel.left 66 | rightMargin: Theme.paddingLarge 67 | verticalCenter: parent.verticalCenter 68 | } 69 | elide: Text.ElideRight 70 | text: (model.title === undefined) ? "" : model.title 71 | color: bg.highlighted ? Theme.highlightColor : Theme.primaryColor 72 | truncationMode: TruncationMode.Fade 73 | } 74 | Label { 75 | id: pageNumberLabel 76 | 77 | anchors { 78 | right: parent.right 79 | rightMargin: Theme.horizontalPageMargin 80 | verticalCenter: parent.verticalCenter 81 | } 82 | text: (model.pageNumber === undefined) ? "" : model.pageNumber 83 | color: bg.highlighted ? Theme.highlightColor : Theme.primaryColor 84 | } 85 | 86 | onClicked: { 87 | page.pageSelected(model.pageNumber - 1) 88 | pageStack.navigateBack(PageStackAction.Animated) 89 | } 90 | } 91 | 92 | VerticalScrollDecorator { } 93 | } 94 | 95 | PanelBackground { 96 | id: gotoPage 97 | 98 | anchors.top: tocListView.bottom 99 | width: parent.width 100 | height: Theme.itemSizeMedium 101 | 102 | TextField { 103 | property IntValidator _validator: IntValidator {bottom: 1; top: page.pageCount } 104 | 105 | x: Theme.paddingLarge 106 | width: parent.width - Theme.paddingMedium - Theme.paddingLarge 107 | anchors.verticalCenter: parent.verticalCenter 108 | 109 | //% "Go to page" 110 | placeholderText: qsTrId("sailfish-office-lb-goto-page") 111 | //% "document has %n pages" 112 | label: qsTrId("sailfish-office-lb-%n-pages", page.pageCount) 113 | 114 | // We enter page numbers 115 | validator: text.length ? _validator : null 116 | inputMethodHints: Qt.ImhDigitsOnly 117 | EnterKey.enabled: text.length > 0 && acceptableInput 118 | EnterKey.iconSource: "image://theme/icon-m-enter-accept" 119 | EnterKey.onClicked: { 120 | page.pageSelected(Math.round(text) - 1) 121 | pageStack.navigateBack(PageStackAction.Animated) 122 | } 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /plugin/PDFSelectionDrag.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Caliste Damien. 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | 22 | MouseArea { 23 | id: root 24 | 25 | property point handle 26 | property Item flickable 27 | 28 | property real _contentY0 29 | property real _contentY: flickable ? flickable.contentY : 0.0 30 | property real _dragX0 31 | property real _dragY0 32 | property real dragX 33 | property real dragY 34 | 35 | signal dragged(point at) 36 | 37 | function reset() { 38 | dragX = 0 39 | dragY = 0 40 | } 41 | 42 | width: Theme.itemSizeSmall 43 | height: width 44 | 45 | enabled: visible 46 | preventStealing: true 47 | onPressed: { 48 | _dragX0 = mouseX 49 | _dragY0 = mouseY 50 | _contentY0 = (flickable ? flickable.contentY : 0.0) 51 | } 52 | onCanceled: reset() 53 | onReleased: reset() 54 | 55 | Binding { 56 | target: root 57 | property: "x" 58 | value: root.handle.x - root.width / 2 59 | when: !root.pressed 60 | } 61 | Binding { 62 | target: root 63 | property: "y" 64 | value: root.handle.y - root.height / 2 65 | when: !root.pressed 66 | } 67 | onMouseXChanged: dragX = pressed ? mouseX - _dragX0 : 0. 68 | onMouseYChanged: dragY = pressed ? mouseY - _dragY0 - _contentY + _contentY0 : 0. 69 | onDragXChanged: { 70 | if (pressed) { 71 | root.dragged(Qt.point(x + width / 2 + dragX, y + height / 2 + dragY)) 72 | } 73 | } 74 | onDragYChanged: { 75 | if (pressed) { 76 | root.dragged(Qt.point(x + width / 2 + dragX, y + height / 2 + dragY)) 77 | } 78 | } 79 | 80 | Rectangle { 81 | x: (root.width - width) / 2 + dragX 82 | y: (root.height - height) / 2 + dragY 83 | width: Theme.iconSizeSmall / 2 * 1.414 84 | height: width 85 | visible: opacity > 0. 86 | opacity: root.pressed ? 0.25 : 0. 87 | Behavior on opacity { FadeAnimator {} } 88 | radius: width / 2 89 | color: Qt.rgba(1. - Theme.highlightDimmerColor.r, 90 | 1. - Theme.highlightDimmerColor.g, 91 | 1. - Theme.highlightDimmerColor.b, 92 | 1.) 93 | Rectangle { 94 | anchors.centerIn: parent 95 | color: Theme.highlightDimmerColor 96 | width: Theme.iconSizeSmall / 2 97 | height: width 98 | radius: width / 2 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /plugin/PDFSelectionHandle.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Caliste Damien. 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.6 20 | import Sailfish.Silica 1.0 21 | 22 | Rectangle { 23 | id: root 24 | 25 | property alias attachX: translationMove.from 26 | property point handle 27 | property bool dragged 28 | property real dragHeight 29 | 30 | x: handle.x - width / 2 31 | y: handle.y - height / 2 32 | opacity: 0.5 33 | color: Theme.highlightDimmerColor 34 | width: Math.round(Theme.iconSizeSmall / 4) * 2 // ensure even number 35 | height: width 36 | radius: width / 2 37 | 38 | states: State { 39 | when: dragged 40 | name: "dragged" 41 | PropertyChanges { 42 | target: root 43 | width: Theme.paddingSmall / 2 44 | height: dragHeight 45 | radius: 0 46 | } 47 | } 48 | 49 | transitions: Transition { 50 | to: "dragged" 51 | reversible: true 52 | SequentialAnimation { 53 | NumberAnimation { property: "width"; duration: 100 } 54 | PropertyAction { property: "radius" } 55 | NumberAnimation { property: "height"; duration: 100 } 56 | } 57 | } 58 | 59 | ParallelAnimation { 60 | id: appearingMove 61 | 62 | FadeAnimator { 63 | target: root 64 | from: 0.0 65 | to: 0.5 66 | } 67 | XAnimator { 68 | id: translationMove 69 | 70 | duration: 200 71 | easing.type: Easing.InOutQuad 72 | target: root 73 | to: root.x 74 | } 75 | } 76 | 77 | onVisibleChanged: { 78 | if (visible) { 79 | appearingMove.start() 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /plugin/PDFSelectionView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Caliste Damien. 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | 22 | Repeater { 23 | id: root 24 | 25 | property Item flickable 26 | property bool draggable: true 27 | property alias dragHandle1: handle1.dragged 28 | property alias dragHandle2: handle2.dragged 29 | 30 | visible: (model !== undefined && model.count > 0) 31 | 32 | delegate: Rectangle { 33 | opacity: 0.5 34 | color: Theme.highlightColor 35 | x: rect.x 36 | y: rect.y 37 | width: rect.width 38 | height: rect.height 39 | } 40 | 41 | children: [ 42 | PDFSelectionHandle { 43 | id: handle1 44 | 45 | visible: root.draggable 46 | attachX: root.flickable !== undefined 47 | ? flickable.contentX 48 | : handle.x - Theme.itemSizeExtraLarge 49 | handle: root.model.handle1 50 | dragHeight: root.model.handle1Height 51 | }, 52 | PDFSelectionHandle { 53 | id: handle2 54 | 55 | visible: root.draggable 56 | attachX: root.flickable !== undefined 57 | ? flickable.contentX + flickable.width 58 | : handle.x + Theme.itemSizeExtraLarge 59 | handle: root.model.handle2 60 | dragHeight: root.model.handle2Height 61 | } 62 | ] 63 | } 64 | -------------------------------------------------------------------------------- /plugin/PDFStorage.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Caliste Damien. 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | var Settings = function(file) { 20 | this.db = LocalStorage.openDatabaseSync("sailfish-office", "1.0", 21 | "Local storage for the document viewer.", 10000) 22 | this.source = file 23 | } 24 | 25 | /* Different tables. */ 26 | function createTableLastViewSettings(tx) { 27 | /* Currently store the last page, may be altered later to store 28 | zoom level or page position. */ 29 | tx.executeSql("CREATE TABLE IF NOT EXISTS LastViewSettings(" 30 | + "file TEXT NOT NULL," 31 | + "page INT NOT NULL," 32 | + "top REAL ," 33 | + "left REAL ," 34 | + "width INT CHECK(width > 0))") 35 | tx.executeSql('CREATE UNIQUE INDEX IF NOT EXISTS idx_file ON LastViewSettings(file)') 36 | } 37 | 38 | /* Get and set operations. */ 39 | Settings.prototype.getLastPage = function() { 40 | var page = 0 41 | var top = 0 42 | var left = 0 43 | var width = 0 44 | var file = this.source 45 | this.db.transaction(function(tx) { 46 | createTableLastViewSettings(tx) 47 | var rs = tx.executeSql('SELECT page, top, left, width FROM LastViewSettings WHERE file = ?', [file]) 48 | if (rs.rows.length > 0) { 49 | page = rs.rows.item(0).page 50 | top = rs.rows.item(0).top 51 | left = rs.rows.item(0).left 52 | width = rs.rows.item(0).width 53 | } 54 | }) 55 | // Return page is in [1:] 56 | return [page, top, left, width] 57 | } 58 | Settings.prototype.setLastPage = function(page, top, left, width) { 59 | // page is in [1:] 60 | var file = this.source 61 | this.db.transaction(function(tx) { 62 | createTableLastViewSettings(tx) 63 | var rs = tx.executeSql('INSERT OR REPLACE INTO LastViewSettings(file, page, top, left, width) VALUES (?,?,?,?,?)', 64 | [file, page, top, left, width]) 65 | }) 66 | } 67 | -------------------------------------------------------------------------------- /plugin/PresentationDetailsPage.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2024 Damien Caliste 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | import Sailfish.Office 1.0 22 | 23 | DetailsPage { 24 | DetailItem { 25 | //: Slide count detail of the presentation 26 | //% "Slides" 27 | label: qsTrId("sailfish-office-la-slidecount") 28 | value: document.indexCount 29 | alignment: Qt.AlignLeft 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /plugin/PresentationPage.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2020 Jolla Ltd. 3 | * Copyright (c) 2020 Open Mobile Platform LLC. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | import Sailfish.Silica.private 1.0 22 | import org.kde.calligra 1.0 as Calligra 23 | 24 | CalligraDocumentPage { 25 | id: page 26 | 27 | icon: "image://theme/icon-m-file-presentation" 28 | backgroundColor: "black" 29 | coverAlignment: Qt.AlignCenter 30 | coverFillMode: Image.PreserveAspectFit 31 | busyIndicator.y: Math.round(page.height/2 - busyIndicator.height/2) 32 | 33 | function currentIndex() { 34 | return view.currentIndex >= 0 ? view.currentIndex : document.currentIndex 35 | } 36 | 37 | contents.thumbnailSize { 38 | width: page.width 39 | height: page.width * 0.75 40 | } 41 | 42 | SlideshowView { 43 | id: view 44 | 45 | property bool contentAvailable: !page.busy 46 | 47 | anchors.fill: parent 48 | orientation: Qt.Vertical 49 | currentIndex: page.document.currentIndex 50 | 51 | enabled: !page.busy 52 | opacity: enabled ? 1.0 : 0.0 53 | Behavior on opacity { FadeAnimator { duration: 400 }} 54 | 55 | model: page.contents 56 | 57 | delegate: ZoomableFlickable { 58 | id: flickable 59 | 60 | readonly property bool active: PathView.isCurrentItem || viewMoving 61 | onActiveChanged: { 62 | if (!active) { 63 | resetZoom() 64 | largeThumb.data = page.contents.thumbnail(-1, 0) 65 | } 66 | } 67 | 68 | onZoomedChanged: overlay.active = !zoomed 69 | onZoomFinished: if (largeThumb.implicitWidth === 0) largeThumb.data = page.contents.thumbnail(model.index, 3264) 70 | 71 | width: view.width 72 | height: view.height 73 | viewMoving: view.moving 74 | scrollDecoratorColor: Theme.highlightDimmerFromColor(Theme.highlightDimmerColor, Theme.DarkOnLight) 75 | implicitContentWidth: thumb.implicitWidth 76 | implicitContentHeight: thumb.implicitHeight 77 | 78 | MouseArea { 79 | anchors.fill: parent 80 | onClicked: { 81 | if (zoomed) { 82 | zoomOut() 83 | } else { 84 | overlay.active = !overlay.active 85 | } 86 | } 87 | } 88 | 89 | Calligra.ImageDataItem { 90 | id: thumb 91 | 92 | property bool initialized 93 | property bool ready: initialized && !viewMoving 94 | 95 | Component.onCompleted: initialized = true 96 | onReadyChanged: { 97 | if (ready) { 98 | ready = true // remove binding 99 | data = page.contents.thumbnail(model.index, Screen.height) 100 | } 101 | } 102 | 103 | anchors.fill: parent 104 | } 105 | Calligra.ImageDataItem { 106 | id: largeThumb 107 | 108 | visible: implicitWidth > 0 109 | anchors.fill: parent 110 | } 111 | } 112 | } 113 | 114 | Item { 115 | id: overlay 116 | 117 | property bool active: true 118 | 119 | enabled: active 120 | anchors.fill: parent 121 | opacity: enabled ? 1.0 : 0.0 122 | Behavior on opacity { FadeAnimator {}} 123 | 124 | FadeGradient { 125 | topDown: true 126 | width: parent.width 127 | height: header.height + Theme.paddingLarge 128 | } 129 | 130 | DocumentHeader { 131 | id: header 132 | 133 | detailsPage: "PresentationDetailsPage.qml" 134 | color: Theme.lightPrimaryColor 135 | page: page 136 | } 137 | 138 | OverlayToolbar { 139 | enabled: page.document.status == Calligra.DocumentStatus.Loaded 140 | opacity: enabled ? 1.0 : 0.0 141 | Behavior on opacity { FadeAnimator { duration: 400 }} 142 | 143 | DeleteButton { 144 | page: page 145 | icon.color: Theme.lightPrimaryColor 146 | } 147 | 148 | ShareButton { 149 | page: page 150 | icon.color: Theme.lightPrimaryColor 151 | } 152 | 153 | IndexButton { 154 | onClicked: pageStack.animatorPush(Qt.resolvedUrl("PresentationThumbnailPage.qml"), { document: page.document }) 155 | 156 | index: Math.max(1, view.currentIndex + 1) 157 | count: page.document.indexCount 158 | color: Theme.lightPrimaryColor 159 | } 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /plugin/PresentationThumbnailPage.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | import org.kde.calligra 1.0 as Calligra 22 | 23 | Page { 24 | id: page 25 | 26 | property QtObject document 27 | 28 | allowedOrientations: Orientation.All 29 | 30 | SilicaGridView { 31 | id: grid 32 | 33 | anchors.fill: parent 34 | 35 | cellWidth: page.width / 3 36 | cellHeight: cellWidth * 0.75 37 | 38 | currentIndex: page.document.currentIndex 39 | 40 | //: Page with slide overview 41 | //% "Slides" 42 | header: PageHeader { title: qsTrId("sailfish-office-he-slide_index") } 43 | 44 | model: Calligra.ContentsModel { 45 | document: page.document 46 | thumbnailSize.width: grid.cellWidth 47 | thumbnailSize.height: grid.cellHeight 48 | } 49 | 50 | delegate: Item { 51 | id: root 52 | width: GridView.view.cellWidth 53 | height: GridView.view.cellHeight 54 | 55 | Rectangle { 56 | anchors.fill: parent 57 | border.width: 1 58 | 59 | Calligra.ImageDataItem { 60 | anchors.fill: parent 61 | data: model.thumbnail 62 | } 63 | 64 | Rectangle { 65 | anchors.centerIn: parent 66 | width: label.width + Theme.paddingMedium 67 | height: label.height 68 | radius: Theme.paddingSmall 69 | color: root.GridView.isCurrentItem ? Theme.highlightColor : Theme.darkPrimaryColor 70 | } 71 | 72 | Label { 73 | id: label 74 | 75 | anchors.centerIn: parent 76 | text: model.contentIndex + 1 77 | color: Theme.lightPrimaryColor 78 | } 79 | 80 | Rectangle { 81 | anchors.fill: parent 82 | color: mouseArea.pressed && mouseArea.containsMouse ? Theme.highlightBackgroundColor 83 | : "transparent" 84 | opacity: Theme.highlightBackgroundOpacity 85 | } 86 | 87 | } 88 | 89 | MouseArea { 90 | id: mouseArea 91 | 92 | anchors.fill: parent 93 | onClicked: { 94 | page.document.currentIndex = model.contentIndex 95 | pageStack.navigateBack(PageStackAction.Animated) 96 | } 97 | } 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /plugin/ShareButton.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Jolla Ltd. 3 | * Copyright (C) 2021 Open Mobile Platform LLC. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | import Sailfish.Share 1.0 22 | 23 | IconButton { 24 | property DocumentPage page 25 | 26 | icon.source: "image://theme/icon-m-share" 27 | visible: page.source != "" && !page.error 28 | anchors.verticalCenter: parent.verticalCenter 29 | onClicked: { 30 | shareAction.trigger() 31 | } 32 | 33 | ShareAction { 34 | id: shareAction 35 | 36 | resources: [page.source] 37 | mimeType: page.mimeType 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /plugin/SpreadsheetDetailsPage.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2024 Damien Caliste 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | import Sailfish.Office 1.0 22 | 23 | DetailsPage { 24 | DetailItem { 25 | //: Sheet count of the spreadsheet 26 | //% "Sheets" 27 | label: qsTrId("sailfish-office-la-sheetcount") 28 | value: document.indexCount 29 | alignment: Qt.AlignLeft 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /plugin/SpreadsheetListPage.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | import org.kde.calligra 1.0 as Calligra 22 | 23 | Page { 24 | id: page 25 | 26 | property QtObject document 27 | 28 | allowedOrientations: Orientation.All 29 | 30 | SilicaListView { 31 | id: view 32 | 33 | anchors.fill: parent 34 | 35 | //: Page with sheet selector 36 | //% "Sheets" 37 | header: PageHeader { title: qsTrId("sailfish-office-he-sheet_index") } 38 | 39 | model: Calligra.ContentsModel { 40 | document: page.document 41 | thumbnailSize.width: Theme.itemSizeLarge 42 | thumbnailSize.height: Theme.itemSizeLarge 43 | } 44 | 45 | delegate: BackgroundItem { 46 | Calligra.ImageDataItem { 47 | id: thumbnail 48 | 49 | anchors { 50 | left: parent.left 51 | verticalCenter: parent.verticalCenter 52 | } 53 | 54 | width: parent.height 55 | height: parent.height 56 | 57 | data: model.thumbnail 58 | } 59 | 60 | Label { 61 | anchors { 62 | left: thumbnail.right 63 | leftMargin: Theme.paddingLarge 64 | verticalCenter: parent.verticalCenter 65 | } 66 | 67 | text: model.title 68 | color: (model.contentIndex == page.document.currentIndex || highlighted) ? Theme.highlightColor 69 | : Theme.primaryColor 70 | truncationMode: TruncationMode.Fade 71 | } 72 | 73 | onClicked: { 74 | page.document.currentIndex = model.contentIndex 75 | pageStack.navigateBack() 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /plugin/SpreadsheetPage.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 - 2019 Jolla Ltd. 3 | * Copyright (c) 2019 Open Mobile Platform LLC. 4 | * 5 | * Contact: Robin Burchell 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; version 2 only. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | import QtQuick 2.0 22 | import Sailfish.Silica 1.0 23 | import Sailfish.Silica.private 1.0 24 | import org.kde.calligra 1.0 as Calligra 25 | 26 | CalligraDocumentPage { 27 | id: page 28 | 29 | onStatusChanged: { 30 | //Reset the position when we change sheets 31 | if (status === PageStatus.Activating) { 32 | flickable.contentX = 0 33 | flickable.contentY = 0 34 | } 35 | } 36 | 37 | icon: "image://theme/icon-m-file-spreadsheet" 38 | backgroundColor: "white" 39 | 40 | document.onStatusChanged: { 41 | if (document.status === Calligra.DocumentStatus.Loaded) { 42 | viewController.zoomToFitWidth(page.width) 43 | } 44 | } 45 | 46 | Calligra.View { 47 | id: documentView 48 | 49 | property bool contentAvailable: !page.busy 50 | 51 | anchors.fill: parent 52 | document: page.document 53 | } 54 | 55 | ControllerFlickable { 56 | id: flickable 57 | 58 | onZoomedChanged: overlay.active = !zoomed 59 | 60 | controller: viewController 61 | anchors.fill: parent 62 | enabled: !page.busy 63 | opacity: enabled ? 1.0 : 0.0 64 | Behavior on opacity { FadeAnimator { duration: 400 }} 65 | 66 | Calligra.ViewController { 67 | id: viewController 68 | 69 | view: documentView 70 | flickable: flickable 71 | useZoomProxy: false 72 | maximumZoom: Math.max(10.0, 2.0 * minimumZoom) 73 | minimumZoomFitsWidth: true 74 | } 75 | 76 | Calligra.LinkArea { 77 | anchors.fill: parent 78 | document: page.document 79 | onClicked: { 80 | if (flickable.zoomed) { 81 | flickable.zoomOut() 82 | } else { 83 | overlay.active = !overlay.active 84 | } 85 | } 86 | onLinkClicked: Qt.openUrlExternally(linkTarget) 87 | controllerZoom: viewController.zoom 88 | } 89 | } 90 | 91 | Item { 92 | id: overlay 93 | 94 | property bool active: true 95 | 96 | enabled: active 97 | anchors.fill: parent 98 | opacity: enabled ? 1.0 : 0.0 99 | Behavior on opacity { FadeAnimator {}} 100 | 101 | FadeGradient { 102 | topDown: true 103 | width: parent.width 104 | height: header.height + Theme.paddingLarge 105 | color: page.backgroundColor 106 | } 107 | 108 | DocumentHeader { 109 | id: header 110 | 111 | detailsPage: "SpreadsheetDetailsPage.qml" 112 | color: Theme.darkPrimaryColor 113 | page: page 114 | } 115 | 116 | OverlayToolbar { 117 | enabled: page.document.status === Calligra.DocumentStatus.Loaded 118 | opacity: enabled ? 1.0 : 0.0 119 | color: page.backgroundColor 120 | Behavior on opacity { FadeAnimator { duration: 400 }} 121 | 122 | DeleteButton { 123 | page: page 124 | icon.color: Theme.darkPrimaryColor 125 | } 126 | 127 | ShareButton { 128 | page: page 129 | icon.color: Theme.darkPrimaryColor 130 | } 131 | 132 | IndexButton { 133 | onClicked: pageStack.animatorPush(Qt.resolvedUrl("SpreadsheetListPage.qml"), { document: page.document }) 134 | index: Math.max(1, page.document.currentIndex + 1) 135 | count: page.document.indexCount 136 | color: Theme.darkPrimaryColor 137 | } 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /plugin/TextDetailsPage.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2024 Damien Caliste 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | import Sailfish.Office 1.0 22 | 23 | DetailsPage { 24 | DetailItem { 25 | //: Page count of the text document 26 | //% "Page Count" 27 | label: qsTrId("sailfish-office-la-pagecount") 28 | value: document.indexCount 29 | alignment: Qt.AlignLeft 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /plugin/TextDocumentPage.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 - 2019 Jolla Ltd. 3 | * Copyright (c) 2019 Open Mobile Platform LLC. 4 | * 5 | * Contact: Robin Burchell 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; version 2 only. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | import QtQuick 2.0 22 | import Sailfish.Silica 1.0 23 | import Sailfish.Silica.private 1.0 24 | import org.kde.calligra 1.0 as Calligra 25 | 26 | CalligraDocumentPage { 27 | id: page 28 | 29 | icon: "image://theme/icon-m-file-formatted" 30 | 31 | function currentIndex() { 32 | // Text document indexes appear to start at 1, model indexes at the traditional 0. 33 | return document.currentIndex - 1 34 | } 35 | 36 | document.onStatusChanged: { 37 | if (document.status === Calligra.DocumentStatus.Loaded) { 38 | viewController.zoomToFitWidth(page.width) 39 | } 40 | } 41 | 42 | Calligra.View { 43 | id: documentView 44 | 45 | property bool contentAvailable: !page.busy 46 | 47 | anchors.fill: flickable 48 | opacity: page.busy ? 0.0 : 1.0 49 | Behavior on opacity { FadeAnimator { duration: 400 }} 50 | document: page.document 51 | } 52 | 53 | ControllerFlickable { 54 | id: flickable 55 | 56 | property bool resetPositionWorkaround 57 | 58 | onContentYChanged: { 59 | if (page.document.status == Calligra.DocumentStatus.Loaded 60 | && !resetPositionWorkaround) { 61 | // Calligra is not Flickable.topMargin aware 62 | contentY = -topMargin 63 | contentX = 0 64 | viewController.useZoomProxy = false 65 | resetPositionWorkaround = true 66 | } 67 | } 68 | 69 | controller: viewController 70 | topMargin: header.height 71 | clip: anchors.bottomMargin > 0 72 | anchors { 73 | fill: parent 74 | bottomMargin: toolbar.offset 75 | } 76 | 77 | 78 | Calligra.ViewController { 79 | id: viewController 80 | view: documentView 81 | flickable: flickable 82 | maximumZoom: Math.max(5.0, 2.0 * minimumZoom) 83 | minimumZoomFitsWidth: true 84 | } 85 | 86 | Calligra.LinkArea { 87 | anchors.fill: parent 88 | document: page.document 89 | onLinkClicked: Qt.openUrlExternally(linkTarget) 90 | onClicked: flickable.zoomOut() 91 | 92 | controllerZoom: viewController.zoom 93 | } 94 | 95 | DocumentHeader { 96 | id: header 97 | detailsPage: "TextDetailsPage.qml" 98 | page: page 99 | width: page.width 100 | x: flickable.contentX 101 | y: -height 102 | } 103 | } 104 | 105 | ToolBar { 106 | id: toolbar 107 | 108 | flickable: flickable 109 | anchors.top: flickable.bottom 110 | forceHidden: page.document.status === Calligra.DocumentStatus.Failed 111 | enabled: page.document.status === Calligra.DocumentStatus.Loaded 112 | opacity: enabled ? 1.0 : 0.0 113 | Behavior on opacity { FadeAnimator { duration: 400 }} 114 | 115 | DeleteButton { 116 | page: page 117 | } 118 | 119 | ShareButton { 120 | page: page 121 | } 122 | 123 | IndexButton { 124 | onClicked: pageStack.animatorPush(Qt.resolvedUrl("TextDocumentToCPage.qml"), 125 | { document: page.document, contents: page.contents }) 126 | 127 | index: Math.max(1, page.document.currentIndex) 128 | count: page.document.indexCount 129 | allowed: page.document.status !== Calligra.DocumentStatus.Failed 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /plugin/TextDocumentToCPage.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | import org.kde.calligra 1.0 as Calligra 22 | 23 | Page { 24 | id: page 25 | 26 | property QtObject document 27 | property alias contents: view.model 28 | 29 | allowedOrientations: Orientation.All 30 | 31 | SilicaListView { 32 | id: view 33 | 34 | anchors.fill: parent 35 | 36 | //: Page with Text document index 37 | //% "Index" 38 | header: PageHeader { title: qsTrId("sailfish-office-he-index") } 39 | 40 | delegate: BackgroundItem { 41 | property bool isCurrentItem: model.contentIndex + 1 == page.document.currentIndex 42 | 43 | Label { 44 | x: Theme.horizontalPageMargin 45 | width: parent.width - 2*x 46 | anchors.verticalCenter: parent.verticalCenter 47 | //% "Page %1" 48 | text: qsTrId("sailfish_office-la-page_number").arg(model.contentIndex + 1) 49 | color: highlighted || isCurrentItem ? Theme.highlightColor : Theme.primaryColor 50 | truncationMode: TruncationMode.Fade 51 | } 52 | onClicked: { 53 | page.document.currentIndex = model.contentIndex 54 | pageStack.navigateBack(PageStackAction.Animated) 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /plugin/ToolBar.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Caliste Damien. 3 | * Contact: Damien Caliste 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | 22 | PanelBackground { 23 | id: toolbar 24 | 25 | property Item flickable 26 | property bool forceHidden 27 | property bool autoShowHide: true 28 | property int offset: _active && !forceHidden && !_pulleyActive ? height : 0 29 | 30 | property bool _active: true 31 | property int _previousContentY 32 | readonly property bool _pulleyActive: flickable && flickable.pullDownMenu && flickable.pullDownMenu.active 33 | default property alias _data: contentItem.data 34 | 35 | width: parent.width 36 | height: isPortrait ? Theme.itemSizeLarge : Theme.itemSizeSmall 37 | 38 | function show() { 39 | if (forceHidden) { 40 | return 41 | } 42 | autoHideTimer.stop() 43 | _active = true 44 | if (autoShowHide) autoHideTimer.restart() 45 | } 46 | function hide() { 47 | _active = false 48 | autoHideTimer.stop() 49 | } 50 | 51 | onAutoShowHideChanged: { 52 | if (autoShowHide) { 53 | if (_active) { 54 | autoHideTimer.start() 55 | } 56 | } else { 57 | autoHideTimer.stop() 58 | // Keep a transiting (and a not transited yet) toolbar visible. 59 | _active = _active || (offset > 0) 60 | } 61 | } 62 | 63 | onForceHiddenChanged: { 64 | // Avoid showing back the toolbar when forceHidden becomes false again. 65 | if (forceHidden && autoShowHide) { 66 | _active = false 67 | autoHideTimer.stop() 68 | } 69 | } 70 | 71 | Behavior on offset { NumberAnimation { duration: 400; easing.type: Easing.InOutQuad } } 72 | 73 | 74 | Row { 75 | id: contentItem 76 | 77 | spacing: Theme.paddingLarge 78 | x: Math.max(0, parent.width/2 - width/2) 79 | height: parent.height 80 | } 81 | 82 | Connections { 83 | target: flickable 84 | onContentYChanged: { 85 | if (!flickable.movingVertically) { 86 | return 87 | } 88 | 89 | if (autoShowHide) { 90 | _active = flickable.contentY < _previousContentY 91 | 92 | if (_active) { 93 | autoHideTimer.restart() 94 | } 95 | } 96 | 97 | _previousContentY = flickable.contentY 98 | } 99 | } 100 | 101 | Timer { 102 | id: autoHideTimer 103 | 104 | interval: 4000 105 | onTriggered: _active = false 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /plugin/plaintextmodel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Open Mobile Platform LLC 3 | * Copyright (C) 2019 Jolla Ltd. 4 | * Contact: Andrew den Exter 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License 8 | * as published by the Free Software Foundation; version 2 only. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef PLAINTEXTMODEL_H 21 | #define PLAINTEXTMODEL_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | class PlainTextModel : public QAbstractItemModel 34 | { 35 | Q_OBJECT 36 | Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) 37 | Q_PROPERTY(Status status READ status NOTIFY statusChanged) 38 | Q_PROPERTY(int lineCount READ rowCount NOTIFY countChanged) 39 | Q_DISABLE_COPY(PlainTextModel) 40 | public: 41 | static constexpr qint64 maximumFileSize = INT_MAX; // This is probably a little optimistic. 42 | static constexpr qint64 maximumSynchronousSize = 4000; 43 | static constexpr qint64 maximumCost = 16000; 44 | 45 | enum Roles { 46 | LineText 47 | }; 48 | 49 | enum Status { 50 | Null, 51 | Loading, 52 | Ready, 53 | Error 54 | }; 55 | Q_ENUM(Status) 56 | 57 | explicit PlainTextModel(QObject *parent = nullptr); 58 | ~PlainTextModel(); 59 | 60 | QUrl source() const; 61 | void setSource(const QUrl &source); 62 | 63 | Status status() const; 64 | 65 | Q_INVOKABLE QString textAt(int index) const; 66 | 67 | QHash roleNames() const override; 68 | 69 | QVariant data(const QModelIndex &index, int role) const override; 70 | QModelIndex index(int row, int column, const QModelIndex &parent) const override; 71 | QModelIndex parent(const QModelIndex &child) const override; 72 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; 73 | int columnCount(const QModelIndex &parent) const override; 74 | 75 | signals: 76 | void sourceChanged(); 77 | void statusChanged(); 78 | void countChanged(); 79 | 80 | private: 81 | struct FileData; 82 | class Reader; 83 | class ReaderEvent; 84 | 85 | friend struct FileData; 86 | friend class Reader; 87 | friend class ReaderEvent; 88 | 89 | struct Line 90 | { 91 | Line() = default; 92 | Line(qint64 offset, qint64 length) : offset(offset), length(length) {} 93 | qint64 offset = 0; 94 | qint64 length = 0; 95 | }; 96 | 97 | inline QString *lineAt(int index); 98 | inline static bool readLines( 99 | QTextStream *stream, std::vector *lines, std::vector *cache); 100 | static QTextCodec * detectCodec(const char *encodedCharacters, qint64 length); 101 | 102 | std::vector m_lines; 103 | QCache m_textCache { maximumCost + (maximumCost / 20) }; 104 | QExplicitlySharedDataPointer m_fileData; 105 | QFile m_file; 106 | QTextStream m_textStream; 107 | QUrl m_source; 108 | qint64 m_cost = 0; 109 | Status m_status = Null; 110 | }; 111 | 112 | #endif // DOCUMENTLISTMODEL_H 113 | -------------------------------------------------------------------------------- /plugin/qmldir: -------------------------------------------------------------------------------- 1 | module Sailfish.Office 2 | PDFDocumentPage 1.0 PDFDocumentPage.qml 3 | PresentationPage 1.0 PresentationPage.qml 4 | SpreadsheetPage 1.0 SpreadsheetPage.qml 5 | TextDocumentPage 1.0 TextDocumentPage.qml 6 | PlainTextDocumentPage 1.0 PlainTextDocumentPage.qml 7 | plugin sailfishofficeplugin 8 | -------------------------------------------------------------------------------- /plugin/sailfishofficeplugin.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #include "sailfishofficeplugin.h" 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | 26 | #include "plaintextmodel.h" 27 | 28 | #include "config.h" 29 | 30 | class Translator : public QTranslator 31 | { 32 | public: 33 | Translator(QObject *parent) 34 | : QTranslator(parent) 35 | { 36 | qApp->installTranslator(this); 37 | } 38 | 39 | ~Translator() 40 | { 41 | qApp->removeTranslator(this); 42 | } 43 | }; 44 | 45 | SailfishOfficePlugin::SailfishOfficePlugin(QObject *parent) 46 | : QQmlExtensionPlugin(parent) 47 | { 48 | } 49 | 50 | void SailfishOfficePlugin::registerTypes(const char *uri) 51 | { 52 | Q_ASSERT(uri == QLatin1String("Sailfish.Office")); 53 | qmlRegisterType(uri, 1, 0, "PlainTextModel"); 54 | } 55 | 56 | void SailfishOfficePlugin::initializeEngine(QQmlEngine *engine, const char *uri) 57 | { 58 | Q_ASSERT(uri == QLatin1String("Sailfish.Office")); 59 | 60 | Translator *engineeringEnglish = new Translator(engine); 61 | engineeringEnglish->load("sailfish-office_eng_en", TRANSLATION_INSTALL_DIR); 62 | 63 | Translator *translator = new Translator(engine); 64 | translator->load(QLocale(), "sailfish-office", "-", TRANSLATION_INSTALL_DIR); 65 | 66 | QQmlExtensionPlugin::initializeEngine(engine, uri); 67 | } 68 | 69 | -------------------------------------------------------------------------------- /plugin/sailfishofficeplugin.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | #ifndef SAILFISHOFFICEPLUGIN_H 20 | #define SAILFISHOFFICEPLUGIN_H 21 | 22 | #include 23 | #include 24 | 25 | class SailfishOfficePlugin : public QQmlExtensionPlugin 26 | { 27 | Q_OBJECT 28 | Q_PLUGIN_METADATA(IID "Sailfish.Office") 29 | public: 30 | explicit SailfishOfficePlugin(QObject *parent = 0); 31 | 32 | virtual void registerTypes(const char *uri); 33 | virtual void initializeEngine(QQmlEngine *engine, const char *uri); 34 | }; 35 | 36 | #endif // SAILFISHOFFICEPLUGIN_H 37 | -------------------------------------------------------------------------------- /qml/CoverFileItem.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.0 20 | import Sailfish.Silica 1.0 21 | 22 | Item { 23 | id: root 24 | 25 | property alias text: label.text 26 | property bool multiLine 27 | property string iconSource 28 | property int iconSize 29 | 30 | Image { 31 | id: icon 32 | 33 | anchors { 34 | left: parent.left 35 | leftMargin: Theme.paddingLarge - Theme.paddingSmall // counter the padding inside the icon 36 | verticalCenter: root.multiLine ? undefined : parent.verticalCenter 37 | } 38 | source: root.iconSource !== "" ? root.iconSource 39 | : "image://theme/icon-m-document" 40 | 41 | sourceSize { 42 | width: root.iconSize 43 | height: root.iconSize 44 | } 45 | } 46 | Label { 47 | id: label 48 | 49 | anchors { 50 | left: icon.right 51 | leftMargin: Theme.paddingMedium 52 | verticalCenter: root.multiLine ? undefined : parent.verticalCenter 53 | right: parent.right 54 | rightMargin: Theme.paddingLarge - Theme.paddingSmall // counter the margin caused by fading 55 | } 56 | 57 | truncationMode: root.multiLine ? TruncationMode.None : TruncationMode.Fade 58 | wrapMode: root.multiLine ? Text.WrapAnywhere : Text.NoWrap 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /qml/CoverPage.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2014 Jolla Ltd. 3 | * Contact: Robin Burchell 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; version 2 only. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | */ 18 | 19 | import QtQuick 2.4 20 | import Sailfish.Silica 1.0 21 | import Sailfish.Office 1.0 22 | 23 | CoverBackground { 24 | id: root 25 | 26 | property alias preview: previewLoader.sourceComponent 27 | 28 | CoverPlaceholder { 29 | //: Cover placeholder shown when there are no documents 30 | //% "No documents" 31 | text: qsTrId("sailfish-office-la-cover_no_documents") 32 | icon.source: "image://theme/icon-launcher-office" 33 | visible: previewLoader.status !== Loader.Ready && fileListView.count == 0 34 | } 35 | 36 | property int iconSize: Math.round(Theme.iconSizeMedium * 0.8) 37 | 38 | ListView { 39 | id: fileListView 40 | 41 | property int itemHeight: height/maxItemCount 42 | property int maxItemCount: Math.round(height / (Math.max(fontMetrics.height, iconSize) + Theme.paddingSmall)) 43 | 44 | clip: true 45 | interactive: false 46 | model: window.fileListModel 47 | visible: previewLoader.status !== Loader.Ready 48 | anchors { 49 | fill: parent 50 | topMargin: Theme.paddingLarge 51 | bottomMargin: Theme.paddingLarge 52 | } 53 | 54 | delegate: CoverFileItem { 55 | width: fileListView.width 56 | height: fileListView.itemHeight 57 | text: model.fileName 58 | iconSource: window.mimeToIcon(model.fileMimeType) 59 | iconSize: root.iconSize 60 | } 61 | FontMetrics { 62 | id: fontMetrics 63 | font.pixelSize: Theme.fontSizeMedium 64 | } 65 | } 66 | 67 | Loader { 68 | id: previewLoader 69 | 70 | width: root.width 71 | height: root.height 72 | 73 | active: root.status === Cover.Active 74 | sourceComponent: window.coverPreview 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /qml/Main.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 - 2022 Jolla Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License 6 | * as published by the Free Software Foundation; version 2 only. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 | */ 17 | 18 | import QtQuick 2.0 19 | import Sailfish.Silica 1.0 20 | import Sailfish.Office 1.0 21 | import Sailfish.Office.Files 1.0 22 | import Nemo.FileManager 1.0 23 | 24 | ApplicationWindow { 25 | id: window 26 | 27 | readonly property Component coverPreview: pageStack.currentPage && (pageStack.currentPage.preview || null) 28 | 29 | property QtObject fileListModel: trackerProvider.model 30 | property Page _mainPage 31 | 32 | allowedOrientations: defaultAllowedOrientations 33 | _defaultLabelFormat: Text.PlainText 34 | _defaultPageOrientations: Orientation.All 35 | cover: Qt.resolvedUrl("CoverPage.qml") 36 | initialPage: Component { 37 | FileListPage { 38 | id: fileListPage 39 | 40 | model: trackerProvider.model 41 | provider: trackerProvider 42 | Component.onCompleted: window._mainPage = fileListPage 43 | } 44 | } 45 | 46 | TrackerDocumentProvider { 47 | id: trackerProvider 48 | } 49 | 50 | FileInfo { 51 | id: fileInfo 52 | } 53 | 54 | // file = file or url 55 | function openFile(file) { 56 | fileInfo.url = file 57 | 58 | pageStack.pop(window._mainPage, PageStackAction.Immediate) 59 | 60 | var handler = "" 61 | 62 | switch (fileInfo.mimeType) { 63 | case "application/vnd.oasis.opendocument.spreadsheet": 64 | case "application/x-kspread": 65 | case "application/vnd.ms-excel": 66 | case "text/csv": 67 | case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": 68 | case "application/vnd.openxmlformats-officedocument.spreadsheetml.template": 69 | handler = "Sailfish.Office.SpreadsheetPage" 70 | break 71 | 72 | case "application/vnd.oasis.opendocument.presentation": 73 | case "application/vnd.oasis.opendocument.presentation-template": 74 | case "application/x-kpresenter": 75 | case "application/vnd.ms-powerpoint": 76 | case "application/vnd.openxmlformats-officedocument.presentationml.presentation": 77 | case "application/vnd.openxmlformats-officedocument.presentationml.template": 78 | handler = "Sailfish.Office.PresentationPage" 79 | break 80 | 81 | case "application/vnd.oasis.opendocument.text-master": 82 | case "application/vnd.oasis.opendocument.text": 83 | case "application/vnd.oasis.opendocument.text-template": 84 | case "application/msword": 85 | case "application/rtf": 86 | case "application/x-mswrite": 87 | case "application/vnd.openxmlformats-officedocument.wordprocessingml.document": 88 | case "application/vnd.openxmlformats-officedocument.wordprocessingml.template": 89 | case "application/vnd.ms-works": 90 | handler = "Sailfish.Office.TextDocumentPage" 91 | break 92 | 93 | case "text/plain": 94 | handler = "Sailfish.Office.PlainTextDocumentPage" 95 | break 96 | 97 | case "application/pdf": 98 | handler = "Sailfish.Office.PDFDocumentPage" 99 | break 100 | 101 | default: 102 | console.log("Warning: Unrecognised file type for file " + fileInfo.file) 103 | } 104 | 105 | if (handler != "") { 106 | pageStack.push(handler, 107 | { title: fileInfo.fileName, source: fileInfo.url, mimeType: fileInfo.mimeType }, 108 | PageStackAction.Immediate) 109 | } 110 | 111 | activate() 112 | } 113 | 114 | function mimeToIcon(fileMimeType) { 115 | var iconType = "other" 116 | switch (fileMimeType) { 117 | case "text/x-vnote": 118 | iconType = "note" 119 | break 120 | case "application/pdf": 121 | iconType = "pdf" 122 | break 123 | case "application/vnd.oasis.opendocument.spreadsheet": 124 | case "application/x-kspread": 125 | case "application/vnd.ms-excel": 126 | case "text/csv": 127 | case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": 128 | case "application/vnd.openxmlformats-officedocument.spreadsheetml.template": 129 | iconType = "spreadsheet" 130 | break 131 | case "application/vnd.oasis.opendocument.presentation": 132 | case "application/vnd.oasis.opendocument.presentation-template": 133 | case "application/x-kpresenter": 134 | case "application/vnd.ms-powerpoint": 135 | case "application/vnd.openxmlformats-officedocument.presentationml.presentation": 136 | case "application/vnd.openxmlformats-officedocument.presentationml.template": 137 | iconType = "presentation" 138 | break 139 | case "text/plain": 140 | case "application/vnd.oasis.opendocument.text-master": 141 | case "application/vnd.oasis.opendocument.text": 142 | case "application/vnd.oasis.opendocument.text-template": 143 | case "application/msword": 144 | case "application/rtf": 145 | case "application/x-mswrite": 146 | case "application/vnd.openxmlformats-officedocument.wordprocessingml.document": 147 | case "application/vnd.openxmlformats-officedocument.wordprocessingml.template": 148 | case "application/vnd.ms-works": 149 | iconType = "formatted" 150 | break 151 | } 152 | return "image://theme/icon-m-file-" + iconType 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /qml/SortTypeSelectionPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import Sailfish.Silica 1.0 3 | import Sailfish.Office.Files 1.0 4 | 5 | Page { 6 | id: root 7 | 8 | signal sortSelected(int sortType) 9 | 10 | SilicaListView { 11 | anchors.fill: parent 12 | model: sortModel 13 | 14 | header: PageHeader { 15 | //% "Sort by" 16 | title: qsTrId("sailfish_office-he-sort_by") 17 | } 18 | 19 | delegate: BackgroundItem { 20 | Label { 21 | x: Theme.horizontalPageMargin 22 | anchors.verticalCenter: parent.verticalCenter 23 | text: name 24 | color: highlighted ? Theme.highlightColor : Theme.primaryColor 25 | } 26 | 27 | onClicked: root.sortSelected(sortType) 28 | } 29 | VerticalScrollDecorator {} 30 | } 31 | 32 | ListModel { 33 | id: sortModel 34 | 35 | ListElement { 36 | sortType: FilterModel.Name 37 | //: Sort by name 38 | //% "Name" 39 | name: qsTrId("sailfish_office-me-sort_name") 40 | } 41 | 42 | ListElement { 43 | sortType: FilterModel.Type 44 | //: Sort by type 45 | //% "Type" 46 | name: qsTrId("sailfish_office-me-sort_type") 47 | } 48 | 49 | ListElement { 50 | sortType: FilterModel.Date 51 | //: Sort by date 52 | //% "Date" 53 | name: qsTrId("sailfish_office-me-sort_date") 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /qml/translations/StoreDescription.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | 3 | Item { 4 | // providing dummy translations for app descriptions shown on Store 5 | function qsTrIdString() { 6 | //% "Documents you download to the device appear and can be viewed in Documents app." 7 | QT_TRID_NOOP("sailfish-office-la-store_app_summary") 8 | 9 | //% "Documents lists every document stored on your device, SD card or other connected storage device. " 10 | //% "Scroll and zoom opened documents, or jump to a specific part of the document from the attached page. " 11 | //% "In addition PDF viewer supports text search, annotations and adding comments.\n" 12 | //% "\n" 13 | //% "Supported documents and formats include:\n" 14 | //% " - PDF documents\n" 15 | //% " - Text documents (.doc, .docx, .odt, .rtf and .txt)\n" 16 | //% " - Spreadsheets (.xls, .xlsx, .ods and .csv)\n" 17 | //% " - Presentations (.ppt, .pptx and .odp)\n" 18 | //% "\n" 19 | //% "And dozen other less common document formats.\n" 20 | //% "\n" 21 | //% "Share your documents easily by just tapping the share button on the toolbar." 22 | QT_TRID_NOOP("sailfish-office-la-store_app_description") 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /rpm/sailfish-office.spec: -------------------------------------------------------------------------------- 1 | Name: sailfish-office 2 | Version: 1.5.20 3 | Release: 1 4 | Summary: Sailfish office viewer 5 | License: GPLv2 6 | Source0: %{name}-%{version}.tar.gz 7 | BuildRequires: pkgconfig(Qt5Quick) 8 | BuildRequires: pkgconfig(Qt5Widgets) 9 | BuildRequires: pkgconfig(Qt5DBus) 10 | BuildRequires: pkgconfig(Qt5Sql) 11 | BuildRequires: pkgconfig(sailfishsilica) >= 1.1.8 12 | BuildRequires: libqt5sparql-devel 13 | BuildRequires: poppler-qt5-devel poppler-qt5 poppler-devel poppler 14 | BuildRequires: mapplauncherd-qt5-devel 15 | BuildRequires: cmake 16 | BuildRequires: qt5-qttools-linguist 17 | BuildRequires: pkgconfig(icu-i18n) 18 | Requires: calligra-components 19 | Requires: calligra-filters >= 3.1.0+git18 20 | Requires: sailfishsilica-qt5 >= 1.1.107 21 | Requires: sailfish-components-accounts-qt5 22 | Requires: sailfish-components-textlinking 23 | Requires: libqt5sparql-tracker-direct 24 | Requires: sailjail-launch-approval 25 | Requires: nemo-qml-plugin-configuration-qt5 26 | Requires: nemo-qml-plugin-filemanager 27 | Requires: %{name}-all-translations 28 | Requires: sailfish-content-graphics 29 | Requires: qt5-qtdeclarative-import-qtquick2plugin >= 5.4.0 30 | Requires: declarative-transferengine-qt5 >= 0.3.1 31 | 32 | %description 33 | %{summary}. 34 | 35 | %package ts-devel 36 | Summary: Translation source for %{name} 37 | License: GPLv2 38 | 39 | %description ts-devel 40 | %{summary}. 41 | 42 | %prep 43 | %setup -q -n %{name}-%{version} 44 | 45 | %build 46 | %cmake 47 | %cmake_build 48 | 49 | %install 50 | %cmake_install 51 | 52 | %files 53 | %license LICENSE 54 | %{_bindir}/* 55 | %{_libdir}/qt5/qml/Sailfish/Office/ 56 | %{_datadir}/applications/*.desktop 57 | %{_datadir}/%{name}/ 58 | %{_datadir}/translations/*.qm 59 | %{_datadir}/mapplauncherd/privileges.d/sailfish-office.privileges 60 | 61 | %files ts-devel 62 | %{_datadir}/translations/source/*.ts 63 | -------------------------------------------------------------------------------- /sailfish-office.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Name=Documents 4 | X-Amber-Translation-Id-Name=sailfish-office-ap-name 5 | X-Amber-Translation-Catalog=sailfish-office 6 | Icon=icon-launcher-office 7 | Exec=/usr/bin/sailfish-office %U 8 | DBusActivatable=true 9 | MimeType=application/vnd.oasis.opendocument.spreadsheet;application/x-kspread;application/vnd.ms-excel;text/csv;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;application/vnd.openxmlformats-officedocument.spreadsheetml.template;application/vnd.oasis.opendocument.presentation;application/vnd.oasis.opendocument.presentation-template;application/x-kpresenter;application/vnd.ms-powerpoint;application/vnd.openxmlformats-officedocument.presentationml.presentation;application/vnd.openxmlformats-officedocument.presentationml.template;application/vnd.oasis.opendocument.text-master;application/vnd.oasis.opendocument.text;application/vnd.oasis.opendocument.text-template;application/msword;application/rtf;text/plain;application/x-mswrite;application/vnd.openxmlformats-officedocument.wordprocessingml.document;application/vnd.openxmlformats-officedocument.wordprocessingml.template;application/vnd.ms-works;application/pdf;text/plain; 10 | Comment=Document Viewer 11 | 12 | [X-Sailjail] 13 | Permissions=UserDirs;MediaIndexing;RemovableMedia 14 | ApplicationName=Office 15 | OrganizationName=org.sailfishos 16 | ExecDBus=/usr/bin/sailfish-office -prestart 17 | -------------------------------------------------------------------------------- /sailfish-office.privileges: -------------------------------------------------------------------------------- 1 | # need privileges for accounts 2 | /usr/bin/sailfish-office,a 3 | -------------------------------------------------------------------------------- /tests/00-introduction.txt: -------------------------------------------------------------------------------- 1 | These files describe a set of acceptance tests for the sailfish-office application. 2 | 3 | Each file describes related scenarios with a number of steps to complete each scenario. 4 | 5 | The format is as follows: 6 | 7 | Goal: 8 | Initial Conditions: 10 | Steps: 11 | Step: 12 | Action: 13 | Result: 14 | 15 | Note that if any of the results of a step do not match the expectations, the step fails 16 | and thus the scenario fails. 17 | -------------------------------------------------------------------------------- /tests/00-start-application.txt: -------------------------------------------------------------------------------- 1 | Goal: The application runs. 2 | Initial Conditions: A working Sailfish device (either real or emulated). 3 | Steps: 4 | Step: 5 | Action: Launch the application. 6 | Result: The application starts and displays a list with at least a "This device" item. 7 | 8 | -------------------------------------------------------------------------------- /tests/01-odf-loading.txt: -------------------------------------------------------------------------------- 1 | Goal: Load an ODT text document. 2 | Initial Conditions: 3 | The application starts. (00-start-application) 4 | There is at least one ODT file in the Documents folder on the device. 5 | Steps: 6 | Step: 7 | Action: Tap the "This Device" item in the list. 8 | Result: A page opens that lists the ODT along with other files on the device. 9 | Step: 10 | Action: Tap the ODT file to load. 11 | Result: A page opens and the file starts loading. 12 | Step: 13 | Action: Wait for the file to load. 14 | Result: The document is displayed. 15 | 16 | ---- 17 | 18 | Goal: Load an ODS spreadsheet. 19 | Initial Conditions: 20 | The application starts. (00-start-application) 21 | There is at least one ODS file in the Documents folder on the device. 22 | Steps: 23 | Step: 24 | Action: Tap the "This Device" item in the list. 25 | Result: A page opens that lists the ODS along with other files on the device. 26 | Step: 27 | Action: Tap the ODS file to load. 28 | Result: A page opens and the file starts loading. 29 | Step: 30 | Action: Wait for the file to load. 31 | Result: The document is displayed. 32 | 33 | ---- 34 | 35 | Goal: Load an ODP presentation. 36 | Initial Conditions: 37 | The application starts. (00-start-application) 38 | There is at least one ODP file in the Documents folder on the device. 39 | Steps: 40 | Step: 41 | Action: Tap the "This Device" item in the list. 42 | Result: A page opens that lists the ODP along with other files on the device. 43 | Step: 44 | Action: Tap the ODP file to load. 45 | Result: A page opens and the file starts loading. 46 | Step: 47 | Action: Wait for the file to load. 48 | Result: The document is displayed. 49 | -------------------------------------------------------------------------------- /tests/02-pdf-loading.txt: -------------------------------------------------------------------------------- 1 | Goal: Load a PDF file. 2 | Initial Conditions: 3 | The application starts. (00-start-application) 4 | There is at least one PDF file in the Documents folder on the device. 5 | Steps: 6 | Step: 7 | Action: Tap the "This Device" item in the list. 8 | Result: A page opens that lists the PDF along with other files on the device. 9 | Step: 10 | Action: Tap the PDF file to load. 11 | Result: A page opens and the file starts loading. 12 | Step: 13 | Action: Wait for the file to load. 14 | Result: The document is displayed. 15 | -------------------------------------------------------------------------------- /tests/03-msoffice-loading.txt: -------------------------------------------------------------------------------- 1 | Goal: Load a DOC text document. 2 | Initial Conditions: 3 | The application starts. (00-start-application) 4 | There is at least one DOC file in the Documents folder on the device. 5 | Steps: 6 | Step: 7 | Action: Tap the "This Device" item in the list. 8 | Result: A page opens that lists the DOC file along with other files on the device. 9 | Step: 10 | Action: Tap the DOC file to load. 11 | Result: A page opens and the file starts loading. 12 | Step: 13 | Action: Wait for the file to load. 14 | Result: The document is displayed. 15 | 16 | ---- 17 | 18 | Goal: Load an XLS spreadsheet. 19 | Initial Conditions: 20 | The application starts. (00-start-application) 21 | There is at least one XLS file in the Documents folder on the device. 22 | Steps: 23 | Step: 24 | Action: Tap the "This Device" item in the list. 25 | Result: A page opens that lists the XLS along with other files on the device. 26 | Step: 27 | Action: Tap the XLS file to load. 28 | Result: A page opens and the file starts loading. 29 | Step: 30 | Action: Wait for the file to load. 31 | Result: The document is displayed. 32 | 33 | ---- 34 | 35 | Goal: Load a PPT presentation. 36 | Initial Conditions: 37 | The application starts. (00-start-application) 38 | There is at least one PPT file in the Documents folder on the device. 39 | Steps: 40 | Step: 41 | Action: Tap the "This Device" item in the list. 42 | Result: A page opens that lists the PPT along with other files on the device. 43 | Step: 44 | Action: Tap the PPT file to load. 45 | Result: A page opens and the file starts loading. 46 | Step: 47 | Action: Wait for the file to load. 48 | Result: The document is displayed. 49 | -------------------------------------------------------------------------------- /tests/04-msooxml-loading.txt: -------------------------------------------------------------------------------- 1 | Goal: Load a DOCX text document. 2 | Initial Conditions: 3 | The application starts. (00-start-application) 4 | There is at least one DOCX file in the Documents folder on the device. 5 | Steps: 6 | Step: 7 | Action: Tap the "This Device" item in the list. 8 | Result: A page opens that lists the DOCX file along with other files on the device. 9 | Step: 10 | Action: Tap the DOCX file to load. 11 | Result: A page opens and the file starts loading. 12 | Step: 13 | Action: Wait for the file to load. 14 | Result: The document is displayed. 15 | 16 | ---- 17 | 18 | Goal: Load an XLSX spreadsheet. 19 | Initial Conditions: 20 | The application starts. (00-start-application) 21 | There is at least one XLSX file in the Documents folder on the device. 22 | Steps: 23 | Step: 24 | Action: Tap the "This Device" item in the list. 25 | Result: A page opens that lists the XLSX along with other files on the device. 26 | Step: 27 | Action: Tap the XLSX file to load. 28 | Result: A page opens and the file starts loading. 29 | Step: 30 | Action: Wait for the file to load. 31 | Result: The document is displayed. 32 | 33 | ---- 34 | 35 | Goal: Load a PPTX presentation. 36 | Initial Conditions: 37 | The application starts. (00-start-application) 38 | There is at least one PPTX file in the Documents folder on the device. 39 | Steps: 40 | Step: 41 | Action: Tap the "This Device" item in the list. 42 | Result: A page opens that lists the PPTX along with other files on the device. 43 | Step: 44 | Action: Tap the PPTX file to load. 45 | Result: A page opens and the file starts loading. 46 | Step: 47 | Action: Wait for the file to load. 48 | Result: The document is displayed. 49 | -------------------------------------------------------------------------------- /tests/05-contents-listing.txt: -------------------------------------------------------------------------------- 1 | Goal: List the contents of a Text document. 2 | Initial Conditions: 3 | A Text document - odt, doc, docx - loads and displays. (01-odf-loading, 03-msoffice-loading, 04-msooxml-loading) 4 | The text document loaded has at least one header that normally would generate a Table of Contents. 5 | Steps: 6 | Step: 7 | Action: Tap the display. 8 | Result: A drawer opens from the top listing some options and displaying the navigation control. 9 | Step: 10 | Action: Navigate to the attached page using a right-to-left swipe. 11 | Result: The page changes to one listing the contents of the text document. 12 | 13 | ---- 14 | 15 | Goal: List all sheets of a Spreadsheet document. 16 | Initial Conditions: 17 | A spreadsheet - ods, xls, xlsx - loads and displays. (01-odf-loading, 03-msoffice-loading, 04-msooxml-loading) 18 | Steps: 19 | Step: 20 | Action: Tap the display. 21 | Result: A drawer opens from the top listing some options and displaying the navigation control. 22 | Step: 23 | Action: Navigate to the attached page using a right-to-left swipe. 24 | Result: The page changes to one listing all the sheets in the document. 25 | 26 | ---- 27 | 28 | Goal: List all slides of a presentation. 29 | Initial Conditions: 30 | A presentation - odp, ppt, pptx - loads and displays. (01-odf-loading, 03-msoffice-loading, 04-msooxml-loading) 31 | Steps: 32 | Step: 33 | Action: Tap the display. 34 | Result: A drawer opens from the top listing some options and displaying the navigation control. 35 | Step: 36 | Action: Navigate to the attached page using a right-to-left swipe. 37 | Result: The page changes to one listing all the slides in the presentation. 38 | --------------------------------------------------------------------------------