diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -267,10 +267,17 @@ DBus OpenGL Quick + QuickWidgets Sql WebKit - WebKitWidgets +# WebKitWidgets ) +message("**********************************************************************************************************************") +message("**********************************************************************************************************************") +message("Qt WebKitWidgets is required for Stage's html export preview. This will need porting, as that module no longer exists.") +message("**********************************************************************************************************************") +message("**********************************************************************************************************************") + # Qt5Declarative was removed in Qt 5.6.0 so search for it in a separate call # Including it in a collected find_package(Qt5 ...) call can lead to a fatal not-found error: # * Qt5 (required version >= 5.3.0) @@ -291,6 +298,10 @@ PURPOSE "Required for QtQuick2 components" TYPE RECOMMENDED ) +set_package_properties(Qt5QuickWidgets PROPERTIES + PURPOSE "Required for Calligra Gemini" + TYPE RECOMMENDED +) set_package_properties(Qt5Sql PROPERTIES PURPOSE "Optional for Sheets' database connection" TYPE OPTIONAL @@ -360,9 +371,11 @@ # overcome some platform incompatibilities if(WIN32) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/winquirks) - add_definitions(-D_USE_MATH_DEFINES) - add_definitions(-DNOMINMAX) + if(NOT MINGW) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/winquirks) + add_definitions(-D_USE_MATH_DEFINES) + add_definitions(-DNOMINMAX) + endif() set(WIN32_PLATFORM_NET_LIBS ws2_32.lib netapi32.lib) endif() @@ -816,10 +829,9 @@ ## -## Test for libgit2 and Libqgit2 +## Test for libgit2 ## macro_optional_find_package(Libgit2) -macro_optional_find_package(Libqgit2) ## ## Generate a file for prefix information @@ -987,9 +999,9 @@ Soprano_FOUND "Soprano not found" ) -calligra_drop_product_on_bad_condition( PART_STAGE - Qt5WebKitWidgets_FOUND "Qt5WebKitWidgets devel not found" -) +# calligra_drop_product_on_bad_condition( PART_STAGE +# Qt5WebKitWidgets_FOUND "Qt5WebKitWidgets devel not found" +# ) calligra_drop_product_on_bad_condition( PART_SHEETS EIGEN3_FOUND "Eigen devel not found" @@ -1081,7 +1093,6 @@ calligra_drop_product_on_bad_condition( PLUGIN_CALLIGRAGEMINI_GIT LIBGIT2_FOUND "libgit2 devel not found" - LIBQGIT2_FOUND "libqgit2 devel not found" ) calligra_drop_product_on_bad_condition( PART_QTQUICK diff --git a/CalligraProducts.cmake b/CalligraProducts.cmake --- a/CalligraProducts.cmake +++ b/CalligraProducts.cmake @@ -99,7 +99,7 @@ calligra_define_product(DOC "Calligra Documentations" STAGING) # staging apps -calligra_define_product(APP_GEMINI "The Calligra Gemini application" STAGING REQUIRES PART_QTQUICK PART_COMPONENTS) +calligra_define_product(APP_GEMINI "The Calligra Gemini application" REQUIRES PART_COMPONENTS) # TODO: this needs to be split up by app products @@ -132,7 +132,7 @@ calligra_define_product(PLUGIN_SHAPEFILTEREFFECTS "Default shape filtereffects plugin" REQUIRES LIB_CALLIGRA) calligra_define_product(PLUGIN_STENCILSDOCKER "Stencils docker plugin" REQUIRES LIB_CALLIGRA) calligra_define_product(PLUGIN_KARBONPLUGINS "Semantic items plugins" REQUIRES LIB_CALLIGRA) -calligra_define_product(PLUGIN_CALLIGRAGEMINI_GIT "Git support plugin for Calligra Gemini" UNPORTED) +calligra_define_product(PLUGIN_CALLIGRAGEMINI_GIT "Git support plugin for Calligra Gemini") # staging plugins calligra_define_product(PLUGIN_THREEDSHAPE "3D shape plugin" STAGING REQUIRES LIB_CALLIGRA) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -28,7 +28,11 @@ impl/ComponentsKoCanvasController.cpp ) +if(WIN32) +add_library(CalligraComponentsPlugin MODULE ${components_SRCS}) +else() add_library(CalligraComponentsPlugin SHARED ${components_SRCS}) +endif() target_include_directories(CalligraComponentsPlugin PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} @@ -45,5 +49,5 @@ koplugin ) -install(TARGETS CalligraComponentsPlugin DESTINATION ${QML_INSTALL_DIR}/org/kde/calligra) -install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/calligra) +install(TARGETS CalligraComponentsPlugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/calligra) +install(FILES qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/calligra) diff --git a/components/Document.cpp b/components/Document.cpp --- a/components/Document.cpp +++ b/components/Document.cpp @@ -186,7 +186,7 @@ QObject* Document::part() const { - return nullptr; + return d->impl->part(); } QObject* Document::document() const diff --git a/components/ViewController.cpp b/components/ViewController.cpp --- a/components/ViewController.cpp +++ b/components/ViewController.cpp @@ -283,10 +283,11 @@ ViewModeSynchronisationObject* syncObject = static_cast(event)->synchronisationObject(); if (d->canvasController) { - syncObject->documentOffset = d->canvasController->documentOffset(); + syncObject->scrollBarValue = d->canvasController->documentOffset(); syncObject->zoomLevel = zoom(); syncObject->activeToolId = KoToolManager::instance()->activeToolId(); syncObject->shapes = d->canvasController->canvas()->shapeManager()->shapes(); + syncObject->currentIndex = d->view->document()->currentIndex(); syncObject->initialized = true; } @@ -304,7 +305,13 @@ setZoom(syncObject->zoomLevel); qApp->processEvents(); - emit d->canvasController->proxyObject->moveDocumentOffset(syncObject->documentOffset); + if(syncObject->scrollBarValue.isNull()) { + d->view->document()->setCurrentIndex(syncObject->currentIndex); + } + else { + d->canvasController->setScrollBarValue(syncObject->scrollBarValue); + } + emit d->view->document()->requestViewUpdate(); } return true; diff --git a/components/impl/DocumentImpl.h b/components/impl/DocumentImpl.h --- a/components/impl/DocumentImpl.h +++ b/components/impl/DocumentImpl.h @@ -62,6 +62,7 @@ KoZoomController* zoomController() const; QSize documentSize() const; KoDocument* koDocument() const; + virtual QObject* part() const = 0; Q_SIGNALS: void documentSizeChanged(); diff --git a/components/impl/SpreadsheetImpl.h b/components/impl/SpreadsheetImpl.h --- a/components/impl/SpreadsheetImpl.h +++ b/components/impl/SpreadsheetImpl.h @@ -40,6 +40,7 @@ virtual void setCurrentIndex(int newValue); virtual int indexCount() const; virtual QUrl urlAtPoint(QPoint point); + virtual QObject* part() const; private Q_SLOTS: void updateDocumentSize(const QSize& size); diff --git a/components/impl/SpreadsheetImpl.cpp b/components/impl/SpreadsheetImpl.cpp --- a/components/impl/SpreadsheetImpl.cpp +++ b/components/impl/SpreadsheetImpl.cpp @@ -238,3 +238,8 @@ } return QUrl(); } + +QObject* SpreadsheetImpl::part() const +{ + return d->part; +} diff --git a/components/impl/TextDocumentImpl.cpp b/components/impl/TextDocumentImpl.cpp --- a/components/impl/TextDocumentImpl.cpp +++ b/components/impl/TextDocumentImpl.cpp @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include "ComponentsKoCanvasController.h" #include @@ -51,9 +53,9 @@ Private() : part{nullptr}, document{nullptr} { } - KWPart* part; - KWDocument* document; - KWCanvasItem* canvas; + QPointer part; + QPointer document; + QPointer canvas; QTimer indexChangedDelay; QList< QPair< QRectF, QUrl > > links; @@ -184,6 +186,7 @@ d->document->setCheckAutoSaveFile(false); bool retval = d->document->openUrl(url); + qDebug() << "Attempting to open" << url << "and our success was" << retval; d->canvas = static_cast(d->part->canvasItem(d->document)); diff --git a/components/models/TextContentsModelImpl.cpp b/components/models/TextContentsModelImpl.cpp --- a/components/models/TextContentsModelImpl.cpp +++ b/components/models/TextContentsModelImpl.cpp @@ -64,10 +64,12 @@ { d->document = qobject_cast(document); Q_ASSERT(d->document); - d->textDocument = d->document->mainFrameSet()->document(); - d->layout = qobject_cast(d->textDocument->documentLayout()); - connect(d->layout, &KoTextDocumentLayout::finishedLayout, this, &TextContentsModelImpl::documentLayoutFinished); - d->layout->scheduleLayout(); + if(d->document->mainFrameSet() && d->document->mainFrameSet()->document()) { + d->textDocument = d->document->mainFrameSet()->document(); + d->layout = qobject_cast(d->textDocument->documentLayout()); + connect(d->layout, &KoTextDocumentLayout::finishedLayout, this, &TextContentsModelImpl::documentLayoutFinished); + d->layout->scheduleLayout(); + } d->canvas = canvas; } diff --git a/filters/libmsooxml/CMakeLists.txt b/filters/libmsooxml/CMakeLists.txt --- a/filters/libmsooxml/CMakeLists.txt +++ b/filters/libmsooxml/CMakeLists.txt @@ -38,7 +38,6 @@ PredefinedShapeHelper.cpp ComplexShapeHandler.cpp ${CMAKE_SOURCE_DIR}/filters/sheets/xlsx/XlsxChartOdfWriter.cpp - ${CMAKE_SOURCE_DIR}/filters/libodf2/chart/KoOdfChartWriter.cpp # TODO: move back to kolibs KoOdfExporter.cpp ) diff --git a/filters/stage/pptx/CMakeLists.txt b/filters/stage/pptx/CMakeLists.txt --- a/filters/stage/pptx/CMakeLists.txt +++ b/filters/stage/pptx/CMakeLists.txt @@ -16,7 +16,6 @@ PptxXmlCommentsReader.cpp PptxXmlCommentAuthorsReader.cpp ${CMAKE_SOURCE_DIR}/filters/sheets/xlsx/XlsxChartOdfWriter.cpp - ${CMAKE_SOURCE_DIR}/filters/libodf2/chart/KoOdfChartWriter.cpp ${CMAKE_SOURCE_DIR}/filters/sheets/xlsx/XlsxXmlChartReader.cpp ) diff --git a/filters/words/docx/import/CMakeLists.txt b/filters/words/docx/import/CMakeLists.txt --- a/filters/words/docx/import/CMakeLists.txt +++ b/filters/words/docx/import/CMakeLists.txt @@ -22,7 +22,6 @@ DocxXmlSettingsReader.cpp DocxImport.cpp ${CMAKE_SOURCE_DIR}/filters/sheets/xlsx/XlsxChartOdfWriter.cpp - ${CMAKE_SOURCE_DIR}/filters/libodf2/chart/KoOdfChartWriter.cpp ${CMAKE_SOURCE_DIR}/filters/sheets/xlsx/XlsxXmlChartReader.cpp ) diff --git a/filters/words/msword-odf/CMakeLists.txt b/filters/words/msword-odf/CMakeLists.txt --- a/filters/words/msword-odf/CMakeLists.txt +++ b/filters/words/msword-odf/CMakeLists.txt @@ -22,7 +22,7 @@ add_library(calligra_filter_doc2odt MODULE ${doc2odt_PART_SRCS}) calligra_filter_desktop_to_json(calligra_filter_doc2odt calligra_filter_doc2odt.desktop) -target_link_libraries(calligra_filter_doc2odt kowv2 komain mso) +target_link_libraries(calligra_filter_doc2odt mso kowv2 komain) install(TARGETS calligra_filter_doc2odt DESTINATION ${PLUGIN_INSTALL_DIR}/calligra/formatfilters) diff --git a/filters/words/msword-odf/wv2/CMakeLists.txt b/filters/words/msword-odf/wv2/CMakeLists.txt --- a/filters/words/msword-odf/wv2/CMakeLists.txt +++ b/filters/words/msword-odf/wv2/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required(VERSION 2.8.0) +add_definitions(-DUNICODE -D_UNICODE) + #cmake_policy CMP0017 was introduced in version 2.8.4 if(${CMAKE_VERSION} VERSION_GREATER 2.8.3) cmake_policy(SET CMP0017 NEW) @@ -64,6 +66,9 @@ check_function_exists( isinf HAVE_FUNC_ISINF ) check_function_exists( isnan HAVE_FUNC_ISNAN ) +if(MINGW) +add_definitions( -DHAVE_FUNC_ISFINITE ) +endif() check_function_exists( finite HAVE_FUNC_FINITE ) check_function_exists( _finite HAVE_FUNC__FINITE ) diff --git a/filters/words/msword-odf/wv2/config.h.cmake b/filters/words/msword-odf/wv2/config.h.cmake --- a/filters/words/msword-odf/wv2/config.h.cmake +++ b/filters/words/msword-odf/wv2/config.h.cmake @@ -12,6 +12,9 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_FLOAT_H 1 +/* Define if you have isfinite */ +#cmakedefine HAVE_FUNC_ISFINITE + /* Define if you have finite */ #cmakedefine HAVE_FUNC_FINITE diff --git a/filters/words/msword-odf/wv2/src/ustring.cpp b/filters/words/msword-odf/wv2/src/ustring.cpp --- a/filters/words/msword-odf/wv2/src/ustring.cpp +++ b/filters/words/msword-odf/wv2/src/ustring.cpp @@ -77,6 +77,8 @@ { #if defined(HAVE_FUNC_ISINF) return (isinf(d) == 1); +#elif defined(HAVE_FUNC_ISFINITE) + return isfinite(d) == 0 && d == d; // ### can we distinguish between + and - ? #elif defined(HAVE_FUNC_FINITE) return finite(d) == 0 && d == d; // ### can we distinguish between + and - ? #elif defined(HAVE_FUNC__FINITE) @@ -90,6 +92,8 @@ { #if defined(HAVE_FUNC_ISINF) return (isinf(d) == -1); +#elif defined(HAVE_FUNC_ISFINITE) + return isfinite(d) == 0 && d == d; // ### #elif defined(HAVE_FUNC_FINITE) return finite(d) == 0 && d == d; // ### #elif defined(HAVE_FUNC__FINITE) diff --git a/gemini/CMakeLists.txt b/gemini/CMakeLists.txt --- a/gemini/CMakeLists.txt +++ b/gemini/CMakeLists.txt @@ -1,9 +1,9 @@ project(calligragemini) # TEMPORARY: for Qt5/KF5 build porting phase deprecation warnings are only annoying noise -if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUC) - add_definitions(-Wno-deprecated -Wno-deprecated-declarations) -endif () +# if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUC) + # add_definitions(-Wno-deprecated -Wno-deprecated-declarations) +# endif () add_subdirectory(lib) if (WIN32) @@ -55,12 +55,8 @@ ThumbnailHelperImpl.cpp ) -if (WIN32) - set(calligragemini_SRCS ${calligragemini_SRCS} calligrageminiwin.rc) -else () - file(GLOB ICONS_SRCS "pics/*-apps-calligragemini.png") - ecm_add_app_icon(calligragemini_SRCS ICONS ${ICONS_SRCS}) -endif () +file(GLOB ICONS_SRCS "pics/*-apps-calligragemini.png") +ecm_add_app_icon(calligragemini_SRCS ICONS ${ICONS_SRCS}) # Thumbnail helper application # ============================================================================= @@ -78,6 +74,7 @@ target_link_libraries(calligragemini Qt5::Quick + Qt5::QuickWidgets Qt5::Qml Qt5::Gui Qt5::Core diff --git a/gemini/CloudAccountsModel.cpp b/gemini/CloudAccountsModel.cpp --- a/gemini/CloudAccountsModel.cpp +++ b/gemini/CloudAccountsModel.cpp @@ -241,7 +241,7 @@ void CloudAccountsModel::removeAccount(int index) { - if(index > -1 && index < d->entries.count() - 1) + if(index > -1 && index < d->entries.count()) { beginRemoveRows(QModelIndex(), index, index); delete(d->entries.takeAt(index)); diff --git a/gemini/MainWindow.cpp b/gemini/MainWindow.cpp --- a/gemini/MainWindow.cpp +++ b/gemini/MainWindow.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include #include @@ -40,7 +40,6 @@ #include #include -#include #include #include #include @@ -88,7 +87,7 @@ #ifdef Q_OS_WIN // Slate mode/docked detection stuff -#include +#include #define SM_CONVERTIBLESLATEMODE 0x2003 #define SM_SYSTEMDOCKED 0x2004 #endif @@ -103,7 +102,7 @@ , desktopView(0) , currentView(0) , settings(0) - , slateMode(true) + , slateMode(false) , docked(false) , touchKoView(0) , touchEventReceiver(0) @@ -119,17 +118,16 @@ , alternativeSaveAction(0) { #ifdef Q_OS_WIN -// slateMode = (GetSystemMetrics(SM_CONVERTIBLESLATEMODE) == 0); -// docked = (GetSystemMetrics(SM_SYSTEMDOCKED) != 0); + // slateMode = (GetSystemMetrics(SM_CONVERTIBLESLATEMODE) == 0); + // docked = (GetSystemMetrics(SM_SYSTEMDOCKED) != 0); #endif fullScreenThrottle = new QTimer(qq); fullScreenThrottle->setInterval(500); fullScreenThrottle->setSingleShot(true); } MainWindow* q; bool allowClose; - QWidget* touchWidget; - QQuickView* touchView; + QQuickWidget* touchView; QPointer desktopView; QObject* currentView; Settings *settings; @@ -155,7 +153,7 @@ void initTouchView(QObject* parent) { - touchView = new QQuickView(); + touchView = new QQuickWidget(); QmlGlobalEngine::instance()->setEngine(touchView->engine()); touchView->engine()->addImageProvider(QLatin1String("recentimage"), new RecentImageImageProvider); touchView->engine()->rootContext()->setContextProperty("mainWindow", parent); @@ -187,7 +185,8 @@ touchView->engine()->addImportPath(appdir.canonicalPath() + "/imports"); touchView->engine()->addImportPath(appdir.canonicalPath() + "/lib/calligra/imports"); touchView->engine()->addImportPath(appdir.canonicalPath() + "/lib64/calligra/imports"); - QString mainqml = appdir.canonicalPath() + "/share/apps/calligragemini/calligragemini.qml"; + touchView->engine()->addImportPath(appdir.canonicalPath() + "/bin/data/calligragemini"); + QString mainqml = appdir.canonicalPath() + "/bin/data/calligragemini/calligragemini.qml"; #else QString mainqml = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("calligragemini/calligragemini.qml")); #endif @@ -199,7 +198,7 @@ QFileInfo fi(mainqml); touchView->setSource(QUrl::fromLocalFile(fi.canonicalFilePath())); - touchView->setResizeMode( QQuickView::SizeRootObjectToView ); + touchView->setResizeMode( QQuickWidget::SizeRootObjectToView ); toDesktop = new QAction(q); toDesktop->setEnabled(true); @@ -217,8 +216,6 @@ if(settings->currentFile().isEmpty()) { return; } - // Tell the iconloader about share/apps/calligra/icons - KIconLoader::global()->addAppDir("calligra"); // Initialize all Calligra directories etc. KoGlobal::initialize(); @@ -286,11 +283,12 @@ qmlRegisterType("org.calligra", 1, 0, "TemplatesModel"); qmlRegisterType("org.calligra", 1, 0, "CloudAccountsModel"); qmlRegisterType(); + qRegisterMetaType(); qApp->setActiveWindow( this ); - setWindowTitle(i18n("Calligra Gemini")); setWindowIcon(koIcon("calligragemini"));//gemini")); + resize(QApplication::desktop()->availableGeometry().size() * 3/4); foreach(const QString &fileName, fileNames) { DocumentManager::instance()->recentFileManager()->addRecent( QDir::current().absoluteFilePath( fileName ) ); @@ -348,6 +346,7 @@ { QTime timer; timer.start(); + qDebug() << "Switching to touch"; if (d->toTouch) { @@ -369,13 +368,7 @@ d->desktopView->setParent(0); } - QWidget* container = QWidget::createWindowContainer(d->touchView); - d->touchWidget = new QWidget(); - d->touchWidget->setLayout(new QVBoxLayout()); - d->touchWidget->layout()->setContentsMargins(0,0,0,0); - d->touchWidget->layout()->setSpacing(0); - d->touchWidget->layout()->addWidget(container); - setCentralWidget(d->touchWidget); + setCentralWidget(d->touchView); qApp->processEvents(); d->touchView->setVisible(true); resize(size()); @@ -393,7 +386,7 @@ void MainWindow::touchChange() { - if (centralWidget() != d->touchWidget || !d->syncObject) + if (centralWidget() != d->touchView || !d->syncObject) return; if (d->desktopView) @@ -423,6 +416,7 @@ { QTime timer; timer.start(); + qDebug() << "Switching to desktop"; if (d->toDesktop) d->toDesktop->setEnabled(false); @@ -442,13 +436,9 @@ if (d->currentTouchPage == "MainPage") { - d->touchWidget->setParent(0); d->touchView->setParent(0); d->touchView->setVisible(false); setCentralWidget(d->desktopView); - if(d->touchWidget) { - d->touchWidget = 0; - } } if (view) { @@ -470,8 +460,9 @@ if(DocumentManager::instance()->document()) { disconnect(DocumentManager::instance()->document(), SIGNAL(modified(bool)), this, SLOT(resetWindowTitle())); } - DocumentManager::instance()->setDocAndPart(qobject_cast(document), qobject_cast(part)); + qDebug() << "Attempting to set doc and part to" << document << "and" << part; d->touchEventReceiver = d->touchView->rootObject()->findChild("controllerItem"); + DocumentManager::instance()->setDocAndPart(qobject_cast(document), qobject_cast(part)); if(DocumentManager::instance()->document()) { connect(DocumentManager::instance()->document(), SIGNAL(modified(bool)), this, SLOT(resetWindowTitle())); } @@ -630,7 +621,7 @@ dialog.setMimeTypeFilters(mimeFilter); QString filename = dialog.filename(); if(!filename.isEmpty()) { - QMetaObject::invokeMethod(d->touchView->rootObject(), "openFile", Q_ARG(QVariant, filename)); + QMetaObject::invokeMethod(d->touchView->rootObject(), "openFile", Q_ARG(QVariant, filename), Q_ARG(QVariant, 0)); } } @@ -691,7 +682,7 @@ { Q_UNUSED(key) Q_UNUSED(v) - if(centralWidget() == d->touchWidget) + if(centralWidget() == d->touchView) return; } diff --git a/gemini/Settings.cpp b/gemini/Settings.cpp --- a/gemini/Settings.cpp +++ b/gemini/Settings.cpp @@ -61,7 +61,8 @@ QString Settings::currentFile() const { - return d->currentFile; + QUrl url = QUrl::fromLocalFile(d->currentFile); + return url.toString(); } QString Settings::currentFileClass() const diff --git a/gemini/Theme.h b/gemini/Theme.h --- a/gemini/Theme.h +++ b/gemini/Theme.h @@ -22,6 +22,7 @@ #include #include +#include class Theme : public QObject { @@ -221,6 +222,10 @@ * Get an icon from the theme. */ Q_INVOKABLE QUrl icon(const QString& name, bool useSystemFallback = false); + /** + * Get an icon from the theme. + */ + Q_INVOKABLE QIcon iconActual(const QString& name); /** * Get a font from the theme. */ diff --git a/gemini/Theme.cpp b/gemini/Theme.cpp --- a/gemini/Theme.cpp +++ b/gemini/Theme.cpp @@ -323,6 +323,11 @@ return QUrl::fromLocalFile(url); } +QIcon Theme::iconActual(const QString& name) +{ + return QIcon(icon(name).toLocalFile()); +} + QString Theme::imagePath() const { return d->imagePath; @@ -368,7 +373,7 @@ // for now, the app in bin/ and we still use the env.bat script appdir.cdUp(); - qml = QString("%1/share/apps/calligragemini/themes/%2/theme.qml").arg(appdir.canonicalPath(), id); + qml = QString("%1/bin/data/calligragemini/themes/%2/theme.qml").arg(appdir.canonicalPath(), id); #else const QString qmlFileSubPath = QStringLiteral("calligragemini/themes/") + id + QStringLiteral("/theme.qml"); qml = QStandardPaths::locate(QStandardPaths::GenericDataLocation, qmlFileSubPath); diff --git a/gemini/calligragemini.qml b/gemini/calligragemini.qml --- a/gemini/calligragemini.qml +++ b/gemini/calligragemini.qml @@ -20,12 +20,9 @@ import QtQuick.Controls 1.3 import "qml" import "qml/components" -import org.kde.calligra 1.0 as Calligra Item { id: base; -// width: 1280; -// height: 768; onWidthChanged: Constants.setGridWidth( width / Constants.GridColumns ); onHeightChanged: Constants.setGridHeight( height / Constants.GridRows ); property QtObject window: mainWindow; @@ -36,6 +33,8 @@ RecentFileManager.addRecent(fileName); mainWindow.setAlternativeSaveAction(alternativeSaveAction); } + function applicationWindow() { return base; } + property QtObject pageStack: mainPageStack; StackView { id: mainPageStack; anchors.fill: parent; diff --git a/gemini/cloud/dropbox/CMakeLists.txt b/gemini/cloud/dropbox/CMakeLists.txt --- a/gemini/cloud/dropbox/CMakeLists.txt +++ b/gemini/cloud/dropbox/CMakeLists.txt @@ -13,7 +13,11 @@ controller.cc dropboxplugin.cpp) +if(WIN32) +add_library(calligrageminidropboxplugin MODULE ${dropbox_plugin_SRCS} ${dropbox_lib_SRCS}) +else() add_library(calligrageminidropboxplugin SHARED ${dropbox_plugin_SRCS} ${dropbox_lib_SRCS}) +endif() target_link_libraries(calligrageminidropboxplugin Qt5::Core diff --git a/gemini/cloud/git/CMakeLists.txt b/gemini/cloud/git/CMakeLists.txt --- a/gemini/cloud/git/CMakeLists.txt +++ b/gemini/cloud/git/CMakeLists.txt @@ -1,7 +1,4 @@ -include_directories(${LIBGIT2_INCLUDE_DIR} ${LIBQGIT2_INCLUDE_DIR}) - -# LibQGit2 requires exception support to be turned on -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions") +include_directories(${LIBGIT2_INCLUDE_DIR}) set(git_plugin_SRCS gitplugin.cpp @@ -11,15 +8,20 @@ checkoutcreator.cpp ) -automoc4_add_library(calligrageminigitplugin MODULE ${git_plugin_SRCS}) +if(WIN32) +add_library(calligrageminigitplugin MODULE ${git_plugin_SRCS}) +else() +add_library(calligrageminigitplugin SHARED ${git_plugin_SRCS}) +endif() target_link_libraries(calligrageminigitplugin - Qt5::Declarative - Qt5::Gui Qt5::Core + Qt5::Gui + Qt5::Qml + Qt5::Quick ${LIBGIT2_LIBRARIES} - ${LIBQGIT2_LIBRARIES} komain + KF5::I18n ) install(TARGETS calligrageminigitplugin DESTINATION ${QML_INSTALL_DIR}/Calligra/Gemini/Git) diff --git a/gemini/cloud/git/checkoutcreator.cpp b/gemini/cloud/git/checkoutcreator.cpp --- a/gemini/cloud/git/checkoutcreator.cpp +++ b/gemini/cloud/git/checkoutcreator.cpp @@ -21,31 +21,34 @@ #include "checkoutcreator.h" -#include #include #include #include #include +#include #include #include #include #include -#include -#include +#include +#include class CheckoutCreator::Private { public: - Private() - : needsPrivateKeyPassphrase(false) + Private(CheckoutCreator* qq) + : q(qq) + , needsPrivateKeyPassphrase(false) , signature(0) + , progress(0) {} ~Private() { git_signature_free(signature); } + CheckoutCreator* q; QString privateKey; QString publicKey; QString userForRemote; @@ -55,12 +58,14 @@ QString userEmail; git_signature* signature; + int progress; + QString getPassword() { if(!needsPrivateKeyPassphrase) return QString(); KPasswordDialog dlg; - dlg.setCaption("Private Key Passphrase"); + dlg.setWindowTitle("Private Key Passphrase"); dlg.setPrompt("Your private key file requires a password. Please enter it here. You will be asked again each time it is accessed, and the password is not stored."); dlg.exec(); return dlg.password(); @@ -119,27 +124,58 @@ git_signature_now(&signature, userName.toLocal8Bit(), userEmail.toLocal8Bit()); return true; } + + static int transferProgressCallback(const git_transfer_progress* stats, void* data) + { + if (!data) { + return 1; + } + + Private *payload = static_cast(data); + int percent = (int)(0.5 + 100.0 * ((double)stats->received_objects) / ((double)stats->total_objects)); + if (percent != payload->progress) { + emit payload->q->cloneProgress(percent); + payload->progress = percent; + } + return 0; + } + + static int acquireCredentialsCallback(git_cred **cred, const char */*url*/, const char *username_from_url, unsigned int /*allowed_types*/, void *data) + { + int result = -1; + if (data) { + Private* payload = static_cast(data); + if(payload->needsPrivateKeyPassphrase) { + result = git_cred_ssh_key_new(cred, username_from_url, payload->publicKey.toLatin1(), payload->privateKey.toLatin1(), payload->getPassword().toLatin1()); + } + else { + result = git_cred_ssh_key_new(cred, username_from_url, payload->publicKey.toLatin1(), payload->privateKey.toLatin1(), ""); + } + } + + return result; + } }; CheckoutCreator::CheckoutCreator(QObject* parent) : QObject(parent) - , d(new Private) + , d(new Private(this)) { - LibQGit2::initLibQGit2(); + git_libgit2_init(); } CheckoutCreator::~CheckoutCreator() { - LibQGit2::shutdownLibQGit2(); + git_libgit2_shutdown(); delete d; } QString CheckoutCreator::getFile(QString caption, QString filter, QString extraSubDir) const { QUrl searchDir; if(QDir::home().exists(extraSubDir)) searchDir = QUrl(QDir::homePath().append(QDir::separator()).append(extraSubDir)); - QString url = KFileDialog::getOpenFileName(searchDir, filter, 0, caption); + QString url = QFileDialog::getOpenFileName(0, caption, searchDir.toLocalFile(), filter); return url; } @@ -161,15 +197,15 @@ { if(!d->checkUserDetails()) { KMessageBox::sorry(0, "I'm sorry, we cannot perform git actions without a name and email set, and the git setup on this machine lacks this information. As a result, we are aborting this clone. Please try again, and enter your name and email next time."); - LibQGit2::shutdownLibQGit2(); + git_libgit2_shutdown(); return QString(); } if(userVisibleName.isEmpty()) { // this should normally not be hit, as the form which calls this checks for this // anyway, but let's just be sure KMessageBox::sorry(0, "You forgot to name your account. Please do that and try again."); - LibQGit2::shutdownLibQGit2(); + git_libgit2_shutdown(); return QString(); } @@ -182,7 +218,7 @@ if(!QFile::exists(d->publicKey) && credentialsOk) { credentialsOk = false; } if(!credentialsOk) { KMessageBox::sorry(0, "Something is wrong with your security credentials. Please check them and try again. This is likely due to one or another keyfile not existing, or there being no username entered."); - LibQGit2::shutdownLibQGit2(); + git_libgit2_shutdown(); return QString(); } @@ -196,16 +232,18 @@ } QString checkoutLocation = QString("%1%2%3").arg(localPath).arg(QDir::separator()).arg(repoName); - LibQGit2::Repository repo; - connect(&repo, SIGNAL(cloneProgress(int)), this, SIGNAL(cloneProgress(int))); - try { - repo.setRemoteCredentials("origin", LibQGit2::Credentials::ssh(d->privateKey, d->publicKey, d->userForRemote.toUtf8(), d->getPassword().toUtf8())); - repo.clone(url, checkoutLocation); - } - catch (const LibQGit2::Exception& ex) { - qDebug() << ex.what() << ex.category(); - return QString(); - } + + git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; + clone_opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + // clone_opts.checkout_opts.progress_cb = &Private::transferProgressCallback; + // clone_opts.checkout_opts.progress_payload = (void*)this->d; + clone_opts.fetch_opts.callbacks.transfer_progress = &Private::transferProgressCallback; + clone_opts.fetch_opts.callbacks.credentials = &Private::acquireCredentialsCallback; + clone_opts.fetch_opts.callbacks.payload = (void*)this->d; + + git_repository *repo = NULL; + int error = git_clone(&repo, url.toLatin1(), checkoutLocation.toLatin1(), &clone_opts); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return QString(); } return checkoutLocation; } diff --git a/gemini/cloud/git/documentlistmodel.h b/gemini/cloud/git/documentlistmodel.h --- a/gemini/cloud/git/documentlistmodel.h +++ b/gemini/cloud/git/documentlistmodel.h @@ -23,21 +23,21 @@ #define CALLIGRAGEMINI_GIT_DOCUMENTLISTMODEL_H #include -#include +#include #include #include class SearchThread; -class DocumentListModel : public QAbstractListModel, public QDeclarativeParserStatus +class DocumentListModel : public QAbstractListModel, public QQmlParserStatus { Q_OBJECT Q_PROPERTY(DocumentListModel::DocumentType filter READ filter WRITE setFilter NOTIFY filterChanged) Q_PROPERTY(QString documentsFolder READ documentsFolder CONSTANT) Q_ENUMS(GroupBy) Q_ENUMS(Filter) Q_ENUMS(DocumentType) - Q_INTERFACES(QDeclarativeParserStatus) + Q_INTERFACES(QQmlParserStatus) public: explicit DocumentListModel(QObject *parent = 0); diff --git a/gemini/cloud/git/gitcontroller.cpp b/gemini/cloud/git/gitcontroller.cpp --- a/gemini/cloud/git/gitcontroller.cpp +++ b/gemini/cloud/git/gitcontroller.cpp @@ -23,6 +23,7 @@ #include "documentlistmodel.h" #include +#include #include #include @@ -36,19 +37,19 @@ #include #include -#include -#include - #include #include #include #include #include +#include +#include class GitOpsThread::Private { public: - Private(QString privateKey, QString publicKey, QString userForRemote, bool needsPrivateKeyPassphrase, git_signature* signature, QString gitDir, GitOperation operation, QString currentFile, QString message) - : privateKey(privateKey) + Private(GitOpsThread* qq, QString privateKey, QString publicKey, QString userForRemote, bool needsPrivateKeyPassphrase, git_signature* signature, QString gitDir, GitOperation operation, QString currentFile, QString message) + : q(qq) + , privateKey(privateKey) , publicKey(publicKey) , userForRemote(userForRemote) , needsPrivateKeyPassphrase(needsPrivateKeyPassphrase) @@ -58,8 +59,10 @@ , signature(signature) , gitDir(gitDir) , gitOp(operation) + , progress(0) {} + GitOpsThread* q; QString privateKey; QString publicKey; QString userForRemote; @@ -73,12 +76,14 @@ QString gitDir; GitOperation gitOp; + int progress; + QString getPassword() { if(!needsPrivateKeyPassphrase) return QString(); KPasswordDialog dlg; - dlg.setCaption("Private Key Passphrase"); + dlg.setWindowTitle("Private Key Passphrase"); dlg.setPrompt("Your private key file requires a password. Please enter it here. You will be asked again each time it is accessed, and the password is not stored."); dlg.exec(); return dlg.password(); @@ -93,11 +98,42 @@ } return true; } + + static int transferProgressCallback(const git_transfer_progress* stats, void* data) + { + if (!data) { + return 1; + } + + Private *payload = static_cast(data); + int percent = (int)(0.5 + 100.0 * ((double)stats->received_objects) / ((double)stats->total_objects)); + if (percent != payload->progress) { + emit payload->q->transferProgress(percent); + payload->progress = percent; + } + return 0; + } + + static int acquireCredentialsCallback(git_cred **cred, const char */*url*/, const char *username_from_url, unsigned int /*allowed_types*/, void *data) + { + int result = -1; + if (data) { + Private* payload = static_cast(data); + if(payload->needsPrivateKeyPassphrase) { + result = git_cred_ssh_key_new(cred, username_from_url, payload->publicKey.toLatin1(), payload->privateKey.toLatin1(), payload->getPassword().toLatin1()); + } + else { + result = git_cred_ssh_key_new(cred, username_from_url, payload->publicKey.toLatin1(), payload->privateKey.toLatin1(), ""); + } + } + + return result; + } }; GitOpsThread::GitOpsThread(QString privateKey, QString publicKey, QString userForRemote, bool needsPrivateKeyPassphrase, git_signature* signature, QString gitDir, GitOperation operation, QString currentFile, QString message, QObject *parent) : QObject(parent) - , d(new Private(privateKey, publicKey, userForRemote, needsPrivateKeyPassphrase, signature, gitDir, operation, currentFile, message)) + , d(new Private(this, privateKey, publicKey, userForRemote, needsPrivateKeyPassphrase, signature, gitDir, operation, currentFile, message)) { } @@ -130,233 +166,274 @@ void GitOpsThread::performPush() { - // ensure file is in current repository - LibQGit2::Repository repo; - connect(&repo, SIGNAL(cloneProgress(int)), SIGNAL(transferProgress(int))); - try { - repo.open(QString("%1/.git").arg(d->gitDir)); - // Get the current index - LibQGit2::Index index = repo.index(); - // refresh it, and add the file - index.read(true); - QString relative = d->currentFile.mid(d->gitDir.length() + 1); - index.addByPath(relative); - index.write(); - // convert the index to a tree, so we can use that to create the commit - LibQGit2::Tree newTree = repo.lookupTree(index.createTree()); - // create the commit - LibQGit2::Commit headCommit = repo.lookupCommit(repo.head().target()); - QList parents; - parents << headCommit; - repo.createCommit(newTree, parents, LibQGit2::Signature(d->signature), LibQGit2::Signature(d->signature), d->message, "HEAD"); - - // Find the current branch's upstream remote - git_reference *current_branch; - git_repository_head(¤t_branch, repo.data()); - LibQGit2::Reference currentBranch(current_branch); - - git_reference *upstream; - git_branch_upstream(&upstream, currentBranch.data()); - LibQGit2::Reference upstreamRef(upstream); - - // Now find the name of the remote - git_buf remote_name = {0,0,0}; - git_branch_remote_name(&remote_name, repo.data(), git_reference_name(upstreamRef.data())); - QString remoteName = QString::fromUtf8(remote_name.ptr); - git_buf_free(&remote_name); - - // And the upstream and local branch names... - const char *branch_name; - git_branch_name(&branch_name, upstreamRef.data()); - QString upstreamBranchName = QString::fromUtf8(branch_name); - upstreamBranchName.remove(0, remoteName.length() + 1); - git_branch_name(&branch_name, currentBranch.data()); - QString branchName = QString::fromUtf8(branch_name); - - repo.setRemoteCredentials(remoteName, LibQGit2::Credentials::ssh(d->privateKey, d->publicKey, d->userForRemote.toUtf8(), d->getPassword().toUtf8())); - connect(repo.remote(remoteName), SIGNAL(transferProgress(int)), SIGNAL(transferProgress(int))); - LibQGit2::Push push = repo.push(remoteName); - push.addRefSpec(QString("refs/heads/%1:refs/heads/%2").arg(branchName).arg(upstreamBranchName)); - push.execute(); - emit pushCompleted(); - } - catch (const LibQGit2::Exception& ex) { - qDebug() << ex.what() << ex.category(); - } + git_repository* repository; + int error = git_repository_open(&repository, QString("%1/.git").arg(d->gitDir).toLatin1()); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 1, error code from git2 was" << error << "which is described as" << err->message; return; } + + // Get the current index + git_index* index; + error = git_repository_index(&index, repository); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 2, error code from git2 was" << error << "which is described as" << err->message; return; } + + // refresh it, and add the file + error = git_index_read(index, true); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 3, error code from git2 was" << error << "which is described as" << err->message; return; } +#ifdef Q_OS_WIN + QString relative = d->currentFile.mid(d->gitDir.length() + 9); // That is, 1 for the leading slash, and 8 for the file:/// +#else + QString relative = d->currentFile.mid(d->gitDir.length() + 8); // That is, 1 for the leading slash, and 8 for the file:// +#endif + error = git_index_add_bypath(index, relative.toLocal8Bit()); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 4, error code from git2 was" << error << "which is described as" << err->message; return; } + error = git_index_write(index); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 5, error code from git2 was" << error << "which is described as" << err->message; return; } + + // convert the index to a tree, so we can use that to create the commit + git_tree* tree; + git_oid tree_id; + error = git_index_write_tree(&tree_id, index); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 6, error code from git2 was" << error << "which is described as" << err->message; return; } + error = git_tree_lookup(&tree, repository, &tree_id); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 7, error code from git2 was" << error << "which is described as" << err->message; return; } + + // get where we want to parent things to + git_oid obj; + error = git_reference_name_to_id(&obj, repository, "HEAD"); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 8, error code from git2 was" << error << "which is described as" << err->message; return; } + git_commit *parent = NULL; + error = git_commit_lookup(&parent, repository, &obj); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 9, error code from git2 was" << error << "which is described as" << err->message; return; } + + // create the commit + git_oid oid; + error = git_commit_create_v(&oid, repository, "HEAD", d->signature, d->signature, "UTF-8", d->message.toLatin1(), tree, 1, parent); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 10, error code from git2 was" << error << "which is described as" << err->message; return; } + + error = git_repository_state_cleanup(repository); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 11, error code from git2 was" << error << "which is described as" << err->message; return; } + + + // Find the current branch's upstream remote + git_reference *current_branch; + error = git_repository_head(¤t_branch, repository); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 12, error code from git2 was" << error << "which is described as" << err->message; return; } + + git_reference *upstream; + error = git_branch_upstream(&upstream, current_branch); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 13, error code from git2 was" << error << "which is described as" << err->message; return; } + + // Now find the name of the remote + git_buf remote_name = {0,0,0}; + error = git_branch_remote_name(&remote_name, repository, git_reference_name(upstream)); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 14, error code from git2 was" << error << "which is described as" << err->message; return; } + QString remoteName = QString::fromUtf8(remote_name.ptr); + git_buf_free(&remote_name); + + // And the upstream and local branch names... + const char *branch_name; + error = git_branch_name(&branch_name, upstream); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 15, error code from git2 was" << error << "which is described as" << err->message; return; } + QString upstreamBranchName = QString::fromUtf8(branch_name); + upstreamBranchName.remove(0, remoteName.length() + 1); + error = git_branch_name(&branch_name, current_branch); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 16, error code from git2 was" << error << "which is described as" << err->message; return; } + QString branchName = QString::fromUtf8(branch_name); + + git_remote_callbacks remoteCallbacks = GIT_REMOTE_CALLBACKS_INIT; + remoteCallbacks.payload = (void*)this->d; + remoteCallbacks.transfer_progress = &Private::transferProgressCallback; + remoteCallbacks.credentials = &Private::acquireCredentialsCallback; + git_remote* remote; + error = git_remote_lookup(&remote, repository, "origin"); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 17, error code from git2 was" << error << "which is described as" << err->message; return; } + + char tempPath[512] = "refs/heads/"; + char tempPath2[512] = "refs/heads/"; + strcat(tempPath, branch_name); + strcat(tempPath2, upstreamBranchName.toLocal8Bit()); + char *refs[2] = { tempPath, tempPath2 }; + git_strarray uploadrefs; + uploadrefs.strings = refs; + uploadrefs.count = 2; + + git_push_options pushOptions; + error = git_push_init_options(&pushOptions, GIT_PUSH_OPTIONS_VERSION); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 18, error code from git2 was" << error << "which is described as" << err->message; return; } + pushOptions.callbacks = remoteCallbacks; + + error = git_remote_push(remote, &uploadrefs, &pushOptions); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Push 19, error code from git2 was" << error << "which is described as" << err->message; return; } + + emit pushCompleted(); } void GitOpsThread::performPull() { - LibQGit2::Repository qrepo; - connect(&qrepo, SIGNAL(cloneProgress(int)), SIGNAL(transferProgress(int))); - try { - qrepo.open(QString("%1/.git").arg(d->gitDir)); - - // Find the current branch's upstream remote - git_reference *current_branch; - git_repository_head(¤t_branch, qrepo.data()); - LibQGit2::Reference currentBranch(current_branch); - - git_reference *upstream; - git_branch_upstream(&upstream, currentBranch.data()); - LibQGit2::Reference upstreamRef(upstream); - - // Now find the name of the remote - git_buf remote_name = {0,0,0}; - git_branch_remote_name(&remote_name, qrepo.data(), git_reference_name(upstreamRef.data())); - QString remoteName = QString::fromUtf8(remote_name.ptr); - git_buf_free(&remote_name); - - // Finally set the credentials on it that we're given, and fetch it - qrepo.setRemoteCredentials(remoteName, LibQGit2::Credentials::ssh(d->privateKey, d->publicKey, d->userForRemote.toUtf8(), d->getPassword().toUtf8())); - connect(qrepo.remote(remoteName), SIGNAL(transferProgress(int)), SIGNAL(transferProgress(int))); - qrepo.fetch(remoteName); - - git_branch_upstream(&upstream, currentBranch.data()); - upstreamRef = LibQGit2::Reference(upstream); - - // Let's check and see what sort of merge we should be doing... - git_merge_analysis_t analysis; - git_merge_preference_t preference; - git_merge_head *merge_heads[1]; - - git_merge_head_from_ref(&merge_heads[0], qrepo.data(), upstreamRef.data()); - int error = git_merge_analysis(&analysis, &preference, qrepo.data(), (const git_merge_head **)&merge_heads, 1); - if(error == GIT_OK) { - if(GIT_MERGE_ANALYSIS_UP_TO_DATE == (analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE)) { - // If we're already up to date, yay, no need to do anything! - qDebug() << "all up to date, yeah!"; - git_merge_head_free(merge_heads[0]); - } else if(GIT_MERGE_ANALYSIS_UNBORN == (analysis & GIT_MERGE_ANALYSIS_UNBORN)) { - // this is silly, don't give me an unborn repository you silly person - qDebug() << "huh, we have an unborn repo here..."; - git_merge_head_free(merge_heads[0]); - } else if(GIT_MERGE_ANALYSIS_FASTFORWARD == (analysis & GIT_MERGE_ANALYSIS_FASTFORWARD) && (GIT_MERGE_PREFERENCE_NO_FASTFORWARD != (preference & GIT_MERGE_PREFERENCE_NO_FASTFORWARD))) { - // If the analysis says we can fast forward, then let's fast forward! - // ...unless preferences say to never fast forward, of course - qDebug() << "fast forwarding all up in that thang"; - - // the code below was modified from an original (GPL2) version by the git2r community - const git_oid *oid; - git_buf log_message = {0,0,0}; - git_commit *commit = NULL; - git_tree *tree = NULL; - git_reference *reference = NULL; - git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; - - git_repository_message(&log_message, qrepo.data()); - - oid = git_merge_head_id(merge_heads[0]); - error = git_commit_lookup(&commit, qrepo.data(), oid); + git_repository* repository; + int error = git_repository_open(&repository, QString("%1/.git").arg(d->gitDir).toLatin1()); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return; } + + // Find the current branch's upstream remote + git_reference *current_branch; + error = git_repository_head(¤t_branch, repository); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return; } + + git_reference *upstream; + error = git_branch_upstream(&upstream, current_branch); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return; } + + // Now find the name of the remote + git_buf remote_name = {0,0,0}; + error = git_branch_remote_name(&remote_name, repository, git_reference_name(upstream)); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return; } + + // Finally set the credentials on it that we're given, and fetch it + git_remote_callbacks remoteCallbacks = GIT_REMOTE_CALLBACKS_INIT; + remoteCallbacks.payload = (void*)this->d; + remoteCallbacks.transfer_progress = &Private::transferProgressCallback; + remoteCallbacks.credentials = &Private::acquireCredentialsCallback; + git_remote* remote; + error = git_remote_lookup(&remote, repository, remote_name.ptr); + git_buf_free(&remote_name); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return; } + git_fetch_options fetch_options = GIT_FETCH_OPTIONS_INIT; + fetch_options.callbacks = remoteCallbacks; + error = git_remote_fetch(remote, NULL, &fetch_options, NULL); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return; } + + error = git_branch_upstream(&upstream, current_branch); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return; } + + // Let's check and see what sort of merge we should be doing... + git_merge_analysis_t analysis; + git_merge_preference_t preference; + git_annotated_commit *merge_heads[1]; + + git_annotated_commit_from_ref(&merge_heads[0], repository, upstream); + error = git_merge_analysis(&analysis, &preference, repository, (const git_annotated_commit **)merge_heads, 1); + if(error == GIT_OK) { + if(GIT_MERGE_ANALYSIS_UP_TO_DATE == (analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE)) { + // If we're already up to date, yay, no need to do anything! + qDebug() << "all up to date, yeah!"; + git_annotated_commit_free(merge_heads[0]); + } else if(GIT_MERGE_ANALYSIS_UNBORN == (analysis & GIT_MERGE_ANALYSIS_UNBORN)) { + // this is silly, don't give me an unborn repository you silly person + qDebug() << "huh, we have an unborn repo here..."; + git_annotated_commit_free(merge_heads[0]); + } else if(GIT_MERGE_ANALYSIS_FASTFORWARD == (analysis & GIT_MERGE_ANALYSIS_FASTFORWARD) && (GIT_MERGE_PREFERENCE_NO_FASTFORWARD != (preference & GIT_MERGE_PREFERENCE_NO_FASTFORWARD))) { + // If the analysis says we can fast forward, then let's fast forward! + // ...unless preferences say to never fast forward, of course + qDebug() << "fast forwarding all up in that thang"; + git_merge_options mergeopts = GIT_MERGE_OPTIONS_INIT; + git_checkout_options checkoutopts = GIT_CHECKOUT_OPTIONS_INIT; + checkoutopts.checkout_strategy = GIT_CHECKOUT_SAFE; + git_merge(repository, (const git_annotated_commit **)merge_heads, 1, &mergeopts, &checkoutopts); + + + // the code below was modified from an original (GPL2) version by the git2r community + const git_oid *oid; + git_buf log_message = {0,0,0}; + git_commit *commit = NULL; + git_tree *tree = NULL; + git_reference *reference = NULL; + git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; + + git_repository_message(&log_message, repository); + + oid = git_annotated_commit_id(merge_heads[0]); + error = git_commit_lookup(&commit, repository, oid); + if (error == GIT_OK) { + error = git_commit_tree(&tree, commit); if (error == GIT_OK) { - error = git_commit_tree(&tree, commit); + opts.checkout_strategy = GIT_CHECKOUT_SAFE; + error = git_checkout_tree(repository, (git_object*)tree, &opts); if (error == GIT_OK) { - opts.checkout_strategy = GIT_CHECKOUT_SAFE; - error = git_checkout_tree(qrepo.data(), (git_object*)tree, &opts); - if (error == GIT_OK) { - error = git_repository_head(&reference, qrepo.data()); - if (error == GIT_OK && error != GIT_ENOTFOUND) { - if (error == GIT_OK) { - if (error == GIT_ENOTFOUND) { - error = git_reference_create( - &reference, - qrepo.data(), - "HEAD", - git_commit_id(commit), - 0, /* force */ - d->signature, - log_message.ptr); - } else { - git_reference *target_ref = NULL; - - error = git_reference_set_target( - &target_ref, - reference, - git_commit_id(commit), - d->signature, - log_message.ptr); - - if (target_ref) { - git_reference_free(target_ref); - } + error = git_repository_head(&reference, repository); + if (error == GIT_OK && error != GIT_ENOTFOUND) { + if (error == GIT_OK) { + if (error == GIT_ENOTFOUND) { + error = git_reference_create( + &reference, + repository, + "HEAD", + git_commit_id(commit), + 0, // force + log_message.ptr); + } else { + git_reference *target_ref = NULL; + + error = git_reference_set_target( + &target_ref, + reference, + git_commit_id(commit), + log_message.ptr); + + if (target_ref) { + git_reference_free(target_ref); } } } } } } - if (commit) { - git_commit_free(commit); - } - if (reference) { - git_reference_free(reference); - } - if (tree) { - git_tree_free(tree); - } - // Leaving this code in for now - this /should/ as far as i can tell do the same - // as the code above. However, it looks as though it doesn't. If anybody can work - // out why, i would appreciate learning what went wrong :P - //const git_oid* id = git_merge_head_id(merge_heads[0]); - //LibQGit2::OId mergeId(id); - //LibQGit2::Commit headCommit = qrepo.lookupCommit(mergeId); - - //qrepo.checkoutTree(headCommit.tree()); - //qrepo.head().setTarget(headCommit.oid()); - //qrepo.reset(headCommit); - git_merge_head_free(merge_heads[0]); - git_repository_state_cleanup(qrepo.data()); } - else if(GIT_MERGE_ANALYSIS_NORMAL == (analysis & GIT_MERGE_ANALYSIS_NORMAL)) { - // If the analysis says we are able to do a normal merge, let's attempt one of those... - if(GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY == (preference & GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY)) { - // but only if we're not told to not try and not do fast forwards! - KMessageBox::sorry(0, "Fast Forward Only", "We're attempting to merge, but the repository is set to only do fast forwarding - sorry, we don't support this scenario and you'll need to handle things yourself..."); + if (commit) { + git_commit_free(commit); + } + if (reference) { + git_reference_free(reference); + } + if (tree) { + git_tree_free(tree); + } + git_annotated_commit_free(merge_heads[0]); + git_repository_state_cleanup(repository); + } + else if(GIT_MERGE_ANALYSIS_NORMAL == (analysis & GIT_MERGE_ANALYSIS_NORMAL)) { + // If the analysis says we are able to do a normal merge, let's attempt one of those... + if(GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY == (preference & GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY)) { + // but only if we're not told to not try and not do fast forwards! + KMessageBox::sorry(0, "Fast Forward Only", "We're attempting to merge, but the repository is set to only do fast forwarding - sorry, we don't support this scenario and you'll need to handle things yourself..."); + } else { + git_merge(repository, (const git_annotated_commit **) merge_heads, 1, NULL, NULL); + git_annotated_commit_free(merge_heads[0]); + git_index* index; + git_repository_index(&index, repository); + if (git_index_has_conflicts(index)) { + qDebug() << "There were conflicts merging. Please resolve them and commit"; } else { - git_merge(qrepo.data(), (const git_merge_head **) merge_heads, 1, NULL, NULL); - git_merge_head_free(merge_heads[0]); - if (qrepo.index().hasConflicts()) { - qDebug() << "There were conflicts merging. Please resolve them and commit"; - } else { - git_oid commit_id; - git_buf message = {0,0,0}; - git_commit *parents[2]; - LibQGit2::Index index = qrepo.index(); - LibQGit2::OId tree_id = index.createTree(); - LibQGit2::Tree tree = qrepo.lookupTree(tree_id); - - git_repository_message(&message, qrepo.data()); - const char *branch_name; - git_branch_name(&branch_name, upstreamRef.data()); - QString upstreamBranchName = QString::fromUtf8(branch_name); - git_branch_name(&branch_name, currentBranch.data()); - QString branchName = QString::fromUtf8(branch_name); - - git_reference *upstream; - git_branch_upstream(&upstream, currentBranch.data()); - LibQGit2::Reference upstreamRef(upstream); - - error = git_commit_lookup(&parents[0], qrepo.data(), qrepo.head().target().data()); - d->check_error(error, "looking up current branch"); - error = git_commit_lookup(&parents[1], qrepo.data(), upstreamRef.target().data()); - d->check_error(error, "looking up remote branch"); - - git_commit_create(&commit_id, qrepo.data(), "HEAD", d->signature, d->signature, - NULL, message.ptr, - tree.data(), 2, (const git_commit **) parents); - } + git_buf message = {0, 0, 0}; + git_oid commit_id, tree_id; + git_commit *parents[2]; + git_tree *tree; + + git_index_write_tree(&tree_id, index); + + git_repository_message(&message, repository); + + git_tree_lookup(&tree, repository, &tree_id); + + error = git_commit_lookup(&parents[0], repository, git_reference_target(current_branch)); + d->check_error(error, "looking up current branch"); + error = git_commit_lookup(&parents[1], repository, git_reference_target(upstream)); + d->check_error(error, "looking up remote branch"); + + git_commit_create(&commit_id, repository, "HEAD", d->signature, d->signature, + NULL, message.ptr, + tree, 2, (const git_commit **) parents); + git_tree_free(tree); } - } else { - // how did i get here, i am not good with undefined entries in enums - qDebug() << "wait, what?"; - git_merge_head_free(merge_heads[0]); + git_index_free(index); } + } else { + // how did i get here, i am not good with undefined entries in enums + qDebug() << "wait, what?"; + git_annotated_commit_free(merge_heads[0]); } - git_repository_state_cleanup(qrepo.data()); - emit pullCompleted(); - } catch (const LibQGit2::Exception& ex) { - qDebug() << ex.what() << ex.category(); } + git_repository_state_cleanup(repository); + git_repository_free(repository); + emit pullCompleted(); } class GitController::Private { @@ -393,20 +470,29 @@ if(!needsPrivateKeyPassphrase) return QString(); KPasswordDialog dlg; - dlg.setCaption("Private Key Passphrase"); + dlg.setWindowTitle("Private Key Passphrase"); dlg.setPrompt("Your private key file requires a password. Please enter it here. You will be asked again each time it is accessed, and the password is not stored."); dlg.exec(); return dlg.password(); } bool checkUserDetails() { + git_config* configActual; + int error = git_config_open_default(&configActual); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return false; } + git_config* config; - git_config_open_default(&config); + error = git_config_snapshot(&config, configActual); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return false; } + const char* name; - git_config_get_string(&name, config, "user.name"); + error = git_config_get_string(&name, config, "user.name"); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return false; } + const char* email; - git_config_get_string(&email, config, "user.email"); + error = git_config_get_string(&email, config, "user.email"); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return false; } userName = QString::fromLocal8Bit(name); userEmail = QString::fromLocal8Bit(email); @@ -425,7 +511,8 @@ return false; } userName = newName; - git_config_set_string(config, "user.name", newName.toLocal8Bit()); + error = git_config_set_string(config, "user.name", newName.toLocal8Bit()); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return false; } } if(userEmail.isEmpty()) { bool ok; @@ -441,15 +528,17 @@ return false; } userEmail = newEmail; - git_config_set_string(config, "user.email", newEmail.toLocal8Bit()); + error = git_config_set_string(config, "user.email", newEmail.toLocal8Bit()); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return false; } } git_config_free(config); if(userName.isEmpty() || userEmail.isEmpty()) { return false; } - git_signature_now(&signature, userName.toLocal8Bit(), userEmail.toLocal8Bit()); + error = git_signature_now(&signature, userName.toLocal8Bit(), userEmail.toLocal8Bit()); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return false; } return true; } @@ -467,14 +556,14 @@ GitController::GitController(QObject* parent) : QObject(parent) { - LibQGit2::initLibQGit2(); + git_libgit2_init(); d = new Private(this); } GitController::~GitController() { delete d; - LibQGit2::shutdownLibQGit2(); + git_libgit2_shutdown(); } QString GitController::cloneDir() const @@ -501,9 +590,9 @@ // OK, so some silliness here. This ensures a bit of sanity later, because otherwise we // end up comparing a localised checkout dir to a non-localised current file (since that // is created from a URL, and the checkout dir isn't) - if("\\" == QDir::separator() && newFile.contains("/")) { - d->currentFile = d->currentFile.replace("/", QDir::separator()); - } + // if("\\" == QDir::separator() && newFile.contains("/")) { + // d->currentFile = d->currentFile.replace("/", QDir::separator()); + // } emit currentFileChanged(); } @@ -578,7 +667,7 @@ return; } - if(d->currentFile.startsWith(d->cloneDir)) { + if(d->currentFile.startsWith(QString("file:///%1").arg(d->cloneDir)) || d->currentFile.startsWith(QString("file://%1").arg(d->cloneDir))) { // ask commit message and checkbox for push (default on, remember?) bool ok = false; QString message = QInputDialog::getMultiLineText(0, diff --git a/gemini/cloud/git/gitlogmodel.cpp b/gemini/cloud/git/gitlogmodel.cpp --- a/gemini/cloud/git/gitlogmodel.cpp +++ b/gemini/cloud/git/gitlogmodel.cpp @@ -21,8 +21,11 @@ #include "gitlogmodel.h" -#include -#include +// #include +// #include + +#include +#include #include #include @@ -128,37 +131,42 @@ beginResetModel(); qDeleteAll(d->entries); d->entries.clear(); - try { - LibQGit2::Repository repo; - repo.open(QString("%1/.git").arg(d->repoDir)); - LibQGit2::RevWalk rw(repo); + git_repository* repository; + int error = git_repository_open(&repository, QString("%1/.git").arg(d->repoDir).toLatin1()); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return; } - rw.setSorting(LibQGit2::RevWalk::Topological); + git_revwalk *walker; + error = git_revwalk_new(&walker, repository); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return; } + error = git_revwalk_push_range(walker, "HEAD~100..HEAD"); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return; } - rw.pushHead(); + git_oid oid; + git_commit *commit = NULL; + while (git_revwalk_next(&oid, walker) == 0) { + error = git_commit_lookup(&commit, repository, &oid); + if(error != 0) { const git_error* err = giterr_last(); qDebug() << "Kapow, error code from git2 was" << error << "which is described as" << err->message; return; } - LibQGit2::Commit commit; - // loop control, limit the run to the hundred most recent commits - int i = 100; - while(rw.next(commit)) { - if(--i < 0) { - break; - } - LogEntry* entry = new LogEntry(); - entry->authorName = commit.author().name(); - if(entry->authorName.isEmpty()) - entry->authorName = "Unknown"; - entry->authorEmail = commit.author().email(); - entry->time = commit.dateTime(); - entry->oid = commit.oid().format(); - entry->shortMessage = commit.shortMessage(); - entry->message = commit.message(); - d->entries.append(entry); - } + const git_signature *author = git_commit_author(commit); + + LogEntry* entry = new LogEntry(); + entry->authorName = author->name; + if(entry->authorName.isEmpty()) + entry->authorName = "Unknown"; + entry->authorEmail = author->email; + + git_time_t time = git_commit_time(commit); + entry->time = QDateTime::fromMSecsSinceEpoch(time * 1000); + + entry->oid = QString::fromAscii(git_oid_tostr_s(git_commit_id(commit))); + entry->message = QString::fromAscii(git_commit_message(commit)); + entry->shortMessage = entry->message.left(120).split(QRegExp("(\\r|\\n)")).first(); + + d->entries.append(entry); - } catch (const LibQGit2::Exception& ex) { - qDebug() << ex.what() << ex.category(); + git_commit_free(commit); } + git_repository_free(repository); endResetModel(); } diff --git a/gemini/cloud/git/gitplugin.h b/gemini/cloud/git/gitplugin.h --- a/gemini/cloud/git/gitplugin.h +++ b/gemini/cloud/git/gitplugin.h @@ -22,16 +22,15 @@ #ifndef GITPLUGIN_H #define GITPLUGIN_H -#include +#include -class GitPlugin : public QDeclarativeExtensionPlugin +class GitPlugin : public QQmlExtensionPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") public: virtual void registerTypes(const char* uri); - virtual void initializeEngine(QDeclarativeEngine* engine, const char* uri); + virtual void initializeEngine(QQmlEngine* engine, const char* uri); }; -Q_EXPORT_PLUGIN2(calligrageminigitplugin, GitPlugin) - #endif // GITPLUGIN_H diff --git a/gemini/cloud/git/gitplugin.cpp b/gemini/cloud/git/gitplugin.cpp --- a/gemini/cloud/git/gitplugin.cpp +++ b/gemini/cloud/git/gitplugin.cpp @@ -24,9 +24,9 @@ #include "gitlogmodel.h" #include "checkoutcreator.h" -#include -#include -#include +#include +#include +#include #include void GitPlugin::registerTypes(const char* uri) @@ -38,15 +38,13 @@ qmlRegisterType(); } -void GitPlugin::initializeEngine(QDeclarativeEngine* engine, const char* uri) +void GitPlugin::initializeEngine(QQmlEngine* engine, const char* uri) { Q_UNUSED(uri) Q_ASSERT( uri == QLatin1String( "Calligra.Gemini.Git" ) ); CheckoutCreator* ac = new CheckoutCreator(qApp); - QDeclarativeContext *context = engine->rootContext(); + QQmlContext *context = engine->rootContext(); context->setContextProperty("GitCheckoutCreator", ac); } - -#include "gitplugin.moc" diff --git a/gemini/lib/CMakeLists.txt b/gemini/lib/CMakeLists.txt --- a/gemini/lib/CMakeLists.txt +++ b/gemini/lib/CMakeLists.txt @@ -4,10 +4,17 @@ GeminiMainWindow.cpp ) -kde4_add_library(gemini SHARED ${gemini_SRCS}) +add_library(gemini SHARED ${gemini_SRCS}) +generate_export_header(gemini) target_link_libraries(gemini Qt5::Quick Qt5::Gui Qt5::Core Qt5::Widgets ) + +set_target_properties(gemini PROPERTIES + VERSION ${GENERIC_CALLIGRA_LIB_VERSION} SOVERSION ${GENERIC_CALLIGRA_LIB_SOVERSION} +) + +install(TARGETS gemini ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/gemini/lib/GeminiMainWindow.h b/gemini/lib/GeminiMainWindow.h --- a/gemini/lib/GeminiMainWindow.h +++ b/gemini/lib/GeminiMainWindow.h @@ -21,13 +21,14 @@ #define GEMINIMAINWINDOW_H #include +#include "gemini_export.h" class QQuickView; /** * \short * */ -class GeminiMainWindow : public QMainWindow +class GEMINI_EXPORT GeminiMainWindow : public QMainWindow { Q_OBJECT Q_PROPERTY(GeminiState currentState READ currentState NOTIFY currentStateChanged) diff --git a/gemini/lib/GeminiMainWindow.cpp b/gemini/lib/GeminiMainWindow.cpp --- a/gemini/lib/GeminiMainWindow.cpp +++ b/gemini/lib/GeminiMainWindow.cpp @@ -26,6 +26,13 @@ #include #include +#ifdef Q_OS_WIN +// Slate mode/docked detection stuff +#include +#define SM_CONVERTIBLESLATEMODE 0x2003 +#define SM_SYSTEMDOCKED 0x2004 +#endif + struct View { View() : quickView(0), widget(0) {} QQuickView* quickView; diff --git a/gemini/lib/GeminiModeSwitchEvent.h b/gemini/lib/GeminiModeSwitchEvent.h --- a/gemini/lib/GeminiModeSwitchEvent.h +++ b/gemini/lib/GeminiModeSwitchEvent.h @@ -31,9 +31,14 @@ class GeminiModeSwitchEvent : public QEvent { public: + /** + * Which type of event you are dealing with. You will only receive this in two cases: + * When you are about to switch away from a particular mode (sent to fromView before switching) + * When you have been made the current mode (sent to toView after switching) + */ enum GeminiModeEventType { - AboutToSwitchViewModeEvent = QEvent::User + 1, - SwitchedToThisModeEvent ///< This is the case when + AboutToSwitchViewModeEvent = QEvent::User + 1, ///< Write information into the event (and mark the sync object as initialized) + SwitchedToThisModeEvent ///< Read information out of the event }; inline GeminiModeSwitchEvent(GeminiModeEventType type, QObject* fromView, QObject* toView, GeminiModeSynchronisationObject* syncObject) diff --git a/gemini/main.cpp b/gemini/main.cpp --- a/gemini/main.cpp +++ b/gemini/main.cpp @@ -57,6 +57,7 @@ QStringLiteral("https://www.calligra.org"), QStringLiteral("submit@bugs.kde.org")); + app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true); KAboutData::setApplicationData(aboutData); QCommandLineParser parser; @@ -77,23 +78,14 @@ } } - KIconLoader::global()->addAppDir("calligrawords"); - KIconLoader::global()->addAppDir("words"); - KIconLoader::global()->addAppDir("calligrastage"); - KIconLoader::global()->addAppDir("stage"); - #ifdef Q_OS_WIN QDir appdir(app.applicationDirPath()); appdir.cdUp(); QString envStringSet; QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - if (!env.contains("KDESYCOCA")) { - _putenv_s("KDESYCOCA", QString(appdir.absolutePath() + "/sycoca").toLocal8Bit()); - envStringSet.append("KDESYCOCA "); - } if (!env.contains("XDG_DATA_DIRS")) { - _putenv_s("XDG_DATA_DIRS", QString(appdir.absolutePath() + "/share").toLocal8Bit()); + _putenv_s("XDG_DATA_DIRS", QString(appdir.absolutePath() + "/bin/data").toLocal8Bit()); envStringSet.append("XDG_DATA_DIRS "); } _putenv_s("PATH", QString(appdir.absolutePath() + "/bin" + ";" @@ -104,34 +96,26 @@ if(envStringSet.length() > 0) { qDebug() << envStringSet << "were set from main, restarting application in new environment!"; // Pass all the arguments along, but don't include the application name... - QProcess::startDetached(app.applicationFilePath(), KCmdLineArgs::allArguments().mid(1)); + QStringList allArguments; + for(int i = 0; i < argc; i++) { + allArguments << argv[i]; + } + QProcess::startDetached(app.applicationFilePath(), allArguments.mid(1)); exit(0); } app.addLibraryPath(appdir.absolutePath()); app.addLibraryPath(appdir.absolutePath() + "/bin"); app.addLibraryPath(appdir.absolutePath() + "/lib"); app.addLibraryPath(appdir.absolutePath() + "/lib/kde4"); - - QStringList iconThemePaths; - iconThemePaths << appdir.absolutePath() + "/share/icons"; - QIcon::setThemeSearchPaths(iconThemePaths); - QIcon::setThemeName("oxygen"); #endif - if (qgetenv("KDE_FULL_SESSION").isEmpty()) { - // There are two themes that work for Krita, oxygen and plastique. Try to set plastique first, then oxygen - qobject_cast(QApplication::instance())->setStyle("Plastique"); - qobject_cast(QApplication::instance())->setStyle("Oxygen"); - } + KIconLoader::global()->addAppDir("calligra"); + KIconLoader::global()->addAppDir("calligragemini"); + KIconLoader::global()->addAppDir("calligrawords"); + KIconLoader::global()->addAppDir("calligrastage"); + KIconLoader::global()->addAppDir("calligrasheets"); - // then create the pixmap from an xpm: we cannot get the - // location of our datadir before we've started our components, - // so use an xpm. -// QPixmap pm(splash_screen_xpm); -// QSplashScreen splash(pm); -// splash.show(); -// splash.showMessage("."); app.processEvents(); MainWindow window(fileNames); @@ -145,7 +129,6 @@ #else window.show(); #endif -// splash.finish(&window); return app.exec(); } diff --git a/gemini/qml/StageDocumentPage.qml b/gemini/qml/StageDocumentPage.qml --- a/gemini/qml/StageDocumentPage.qml +++ b/gemini/qml/StageDocumentPage.qml @@ -23,7 +23,7 @@ Item { id: base; signal canvasInteractionStarted(); - property alias document: stageDocument.document; + property alias document: stageDocument; property alias textEditor: stageDocument.textEditor; property QtObject canvas: stageCanvas; property alias source: stageDocument.source; @@ -36,8 +36,8 @@ baseLoadingDialog.visible = true; } else if(status == Calligra.DocumentStatus.Loaded) { - console.debug("doc and part: " + stageDocument.doc + " " + stageDocument.part); - mainWindow.setDocAndPart(stageDocument.doc, stageDocument.part); + console.debug("doc and part: " + stageDocument.document + " " + stageDocument.part); + mainWindow.setDocAndPart(stageDocument.document, stageDocument.part); baseLoadingDialog.hideMe(); // thumbnailSize = Qt.size(Settings.theme.adjustedPixel(280), Settings.theme.adjustedPixel(360)); } diff --git a/gemini/qml/WelcomePage.qml b/gemini/qml/WelcomePage.qml --- a/gemini/qml/WelcomePage.qml +++ b/gemini/qml/WelcomePage.qml @@ -19,234 +19,73 @@ import QtQuick 2.0 import QtQuick.Controls 1.3 import org.calligra 1.0 -import "components" +import org.kde.kirigami 2.1 as Kirigami import "welcomepages" -Page { +Kirigami.ApplicationItem { id: base; DocumentListModel { id: allDocumentsModel; } DocumentListModel { id: textDocumentsModel; filter: DocumentListModel.TextDocumentType; } DocumentListModel { id: presentationDocumentsModel; filter: DocumentListModel.PresentationType; } Component.onCompleted: { if(RecentFileManager.size() > 0) { - for(var i = 1; i < sidebarList.count; i++) { - sidebarList.setProperty(i, "selected", false); - } - sidebarList.setProperty(0, "selected", true); - welcomeStack.replace(welcomePageRecent); + pageStack.replace(welcomePageRecent); } } - Item { - id: welcomeToolbar; - anchors { - top: parent.top; - left: parent.left; - right: parent.right; - } - height: Settings.theme.adjustedPixel(86); - Rectangle { - anchors.fill: parent; - color: "#f2b200"; - } - Image { - anchors { - top: parent.top; - left: parent.left; - bottom: parent.bottom; - margins: Constants.DefaultMargin; - } - width: height; - source: Settings.theme.icon("Calligra-MockIcon-1"); - sourceSize.width: width > height ? height : width; - sourceSize.height: width > height ? height : width; - Label { - anchors { - left: parent.right; - leftMargin: Constants.DefaultMargin; - verticalCenter: parent.verticalCenter; - } - text: "Calligra Gemini"; - font: Settings.theme.font("welcomeHeader"); - color: "white"; - } - } - Image { - id: settingsButton; - anchors { - right: parent.right; - rightMargin: Settings.theme.adjustedPixel(19); - verticalCenter: parent.verticalCenter; + globalDrawer: Kirigami.GlobalDrawer { + id: welcomeSidebar; + title: "Calligra Gemini" + titleIcon: Settings.theme.iconActual("Calligra-MockIcon-1"); + actions: [ + Kirigami.Action { + text: "OPEN" + }, + Kirigami.Action { + text: "Recent Documents" + iconName: "document-open-recent" + onTriggered: if(pageStack.currentItem.objectName != "welcomePageRecent") pageStack.replace(welcomePageRecent); + checked: pageStack.currentItem !== null && pageStack.currentItem.objectName == "WelcomePageRecent"; + }, + Kirigami.Action { + text: "Library" + iconName: "folder-documents" + onTriggered: if(pageStack.currentItem.objectName != "WelcomePageFilebrowser") pageStack.replace(welcomePageFilebrowser); + checked: pageStack.currentItem !== null && pageStack.currentItem.objectName == "WelcomePageFilebrowser"; + }, + Kirigami.Action { + text: "Cloud" + iconName: "folder-cloud" + onTriggered: if(pageStack.currentItem.objectName != "WelcomePageCloud") pageStack.replace(welcomePageCloud); + checked: pageStack.currentItem !== null && pageStack.currentItem.objectName == "WelcomePageCloud"; + }, + Kirigami.Action { + text: "CREATE NEW" + }, + Kirigami.Action { + text: "Document" + iconName: "x-office-document" + onTriggered: if(pageStack.currentItem.objectName != "WelcomePageWords") pageStack.replace(welcomePageWords); + checked: pageStack.currentItem !== null && pageStack.currentItem.objectName == "WelcomePageWords"; + }, + Kirigami.Action { + text: "Presentation" + iconName: "x-office-presentation" + onTriggered: if(pageStack.currentItem.objectName != "WelcomePageStage") pageStack.replace(welcomePageStage); + checked: pageStack.currentItem !== null && pageStack.currentItem.objectName == "WelcomePageStage"; } - width: Settings.theme.adjustedPixel(48); - height: width; - source: Settings.theme.icon("SVG-Icon-OptionsWhite-1"); - sourceSize.width: width > height ? height : width; - sourceSize.height: width > height ? height : width; - } - Rectangle { - anchors { - left: parent.left; - right: parent.right; - bottom: parent.bottom; - } - height: 1; - color: "black"; - opacity: 0.1; - } + ] } - Item { - anchors { - top: welcomeToolbar.bottom; - left: parent.left; - right: parent.right; - bottom: parent.bottom; - } - Item { - id: sidebar; - anchors { - top: parent.top; - left: parent.left; - bottom: parent.bottom; - } - width: parent.width / 5; - ListModel { - id: sidebarList; - ListElement { header: "OPEN"; text: "Recent Documents"; icon: "SVG-Icon-RecentDocuments-1"; selected: false; stackComponent: "welcomePageRecent"; } - ListElement { text: "Library"; icon: "SVG-Icon-MyDocuments-1"; selected: true; stackComponent: "welcomePageFilebrowser"; } - ListElement { text: "Cloud"; icon: "SVG-Icon-Cloud-1"; selected: false; stackComponent: "welcomePageCloud"; } - ListElement { header: "COMPOSE NEW"; text: "Document"; icon: "SVG-Icon-NewDocument-1"; selected: false; stackComponent: "welcomePageWords"; } - ListElement { text: "Presentation"; icon: "SVG-Icon-NewPresentation-1"; selected: false; stackComponent: "welcomePageStage"; } - //ListElement { text: "Spreadsheet"; icon: "SVG-Icon-NewSpreadsheet-1"; selected: false; stackComponent: "welcomePageCustom"; } - //ListElement { text: "Sketch"; icon: "SVG-Icon-NewSketch-1"; selected: false; stackComponent: "welcomePageCustom"; } - } - Rectangle { - anchors.fill: parent; - color: "#e8e9ea"; - } - ListView { - anchors.fill: parent; - clip: true; - model: sidebarList; - delegate: Item { - width: ListView.view.width; - height: model.header ? Constants.GridHeight * 1.5 : Constants.GridHeight; - Item { - id: delegateHeader; - height: model.header ? Constants.GridHeight / 2 : 0; - width: parent.width; - Label { - anchors { - fill: parent; - leftMargin: Constants.DefaultMargin; - } - verticalAlignment: Text.AlignBottom; - horizontalAlignment: Text.AlignLeft; - text: model.header ? model.header : ""; - font: Settings.theme.font("filelistheader"); - color: "#f2b200"; - } - } - Item { - anchors.top: delegateHeader.bottom; - width: parent.width; - height: Constants.GridHeight; - Rectangle { - anchors.fill: parent; - color: "#00adf5"; - opacity: model.selected ? 0.6 : 0; - Behavior on opacity { PropertyAnimation { duration: Constants.AnimationDuration; } } - } - Image { - anchors { - left: parent.left; - leftMargin: Constants.DefaultMargin; - verticalCenter: parent.verticalCenter; - } - height: parent.height - Constants.DefaultMargin * 2; - width: height; - source: Settings.theme.icon(model.icon); - sourceSize.width: width > height ? height : width; - sourceSize.height: width > height ? height : width; - } - Label { - anchors { - left: parent.left; - leftMargin: parent.height; - verticalCenter: parent.verticalCenter; - } - text: model.text; - font: Settings.theme.font("welcomeSidebar"); - } - MouseArea { - anchors.fill: parent; - function elementFromName(name) { - var elements = { - "welcomePageFilebrowser": welcomePageFilebrowser, - "welcomePageRecent": welcomePageRecent, - "welcomePageStage": welcomePageStage, - "welcomePageWords": welcomePageWords, - "welcomePageCustom": welcomePageCustom, - "welcomePageCloud": welcomePageCloud - }; - return elements[name]; - } - onClicked: { - console.debug("boop! " + index); - if(model.selected) { - return; - } - for(var i = 0; i < sidebarList.count; i++) { - sidebarList.setProperty(i, "selected", false); - } - sidebarList.setProperty(index, "selected", true); - welcomeStack.replace(elementFromName(model.stackComponent)); - } - } - } - } - } - Rectangle { - anchors { - top: parent.top; - right: parent.right; - bottom: parent.bottom; - } - width: 1; - color: "black"; - opacity: 0.1; - } - } - Rectangle { - anchors { - top: parent.top; - left: sidebar.right; - right: parent.right; - bottom: parent.bottom; - } - color: "#e8e9ea"; - } - StackView { - id: welcomeStack; - clip: true; - anchors { - top: parent.top; - left: sidebar.right; - leftMargin: Constants.DefaultMargin * 3; - right: parent.right; - bottom: parent.bottom; - } - initialItem: welcomePageFilebrowser; - } - Component { id: welcomePageFilebrowser; WelcomePageFilebrowser { } } - Component { id: welcomePageRecent; WelcomePageRecent { } } - Component { id: welcomePageStage; WelcomePageStage { } } - Component { id: welcomePageWords; WelcomePageWords { } } - Component { id: welcomePageCustom; WelcomePageCustom { } } - Component { id: welcomePageCloud; WelcomePageCloud { } } + pageStack.initialPage: welcomePageFilebrowser; + Component { id: welcomePageFilebrowser; WelcomePageFilebrowser { } } + Component { id: welcomePageRecent; WelcomePageRecent { } } + Component { id: welcomePageStage; WelcomePageStage { } } + Component { id: welcomePageWords; WelcomePageWords { } } + Component { id: welcomePageCustom; WelcomePageCustom { } } + Component { id: welcomePageCloud; WelcomePageCloud { } } + + Component { id: mainPage; MainPage { } } - Component { id: mainPage; MainPage { } } - } VariantSelector { id: variantSelector; } VariantSelector { id: wordsVariantSelector; selectorType: "words"; } } diff --git a/gemini/qml/WordsDocumentPage.qml b/gemini/qml/WordsDocumentPage.qml --- a/gemini/qml/WordsDocumentPage.qml +++ b/gemini/qml/WordsDocumentPage.qml @@ -23,7 +23,7 @@ Item { id: base; signal canvasInteractionStarted(); - property alias document: wordsDocument.document; + property alias document: wordsDocument; property alias textEditor: wordsDocument.textEditor; property QtObject canvas: wordsCanvas; property alias source: wordsDocument.source; diff --git a/gemini/qml/components/BusyIndicator.qml b/gemini/qml/components/BusyIndicator.qml deleted file mode 100644 --- a/gemini/qml/components/BusyIndicator.qml +++ /dev/null @@ -1,82 +0,0 @@ -/* -* Copyright (C) 2010 by Artur Duque de Souza -* Copyright (C) 2011 by Daker Fernandes Pinheiro -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU Library General Public License as -* published by the Free Software Foundation; either version 2, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details -* -* You should have received a copy of the GNU Library General Public -* License along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -import QtQuick 2.0 - -/** - * A simple busy indicator, - * It is used to indicate a task whose duration is unknown. If the task - * duration/number of steps is known, a ProgressBar should be used instead. - * - * This is essentially the Plasma QML component, just without the - * Plasma (SVG)requirement, for smaller footprint for the time being. - */ -Item { - id: busy - - /** - * This property holds whether the busy animation is running. - * - * The default value is false. - */ - property bool running: false - - // Plasma API - /** - * Set this property if you don't want to apply a filter to smooth - * the busy icon while animating. - * Smooth filtering gives better visual quality, but is slower. - * - * The default value is true. - */ - property bool smoothAnimation: true - - implicitWidth: 52 - implicitHeight: 52 - - // Should use animation's pause to keep the - // rotation smooth when running changes but - // it has lot's of side effects on - // initialization. - onRunningChanged: { - rotationAnimation.from = rotation; - rotationAnimation.to = rotation + 360; - } - - RotationAnimation on rotation { - id: rotationAnimation - - from: 0 - to: 360 - duration: 1500 - running: busy.running - loops: Animation.Infinite - } - - Image { - id: widget - source: Settings.theme.image("busyindicator.png"); - anchors.centerIn: parent - width: Math.min(busy.width, busy.height) - height: width - fillMode: Image.PreserveAspectFit - smooth: !running || smoothAnimation - } -} diff --git a/gemini/qml/components/Dialog.qml b/gemini/qml/components/Dialog.qml --- a/gemini/qml/components/Dialog.qml +++ b/gemini/qml/components/Dialog.qml @@ -17,6 +17,7 @@ */ import QtQuick 2.0 +import QtQuick.Controls 1.4 as QtControls import org.calligra 1.0 Item { @@ -199,7 +200,7 @@ color: Settings.theme.color("components/dialog/progress/bar"); } } - BusyIndicator { + QtControls.BusyIndicator { id: busy; anchors.fill: progressBase; opacity: (progress > -1 && progressBase.opacity === 0) ? 1 : 0; diff --git a/gemini/qml/components/RangeInput.qml b/gemini/qml/components/RangeInput.qml --- a/gemini/qml/components/RangeInput.qml +++ b/gemini/qml/components/RangeInput.qml @@ -17,27 +17,20 @@ */ import QtQuick 2.0 +import QtQuick.Controls 1.4 as QtControls Item { id: base; property bool enabled: true; - property alias placeholder: textField.placeholder; + property alias placeholder: textField.placeholderText; property real value: 0; property real min: 0; property real max: 1000; property int decimals: 2; - property alias useExponentialValue: valueSlider.useExponentialValue; height: textField.height + valueSlider.height; - property alias border: valueSlider.border; - property alias background: valueSlider.background; - - onDecimalsChanged: d.fixHandle(); - onUseExponentialValueChanged: d.fixHandle(); - onMinChanged: d.fixHandle(); - onMaxChanged: d.fixHandle(); onValueChanged: { if (decimals === 0) { if (value !== Math.round(value)) @@ -61,64 +54,30 @@ if (textField.text != value) { textField.text = value.toFixed(decimals); } - if (useExponentialValue) { - var newValue = ( (value - min) / (max - min) ) * 100; - if (valueSlider.exponentialValue !== newValue) { - valueSlider.exponentialValue = newValue; - } - } - else { - if (valueSlider.value !== value) { - valueSlider.value = ( (value - min) / (max - min) ) * 100; - } + if (valueSlider.value !== (value / (max - min))) { + valueSlider.value = ( (value - min) / (max - min) ); } } - PanelTextField { + QtControls.TextField { id: textField anchors { top: parent.top; left: parent.left; right: parent.right; } - onFocusLost: value = text; - onAccepted: value = text; - numeric: true; - - border.width: valueSlider.border.width; - border.color: valueSlider.border.color; - background: valueSlider.background; + inputMethodHints: Qt.ImhFormattedNumbersOnly; + onAccepted: value = (text / (base.max - base.min)); } - Slider { + QtControls.Slider { id: valueSlider; anchors { top: textField.bottom; left: parent.left; right: parent.right; leftMargin: Constants.DefaultMargin; rightMargin: Constants.DefaultMargin; } - highPrecision: true; - onExponentialValueChanged: { - if (useExponentialValue) { - base.value = base.min + ((exponentialValue / 100) * (base.max - base.min)) - } - } - onValueChanged: { - if (!useExponentialValue) { - base.value = base.min + ((value / 100) * (base.max - base.min)); - } - } - } - QtObject { - id: d; - function fixHandle() { - var currentVal = base.value; - // Set the value to something it isn't currently - base.value = base.min; - base.value = base.max; - // Set it back to what it was - base.value = currentVal; - } + onValueChanged: base.value = base.min + (value * (base.max - base.min)); } } diff --git a/gemini/qml/welcomepages/CustomDocWords.qml b/gemini/qml/welcomepages/CustomDocWords.qml --- a/gemini/qml/welcomepages/CustomDocWords.qml +++ b/gemini/qml/welcomepages/CustomDocWords.qml @@ -17,6 +17,7 @@ */ import QtQuick 2.0 +import QtQuick.Controls 1.4 as QtControls import org.calligra 1.0 import "../components" @@ -172,10 +173,9 @@ width: parent.width; text: "Unit:" } - ExpandingListView { + QtControls.ComboBox { id: unitList; width: parent.width; - expandedHeight: Constants.GridHeight * 3; currentIndex: 6; model: ListModel { id: unitModel; @@ -192,11 +192,10 @@ width: parent.width; text: "Size:" } - ExpandingListView { + QtControls.ComboBox { id: paperSizeList; width: parent.width; - expandedHeight: Constants.GridHeight * 6; - currentIndex: 7; + Component.onCompleted: currentIndex = 7; onCurrentIndexChanged: { if(widthInput !== null) { widthInput.text = paperSizeModel.get(currentIndex).width; @@ -245,29 +244,29 @@ opacity: paperSizeList.currentIndex === 0 ? 1 : 0; Behavior on opacity { PropertyAnimation { duration: Constants.AnimationDuration; } } clip: true; - PanelTextField { + QtControls.TextField { id: widthInput; anchors { top: parent.top; left: parent.left; right: parent.horizontalCenter; } width: parent.width; - placeholder: landscapeCheck.checked ? "Height" : "Width"; + placeholderText: landscapeCheck.checked ? "Height" : "Width"; validator: DoubleValidator{ bottom: 1; top: 999999; decimals: 2; } - numeric: true; + inputMethodHints: Qt.ImhFormattedNumbersOnly; } - PanelTextField { + QtControls.TextField { id: heightInput; anchors { top: parent.top; left: parent.horizontalCenter; right: parent.right; } width: parent.width; - placeholder: landscapeCheck.checked ? "Width" : "Height"; + placeholderText: landscapeCheck.checked ? "Width" : "Height"; validator: DoubleValidator{ bottom: 1; top: 999999; decimals: 2; } - numeric: true; + inputMethodHints: Qt.ImhFormattedNumbersOnly; } } Label { @@ -363,7 +362,6 @@ id: columnSpacing; width: parent.width / 2; placeholder: "Spacing"; - useExponentialValue: true; min: 0; max: (heightInput.text > widthInput.text ? heightInput.text : widthInput.text) / columnCount.value; decimals: 2; @@ -386,7 +384,6 @@ id: marginTop; width: parent.width / 3; placeholder: "Top"; - useExponentialValue: true; min: 1; max: 999; decimals: 2; value: 20; } @@ -398,7 +395,6 @@ id: marginLeft; width: parent.width / 3; placeholder: facingCheck.checked ? "Binding" : "Left"; - useExponentialValue: true; min: 1; max: 999; decimals: 2; value: 20; } @@ -413,7 +409,6 @@ id: marginRight; width: parent.width / 3; placeholder: facingCheck.checked ? "Outside" : "Right"; - useExponentialValue: true; min: 1; max: 999; decimals: 2; value: 20; } @@ -429,24 +424,20 @@ id: marginBottom; width: parent.width / 3; placeholder: "Bottom"; - useExponentialValue: true; min: 1; max: 999; decimals: 2; value: 20; } } } } - CohereButton { + QtControls.Button { id: createDocButton; anchors { right: parent.right; bottom: parent.bottom; margins: Constants.DefaultMargin; } text: "Create Document"; - textColor: "white"; - textSize: Settings.theme.adjustedPixel(18); - color: "#4e5359"; onClicked: { var queryString = "newfile:///"; queryString += "?mimetype=" + WORDS_MIME_TYPE; diff --git a/gemini/qml/welcomepages/WelcomePageCloud.qml b/gemini/qml/welcomepages/WelcomePageCloud.qml --- a/gemini/qml/welcomepages/WelcomePageCloud.qml +++ b/gemini/qml/welcomepages/WelcomePageCloud.qml @@ -23,6 +23,7 @@ Page { id: base; + objectName: "WelcomePageCloud"; /* ListModel { id: cloudAccounts; ListElement { text: "Dropbox"; selected: false; accountType: "DropBox"; stackComponent: "accountsPageDropbox"; accountDetails: [ ListElement { userkey: "asfdoijfdshaloiuhs" } ] } @@ -112,7 +113,16 @@ bottomMargin: 0; } } - Component { id: accountsPage; CloudAccounts { accountsList: cloudAccounts; } } + Component { id: accountsPage; + CloudAccounts { + accountsList: cloudAccounts; + onShowAccount: { + cloudAccounts.selectIndex(index); + cloudStack.replace(accountsRow.elementFromName(stackComponent)); + cloudStack.currentPage.accountDetails = accountDetails; + } + } + } Component { id: accountsPageDropbox; Dropbox { } } Component { id: accountsPageWebdav; Webdav { } } Component { id: accountsPageGit; Git { } } diff --git a/gemini/qml/welcomepages/WelcomePageFilebrowser.qml b/gemini/qml/welcomepages/WelcomePageFilebrowser.qml --- a/gemini/qml/welcomepages/WelcomePageFilebrowser.qml +++ b/gemini/qml/welcomepages/WelcomePageFilebrowser.qml @@ -17,12 +17,34 @@ */ import QtQuick 2.0 +import org.kde.kirigami 2.1 as Kirigami import org.calligra 1.0 import "../components" Page { id: base; + objectName: "WelcomePageFilebrowser"; property string categoryUIName: (docList.model === textDocumentsModel) ? "text documents" : "presentations" + GridView { + id: docList; + contentWidth: width; + anchors { + margins: Constants.DefaultMargin; + top: docTypeSelectorRow.bottom; + left: parent.left; + right: parent.right; + bottom: parent.bottom; + bottomMargin: 0; + } + cellWidth: width / 4 - Constants.DefaultMargin; + cellHeight: cellWidth + Settings.theme.font("templateLabel").pixelSize + Constants.DefaultMargin * 4; + model: textDocumentsModel; + delegate: documentTile; + ScrollDecorator { flickableItem: docList; } + } + Rectangle { + anchors.fill: docTypeSelectorRow; + } Label { id: docTypeSelectorRow; anchors { @@ -76,39 +98,30 @@ } } } - GridView { - id: docList; - clip: true; - contentWidth: width; - anchors { - margins: Constants.DefaultMargin; - top: docTypeSelectorRow.bottom; - left: parent.left; - right: parent.right; - bottom: parent.bottom; - bottomMargin: 0; - } - cellWidth: width / 4 - Constants.DefaultMargin; - cellHeight: cellWidth + Settings.theme.font("templateLabel").pixelSize + Constants.DefaultMargin * 4; - model: textDocumentsModel; - delegate: documentTile; - ScrollDecorator { flickableItem: docList; } - } - Label { + Kirigami.Label { anchors.fill: parent; text: "No %1\n\nPlease drop some into your Documents folder\n(%2)".arg(base.categoryUIName).arg(docList.model.documentsFolder); horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignVCenter; - font: Settings.theme.font("templateLabel"); - color: "#5b6573"; visible: docList.count === 0; } Component { id: documentTile; Item { width: docList.cellWidth; height: docList.cellHeight + Rectangle { + x: documentImage.x - Constants.DefaultMargin + (documentImage.width - documentImage.paintedWidth) / 2; + y: documentImage.y - Constants.DefaultMargin + (documentImage.height - documentImage.paintedHeight) / 2; + width: documentImage.paintedWidth + Constants.DefaultMargin * 2; + height: documentImage.paintedHeight + Constants.DefaultMargin * 2; + border { + color: "silver"; + width: 1; + } + } Image { + id: documentImage; source: "image://recentimage/" + model.filePath; anchors { top: parent.top; @@ -121,7 +134,7 @@ smooth: true; asynchronous: true; } - Label { + Kirigami.Label { id: lblName; anchors { left: parent.left; @@ -134,8 +147,6 @@ horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignVCenter; text: model.fileName ? model.fileName : ""; - font: Settings.theme.font("templateLabel"); - color: "#5b6573"; } MouseArea { anchors.fill: parent; diff --git a/gemini/qml/welcomepages/WelcomePageRecent.qml b/gemini/qml/welcomepages/WelcomePageRecent.qml --- a/gemini/qml/welcomepages/WelcomePageRecent.qml +++ b/gemini/qml/welcomepages/WelcomePageRecent.qml @@ -22,13 +22,14 @@ Page { id: base; + objectName: "WelcomePageRecent"; GridView { id: docList; - clip: true; contentWidth: width; anchors { margins: Constants.DefaultMargin; top: parent.top; + topMargin: Constants.DefaultMargin * 3; left: parent.left; right: parent.right; bottom: parent.bottom; @@ -54,7 +55,18 @@ Item { width: docList.cellWidth; height: docList.cellHeight + Rectangle { + x: documentImage.x - Constants.DefaultMargin + (documentImage.width - documentImage.paintedWidth) / 2; + y: documentImage.y - Constants.DefaultMargin + (documentImage.height - documentImage.paintedHeight) / 2; + width: documentImage.paintedWidth + Constants.DefaultMargin * 2; + height: documentImage.paintedHeight + Constants.DefaultMargin * 2; + border { + color: "silver"; + width: 1; + } + } Image { + id: documentImage; source: model.image; anchors { top: parent.top; diff --git a/gemini/qml/welcomepages/WelcomePageStage.qml b/gemini/qml/welcomepages/WelcomePageStage.qml --- a/gemini/qml/welcomepages/WelcomePageStage.qml +++ b/gemini/qml/welcomepages/WelcomePageStage.qml @@ -22,6 +22,7 @@ Page { id: base; + objectName: "WelcomePageStage"; function activateTemplate(templateFile) { console.debug(templateFile); if(templateFile.slice(-1) === "/" || templateFile === "") { diff --git a/gemini/qml/welcomepages/WelcomePageWords.qml b/gemini/qml/welcomepages/WelcomePageWords.qml --- a/gemini/qml/welcomepages/WelcomePageWords.qml +++ b/gemini/qml/welcomepages/WelcomePageWords.qml @@ -22,6 +22,7 @@ Page { id: base; + objectName: "WelcomePageWords" Label { id: docTypeSelectorRow; anchors { diff --git a/gemini/qml/welcomepages/cloud/AddDropbox.qml b/gemini/qml/welcomepages/cloud/AddDropbox.qml --- a/gemini/qml/welcomepages/cloud/AddDropbox.qml +++ b/gemini/qml/welcomepages/cloud/AddDropbox.qml @@ -18,7 +18,7 @@ import QtQuick 2.0 import org.calligra 1.0 -import "../../components" +import QtQuick.Controls 1.4 as QtControls import "dropbox" as Dropbox Rectangle { @@ -32,26 +32,24 @@ anchors { fill: parent; margins: -Settings.theme.adjustedPixel(16); + topMargin: -(Settings.theme.adjustedPixel(8) + Constants.GridHeight * 1.5); } - opacity: 0.3; + opacity: 0.5; color: "white"; MouseArea { anchors.fill: parent; onClicked: { /*nothing */ } } SimpleTouchArea { anchors.fill: parent; onTouched: { /*nothing */ } } } Dropbox.SetupPage { anchors.fill: parent; anchors.margins: Settings.theme.adjustedPixel(8); } - CohereButton { + QtControls.Button { anchors { bottom: parent.bottom; right: parent.right; margins: Settings.theme.adjustedPixel(8); } text: "Close"; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; onClicked: dlgStack.replace(addEmpty); } } diff --git a/gemini/qml/welcomepages/cloud/AddGit.qml b/gemini/qml/welcomepages/cloud/AddGit.qml --- a/gemini/qml/welcomepages/cloud/AddGit.qml +++ b/gemini/qml/welcomepages/cloud/AddGit.qml @@ -18,7 +18,7 @@ import QtQuick 2.0 import org.calligra 1.0 -import "../../components" +import QtQuick.Controls 1.4 as QtControls Rectangle { anchors.fill: parent; @@ -31,8 +31,9 @@ anchors { fill: parent; margins: -Settings.theme.adjustedPixel(16); + topMargin: -(Settings.theme.adjustedPixel(8) + Constants.GridHeight * 1.5); } - opacity: 0.3; + opacity: 0.5; color: "white"; MouseArea { anchors.fill: parent; onClicked: { /*nothing */ } } SimpleTouchArea { anchors.fill: parent; onTouched: { /*nothing */ } } @@ -47,17 +48,14 @@ } source: "git/createCheckoutContainer.qml"; } - CohereButton { + QtControls.Button { id: closeButton; anchors { bottom: parent.bottom; right: parent.right; margins: Settings.theme.adjustedPixel(8); } text: "Close"; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; onClicked: dlgStack.replace(addEmpty); } } diff --git a/gemini/qml/welcomepages/cloud/AddWebdav.qml b/gemini/qml/welcomepages/cloud/AddWebdav.qml --- a/gemini/qml/welcomepages/cloud/AddWebdav.qml +++ b/gemini/qml/welcomepages/cloud/AddWebdav.qml @@ -18,7 +18,8 @@ import QtQuick 2.0 import org.calligra 1.0 -import "../../components" +import QtQuick.Controls 1.4 as QtControls +import org.kde.kirigami 2.1 as Kirigami Rectangle { anchors.fill: parent; @@ -31,27 +32,25 @@ anchors { fill: parent; margins: -Settings.theme.adjustedPixel(16); + topMargin: -(Settings.theme.adjustedPixel(8) + Constants.GridHeight * 1.5); } - opacity: 0.3; + opacity: 0.5; color: "white"; MouseArea { anchors.fill: parent; onClicked: { /*nothing */ } } SimpleTouchArea { anchors.fill: parent; onTouched: { /*nothing */ } } } - Label { + Kirigami.Label { anchors.fill: parent; horizontalAlignment: Text.AlignHCenter; text: "Sorry, support for WebDav is not yet implemented."; } - CohereButton { + QtControls.Button { anchors { bottom: parent.bottom; right: parent.right; margins: Settings.theme.adjustedPixel(8); } text: "Close"; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; onClicked: dlgStack.replace(addEmpty); } } diff --git a/gemini/qml/welcomepages/cloud/CloudAccounts.qml b/gemini/qml/welcomepages/cloud/CloudAccounts.qml --- a/gemini/qml/welcomepages/cloud/CloudAccounts.qml +++ b/gemini/qml/welcomepages/cloud/CloudAccounts.qml @@ -17,6 +17,8 @@ */ import QtQuick 2.0 +import QtQuick.Controls 1.4 as QtControls +import org.kde.kirigami 2.1 as Kirigami import org.calligra 1.0 import Calligra.Gemini.Dropbox 1.0 import "../../components" @@ -27,6 +29,7 @@ id: base; property string pageName: "accountsPage"; property QtObject accountsList; + signal showAccount(var index, var stackComponent, var accountDetails); Connections { target: controllerMIT; @@ -57,15 +60,24 @@ delegate: Item { height: Settings.theme.adjustedPixel(64); width: ListView.view.width; - Label { - anchors.fill: parent; + Kirigami.Label { + anchors { + top: parent.top; + left: parent.left; + right: accountControls.left; + bottom: parent.bottom; + } text: model.text; horizontalAlignment: Text.AlignLeft; verticalAlignment: Text.AlignVCenter; font: Settings.theme.font("templateLabel"); - color: "#5b6573"; + MouseArea { + anchors.fill: parent; + onClicked: base.showAccount(model.index, model.stackComponent, model.accountDetails); + } } Row { + id: accountControls; anchors { verticalCenter: parent.verticalCenter; right: parent.right; @@ -82,26 +94,20 @@ color: "#5b6573"; visible: model.accountType !== "DropBox"; } - CohereButton { + QtControls.Button { anchors.verticalCenter: parent.verticalCenter; text: (model.accountType === "DropBox") ? "Sign Out" : "Edit Account"; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; onClicked: { dlgStack.replace(base.editComponentFromName(model.accountType)); if(dlgStack.currentPage.accountIndex !== undefined) { dlgStack.currentPage.accountIndex = index; dlgStack.currentPage.text = model.text; } } } - CohereButton { + QtControls.Button { anchors.verticalCenter: parent.verticalCenter; text: "Remove"; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; visible: model.accountType !== "DropBox"; onClicked: { dlgStack.replace(removeAccountDlg); @@ -114,13 +120,11 @@ } } } - Label { + Kirigami.Label { anchors.fill: accountsView; text: "You have no cloud accounts defined. Please add one by clicking on your service of choice below."; horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignVCenter; - font: Settings.theme.font("templateLabel"); - color: "#5b6573"; opacity: accountsList.count === 0 ? 1 : 0; Behavior on opacity { PropertyAnimation { duration: Constants.AnimationDuration; } } } @@ -132,13 +136,11 @@ bottom: parent.bottom; } height: bottomButtonRow.height + Settings.theme.adjustedPixel(8); - Label { + Kirigami.Label { anchors.fill: parent; text: "Add new account:"; horizontalAlignment: Text.AlignLeft; verticalAlignment: Text.AlignVCenter; - font: Settings.theme.font("templateLabel"); - color: "#5b6573"; } Row { id: bottomButtonRow; @@ -157,11 +159,8 @@ //ListElement { text: "GitHub"; accountType: "Git"; serviceName: "github"; } //ListElement { text: "bitbucket (git)"; accountType: "Git"; serviceName: "bitbucket"; } } - CohereButton { + QtControls.Button { text: model.text - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; onClicked: { dlgStack.replace(base.addComponentFromName(model.accountType)); dlgStack.currentPage.serviceName = model.serviceName; @@ -172,7 +171,10 @@ } PageStack { id: dlgStack; - anchors.fill: base; + anchors { + fill: base; + margins: -Settings.theme.adjustedPixel(8); + } initialPage: addEmptyComp; } function addComponentFromName(name) { diff --git a/gemini/qml/welcomepages/cloud/EditDetailsBase.qml b/gemini/qml/welcomepages/cloud/EditDetailsBase.qml --- a/gemini/qml/welcomepages/cloud/EditDetailsBase.qml +++ b/gemini/qml/welcomepages/cloud/EditDetailsBase.qml @@ -1,4 +1,3 @@ - /* This file is part of the KDE project * Copyright (C) 2014 Dan Leinir Turthra Jensen * @@ -19,6 +18,7 @@ import QtQuick 2.0 import org.calligra 1.0 +import QtQuick.Controls 1.4 as QtControls import "../../components" Rectangle { @@ -36,8 +36,9 @@ anchors { fill: parent; margins: -Settings.theme.adjustedPixel(16); + topMargin: -(Settings.theme.adjustedPixel(8) + Constants.GridHeight * 1.5); } - opacity: 0.3; + opacity: 0.5; color: "white"; MouseArea { anchors.fill: parent; onClicked: { /*nothing */ } } SimpleTouchArea { anchors.fill: parent; onTouched: { /*nothing */ } } @@ -52,33 +53,27 @@ } placeholder: "Account Name"; } - CohereButton { + QtControls.Button { id: okButton; anchors { bottom: parent.bottom; right: cancelButton.left; margins: Settings.theme.adjustedPixel(8); } text: "Save"; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; onClicked: { cloudAccounts.renameAccount(base.accountIndex, nameField.text); dlgStack.replace(addEmpty); } } - CohereButton { + QtControls.Button { id: cancelButton; anchors { bottom: parent.bottom; right: parent.right; margins: Settings.theme.adjustedPixel(8); } text: "Cancel"; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; onClicked: dlgStack.replace(addEmpty); } } diff --git a/gemini/qml/welcomepages/cloud/EditGit.qml b/gemini/qml/welcomepages/cloud/EditGit.qml --- a/gemini/qml/welcomepages/cloud/EditGit.qml +++ b/gemini/qml/welcomepages/cloud/EditGit.qml @@ -17,6 +17,7 @@ */ import QtQuick 2.0 +import QtQuick.Controls 1.4 as QtControls import org.calligra 1.0 import "../../components" @@ -40,33 +41,31 @@ anchors { fill: parent; margins: -Settings.theme.adjustedPixel(16); + topMargin: -(Settings.theme.adjustedPixel(8) + Constants.GridHeight * 1.5); } - opacity: 0.3; + opacity: 0.5; color: "white"; MouseArea { anchors.fill: parent; onClicked: { /*nothing */ } } SimpleTouchArea { anchors.fill: parent; onTouched: { /*nothing */ } } } - TextField { + QtControls.TextField { id: nameField; anchors { verticalCenter: parent.verticalCenter; left: parent.left; right: parent.right; margins: Settings.theme.adjustedPixel(16); } - placeholder: "Account Name"; + placeholderText: "Account Name"; } - CohereButton { + QtControls.Button { id: credentialsButton; anchors { top: nameField.bottom; right: parent.right; margins: Settings.theme.adjustedPixel(8); } text: "Edit User Credentials"; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; onClicked: { dlgStack.push(userCredentials.item); if(accountDetails.readProperty("userForRemote") !== undefined) { @@ -83,33 +82,27 @@ } } } - CohereButton { + QtControls.Button { id: okButton; anchors { bottom: parent.bottom; right: cancelButton.left; margins: Settings.theme.adjustedPixel(8); } text: "Save"; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; onClicked: { cloudAccounts.renameAccount(base.accountIndex, nameField.text); dlgStack.replace(addEmpty); } } - CohereButton { + QtControls.Button { id: cancelButton; anchors { bottom: parent.bottom; right: parent.right; margins: Settings.theme.adjustedPixel(8); } text: "Cancel"; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; onClicked: dlgStack.replace(addEmpty); } diff --git a/gemini/qml/welcomepages/cloud/RemoveAccountDlg.qml b/gemini/qml/welcomepages/cloud/RemoveAccountDlg.qml --- a/gemini/qml/welcomepages/cloud/RemoveAccountDlg.qml +++ b/gemini/qml/welcomepages/cloud/RemoveAccountDlg.qml @@ -18,10 +18,12 @@ */ import QtQuick 2.0 +import QtQuick.Controls 1.4 as QtControls +import org.kde.kirigami 2.1 as Kirigami import org.calligra 1.0 -import "../../components" Rectangle { + id: base; anchors.fill: parent; anchors.margins: Settings.theme.adjustedPixel(16); property int accountIndex: -1; @@ -36,25 +38,25 @@ anchors { fill: parent; margins: -Settings.theme.adjustedPixel(16); + topMargin: -(Settings.theme.adjustedPixel(8) + Constants.GridHeight * 1.5); } - opacity: 0.3; + opacity: 0.5; color: "white"; MouseArea { anchors.fill: parent; onClicked: { /*nothing */ } } SimpleTouchArea { anchors.fill: parent; onTouched: { /*nothing */ } } } - Text { + Kirigami.Label { anchors { bottom: parent.verticalCenter; left: parent.left; right: parent.right; margins: Settings.theme.adjustedPixel(16); } verticalAlignment: Text.AlignVCenter; horizontalAlignment: Text.AlignHCenter; - font: Settings.theme.font("application"); text: "Do you wish to remove this account?"; } - Text { + Kirigami.Label { id: nameField; anchors { top: parent.verticalCenter; @@ -64,47 +66,39 @@ } verticalAlignment: Text.AlignVCenter; horizontalAlignment: Text.AlignHCenter; - font: Settings.theme.font("application"); } - Text { + Kirigami.Label { anchors { top: nameField.bottom; left: parent.left; right: parent.right; margins: Settings.theme.adjustedPixel(16); } verticalAlignment: Text.AlignVCenter; horizontalAlignment: Text.AlignHCenter; - font: Settings.theme.font("applicationSemi"); text: "(removing the account will leave all files in place, this only removes it from Calligra Gemini's list)"; } - CohereButton { + QtControls.Button { id: okButton; anchors { bottom: parent.bottom; right: cancelButton.left; margins: Settings.theme.adjustedPixel(8); } text: "Remove Account"; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; onClicked: { cloudAccounts.removeAccount(base.accountIndex); dlgStack.replace(addEmpty); } } - CohereButton { + QtControls.Button { id: cancelButton; anchors { bottom: parent.bottom; right: parent.right; margins: Settings.theme.adjustedPixel(8); } text: "Cancel"; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; onClicked: dlgStack.replace(addEmpty); } } diff --git a/gemini/qml/welcomepages/cloud/dropbox/DropboxWebView.qml b/gemini/qml/welcomepages/cloud/dropbox/DropboxWebView.qml --- a/gemini/qml/welcomepages/cloud/dropbox/DropboxWebView.qml +++ b/gemini/qml/welcomepages/cloud/dropbox/DropboxWebView.qml @@ -18,7 +18,8 @@ import QtQuick 2.0 import QtWebKit 3.0 -import "../../../components" +import org.kde.kirigami 2.1 as Kirigami +import QtQuick.Controls 1.4 as QtControls WebView { id: webView @@ -33,13 +34,13 @@ } } - Label { + Kirigami.Label { id: tryingText anchors.centerIn: parent; text: "Trying to load login page..." color: "Grey" z: 10 - BusyIndicator { + QtControls.BusyIndicator { id: b_indicator anchors { top: parent.verticalCenter diff --git a/gemini/qml/welcomepages/cloud/dropbox/FileNavigator.qml b/gemini/qml/welcomepages/cloud/dropbox/FileNavigator.qml --- a/gemini/qml/welcomepages/cloud/dropbox/FileNavigator.qml +++ b/gemini/qml/welcomepages/cloud/dropbox/FileNavigator.qml @@ -19,6 +19,8 @@ import QtQuick 2.0 import org.calligra 1.0 import Calligra.Gemini.Dropbox 1.0 +import QtQuick.Controls 1.4 as QtControls +import org.kde.kirigami 2.1 as Kirigami import "../../../components" Item { @@ -49,11 +51,14 @@ InfoBanner { id: i_infobanner; } Component { id: itemDelegate; - Button { + MouseArea { width: folderListView.cellWidth; height: folderListView.cellHeight; enabled: model.is_dir ? true : Settings.mimeTypeToDocumentClass(model.mime_type) !== DocumentListModel.UnknownType; - opacity: enabled ? 1 : 0.3 + Rectangle { + anchors.fill: parent; + opacity: parent.enabled ? 1 : 0.3 + } Image { id: icon; @@ -87,7 +92,7 @@ sourceSize.width: width; sourceSize.height: height; } - Label { + Kirigami.Label { id: lblName; anchors { left: parent.left; @@ -162,34 +167,31 @@ height: Constants.DefaultMargin; } - Label { + Kirigami.Label { id: l_name anchors.horizontalCenter: parent.horizontalCenter; height: font.pixelSize; text: { var filename1 = model.filename.split("/"); var filename2 = filename1[filename1.length-1]; return filename2; } - color: "black" } - ProgressBar { + QtControls.ProgressBar { id: pb_updown anchors.horizontalCenter: parent.horizontalCenter; visible: !is_finished && !in_queue width: parent.width - 120 height: 18 - progress: progressing + value: progressing } - Label { + Kirigami.Label { id: lb_updown_total anchors.horizontalCenter: parent.horizontalCenter; height: visible ? font.pixelSize : 0; visible: !is_finished && !in_queue - font: Settings.theme.font("templateLabel"); - color: "#5b6573"; text:"" } @@ -229,7 +231,7 @@ id: pageHeader; height: currentDir !== "/" ? backToRootButton.height : 0; width: page.width; - Button { + QtControls.Button { id: backToRootButton; anchors { top: parent.top; @@ -239,10 +241,8 @@ height: Settings.theme.adjustedPixel(64); opacity: currentDir !== "/" ? 1 : 0; Behavior on opacity{ PropertyAnimation{ duration: Constants.AnimationDuration; } } - image: Settings.theme.icon("SVG-Icon-MenuBack-1"); - imageMargin: Settings.theme.adjustedPixel(8); + iconSource: Settings.theme.icon("SVG-Icon-MenuBack-1"); text: "Back to parent folder" - textColor: "#5B6573"; onClicked: { controllerMIT.backtoRootDir() controllerMIT.getlistoffolder() @@ -256,7 +256,7 @@ id:this_folder_is_empty visible: false anchors.fill: parent - Label { + Kirigami.Label { anchors.centerIn: parent text:"This Folder is Empty" color: "grey" @@ -269,7 +269,7 @@ anchors.centerIn: parent width: parent.width - fakeTheme.paddingLarge height: r_label_x.height + r_button_x.height; - Label { + Kirigami.Label { id: r_label_x anchors { bottom: r_button_x.top; @@ -281,7 +281,7 @@ text: "There was a problem loading your Dropbox. It could be lost connection or a slow network. Check your connection or try again later. The reported error was: " + errorText; wrapMode: Text.Wrap; } - Button { + QtControls.Button { id:r_button_x text:"Retry" anchors { @@ -297,7 +297,7 @@ } } - BusyIndicator { + QtControls.BusyIndicator { id: b_indicator anchors.centerIn: parent running: b_indicator.visible; diff --git a/gemini/qml/welcomepages/cloud/dropbox/SetupPage.qml b/gemini/qml/welcomepages/cloud/dropbox/SetupPage.qml --- a/gemini/qml/welcomepages/cloud/dropbox/SetupPage.qml +++ b/gemini/qml/welcomepages/cloud/dropbox/SetupPage.qml @@ -18,6 +18,8 @@ import QtQuick 2.0 import Calligra.Gemini.Dropbox 1.0 +import QtQuick.Controls 1.4 as QtControls +import org.kde.kirigami 2.1 as Kirigami import "../../../components" Item { @@ -58,14 +60,13 @@ signOutNow(); } } - Text { + Kirigami.Label { anchors { top: parent.bottom; topMargin: Settings.theme.adjustedPixel(16); horizontalCenter: parent.horizontalCenter; } visible: !controllerMIT.needAuthenticate; - font: Settings.theme.font("application"); width: parent.parent.width / 2; height: font.pixelSize * 6; horizontalAlignment: Text.AlignHCenter; @@ -87,15 +88,13 @@ anchors.margins: Settings.theme.adjustedPixel(16); radius: Settings.theme.adjustedPixel(8); color: "white"; - Text { + Kirigami.Label { anchors { bottom: signoutButtonsRow.top; left: parent.left; right: parent.right; margins: Constants.DefaultMargin; } - color: "black" - font: Settings.theme.font("application"); wrapMode: Text.Wrap horizontalAlignment: Text.AlignHCenter text: "Do you really want to log out of DropBox?" @@ -105,20 +104,14 @@ anchors.centerIn: parent; width: childrenRect.width; spacing: Settings.theme.adjustedPixel(8); - CohereButton { - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; + QtControls.Button { text: "Yes" onClicked: { controllerMIT.logout() pageStack.pop() } } - CohereButton { - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; + QtControls.Button { text: "No" onClicked: { pageStack.pop() diff --git a/gemini/qml/welcomepages/cloud/git/CreateCheckout.qml b/gemini/qml/welcomepages/cloud/git/CreateCheckout.qml --- a/gemini/qml/welcomepages/cloud/git/CreateCheckout.qml +++ b/gemini/qml/welcomepages/cloud/git/CreateCheckout.qml @@ -19,6 +19,8 @@ import QtQuick 2.0 import org.calligra 1.0 import Calligra.Gemini.Git 1.0 +import QtQuick.Controls 1.4 as QtControls +import org.kde.kirigami 2.1 as Kirigami import "../../../components" Item { @@ -38,207 +40,156 @@ } } - Text { - id: pageTitle; - anchors { - top: parent.top; - left: parent.left; - right: parent.right + Column { + width: parent.width; + height: childrenRect.height; + Kirigami.Heading { + text: "Add Git Account" + width: parent.width; } - height: font.pixelHeight + Settings.theme.adjustedPixel(16); - font: Settings.theme.font("pageHeader"); - verticalAlignment: Text.AlignVCenter; - horizontalAlignment: Text.AlignHCenter; - text: "Add Git Account"; - Rectangle { - anchors { - left: parent.left; - right: parent.right; - bottom: parent.bottom; + Text { + id: typeChooser; + anchors.right: parent.right; + width: parent.width - (height / 2); + height: existingCheckoutSelector.height + Settings.theme.adjustedPixel(16); + verticalAlignment: Text.AlignVCenter + font: Settings.theme.font("application"); + text: "Type of repository:"; + CohereButton { + id: existingCheckoutSelector; + anchors { + right: newCheckoutSelector.left; + verticalCenter: parent.verticalCenter; + } + text: "Existing Clone"; + textColor: "#5b6573"; + textSize: Settings.theme.adjustedPixel(18); + checkedColor: "#D2D4D5"; + checked: true; + onClicked: { + if(!checked) { + checked = true; + newCheckoutSelector.checked = false; + } + } + } + CohereButton { + id: newCheckoutSelector; + anchors{ + right: parent.right; + verticalCenter: parent.verticalCenter; + } + text: "New Clone"; + textColor: "#5b6573"; + textSize: Settings.theme.adjustedPixel(18); + checkedColor: "#D2D4D5"; + onClicked: { + if(!checked) { + checked = true; + existingCheckoutSelector.checked = false; + } + } } - height: 1; - color: "black"; - opacity: 0.1; } - } - Item { - id: pageContent; - anchors { - top: pageTitle.bottom; - left: parent.left; - right: parent.right; - bottom: parent.bottom; + QtControls.TextField { + id: checkoutName; + width: parent.width; + placeholderText: "Short name for this account"; } - Column { - anchors { - top: parent.top; - left: parent.left; - right: parent.right; - bottom: parent.verticalCenter; + Item { + width: parent.width; + height: checkoutDir.height; + QtControls.TextField { + id: checkoutDir; + anchors { + left: parent.left; + right: checkoutBrowse.left; + } + placeholderText: "Local clone location"; } - Text { - id: typeChooser; - anchors.right: parent.right; - width: parent.width - (height / 2); - height: existingCheckoutSelector.height + Settings.theme.adjustedPixel(16); - verticalAlignment: Text.AlignVCenter - font: Settings.theme.font("application"); - text: "Type of repository:"; - CohereButton { - id: existingCheckoutSelector; - anchors { - right: newCheckoutSelector.left; - verticalCenter: parent.verticalCenter; - } - text: "Existing Clone"; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - checkedColor: "#D2D4D5"; - checked: true; - onClicked: { - if(!checked) { - checked = true; - newCheckoutSelector.checked = false; - } - } + QtControls.Button { + id: checkoutBrowse; + anchors { + top: checkoutDir.top; + right: parent.right; + bottom: checkoutDir.bottom; } - CohereButton { - id: newCheckoutSelector; - anchors{ - right: parent.right; - verticalCenter: parent.verticalCenter; - } - text: "New Clone"; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - checkedColor: "#D2D4D5"; - onClicked: { - if(!checked) { - checked = true; - existingCheckoutSelector.checked = false; - } + text: "Browse..."; + onClicked: { + var newDir = GitCheckoutCreator.getDir(); + if(newDir !== "") { + checkoutDir.text = newDir; } } } - TextField { - id: checkoutName; - width: parent.width; - placeholder: "Short name for this account"; - } - Item { - width: parent.width; - height: checkoutDir.height; - TextField { - id: checkoutDir; - anchors { - left: parent.left; - right: checkoutBrowse.left; - } - placeholder: "Local clone location"; + } + QtControls.TextField { + id: newCheckoutServer; + width: parent.width; + height: newCheckoutSelector.checked ? Constants.GridHeight : 0; + Behavior on height { PropertyAnimation { duration: Constants.AnimationDuration; } } + opacity: height === 0 ? 0 : 1; + Behavior on opacity { PropertyAnimation { duration: Constants.AnimationDuration; } } + placeholderText: "Clone URL (https or git)"; + } + QtControls.Button { + anchors.right: parent.right; + onClicked: dlgStack.push(userCredentials); + text: "Set User Credentials"; + } + Kirigami.Label { + id: errorLabel; + width: parent.width; + height: cloneAdd.height + Settings.theme.adjustedPixel(16); + verticalAlignment: Text.AlignVCenter + color: "red"; + QtControls.Button { + id: cloneAdd; + anchors { + verticalCenter: parent.verticalCenter; + right: parent.right; } - CohereButton { - id: checkoutBrowse; - anchors { - verticalCenter: checkoutDir.verticalCenter; - right: parent.right; + text: "Add Now"; + onClicked: { + if(checkoutName.text.length < 1) { + errorLabel.text = "You need to enter a name for the account." + return; } - text: "Browse..."; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; - onClicked: { - var newDir = GitCheckoutCreator.getDir(); - if(newDir !== "") { - checkoutDir.text = newDir; - } + if(checkoutDir.text.length < 1) { + errorLabel.text = "You must select a location." + return; } - } - } - TextField { - id: newCheckoutServer; - width: parent.width; - height: newCheckoutSelector.checked ? Constants.GridHeight : 0; - Behavior on height { PropertyAnimation { duration: Constants.AnimationDuration; } } - opacity: height === 0 ? 0 : 1; - Behavior on opacity { PropertyAnimation { duration: Constants.AnimationDuration; } } - placeholder: "Clone URL (https or git)"; - } - CohereButton { - anchors.right: parent.right; - onClicked: dlgStack.push(userCredentials); - text: "Set User Credentials"; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; - } - Text { - id: errorLabel; - width: parent.width; - height: cloneAdd.height + Settings.theme.adjustedPixel(16); - verticalAlignment: Text.AlignVCenter - color: "red"; - font: Settings.theme.font("application"); - CohereButton { - id: cloneAdd; - anchors { - verticalCenter: parent.verticalCenter; - right: parent.right; + if(base.userForRemote.length < 1 || base.privateKeyFile.length < 1 || base.publicKeyFile.length < 1) { + errorLabel.text = "You need to enter your credentials."; + return; } - text: "Add Now"; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; - onClicked: { - if(checkoutName.text.length < 1) { - errorLabel.text = "You need to enter a name for the account." - return; - } - if(checkoutDir.text.length < 1) { - errorLabel.text = "You must select a location." - return; - } - if(base.userForRemote.length < 1 || base.privateKeyFile.length < 1 || base.publicKeyFile.length < 1) { - errorLabel.text = "You need to enter your credentials."; + var createAccount = true; + if(newCheckoutSelector.checked) { + if(newCheckoutServer.text.length < 1) { + errorLabel.text = "You have to enter a remote server location for the clone."; return; } - var createAccount = true; - if(newCheckoutSelector.checked) { - if(newCheckoutServer.text.length < 1) { - errorLabel.text = "You have to enter a remote server location for the clone."; - return; - } - var repoDir = GitCheckoutCreator.createClone(checkoutName.text, newCheckoutServer.text, checkoutDir.text, accountComp.createObject(cloudAccounts)); - if(repoDir.length > 0) { - checkoutDir.text = repoDir; - } - else { - createAccount = false; - } + var repoDir = GitCheckoutCreator.createClone(checkoutName.text, newCheckoutServer.text, checkoutDir.text, accountComp.createObject(cloudAccounts)); + if(repoDir.length > 0) { + checkoutDir.text = repoDir; } else { - if(!GitCheckoutCreator.isGitDir(checkoutDir.text)) { - errorLabel.text = "You must select a location which is actually a git repository." - return; - } + createAccount = false; } - if(createAccount) { - cloudAccounts.addAccount(checkoutName.text, "Git", "accountsPageGit", accountComp.createObject(cloudAccounts)); - dlgStack.replace(addEmpty); + } + else { + if(!GitCheckoutCreator.isGitDir(checkoutDir.text)) { + errorLabel.text = "You must select a location which is actually a git repository." + return; } } + if(createAccount) { + cloudAccounts.addAccount(checkoutName.text, "Git", "accountsPageGit", accountComp.createObject(cloudAccounts)); + dlgStack.replace(addEmpty); + } } } } - Rectangle { - anchors { - left: parent.left; - right: parent.right; - bottom: parent.bottom; - } - height: 1; - color: "black"; - opacity: 0.1; - } } Component { id: userCredentials; diff --git a/gemini/qml/welcomepages/cloud/git/GetUserCredentials.qml b/gemini/qml/welcomepages/cloud/git/GetUserCredentials.qml --- a/gemini/qml/welcomepages/cloud/git/GetUserCredentials.qml +++ b/gemini/qml/welcomepages/cloud/git/GetUserCredentials.qml @@ -19,6 +19,7 @@ import QtQuick 2.0 import org.calligra 1.0 import Calligra.Gemini.Git 1.0 +import QtQuick.Controls 1.4 as QtControls import "../../../components" Item { @@ -80,30 +81,27 @@ right: parent.right; } height: childrenRect.height; - TextField { + QtControls.TextField { id: userName; width: parent.width; - placeholder: "Username"; + placeholderText: "Username"; } Item { height: privateKey.height; width: parent.width; - TextField { + QtControls.TextField { id: privateKey; width: parent.width - privateKeyBrowse.width; anchors.right: privateKeyBrowse.left; - placeholder: "Private Key File"; + placeholderText: "Private Key File"; } - CohereButton { + QtControls.Button { id: privateKeyBrowse; anchors { verticalCenter: privateKey.verticalCenter; right: parent.right; } text: "Browse..."; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; onClicked: { var newFile = GitCheckoutCreator.getFile("Private Key File", "*", ".ssh"); if(newFile !== "") { @@ -115,22 +113,19 @@ Item { height: publicKey.height; width: parent.width; - TextField { + QtControls.TextField { id: publicKey; width: parent.width - privateKeyBrowse.width; anchors.right: publicKeyBrowse.left; - placeholder: "Public Key File"; + placeholderText: "Public Key File"; } - CohereButton { + QtControls.Button { id: publicKeyBrowse; anchors { verticalCenter: publicKey.verticalCenter; right: parent.right; } text: "Browse..."; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; onClicked: { var newFile = GitCheckoutCreator.getFile("Public Key File", "*.pub", ".ssh"); if(newFile !== "") { @@ -157,30 +152,24 @@ } } - CohereButton { + QtControls.Button { id: acceptButton; anchors { top: pageContent.bottom; right: cancelButton.left; margins: Settings.theme.adjustedPixel(8); } text: "Accept"; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; onClicked: base.accepted(); } - CohereButton { + QtControls.Button { id: cancelButton; anchors { top: pageContent.bottom; right: parent.right; margins: Settings.theme.adjustedPixel(8); } text: "Cancel"; - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; onClicked: base.cancelled(); } } diff --git a/gemini/qml/welcomepages/cloud/git/RepositoryContent.qml b/gemini/qml/welcomepages/cloud/git/RepositoryContent.qml --- a/gemini/qml/welcomepages/cloud/git/RepositoryContent.qml +++ b/gemini/qml/welcomepages/cloud/git/RepositoryContent.qml @@ -17,6 +17,8 @@ */ import QtQuick 2.0 +import QtQuick.Controls 1.4 as QtControls +import org.kde.kirigami 2.1 as Kirigami import org.calligra 1.0 import Calligra.Gemini.Git 1.0 import "../../../components" @@ -41,6 +43,7 @@ if(DocumentManager.doc()) { DocumentManager.doc().sigProgress(progress); } + console.log("Transfer progress: " + progress); } onOperationBegun: { console.log(message); @@ -68,23 +71,20 @@ bottomMargin: 0; } width: (parent.width / 4) - Constants.DefaultMargin; - CohereButton { + QtControls.Button { id: pullButton; anchors { top: parent.top; horizontalCenter: parent.horizontalCenter; margins: Settings.theme.adjustedPixel(8); } - textColor: "#5b6573"; - textSize: Settings.theme.adjustedPixel(18); - color: "#D2D4D5"; text: "Pull from upstream"; onClicked: { enabled = false; pullInProgress.opacity = 1; gitController.pull(); } - BusyIndicator { + QtControls.BusyIndicator { id: pullInProgress; opacity: 0; running: true; @@ -99,7 +99,7 @@ } } } - Label { + Kirigami.Label { id: updatedLabel; opacity: 0; Behavior on opacity { @@ -116,8 +116,6 @@ right: parent.right; } text: "Update Completed!"; - font: Settings.theme.font("templateLabel"); - color: "#5b6573"; verticalAlignment: Text.AlignVCenter; horizontalAlignment: Text.AlignHCenter; Timer { id: hideUpdate; running: false; repeat: false; interval: 1000; onTriggered: { updatedLabel.opacity = 0; pullButton.enabled = true; } } @@ -133,41 +131,35 @@ right: parent.right; bottom: parent.bottom; } - header: Label { + header: Kirigami.Label { width: logListView.width; height: Constants.GridHeight / 2; text: "Recent Changes"; - font: Settings.theme.font("templateLabel"); - color: "#5b6573"; verticalAlignment: Text.AlignVCenter; horizontalAlignment: Text.AlignHCenter; } delegate: Column { width: logListView.width; height: childrenRect.height; - Text { + Kirigami.Label { id: messageText; width: parent.width; height: paintedHeight; - font: Settings.theme.font("templateLabel"); - color: "#5b6573"; text: model.shortMessage; wrapMode: Text.Wrap; } - Text { + Kirigami.Label { id: timeText; width: parent.width; height: paintedHeight; - font: Settings.theme.font("applicationLight"); - color: "#5b6573"; + opacity: 0.7; text: "on " + model.time; } - Text { + Kirigami.Label { id: nameText; width: parent.width; height: paintedHeight; - font: Settings.theme.font("applicationLight"); - color: "#5b6573"; + opacity: 0.7 text: "by " + model.authorName; } Item { @@ -183,14 +175,16 @@ } } } + ScrollDecorator { flickableItem: logListView; anchors.fill: logListView; } } GridView { id: docList; clip: true; contentWidth: width; anchors { margins: Constants.DefaultMargin; top: parent.top; + topMargin: Constants.DefaultMargin * 2; left: parent.left; right: logSidebar.left; bottom: parent.bottom; @@ -202,34 +196,43 @@ delegate: documentTile; ScrollDecorator { flickableItem: docList; } } - Label { + Kirigami.Label { anchors.fill: parent; text: "No Documents\n\nPlease add some documents to your reporitory.\n(%1)".arg(docList.model.documentsFolder); horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignVCenter; - font: Settings.theme.font("templateLabel"); - color: "#5b6573"; visible: docList.count === 0; } Component { id: documentTile; Item { width: docList.cellWidth; height: docList.cellHeight + Rectangle { + x: documentImage.x - Constants.DefaultMargin + (documentImage.width - documentImage.paintedWidth) / 2; + y: documentImage.y - Constants.DefaultMargin + (documentImage.height - documentImage.paintedHeight) / 2; + width: documentImage.paintedWidth + Constants.DefaultMargin * 2; + height: documentImage.paintedHeight + Constants.DefaultMargin * 2; + border { + color: "silver"; + width: 1; + } + } Image { + id: documentImage; source: "image://recentimage/" + model.filePath; anchors { top: parent.top; left: parent.left; right: parent.right; - margins: Constants.DefaultMargin / 2; + margins: Constants.DefaultMargin; } height: parent.width; fillMode: Image.PreserveAspectFit; smooth: true; asynchronous: true; } - Label { + Kirigami.Label { id: lblName; anchors { left: parent.left; @@ -242,8 +245,6 @@ horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignVCenter; text: model.fileName ? model.fileName : ""; - font: Settings.theme.font("templateLabel"); - color: "#5b6573"; } MouseArea { anchors.fill: parent; diff --git a/libs/main/gemini/ViewModeSwitchEvent.h b/libs/main/gemini/ViewModeSwitchEvent.h --- a/libs/main/gemini/ViewModeSwitchEvent.h +++ b/libs/main/gemini/ViewModeSwitchEvent.h @@ -22,32 +22,25 @@ #include #include -#include #include class KoShape; -class KoAbstractGradient; -class KoPattern; class KoGridData; struct ViewModeSynchronisationObject { - ViewModeSynchronisationObject() : initialized(false), gridData(0) { } + ViewModeSynchronisationObject() + : initialized(false) + , currentIndex(-1) + , scrollBarValue(QPoint()) + , zoomLevel(0) + , gridData(0) + { } bool initialized; - int currentSlide; - QPoint documentOffset; + int currentIndex; + QPoint scrollBarValue; float zoomLevel; - float rotationAngle; - KoColor backgroundColor; - KoColor foregroundColor; - float exposure; - float gamma; - QString compositeOp; - KoPattern* pattern; - KoAbstractGradient* gradient; - float opacity; - bool globalAlphaLock; QString activeToolId; KoGridData* gridData; diff --git a/stage/part/CMakeLists.txt b/stage/part/CMakeLists.txt --- a/stage/part/CMakeLists.txt +++ b/stage/part/CMakeLists.txt @@ -164,7 +164,7 @@ KF5::Archive KF5::IconThemes Qt5::Svg - Qt5::WebKitWidgets +# Qt5::WebKitWidgets ) if(HAVE_OPENGL) target_link_libraries(calligrastageprivate PRIVATE Qt5::OpenGL) diff --git a/stage/part/KPrView.cpp b/stage/part/KPrView.cpp --- a/stage/part/KPrView.cpp +++ b/stage/part/KPrView.cpp @@ -345,7 +345,7 @@ case ViewModeSwitchEvent::AboutToSwitchViewModeEvent: { ViewModeSynchronisationObject* syncObject = static_cast(event)->synchronisationObject(); if (activePage()) { - syncObject->currentSlide = kopaDocument()->pageIndex(activePage()); + syncObject->currentIndex = kopaDocument()->pageIndex(activePage()); syncObject->shapes = shapeManager()->shapes(); syncObject->initialized = true; } @@ -356,7 +356,7 @@ ViewModeSynchronisationObject* syncObject = static_cast(event)->synchronisationObject(); if (syncObject->initialized) { shapeManager()->setShapes(syncObject->shapes); - doUpdateActivePage( kopaDocument()->pageByIndex(syncObject->currentSlide, false) ); + doUpdateActivePage( kopaDocument()->pageByIndex(syncObject->currentIndex, false) ); KoToolManager::instance()->switchToolRequested("InteractionTool"); } diff --git a/stage/part/ui/KPrHtmlExportDialog.h b/stage/part/ui/KPrHtmlExportDialog.h --- a/stage/part/ui/KPrHtmlExportDialog.h +++ b/stage/part/ui/KPrHtmlExportDialog.h @@ -23,7 +23,7 @@ #include "ui_KPrHtmlExport.h" -#include +// #include #include #include @@ -67,7 +67,7 @@ QList m_allSlides; QString m_title; Ui::KPrHtmlExport ui; - QWebPage preview; +// QWebPage preview; int frameToRender; diff --git a/stage/part/ui/KPrHtmlExportDialog.cpp b/stage/part/ui/KPrHtmlExportDialog.cpp --- a/stage/part/ui/KPrHtmlExportDialog.cpp +++ b/stage/part/ui/KPrHtmlExportDialog.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +// #include #include #include #include @@ -51,7 +51,7 @@ connect(ui.pushbuttonBrowseTemplate, SIGNAL(clicked()), this, SLOT(browserAction())); - connect(&preview, SIGNAL(loadFinished(bool)), this, SLOT(renderPreview())); +// connect(&preview, SIGNAL(loadFinished(bool)), this, SLOT(renderPreview())); connect(ui.klineedit_title, SIGNAL(editingFinished()), this, SLOT(generatePreview())); connect(ui.klineedit_author, SIGNAL(editingFinished()), this, SLOT(generatePreview())); connect(ui.kListBox_slides, SIGNAL(currentRowChanged(int)), this, SLOT(generatePreview(int))); @@ -262,22 +262,22 @@ QUrl url = previewGenerator.exportPreview(KPrHtmlExport::Parameter(templateUrl(), static_cast(parentWidget()), slides, QUrl(), this->author(), ui.klineedit_title->text(), slidesNames, false)); - preview.mainFrame()->load(url); +// preview.mainFrame()->load(url); } void KPrHtmlExportDialog::renderPreview() { - preview.currentFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff); - preview.currentFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); - preview.setViewportSize(preview.currentFrame()->contentsSize()); - QImage image(preview.currentFrame()->contentsSize(), QImage::Format_ARGB32); - QPainter painter(&image); +// preview.currentFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff); +// preview.currentFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); +// preview.setViewportSize(preview.currentFrame()->contentsSize()); +// QImage image(preview.currentFrame()->contentsSize(), QImage::Format_ARGB32); +// QPainter painter(&image); - preview.mainFrame()->render(&painter); - painter.end(); +// preview.mainFrame()->render(&painter); +// painter.end(); - QImage thumbnail = image.scaled(ui.qLabel_preview->size(), Qt::KeepAspectRatio); - ui.qLabel_preview->setPixmap(QPixmap::fromImage(thumbnail)); +// QImage thumbnail = image.scaled(ui.qLabel_preview->size(), Qt::KeepAspectRatio); +// ui.qLabel_preview->setPixmap(QPixmap::fromImage(thumbnail)); } bool KPrHtmlExportDialog::selectedTemplateIsFavorite() diff --git a/words/part/KWView.cpp b/words/part/KWView.cpp --- a/words/part/KWView.cpp +++ b/words/part/KWView.cpp @@ -916,7 +916,7 @@ case ViewModeSwitchEvent::AboutToSwitchViewModeEvent: { ViewModeSynchronisationObject* syncObject = static_cast(event)->synchronisationObject(); if (m_canvas) { - syncObject->documentOffset = m_canvas->documentOffset(); + syncObject->scrollBarValue = m_canvas->canvasController()->scrollBarValue(); syncObject->zoomLevel = zoomController()->zoomAction()->effectiveZoom(); syncObject->activeToolId = KoToolManager::instance()->activeToolId(); syncObject->shapes = m_canvas->shapeManager()->shapes(); @@ -936,7 +936,7 @@ zoomController()->setZoom(KoZoomMode::ZOOM_CONSTANT, syncObject->zoomLevel); qApp->processEvents(); - m_canvas->canvasController()->setScrollBarValue(syncObject->documentOffset); + m_canvas->canvasController()->setScrollBarValue(syncObject->scrollBarValue); qApp->processEvents(); foreach(KoShape *shape, m_canvas->shapeManager()->shapesAt(currentPage().rect())) { diff --git a/words/part/dockers/KWStatisticsWidget.cpp b/words/part/dockers/KWStatisticsWidget.cpp --- a/words/part/dockers/KWStatisticsWidget.cpp +++ b/words/part/dockers/KWStatisticsWidget.cpp @@ -38,6 +38,7 @@ #include #include +#include #include #include #include @@ -311,14 +312,16 @@ }; foreach (KWFrameSet *fs, m_document->frameSets()) { - KWTextFrameSet *tfs = dynamic_cast(fs); + QPointer tfs = dynamic_cast(fs); if (tfs == 0) continue; - QTextDocument *doc = tfs->document(); + QPointer doc = tfs->document(); QTextBlock block = doc->begin(); while (block.isValid()) { // Don't be so heavy on large documents... qApp->processEvents(); + if(!tfs || !doc) + return; m_paragraphs += 1; m_charsWithSpace += block.text().length(); m_charsWithoutSpace += block.text().length() - block.text().count(QRegExp("\\s"));