From: Sven Hoexter Date: Sun, 15 Jun 2025 16:36:39 +0000 (+0200) Subject: New upstream version 2.9.576 X-Git-Tag: upstream/2.9.576^0 X-Git-Url: https://git.sven.stormbind.net/?a=commitdiff_plain;h=40602ebc134430bc546aa782e60c3901490959bd;p=sven%2Fvym.git New upstream version 2.9.576 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 0244037..211d834 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,30 +1,41 @@ -cmake_minimum_required(VERSION 3.12) +cmake_minimum_required(VERSION 3.16) -project(ViewYourMind-release) +project(ViewYourMind-develop LANGUAGES CXX) -find_package(Qt5 COMPONENTS Widgets LinguistTools REQUIRED) +# See also https://doc.qt.io/qt-6.5/cmake-get-started.html + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +if (CMAKE_SYSTEM_NAME STREQUAL Linux) + message(STATUS "using UNIX in cmake") # FIXME-0 still required? +endif() set(QtComponents LinguistTools Network PrintSupport - Script + Qml Svg + SvgWidgets Widgets Xml ) set(QtLibraries - Qt5::Network - Qt5::PrintSupport - Qt5::Script - Qt5::Svg - Qt5::Widgets - Qt5::Xml + Qt6::Network + Qt6::PrintSupport + Qt6::Qml + Qt6::Svg + Qt6::SvgWidgets + Qt6::Widgets + Qt6::Xml ) -# Switch on Debug mode with one of below: +# Switch on Debug mode on command line with # cmake -DCMAKE_BUILD_TYPE=Debug . +# +# or uncomment here: # set(CMAKE_BUILD_TYPE Debug) set(CMAKE_AUTOMOC ON) @@ -34,12 +45,12 @@ set(CMAKE_AUTORCC ON) # On Linux DBUS is used for IPC with vym # On openSUSE install it using: zypper install dbus-1-devel -if (UNIX) +if (CMAKE_SYSTEM_NAME STREQUAL Linux) find_package(DBus1) if(DBus1_FOUND) LIST(APPEND QtComponents DBus) - LIST(APPEND QtLibraries Qt5::DBus) + LIST(APPEND QtLibraries Qt6::DBus) endif() endif() @@ -64,17 +75,15 @@ if(WIN32) include(GNUInstallDirs) -find_package(Qt5 COMPONENTS ${QtComponents} REQUIRED) -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTORCC ON) -set(CMAKE_AUTOUIC ON) +find_package(Qt6 COMPONENTS ${QtComponents} REQUIRED) + list(APPEND CMAKE_AUTOUIC_SEARCH_PATHS "${CMAKE_SOURCE_DIR}/forms") -get_target_property(QtLibraryType Qt5::Widgets TYPE) +get_target_property(QtLibraryType Qt6::Widgets TYPE) if(QtLibraryType STREQUAL STATIC_LIBRARY) message(STATUS "Static Qt linkage") - list(APPEND QtLibraries Qt5::QSvgPlugin) + list(APPEND QtLibraries Qt6::QSvgPlugin) endif() include_directories( @@ -102,8 +111,8 @@ endif() # Translations (release) - # To update the translation files based on source code changes - # first call manually + # To update the translation files based on source code changes + # first call manually # lupdate-qt5 src/ -ts lang/*.ts # # Qt6 will have a dedicated macro: @@ -120,7 +129,7 @@ set_source_files_properties(${ts_files} PROPERTIES OUTPUT_LOCATION ${CMAKE_BINAR #QT5_create_translation(qm_files ${CMAKE_BINARY_DIR} ${ts_files}) #QT5_create_translation(qm_files ${CMAKE_SOURCE_DIR}/src) -QT5_add_translation(qm_files ${ts_files}) +QT6_add_translation(qm_files ${ts_files}) add_compile_definitions(CMAKE_SOURCE_DIR) message(STATUS "CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}") @@ -167,8 +176,9 @@ install(DIRECTORY exports flags icons macros ${CMAKE_BINARY_DIR}/translations sc if(UNIX) install(FILES icons/vym.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps) - file(CREATE_LINK ../apps/vym.png application-x-vym.png SYMBOLIC) - install(FILES ${CMAKE_BINARY_DIR}/application-x-vym.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/mimetypes) + # Disabling PR #109 for now: + # file(CREATE_LINK ../apps/vym.png application-x-vym.png SYMBOLIC) + # install(FILES ${CMAKE_BINARY_DIR}/application-x-vym.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/mimetypes) install(FILES config/vym.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mime/packages) install(FILES config/vym.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) endif() diff --git a/LICENSE.txt b/LICENSE.txt index 427f9a1..ef2d725 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,5 +1,5 @@ VYM - View Your Mind - Copyright (C) 2004-2023 Uwe Drechsel + Copyright (C) 2004-2025 Uwe Drechsel This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by @@ -11,7 +11,7 @@ GNU General Public License below for more details. In addition, as a special exception, Uwe Drechsel - gives permission to link the code of this program with the QT + gives permission to link the code of this program with the QT libraries from trolltech.com (or with modified versions of QT that use the same license as QT), and distribute linked combinations including the two. You must obey the GNU General Public License in diff --git a/README.md b/README.md index acaf9e6..0555db0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,19 @@ -VYM - View Your Mind (c) 2004-2024 by Uwe Drechsel +VYM - View Your Mind (c) 2004-2025 by Uwe Drechsel ================================================== +About +----- + +VYM is a mind mapping application. You can use it to visualize your +thoughts in tree-like structures. It is also useful for time management, +self-organization and sorting through new ideas and complex contexts. + +You can use the scripting capabilities for interesting presentations. +VYM can also retrieve data from the Jira issue tracking system and +talk to the Concluence documentation system. + +VYM runs on Apple and Windows and of course mose Linux platforms. + Documentation ------------- @@ -35,10 +48,11 @@ site: https://sourceforge.net/projects/vym/ -The latest development drops can be found in the Files/Development folder there. +The latest development drops for all platforms can be found there in the +folder Files->Development. -The latest binaries for Linux, Debian and Ubuntu are built and available in the authors -Open Build Service project: +The latest binaries for Linux, Debian and Ubuntu are built and available +in the authors Open Build Service project: https://software.opensuse.org/download.html?project=home%3Ainsilmaril&package=vym @@ -72,7 +86,8 @@ Installation * Compiling Compiling vym from scratch is pretty easy, if you have the - development packages of the Qt5 toolkit installed. + development packages of the Qt6 toolkit installed. (Check also the + homepage above for details): On the command line you can @@ -96,4 +111,3 @@ Bugs and feature requests will be taken care of in Please direct support questions to the mailinglist first: vym-forum@lists.sourceforge.net - diff --git a/demos/ao-report-example.vym b/demos/ao-report-example.vym deleted file mode 100644 index e1be9c8..0000000 Binary files a/demos/ao-report-example.vym and /dev/null differ diff --git a/demos/default-dark.vym b/demos/default-dark.vym index 7df80d7..607343d 100644 Binary files a/demos/default-dark.vym and b/demos/default-dark.vym differ diff --git a/demos/default.vym b/demos/default.vym index 5722de3..4858026 100644 Binary files a/demos/default.vym and b/demos/default.vym differ diff --git a/demos/lifeforms.vym b/demos/lifeforms.vym index 9070fc7..853932c 100644 Binary files a/demos/lifeforms.vym and b/demos/lifeforms.vym differ diff --git a/demos/scripts/confluence-delete-labels.vys b/demos/scripts/confluence-delete-labels.vys new file mode 100644 index 0000000..b6ae558 --- /dev/null +++ b/demos/scripts/confluence-delete-labels.vys @@ -0,0 +1,39 @@ +vym.clearConsole(); +map = vym.currentMap(); + +map.newBranchIterator("it"); +b = map.nextBranch("it"); +vym.print ("Starting with branch: " + b.getHeading() ); + +label = "deletion_candidate"; + +dc_count = 0; +total_count = 0; + +while (b) +{ + total_count++; + + vym.print ("Current page: " + b.getHeading() ); + if (b.hasAttributeWithKey("Confluence.labels.count")) { + n = b.attributeAsInt("Confluence.labels.count"); + for (i = 0; i < n; i++) { + key = "Confluence.label-" + i; + if (b.hasAttributeWithKey(key)) { + if (b.attributeAsString(key) == label) { + // Actions done in map: + b.colorBranch("#00FF00"); + b.setFlagByName("wip"); + b.unsetFlagByName("exclamationmark"); + + vym.print(" -> Found label " + label); + b.deleteConfluencePageLabel(label); + dc_count++; + } + } + } + } + b = map.nextBranch("it"); +} + +vym.print("Triggered removal of " + dc_count + " '" + label + "' labels in " + total_count + " pages"); \ No newline at end of file diff --git a/demos/scripts/confluence-find-labels.vys b/demos/scripts/confluence-find-labels.vys new file mode 100644 index 0000000..670a31a --- /dev/null +++ b/demos/scripts/confluence-find-labels.vys @@ -0,0 +1,37 @@ +vym.clearConsole(); +map = vym.currentMap(); + +map.newBranchIterator("it"); +b = map.nextBranch("it"); +vym.print ("Starting with branch: " + b.getHeading() ); + +label = "deletion_candidate"; + +dc_count = 0; +total_count = 0; + +while (b) +{ + total_count++; + + vym.print ("Current page: " + b.getHeading() ); + if (b.hasAttributeWithKey("Confluence.labels.count")) { + n = b.attributeAsInt("Confluence.labels.count"); + for (i = 0; i < n; i++) { + key = "Confluence.label-" + i; + if (b.hasAttributeWithKey(key)) { + if (b.attributeAsString(key) == label) { + // Actions done in map: + b.colorBranch("#FF0000"); + b.setFlagByName("exclamationmark"); + + vym.print(" -> Found label " + label); + dc_count++; + } + } + } + } + b = map.nextBranch("it"); +} + +vym.print(dc_count + " deletion_candidate labels found in " + total_count + " pages"); \ No newline at end of file diff --git a/demos/scripts/export-image.vys b/demos/scripts/export-image.vys index 2ea58a5..e215b70 100644 --- a/demos/scripts/export-image.vys +++ b/demos/scripts/export-image.vys @@ -1,16 +1,18 @@ vym.clearConsole(); map = vym.currentMap(); -map.exportMap("Image","export-test.png","PNG"); // Last parameter is optional +map.exportMap(["Image","export-test.png","PNG"]); -// Parameters - -0: Export type -1: Filname -2: Image format (optional) for "Image" +// exportMap Parameters +// 0: Export type +// 1: Filname +// 2: Image format (optional) for "Image" // Export types -["Last", "AO", "ASCII", "CSV", "HTML", "Image", "Impress", "LaTeX", "Markdown", "OrgMode", "PDF", "SVG", "XML"] - +// ["Last", "AO", "ASCII", "CSV", "HTML", "Image", "Impress", "LaTeX", "Markdown", "OrgMode", "PDF", "SVG", "XML"] +// +// More details in the code: +// https://github.com/insilmaril/vym/blob/aa5c4544627637344c58f5d8c7319c3b6d3dbd0c/src/vymmodelwrapper.cpp#L241 +// // Image formats -["PNG", "GIF", "JPG", "JPEG", "PNG", "PBM", "PGM", "PPM", "TIFF", "XBM", "]XPM" +// ["PNG", "GIF", "JPG", "JPEG", "PNG", "PBM", "PGM", "PPM", "TIFF", "XBM", "XPM"] diff --git a/demos/scripts/iterating-branches.vys b/demos/scripts/iterating-branches.vys index da70ac8..ff31fd5 100644 --- a/demos/scripts/iterating-branches.vys +++ b/demos/scripts/iterating-branches.vys @@ -1,10 +1,11 @@ vym.clearConsole(); -m1 = vym.currentMap(); +map = vym.currentMap(); -m1.initIterator("foobar"); -print ("Starting with branch: " + m1.getHeadingPlainText() ); +map.newBranchIterator("foobar"); +b = map.nextBranch("foobar"); +vym.print ("Starting with branch: " + b.headingText() ); -while (m1.nextIterator("foobar") ) +while (map.nextBranch("foobar") ) { - print ("Selected branch: " + m1.getHeadingPlainText() ); + vym.print ("Current branch: " + map.headingText() ); } diff --git a/demos/scripts/setSelectionBoxDarkTheme.vys b/demos/scripts/setSelectionBoxDarkTheme.vys index f77dad2..1d2df48 100644 --- a/demos/scripts/setSelectionBoxDarkTheme.vys +++ b/demos/scripts/setSelectionBoxDarkTheme.vys @@ -2,4 +2,4 @@ map = vym.currentMap(); map.setSelectionPenWidth(2); map.setSelectionPenColor("#ffffff00"); map.setSelectionBrushColor("#44ffff00"); -print ("Updated selection box colors."); +vym.print ("Updated selection box colors."); diff --git a/doc/devel/README-layout.md b/doc/devel/README-layout.md new file mode 100644 index 0000000..64f048a --- /dev/null +++ b/doc/devel/README-layout.md @@ -0,0 +1,187 @@ +Data structures +=============== + +The logical structure is equivalent to the view in the TreeEditor: +This is the tree of branches, images, and xlink endpoints. + +The graphical structure holds different and more information, for +example a branch also has a system- and a user-flagrow, which in turn +has a set of flags and so on. + +The logical part is mostly about maintaining and inserting branches and +images, while the graphical is required to maintain the visualization +and calculation of positions and bounding boxes. + +I have decided to maintain both structures indepently, which allows +to use the QAbstractItem for the TreeEditor and general maintenance of +the "logical" tree and at the same time use the parent-child relations +of QGraphicsItems for the more complex graphical layouts, like rotated +elements and also to simplify the positioning algorithms. Actually different +map layouts become only possible by decoupling the logical and the +graphical representations. + +This approach has pros and cons, of course. For example when deleting a +subtree, both logical and graphical structures need to be considered +differently, which is a bit complicate: The graphical tree get's +decoupled and deleted first, then rest of the logical tree is deleted. + +Also for relinking parts to new destinations, the structures need +different considerations. + +On the other hand, if all would be combined in one data structure, a lot +of filtering and special cases would be required to support both the +logical operations and also the visualization in different editors, with +different levels of details. + + +Containers +---------- + +- Container either represents a graphical object, e.g. the + HeadingContainer, which is the text of a branch on the map. Or the + container contains (sic!) a set of other containers + +- Containers containing others use ContainerLayouts and hints for + aligning their subcontainers. This information is used for + repositioning and defined in the MapDesign + +- Container classes (like MapObjs previously) don't follow the rule of + three: This works, because we + - we only use pointers, esp. for passing to functions + - are very care careful to delete containers + - no containers created on stack + +- Structure of containers is dynamic: If a branch has no child + branches, there is no need for container elements required for + layout (branchesContainer, listContainer, linkspaceContainer, ...) + +- Container layout + - BranchContainer + - InnerContainer + - OrnamentsContainer + [Optional: bulletPointContainer] + [Optional: systemFlagsContainer] + [Optional: userFlagsContainer] + - linkContainer + - headingContainer + - [Optional: linkSpaceContainer] + - [Optional: listContainer] + - [Optional: linkSpaceContainer] + - [Optional: imagesContainer] + - [Optional: branchesContainer] + - [Optional: imagesContainer] + - [Optional: branchesContainer] + - [Optional: imagesAndBranchesContainer] if no floating + layouts are use: + - [Optional: imagesContainer] + - [Optional: branchesContainer] + +- Only Horizontal layout supports rotated subcontainers so far + (Vertical layout does not require rotated elements for foreseeable use cases) + +Ideas +----- + +* Load/save of frames and autoDesign of frames + - when loading a map, all frames are saved within map: Those using + autoDesign and those which don't + - when creating a branch manually or via script, autoDesign option + is set for frames and they will be created as defined in + mapDesign + - Saving the autoDesign option of frames: + - in , so that also the NoFrame type can be saved + - autoInnerFrame + - autoOuterFrame + + +* Introduce *reference position*, which can be used in other containers + to position these containers. The reference position should be center + of HeadingContainer + +* Introduce *manual positioning* and *autoPositioning*. Manual + positioning is used for all floating containers, incl. mapCenters and + MainBranches. + + OTOH: If a container is in a floating layout or if it has no + parentItem, it uses manual positioning. + +* New layout type to handle floats in InnerContainer. Inner Container + has one of these two layouts: + - Horizontal (as already in use for non-floating children) + + - *BoundingFloats* when branchesContainer has Floating layout + + First child is *targetContainer*, which will be ornamentsContainer, + next children are (optionally) imagesContainer and branchesContainer. + (LinkSpaceContainer is not used with BoundingFloats!) + + By using this order, the layout of InnerContainer can be switched + between Horizontal and BoundingFloats. + + For BoundingFloats: + + bC and iC are processed first to calc bbox of all children relative to OC + - depending on their rel positions + - ???? + oC is positioned within BoundingFloats, so that upperleft of bbox of + children is again (local) origin. + +* Dedicated containers for links + - Allows more complex links, e.g. curved "bottomlines" under headings, + maybe curved headings later + - Proposition to have names on links, maybe rotated to save screen space + + +Bugs +---- + +* Real positions + - Mainbranches and branches need to keep position when detaching + - Branches keep position when layout changes to float + - Branches and parent branches (!) keep position, when switching to + free float + - keep position when relinking and relinking to rootItem (becoming + MC) + + Ideas: + - Reintroduce relative coordinates for mainbranches and floating + branches + + - Relative coordinates are "real": from center of parent Ornamented + Container to center of orn. container + + - Mapcenters use real scene positions + + - rotate branchesContainer? Could enable interesting layouts + + +Next steps +---------- + +* Moving containers around + - moving and tmp linked: maybe also information about rotation of + - tmp child + + The tmpParentContainer needs to be positioned based on link point and + orientation from above, also considering modifier keys to link + above/below. The bounding rect information and also parent needs to + remain unchanged, to avoid flickering in the tree, but the (relative) + position itself needs to be adjusted => a new layout hint is required. + +* Cleanup MapObj related stuff, which has been replaced by Containers + - MapItem + - Probably pretty much useless once Containers are fully + implemented. Especially the getEditPosition and + getSelectionPath should move to containers + - MapObj + - need at all in the end? + - getSelectionPath + +* Let containers inherit QGraphicsItem and use a QRectF for geometry instead of inheriting QGraphicsRectItem + once drawing boxes is no longer required for debugging + +* Cleanup branchContainer structure handling + + linkSpaceContainer and listContainer seem to be existing independent + of number of children. Should be created on demand only. + diff --git a/doc/devel/architecture-notes.md b/doc/devel/architecture-notes.md new file mode 100644 index 0000000..2058294 --- /dev/null +++ b/doc/devel/architecture-notes.md @@ -0,0 +1,25 @@ +Data structures +================ + +There are two views on the data: + + * Logical view: + + Defines the logical "tree" structure of the objects in a map. This is + used for organization (load/save, inserting and deleting branches, + traversing data for various modifications etc. + + All related changes are organized in the central VymModel class. + VymModel itself is derived from TreeModel, which focuses on the + low-level modifications of data, especially + inserting/deleting/relinking of branches. + + * Graphical view: + + Defines how visible objects are related, e.g. a row of flags, which + is part of a branch, contains several flags, so the flags are a part + of the row. This is done via nested "Container" objects. + + Containers provide various layouts and graphical options, like + defining alingment of contents. + diff --git a/doc/devel/xml-changes.md b/doc/devel/xml-changes.md new file mode 100644 index 0000000..6b5775d --- /dev/null +++ b/doc/devel/xml-changes.md @@ -0,0 +1,29 @@ +* Before 1.4.6 + - is used. Data is read + - from external files mentioned in href attribute + and inserted between elements + - from characters + Not clear: Do empty characters always overwrite the previously set text from file? + +* Before 2.5.0 + - No CDATA to save richText in Heading + - setting only as attribut + +* 2.5.0 to 2.7.562 + - HTML data encoded as CDATA (heading and vymnote) + +* After 2.7.562 + - vymText is used (at least headgin) + + +* pre 1.13.2 elements used to be within and did not + have control points yet + + + -> + - can have + -> + - can have + + + diff --git a/flags/standard/arrow-up-blue.svg b/flags/standard/arrow-up-blue.svg index dc3ad53..cea6651 100644 --- a/flags/standard/arrow-up-blue.svg +++ b/flags/standard/arrow-up-blue.svg @@ -1,21 +1,21 @@ image/svg+xmlimage/svg+xml @@ -2431,7 +2440,7 @@ y1="219.52251" x2="139.35249" y2="219.52251" - gradientTransform="matrix(0,-1,1,0,-166,216)"> + gradientTransform="rotate(-90,25,191)"> + gradientTransform="rotate(90,-11.00025,209.00025)"> + d="M 22.721111,7.7619129 C 25.287123,8.9283929 33.26156,21.829333 37.117459,28.74927 30.084451,31.56049 24.488314,32.002243 14.980566,32.00225 11.27794,32.08482 7.6930517,31.94984 3.6337785,31.268904 c 0,0 1.2092513,0.161628 1.2102599,0.168606 4.0248703,0.677328 7.1007806,0.870883 11.5511196,0.870883 9.507748,0 14.027854,-0.666949 21.060864,-3.478169 C 36.457967,26.677073 26.639826,9.9239739 22.721111,7.7619129 Z" + style="display:inline;opacity:0.6;fill:url(#linearGradient3980);fill-opacity:1;stroke:none;stroke-width:0.431048;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.0878;stroke-opacity:1" /> diff --git a/flags/standard/flash.svg b/flags/standard/flash.svg index 9cffdcc..5b041fc 100644 --- a/flags/standard/flash.svg +++ b/flags/standard/flash.svg @@ -1,18 +1,16 @@ + width="48" + height="48" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> @@ -21,30 +19,9 @@ image/svg+xml - - @@ -68,10 +45,10 @@ @@ -141,14 +116,13 @@ stroke="#ff8600" id="path23" style="display:inline;fill:url(#f);stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;filter:url(#filter1227)" - inkscape:label="bolt shadow" /> + transform="matrix(0.09322758,0,-0.02178224,0.18549785,14.46702,2.051281)" /> + style="display:inline;fill:url(#i);stroke-width:0.394517;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;paint-order:fill markers stroke" /> diff --git a/flags/system/jissue.svg b/flags/system/jissue.svg new file mode 100644 index 0000000..7f35cf2 --- /dev/null +++ b/flags/system/jissue.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + diff --git a/forms/actionlog-dialog.ui b/forms/actionlog-dialog.ui new file mode 100644 index 0000000..bf0e6b7 --- /dev/null +++ b/forms/actionlog-dialog.ui @@ -0,0 +1,108 @@ + + + ActionLogDialog + + + + 0 + 0 + 465 + 129 + + + + Dialog + + + + + + + + + + + + + Use logfile + + + + + + + Qt::RightToLeft + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + false + + + + + + + + + buttonBox + accepted() + ActionLogDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + ActionLogDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/forms/background-dialog.ui b/forms/background-dialog.ui new file mode 100644 index 0000000..ba5bb5d --- /dev/null +++ b/forms/background-dialog.ui @@ -0,0 +1,137 @@ + + + BackgroundDialog + + + + 0 + 0 + 465 + 181 + + + + Dialog + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + false + + + + + + + + + + Use background image + + + + + + + + + + + + + + false + + + + + + + Qt::RightToLeft + + + + + + + + + + Background color + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + buttonBox + accepted() + BackgroundDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + BackgroundDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/forms/branchpropeditor.ui b/forms/branchpropeditor.ui index b997aae..ae0d3d9 100644 --- a/forms/branchpropeditor.ui +++ b/forms/branchpropeditor.ui @@ -6,8 +6,8 @@ 0 0 - 325 - 378 + 358 + 581 @@ -19,500 +19,1045 @@ Branch Property Editor - + - - - 2 + + + true - - - Frame - - - - 6 - - - 9 - - - 9 - - - 9 - - - 9 - + + + + 0 + 0 + 327 + 849 + + + - - - Geometry - - - - - - - 0 - 0 - - - - - No Frame - - - - - Rectangle - - - - - Rounded Rectangle - - - - - Ellipse - - - - - Cloud - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Padding - - - - - - - Borderline width - - - - - - - 50 - - - - - - - 1 - - - 20 - - - - - - - Include children - - - - - - - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - Colors - - - - 7 - - - 7 - - - 7 - - - 7 - - - 6 - - - - - - 32 - 32 - - - - - 20 - 16777215 - - - - - - - - - - - - 0 - 0 - - - - Borderline color - - - framePenColorButton - - - - - - - - 32 - 0 - - - - - 20 - 16777215 - - - - - - - - - - - Background color - - - frameBrushColorButton - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - Layout - - - - - - - - Include images horizontally - - - - - - - Include images vertically - - - - - - - Free positioning of children (experimental!) - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Task - - - - - - - - -10000 - - - 10000 - - - - - - - Delta priority - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - + - Created: - - - - - - - false - - - true + Please select an item in map first. - - - - - - Modified: - - - - - - - false + + Qt::AlignHCenter|Qt::AlignTop - + true - - - Sleep: + + + QTabWidget::Rounded - - - - - - false - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Link - - - - - - Hide link if unselected + + 3 + + + + 0 + 0 + + + + Frames + + + + + + + 0 + 0 + + + + Heading + + + + + + Type + + + + + + + + 0 + 0 + + + + + No Frame + + + + + Rectangle + + + + + Rounded Rectangle + + + + + Pipe + + + + + Ellipse + + + + + Circle + + + + + Cloud + + + + + + + + Padding + + + + + + + 50 + + + + + + + Width + + + + + + + 1 + + + 20 + + + + + + + Frame color + + + innerFrameBrushColorButton + + + + + + + + 0 + 0 + + + + + 53 + 32 + + + + + 16777215 + 16777215 + + + + + + + + + + + + 0 + 0 + + + + Background color + + + innerFramePenColorButton + + + + + + + + 0 + 0 + + + + + 53 + 32 + + + + + 16777215 + 16777215 + + + + + + + + + + + + + + + + + + Automatic + + + + + + + + + + + 0 + 0 + + + + Subtree + + + + + + Type + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + No Frame + + + + + Rectangle + + + + + Rounded Rectangle + + + + + Pipe + + + + + Ellipse + + + + + Circle + + + + + Cloud + + + + + + + + Padding + + + + + + + 50 + + + + + + + Width + + + + + + + 1 + + + 20 + + + + + + + + 0 + 0 + + + + Frame color + + + innerFramePenColorButton + + + + + + + + 0 + 0 + + + + + 53 + 32 + + + + + 16777215 + 16777215 + + + + + + + + + + + Background color + + + innerFrameBrushColorButton + + + + + + + + 0 + 0 + + + + + 53 + 32 + + + + + 16777215 + 16777215 + + + + + + + + + + + Automatic + + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Layout + + + + + + + + true + + + + 0 + 0 + + + + Layout of branches + + + + + + + Automatic + + + + + Vertical + + + + + Horizontal + + + + + Floating bounded + + + + + Floating free + + + + + Grid based on columns + + + + + List + + + + + + + + + + + + + + 0 + 0 + + + + Layout of images + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + false + + + false + + + + + + + Automatic + + + + + Vertical + + + + + Horizontal + + + + + Floating bounded + + + + + Floating free + + + + + Grid based on columns + + + + + + + + + + + Dimensions + + + + + + Automatic + + + + + + + Heading width: + + + + + + + + + 150 + + + Qt::Horizontal + + + + + + + 150 + + + + + + + + + + + + Rotations + + + + + + Automatic + + + + + + + Rotation heading: + + + + + + + + + -90 + + + 90 + + + 5 + + + Qt::Horizontal + + + + + + + -90 + + + 90 + + + + + + + + + Rotation subtree: + + + + + + + + + -90 + + + 90 + + + 5 + + + Qt::Horizontal + + + + + + + -90 + + + 90 + + + + + + + + + + + + Scaling + + + + + + Automatic + + + + + + + Scale heading: + + + + + + + + + -100 + + + 100 + + + 1 + + + 0 + + + 0 + + + Qt::Horizontal + + + QSlider::NoTicks + + + 0 + + + + + + + 2 + + + 0.010000000000000 + + + 10.000000000000000 + + + 0.010000000000000 + + + 1.000000000000000 + + + + + + + + + Scale subtree: + + + + + + + + + -100 + + + 100 + + + 1 + + + 0 + + + 0 + + + Qt::Horizontal + + + + + + + 2 + + + 0.010000000000000 + + + 10.000000000000000 + + + 0.010000000000000 + + + 1.000000000000000 + + + + + + + + + + + + Qt::Vertical + + + + 20 + 79 + + + + + + + + + Link + + + + + + Hide link to parent if unselected + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Task + + + + + + + + -10000 + + + 10000 + + + + + + + Delta priority + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Created: + + + + + + + false + + + true + + + + + + + Modified: + + + + + + + false + + + true + + + + + + + Sleep: + + + + + + + false + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Attributes + + + + + + QAbstractItemView::NoEditTriggers + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + - + + + + + + + Qt::Horizontal + + + + 41 + 31 + + + + + + + + - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Attributes - - - - - - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - + - - - - - - - - - - - - - - - Qt::Horizontal - - - - 41 - 31 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - diff --git a/forms/confluence-settings-dialog.ui b/forms/confluence-settings-dialog.ui index 1818396..be6fe59 100644 --- a/forms/confluence-settings-dialog.ui +++ b/forms/confluence-settings-dialog.ui @@ -7,7 +7,7 @@ 0 0 631 - 356 + 350 diff --git a/forms/darktheme-settings-dialog.ui b/forms/darktheme-settings-dialog.ui index 1ab91e1..84a638d 100644 --- a/forms/darktheme-settings-dialog.ui +++ b/forms/darktheme-settings-dialog.ui @@ -7,7 +7,7 @@ 0 0 278 - 181 + 187 @@ -59,6 +59,9 @@ Never use dark theme + + buttonGroup + diff --git a/forms/editxlinkdialog.ui b/forms/editxlinkdialog.ui index 5934ecd..b079765 100644 --- a/forms/editxlinkdialog.ui +++ b/forms/editxlinkdialog.ui @@ -6,8 +6,8 @@ 0 0 - 337 - 219 + 356 + 246 @@ -23,12 +23,30 @@ 6 - + + 11 + + + 11 + + + 11 + + 11 - + + 0 + + + 0 + + + 0 + + 0 @@ -228,7 +246,16 @@ 6 - + + 0 + + + 0 + + + 0 + + 0 @@ -260,8 +287,7 @@ - src/xlinkitem.h - src/linkablemapobj.h + src/xlink.h diff --git a/forms/extrainfodialog.ui b/forms/extrainfodialog.ui index dd08c6e..995fcba 100644 --- a/forms/extrainfodialog.ui +++ b/forms/extrainfodialog.ui @@ -31,7 +31,7 @@ 11 - + Map: @@ -39,13 +39,49 @@ + + true + true - + + + Author: + + + + + + + + + + + + + Title: + + + + + + + + + + Comment: + + + + + + + + File location: @@ -54,7 +90,7 @@ - false + true false @@ -65,32 +101,26 @@ - - - - + - Title: + File version: - - - - - - Author: + + + true + + + true - - - - Qt::Vertical + Qt::Orientation::Vertical @@ -101,17 +131,7 @@ - - - Comment: - - - - - - - - + Statistics: @@ -120,11 +140,11 @@ - false + true - DejaVu Sans Mono + Courier New @@ -149,10 +169,10 @@ - Qt::Horizontal + Qt::Orientation::Horizontal - QSizePolicy::Expanding + QSizePolicy::Policy::Expanding @@ -175,7 +195,6 @@ - authorLE closeButton mapNameLE diff --git a/forms/scripteditor.ui b/forms/scripteditor.ui index e4b05a0..1d72ac3 100644 --- a/forms/scripteditor.ui +++ b/forms/scripteditor.ui @@ -88,8 +88,8 @@ Save to selected slide - - :/filesave.png:/filesave.png + + .. @@ -144,8 +144,8 @@ Reload - - :/script-reload.svg:/script-reload.svg + + .. @@ -155,8 +155,8 @@ Save - - :/filesave.png:/filesave.png + + .. @@ -224,6 +224,17 @@ + + + + Reload + + + + .. + + + @@ -241,8 +252,8 @@ Save - - :/filesave.png:/filesave.png + + .. @@ -264,8 +275,8 @@ Save as - - :/filesaveas.png:/filesaveas.png + + .. diff --git a/forms/showtextdialog.ui b/forms/showtextdialog.ui index 270a325..2629d76 100644 --- a/forms/showtextdialog.ui +++ b/forms/showtextdialog.ui @@ -6,8 +6,8 @@ 0 0 - 1116 - 748 + 600 + 400 diff --git a/forms/zip-settings-dialog.ui b/forms/zip-settings-dialog.ui deleted file mode 100644 index dda74b4..0000000 --- a/forms/zip-settings-dialog.ui +++ /dev/null @@ -1,114 +0,0 @@ - - - ZipSettingsDialog - - - - 0 - 0 - 766 - 222 - - - - zip settings - - - - - - zip tool: - - - - - - - - - - - - Choose - - - - - - - Status - - - - - - - - - unzip tool: - - - - - - - - - - - - Choose - - - - - - - Status - - - - - - - - - Qt::Vertical - - - - 17 - 28 - - - - - - - - - - Qt::Horizontal - - - - 595 - 20 - - - - - - - - Close - - - - - - - - - - diff --git a/icons/bright/application-exit.svg b/icons/bright/application-exit.svg new file mode 100644 index 0000000..711462f --- /dev/null +++ b/icons/bright/application-exit.svg @@ -0,0 +1,8 @@ + + + + diff --git a/icons/bright/camera-photo.svg b/icons/bright/camera-photo.svg new file mode 100644 index 0000000..c9b0f80 --- /dev/null +++ b/icons/bright/camera-photo.svg @@ -0,0 +1,15 @@ + + + + + + diff --git a/icons/bright/document-close.svg b/icons/bright/document-close.svg new file mode 100644 index 0000000..0e92408 --- /dev/null +++ b/icons/bright/document-close.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/icons/bright/document-export.svg b/icons/bright/document-export.svg new file mode 100644 index 0000000..d29db67 --- /dev/null +++ b/icons/bright/document-export.svg @@ -0,0 +1,11 @@ + + + + + + + diff --git a/icons/bright/document-new.svg b/icons/bright/document-new.svg new file mode 100644 index 0000000..44e5b4c --- /dev/null +++ b/icons/bright/document-new.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/bright/document-open.svg b/icons/bright/document-open.svg new file mode 100644 index 0000000..4a8498c --- /dev/null +++ b/icons/bright/document-open.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/icons/bright/document-print.svg b/icons/bright/document-print.svg new file mode 100644 index 0000000..cc8b5df --- /dev/null +++ b/icons/bright/document-print.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/icons/bright/document-save-as.svg b/icons/bright/document-save-as.svg new file mode 100644 index 0000000..787e911 --- /dev/null +++ b/icons/bright/document-save-as.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/bright/document-save.svg b/icons/bright/document-save.svg new file mode 100644 index 0000000..76c4422 --- /dev/null +++ b/icons/bright/document-save.svg @@ -0,0 +1,46 @@ + + + + + + + + diff --git a/icons/bright/edit-copy.svg b/icons/bright/edit-copy.svg new file mode 100644 index 0000000..2557953 --- /dev/null +++ b/icons/bright/edit-copy.svg @@ -0,0 +1,11 @@ + + + + + + + diff --git a/icons/bright/edit-cut.svg b/icons/bright/edit-cut.svg new file mode 100644 index 0000000..7b236db --- /dev/null +++ b/icons/bright/edit-cut.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/bright/edit-delete.svg b/icons/bright/edit-delete.svg new file mode 100644 index 0000000..0a62e5b --- /dev/null +++ b/icons/bright/edit-delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/bright/edit-find.svg b/icons/bright/edit-find.svg new file mode 100644 index 0000000..c46b0c7 --- /dev/null +++ b/icons/bright/edit-find.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/bright/edit-paste.svg b/icons/bright/edit-paste.svg new file mode 100644 index 0000000..fcec6a1 --- /dev/null +++ b/icons/bright/edit-paste.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/bright/folder-cloud.svg b/icons/bright/folder-cloud.svg new file mode 100644 index 0000000..94d0678 --- /dev/null +++ b/icons/bright/folder-cloud.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/icons/bright/format-justify-center.svg b/icons/bright/format-justify-center.svg new file mode 100644 index 0000000..bb9ea24 --- /dev/null +++ b/icons/bright/format-justify-center.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/icons/bright/format-justify-fill.svg b/icons/bright/format-justify-fill.svg new file mode 100644 index 0000000..4f533b8 --- /dev/null +++ b/icons/bright/format-justify-fill.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/icons/bright/format-justify-left.svg b/icons/bright/format-justify-left.svg new file mode 100644 index 0000000..9bea42c --- /dev/null +++ b/icons/bright/format-justify-left.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/icons/bright/format-justify-right.svg b/icons/bright/format-justify-right.svg new file mode 100644 index 0000000..955e091 --- /dev/null +++ b/icons/bright/format-justify-right.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/icons/bright/format-text-bold.svg b/icons/bright/format-text-bold.svg new file mode 100644 index 0000000..3333362 --- /dev/null +++ b/icons/bright/format-text-bold.svg @@ -0,0 +1,23 @@ + + + + + + + diff --git a/icons/bright/format-text-italic.svg b/icons/bright/format-text-italic.svg new file mode 100644 index 0000000..9f2a045 --- /dev/null +++ b/icons/bright/format-text-italic.svg @@ -0,0 +1,23 @@ + + + + + + + diff --git a/icons/bright/format-text-subscript.svg b/icons/bright/format-text-subscript.svg new file mode 100644 index 0000000..feb2fd0 --- /dev/null +++ b/icons/bright/format-text-subscript.svg @@ -0,0 +1,23 @@ + + + + + + + diff --git a/icons/bright/format-text-superscript.svg b/icons/bright/format-text-superscript.svg new file mode 100644 index 0000000..b5d2681 --- /dev/null +++ b/icons/bright/format-text-superscript.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/icons/bright/format-text-underline.svg b/icons/bright/format-text-underline.svg new file mode 100644 index 0000000..33eb027 --- /dev/null +++ b/icons/bright/format-text-underline.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/icons/bright/go-next.svg b/icons/bright/go-next.svg new file mode 100644 index 0000000..6d17b4a --- /dev/null +++ b/icons/bright/go-next.svg @@ -0,0 +1,10 @@ + + + + diff --git a/icons/bright/go-previous.svg b/icons/bright/go-previous.svg new file mode 100644 index 0000000..3a0c265 --- /dev/null +++ b/icons/bright/go-previous.svg @@ -0,0 +1,10 @@ + + + + diff --git a/icons/bright/insert-image.svg b/icons/bright/insert-image.svg new file mode 100644 index 0000000..8938c7e --- /dev/null +++ b/icons/bright/insert-image.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/bright/transform-rotate-ccw.svg b/icons/bright/transform-rotate-ccw.svg new file mode 100644 index 0000000..f4def0c --- /dev/null +++ b/icons/bright/transform-rotate-ccw.svg @@ -0,0 +1,363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/icons/bright/transform-rotate-cw.svg b/icons/bright/transform-rotate-cw.svg new file mode 100644 index 0000000..ef8e8a4 --- /dev/null +++ b/icons/bright/transform-rotate-cw.svg @@ -0,0 +1,400 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/icons/bright/view-sort-ascending-name.svg b/icons/bright/view-sort-ascending-name.svg new file mode 100644 index 0000000..d45bf2c --- /dev/null +++ b/icons/bright/view-sort-ascending-name.svg @@ -0,0 +1,18 @@ + + + + + + diff --git a/icons/bright/view-sort-descending-name.svg b/icons/bright/view-sort-descending-name.svg new file mode 100644 index 0000000..141dba9 --- /dev/null +++ b/icons/bright/view-sort-descending-name.svg @@ -0,0 +1,18 @@ + + + + + + diff --git a/icons/bright/zoom-fit-best.svg b/icons/bright/zoom-fit-best.svg new file mode 100644 index 0000000..0239de5 --- /dev/null +++ b/icons/bright/zoom-fit-best.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/bright/zoom-in-large.svg b/icons/bright/zoom-in-large.svg new file mode 120000 index 0000000..a74d058 --- /dev/null +++ b/icons/bright/zoom-in-large.svg @@ -0,0 +1 @@ +zoom-in.svg \ No newline at end of file diff --git a/icons/bright/zoom-in.svg b/icons/bright/zoom-in.svg new file mode 100644 index 0000000..69302f8 --- /dev/null +++ b/icons/bright/zoom-in.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/icons/bright/zoom-original.svg b/icons/bright/zoom-original.svg new file mode 100644 index 0000000..6d26104 --- /dev/null +++ b/icons/bright/zoom-original.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/bright/zoom-out-large.svg b/icons/bright/zoom-out-large.svg new file mode 120000 index 0000000..580ed01 --- /dev/null +++ b/icons/bright/zoom-out-large.svg @@ -0,0 +1 @@ +zoom-out.svg \ No newline at end of file diff --git a/icons/bright/zoom-out.svg b/icons/bright/zoom-out.svg new file mode 100644 index 0000000..c67c873 --- /dev/null +++ b/icons/bright/zoom-out.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/icons/classic/application-exit.svg b/icons/classic/application-exit.svg new file mode 100644 index 0000000..175f613 --- /dev/null +++ b/icons/classic/application-exit.svg @@ -0,0 +1,507 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/classic/camera-photo.png b/icons/classic/camera-photo.png new file mode 100644 index 0000000..2d231be Binary files /dev/null and b/icons/classic/camera-photo.png differ diff --git a/icons/classic/document-close.png b/icons/classic/document-close.png new file mode 100644 index 0000000..7cb9859 Binary files /dev/null and b/icons/classic/document-close.png differ diff --git a/icons/classic/document-export.svg b/icons/classic/document-export.svg new file mode 100644 index 0000000..ffb81f8 Binary files /dev/null and b/icons/classic/document-export.svg differ diff --git a/icons/classic/document-new.svg b/icons/classic/document-new.svg new file mode 100644 index 0000000..73dee14 --- /dev/null +++ b/icons/classic/document-new.svg @@ -0,0 +1,1422 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/classic/document-open.svg b/icons/classic/document-open.svg new file mode 100644 index 0000000..4010476 --- /dev/null +++ b/icons/classic/document-open.svg @@ -0,0 +1,4246 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/classic/document-print.svg b/icons/classic/document-print.svg new file mode 100644 index 0000000..8020488 --- /dev/null +++ b/icons/classic/document-print.svg @@ -0,0 +1,13698 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/classic/document-save-as.svg b/icons/classic/document-save-as.svg new file mode 100644 index 0000000..017af3f --- /dev/null +++ b/icons/classic/document-save-as.svg @@ -0,0 +1,29344 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/classic/document-save.svg b/icons/classic/document-save.svg new file mode 100644 index 0000000..9719cfd --- /dev/null +++ b/icons/classic/document-save.svg @@ -0,0 +1,29000 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/classic/edit-copy.svg b/icons/classic/edit-copy.svg new file mode 100644 index 0000000..a17cc2f --- /dev/null +++ b/icons/classic/edit-copy.svg @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + + + + + + + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/classic/edit-cut.svg b/icons/classic/edit-cut.svg new file mode 100644 index 0000000..e7e78c2 --- /dev/null +++ b/icons/classic/edit-cut.svg @@ -0,0 +1,805 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/classic/edit-delete.svg b/icons/classic/edit-delete.svg new file mode 100644 index 0000000..950adb6 --- /dev/null +++ b/icons/classic/edit-delete.svg @@ -0,0 +1,1454 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/classic/edit-find.svg b/icons/classic/edit-find.svg new file mode 100644 index 0000000..2ef0408 --- /dev/null +++ b/icons/classic/edit-find.svg @@ -0,0 +1,2962 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/classic/edit-paste.svg b/icons/classic/edit-paste.svg new file mode 100644 index 0000000..cbc0521 --- /dev/null +++ b/icons/classic/edit-paste.svg @@ -0,0 +1,3160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +   + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +   + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/classic/editsort.png b/icons/classic/editsort.png new file mode 100644 index 0000000..0e85ddf Binary files /dev/null and b/icons/classic/editsort.png differ diff --git a/icons/classic/editsortback.png b/icons/classic/editsortback.png new file mode 100644 index 0000000..29fd9d6 Binary files /dev/null and b/icons/classic/editsortback.png differ diff --git a/icons/classic/fileopen.png b/icons/classic/fileopen.png new file mode 100644 index 0000000..a79982e Binary files /dev/null and b/icons/classic/fileopen.png differ diff --git a/icons/classic/go-next.png b/icons/classic/go-next.png new file mode 100644 index 0000000..5890427 Binary files /dev/null and b/icons/classic/go-next.png differ diff --git a/icons/classic/go-previous.png b/icons/classic/go-previous.png new file mode 100644 index 0000000..d579d18 Binary files /dev/null and b/icons/classic/go-previous.png differ diff --git a/icons/classic/transform-rotate-ccw.svg b/icons/classic/transform-rotate-ccw.svg new file mode 100644 index 0000000..343495b --- /dev/null +++ b/icons/classic/transform-rotate-ccw.svg @@ -0,0 +1,330 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/icons/classic/transform-rotate-cw.svg b/icons/classic/transform-rotate-cw.svg new file mode 100644 index 0000000..56f4c70 --- /dev/null +++ b/icons/classic/transform-rotate-cw.svg @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/icons/classic/viewmag+.png b/icons/classic/viewmag+.png new file mode 100644 index 0000000..a424b61 Binary files /dev/null and b/icons/classic/viewmag+.png differ diff --git a/icons/classic/viewmag-.png b/icons/classic/viewmag-.png new file mode 100644 index 0000000..fc5364a Binary files /dev/null and b/icons/classic/viewmag-.png differ diff --git a/icons/classic/viewmag-reset.png b/icons/classic/viewmag-reset.png new file mode 100644 index 0000000..00c57ee Binary files /dev/null and b/icons/classic/viewmag-reset.png differ diff --git a/icons/classic/viewshowsel.png b/icons/classic/viewshowsel.png new file mode 100644 index 0000000..e08b2a5 Binary files /dev/null and b/icons/classic/viewshowsel.png differ diff --git a/icons/color-text.svg b/icons/color-text.svg new file mode 100644 index 0000000..7304e7c --- /dev/null +++ b/icons/color-text.svg @@ -0,0 +1,898 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +image/svg+xml + + + diff --git a/icons/dark/application-exit.svg b/icons/dark/application-exit.svg new file mode 100644 index 0000000..711462f --- /dev/null +++ b/icons/dark/application-exit.svg @@ -0,0 +1,8 @@ + + + + diff --git a/icons/dark/camera-photo.svg b/icons/dark/camera-photo.svg new file mode 100644 index 0000000..4ca38c7 --- /dev/null +++ b/icons/dark/camera-photo.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/icons/dark/document-close.svg b/icons/dark/document-close.svg new file mode 100644 index 0000000..8ab024c --- /dev/null +++ b/icons/dark/document-close.svg @@ -0,0 +1,11 @@ + + + + + + + diff --git a/icons/dark/document-export.svg b/icons/dark/document-export.svg new file mode 100644 index 0000000..34c2f43 --- /dev/null +++ b/icons/dark/document-export.svg @@ -0,0 +1,11 @@ + + + + + + + diff --git a/icons/dark/document-new.svg b/icons/dark/document-new.svg new file mode 100644 index 0000000..f1b07ed --- /dev/null +++ b/icons/dark/document-new.svg @@ -0,0 +1,73 @@ + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/icons/dark/document-open.svg b/icons/dark/document-open.svg new file mode 100644 index 0000000..0189b95 --- /dev/null +++ b/icons/dark/document-open.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/icons/dark/document-print.svg b/icons/dark/document-print.svg new file mode 100644 index 0000000..6502c27 --- /dev/null +++ b/icons/dark/document-print.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/dark/document-save-as.svg b/icons/dark/document-save-as.svg new file mode 100644 index 0000000..715d393 --- /dev/null +++ b/icons/dark/document-save-as.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/dark/document-save.svg b/icons/dark/document-save.svg new file mode 100644 index 0000000..953c1d8 --- /dev/null +++ b/icons/dark/document-save.svg @@ -0,0 +1,46 @@ + + + + + + + + diff --git a/icons/dark/edit-copy.svg b/icons/dark/edit-copy.svg new file mode 100644 index 0000000..fe4a36a --- /dev/null +++ b/icons/dark/edit-copy.svg @@ -0,0 +1,11 @@ + + + + + + + diff --git a/icons/dark/edit-cut.svg b/icons/dark/edit-cut.svg new file mode 100644 index 0000000..7410809 --- /dev/null +++ b/icons/dark/edit-cut.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/dark/edit-delete.svg b/icons/dark/edit-delete.svg new file mode 100644 index 0000000..0a62e5b --- /dev/null +++ b/icons/dark/edit-delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/dark/edit-find.svg b/icons/dark/edit-find.svg new file mode 100644 index 0000000..2709591 --- /dev/null +++ b/icons/dark/edit-find.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/dark/edit-paste.svg b/icons/dark/edit-paste.svg new file mode 100644 index 0000000..1a75b8d --- /dev/null +++ b/icons/dark/edit-paste.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/dark/folder-cloud.svg b/icons/dark/folder-cloud.svg new file mode 100644 index 0000000..9557564 --- /dev/null +++ b/icons/dark/folder-cloud.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/icons/dark/format-justify-center.svg b/icons/dark/format-justify-center.svg new file mode 100644 index 0000000..0fa0c9a --- /dev/null +++ b/icons/dark/format-justify-center.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/dark/format-justify-fill.svg b/icons/dark/format-justify-fill.svg new file mode 100644 index 0000000..bbe8f4f --- /dev/null +++ b/icons/dark/format-justify-fill.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/dark/format-justify-left.svg b/icons/dark/format-justify-left.svg new file mode 100644 index 0000000..35c4fb9 --- /dev/null +++ b/icons/dark/format-justify-left.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/dark/format-justify-right.svg b/icons/dark/format-justify-right.svg new file mode 100644 index 0000000..911e8e8 --- /dev/null +++ b/icons/dark/format-justify-right.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/dark/format-text-bold.svg b/icons/dark/format-text-bold.svg new file mode 100644 index 0000000..c0cc1ad --- /dev/null +++ b/icons/dark/format-text-bold.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/dark/format-text-italic.svg b/icons/dark/format-text-italic.svg new file mode 100644 index 0000000..7170323 --- /dev/null +++ b/icons/dark/format-text-italic.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/dark/format-text-subscript.svg b/icons/dark/format-text-subscript.svg new file mode 100644 index 0000000..9bf3234 --- /dev/null +++ b/icons/dark/format-text-subscript.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/dark/format-text-superscript.svg b/icons/dark/format-text-superscript.svg new file mode 100644 index 0000000..1be151c --- /dev/null +++ b/icons/dark/format-text-superscript.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/dark/format-text-underline.svg b/icons/dark/format-text-underline.svg new file mode 100644 index 0000000..d01b841 --- /dev/null +++ b/icons/dark/format-text-underline.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/dark/go-next.svg b/icons/dark/go-next.svg new file mode 100644 index 0000000..55b24a4 --- /dev/null +++ b/icons/dark/go-next.svg @@ -0,0 +1,10 @@ + + + + diff --git a/icons/dark/go-previous.svg b/icons/dark/go-previous.svg new file mode 100644 index 0000000..ebfc9c1 --- /dev/null +++ b/icons/dark/go-previous.svg @@ -0,0 +1,10 @@ + + + + diff --git a/icons/dark/insert-image.svg b/icons/dark/insert-image.svg new file mode 100644 index 0000000..46e29cf --- /dev/null +++ b/icons/dark/insert-image.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/dark/transform-rotate-ccw.svg b/icons/dark/transform-rotate-ccw.svg new file mode 100644 index 0000000..86e9198 --- /dev/null +++ b/icons/dark/transform-rotate-ccw.svg @@ -0,0 +1,363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/icons/dark/transform-rotate-cw.svg b/icons/dark/transform-rotate-cw.svg new file mode 100644 index 0000000..d9ae8e9 --- /dev/null +++ b/icons/dark/transform-rotate-cw.svg @@ -0,0 +1,400 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/icons/dark/view-sort-ascending-name.svg b/icons/dark/view-sort-ascending-name.svg new file mode 100644 index 0000000..399b17b --- /dev/null +++ b/icons/dark/view-sort-ascending-name.svg @@ -0,0 +1,18 @@ + + + + + + diff --git a/icons/dark/view-sort-descending-name.svg b/icons/dark/view-sort-descending-name.svg new file mode 100644 index 0000000..e7ceeca --- /dev/null +++ b/icons/dark/view-sort-descending-name.svg @@ -0,0 +1,18 @@ + + + + + + diff --git a/icons/dark/zoom-fit-best.svg b/icons/dark/zoom-fit-best.svg new file mode 100644 index 0000000..fb11eae --- /dev/null +++ b/icons/dark/zoom-fit-best.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/dark/zoom-in.svg b/icons/dark/zoom-in.svg new file mode 100644 index 0000000..94ad01c --- /dev/null +++ b/icons/dark/zoom-in.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/icons/dark/zoom-original.svg b/icons/dark/zoom-original.svg new file mode 100644 index 0000000..a816e59 --- /dev/null +++ b/icons/dark/zoom-original.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/icons/dark/zoom-out.svg b/icons/dark/zoom-out.svg new file mode 100644 index 0000000..d906f3b --- /dev/null +++ b/icons/dark/zoom-out.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/icons/document-new-copy.svg b/icons/document-new-copy.svg new file mode 100644 index 0000000..541733f --- /dev/null +++ b/icons/document-new-copy.svg @@ -0,0 +1,649 @@ + + + + + + + + + + + + + + + + + + + + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/document-save.svg b/icons/document-save.svg deleted file mode 100644 index 9719cfd..0000000 --- a/icons/document-save.svg +++ /dev/null @@ -1,29000 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/icons/draw-brush.svg b/icons/draw-brush.svg new file mode 100644 index 0000000..a2e2ef0 --- /dev/null +++ b/icons/draw-brush.svg @@ -0,0 +1,628 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Oxygen Team + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/edit-clear-list.svg b/icons/edit-clear-list.svg new file mode 100644 index 0000000..8914613 --- /dev/null +++ b/icons/edit-clear-list.svg @@ -0,0 +1,4320 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +   + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +   + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/editcopy.png b/icons/editcopy.png deleted file mode 100644 index ae1cd9f..0000000 Binary files a/icons/editcopy.png and /dev/null differ diff --git a/icons/editcut.png b/icons/editcut.png deleted file mode 100644 index 192b575..0000000 Binary files a/icons/editcut.png and /dev/null differ diff --git a/icons/editpaste.png b/icons/editpaste.png deleted file mode 100644 index b8454f9..0000000 Binary files a/icons/editpaste.png and /dev/null differ diff --git a/icons/editsort.png b/icons/editsort.png deleted file mode 100644 index 0e85ddf..0000000 Binary files a/icons/editsort.png and /dev/null differ diff --git a/icons/editsortback.png b/icons/editsortback.png deleted file mode 100644 index 29fd9d6..0000000 Binary files a/icons/editsortback.png and /dev/null differ diff --git a/icons/edittrash.png b/icons/edittrash.png deleted file mode 100644 index 810efc4..0000000 Binary files a/icons/edittrash.png and /dev/null differ diff --git a/icons/exit.png b/icons/exit.png deleted file mode 100644 index b266020..0000000 Binary files a/icons/exit.png and /dev/null differ diff --git a/icons/file-document-export.png b/icons/file-document-export.png deleted file mode 100644 index ffb81f8..0000000 Binary files a/icons/file-document-export.png and /dev/null differ diff --git a/icons/fileclose.png b/icons/fileclose.png deleted file mode 100644 index 7cb9859..0000000 Binary files a/icons/fileclose.png and /dev/null differ diff --git a/icons/filenew.png b/icons/filenew.png deleted file mode 100644 index 004ca03..0000000 Binary files a/icons/filenew.png and /dev/null differ diff --git a/icons/filenewcopy.png b/icons/filenewcopy.png deleted file mode 100644 index 7bf6b73..0000000 Binary files a/icons/filenewcopy.png and /dev/null differ diff --git a/icons/fileopen.png b/icons/fileopen.png deleted file mode 100644 index a79982e..0000000 Binary files a/icons/fileopen.png and /dev/null differ diff --git a/icons/fileprint.png b/icons/fileprint.png deleted file mode 100644 index a71ee28..0000000 Binary files a/icons/fileprint.png and /dev/null differ diff --git a/icons/filesave.png b/icons/filesave.png deleted file mode 100644 index 3bc2a37..0000000 Binary files a/icons/filesave.png and /dev/null differ diff --git a/icons/filesaveas.png b/icons/filesaveas.png deleted file mode 100644 index c8d4816..0000000 Binary files a/icons/filesaveas.png and /dev/null differ diff --git a/icons/find.png b/icons/find.png deleted file mode 100644 index 1b7a252..0000000 Binary files a/icons/find.png and /dev/null differ diff --git a/icons/formatrichtext.png b/icons/formatrichtext.png deleted file mode 100644 index 98f6173..0000000 Binary files a/icons/formatrichtext.png and /dev/null differ diff --git a/icons/formatrichtext.svg b/icons/formatrichtext.svg new file mode 100644 index 0000000..343811c --- /dev/null +++ b/icons/formatrichtext.svg @@ -0,0 +1,958 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +image/svg+xml + + + diff --git a/icons/formatvarfont.png b/icons/formatvarfont.png deleted file mode 100644 index 9471335..0000000 Binary files a/icons/formatvarfont.png and /dev/null differ diff --git a/icons/modifiers/mode-select.svg b/icons/modifiers/mode-select.svg index 57cdd2f..600c6e3 100644 --- a/icons/modifiers/mode-select.svg +++ b/icons/modifiers/mode-select.svg @@ -1,24 +1,24 @@ + version="1.0" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + inkscape:collect="always" + x="-0.0184" + y="-0.018399997" + width="1.0368" + height="1.0368"> + inkscape:document-rotation="0" + inkscape:showpageshadow="2" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1"> + transform="matrix(0.28164268,0,0,0.28164268,-20.45438,90.409607)" + style="display:none"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/icons/text_block.png b/icons/text_block.png deleted file mode 100644 index 60e79b5..0000000 Binary files a/icons/text_block.png and /dev/null differ diff --git a/icons/text_bold.png b/icons/text_bold.png deleted file mode 100644 index 19dc645..0000000 Binary files a/icons/text_bold.png and /dev/null differ diff --git a/icons/text_center.png b/icons/text_center.png deleted file mode 100644 index acf20f8..0000000 Binary files a/icons/text_center.png and /dev/null differ diff --git a/icons/text_italic.png b/icons/text_italic.png deleted file mode 100644 index d21986d..0000000 Binary files a/icons/text_italic.png and /dev/null differ diff --git a/icons/text_left.png b/icons/text_left.png deleted file mode 100644 index 88c7c7e..0000000 Binary files a/icons/text_left.png and /dev/null differ diff --git a/icons/text_right.png b/icons/text_right.png deleted file mode 100644 index 7fea4e5..0000000 Binary files a/icons/text_right.png and /dev/null differ diff --git a/icons/text_sub.png b/icons/text_sub.png deleted file mode 100644 index 8f53bea..0000000 Binary files a/icons/text_sub.png and /dev/null differ diff --git a/icons/text_super.png b/icons/text_super.png deleted file mode 100644 index 49ca8f7..0000000 Binary files a/icons/text_super.png and /dev/null differ diff --git a/icons/text_under.png b/icons/text_under.png deleted file mode 100644 index 8fccad3..0000000 Binary files a/icons/text_under.png and /dev/null differ diff --git a/icons/transform-rotate-ccw.svg b/icons/transform-rotate-ccw.svg deleted file mode 100644 index 343495b..0000000 --- a/icons/transform-rotate-ccw.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - diff --git a/icons/transform-rotate-cw.svg b/icons/transform-rotate-cw.svg deleted file mode 100644 index 56f4c70..0000000 --- a/icons/transform-rotate-cw.svg +++ /dev/null @@ -1,417 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - diff --git a/icons/viewmag+.png b/icons/viewmag+.png deleted file mode 100644 index a424b61..0000000 Binary files a/icons/viewmag+.png and /dev/null differ diff --git a/icons/viewmag-.png b/icons/viewmag-.png deleted file mode 100644 index fc5364a..0000000 Binary files a/icons/viewmag-.png and /dev/null differ diff --git a/icons/viewmag-reset.png b/icons/viewmag-reset.png deleted file mode 100644 index 00c57ee..0000000 Binary files a/icons/viewmag-reset.png and /dev/null differ diff --git a/icons/viewshowsel.png b/icons/viewshowsel.png deleted file mode 100644 index e08b2a5..0000000 Binary files a/icons/viewshowsel.png and /dev/null differ diff --git a/images/background-grid.png b/images/background-grid.png new file mode 100644 index 0000000..7500c57 Binary files /dev/null and b/images/background-grid.png differ diff --git a/macros/macros.vys b/macros/macros.vys index 4419570..f60b1d7 100644 --- a/macros/macros.vys +++ b/macros/macros.vys @@ -1,19 +1,50 @@ // vim:syntax=javascript +// Macros called when function keys are pressed + + //! Helper function to toggle frame -function toggle_frame(map) +function toggle_frame_branch(map) +{ + map = vym.currentMap(); + b = map.selectedBranch(); + + if (b.getFrameType(true) == "NoFrame" ) { + b.setFrameType (true, "RoundedRectangle"); + } else + b.setFrameType (true, "NoFrame"); +} + +function toggle_frame_subtree(map) { - if (map.getFrameType() == "NoFrame" ) { - map.setFrameType ("RoundedRectangle"); + map = vym.currentMap(); + b = map.selectedBranch(); + + if (b.getFrameType(false) == "NoFrame" ) { + b.setFrameType (false, "RoundedRectangle"); } else - map.setFrameType ("NoFrame"); + b.setFrameType (false, "NoFrame"); } + + +function colorBranchWithQuickColor(n) +{ + map = vym.currentMap(); + vym.selectQuickColor(n); + c = vym.currentColor(); + + b = map.selectedBranch(); + b.colorBranch(c); +} + function colorSubtreeWithQuickColor(n) { map = vym.currentMap(); vym.selectQuickColor(n); c = vym.currentColor(); - map.colorSubtree (c); + + b = map.selectedBranch(); + b.colorSubtree (c); } //! Macro F1: Color subtree red @@ -96,21 +127,25 @@ function macro_f12() // 1 - high prio task with arrows // 2 - done task without arrows, but green hook map = vym.currentMap(); - if (map.hasTask() ) { + b = map.selectedBranch(); + if (b.hasTask() ) { // Switch to state 2 - map.toggleTask(); - map.unsetFlagByName("2arrow-up"); - map.unsetFlagByName("stopsign"); - map.setFlagByName("hook-green"); - map.colorBranch("#0000ff"); + b.toggleTask(); + b.unsetFlagByName("2arrow-up"); + b.unsetFlagByName("stopsign"); + b.setFlagByName("hook-green"); + if (vym.usesDarkTheme()) + colorBranchWithQuickColor(5); + else + colorBranchWithQuickColor(3); } else { - if (map.hasActiveFlag("hook-green")) { + if (b.hasActiveFlag("hook-green")) { // Switch to state 0 - map.unsetFlagByName("hook-green"); + b.unsetFlagByName("hook-green"); } else { // Switch to state 1 - map.setFlagByName("2arrow-up"); - map.toggleTask(); + b.setFlagByName("2arrow-up"); + b.toggleTask(); } } } @@ -120,117 +155,123 @@ function macro_f12() function macro_shift_f1() { map = vym.currentMap(); + b = map.selectedBranch(); status = "Background off"; - if (map.getFrameType() == "NoFrame") { + if (b.getFrameType(true) == "NoFrame") { status = "Background light red"; } - toggle_frame ( map ); - map.setFrameBrushColor("#ffb3b4"); - statusMessage(status); + toggle_frame_branch ( map ); + b.setFrameBrushColor(true, "#ffb3b4"); + vym.statusMessage(status); } //! Macro Shift + F2: Frame background light green function macro_shift_f2() { map = vym.currentMap(); + b = map.selectedBranch(); status = "Background off"; - if (map.getFrameType() == "NoFrame") { + if (b.getFrameType(true) == "NoFrame") { status = "Background light green"; } - toggle_frame ( map ); - map.setFrameBrushColor("#bdffd6"); - statusMessage(status); + toggle_frame_branch ( map ); + b.setFrameBrushColor(true, "#bdffd6"); + vym.statusMessage(status); } //! Macro Shift + F3: Frame background light yellow function macro_shift_f3() { map = vym.currentMap(); + b = map.selectedBranch(); status = "Background off"; - if (map.getFrameType() == "NoFrame") { + if (b.getFrameType(true) == "NoFrame") { status = "Background light yellow"; } - toggle_frame ( map ); - map.setFrameBrushColor("#efefb3"); - statusMessage(status); + toggle_frame_branch ( map ); + b.setFrameBrushColor(true, "#efefb3"); + vym.statusMessage(status); } //! Macro Shift + F4: Frame background light blue function macro_shift_f4() { map = vym.currentMap(); + b = map.selectedBranch(); status = "Background off"; - if (map.getFrameType() == "NoFrame") { + if (b.getFrameType(true) == "NoFrame") { status = "Background light blue"; } - toggle_frame ( map ); - map.setFrameBrushColor("#e2e6ff"); - statusMessage(status); + toggle_frame_branch ( map ); + b.setFrameBrushColor(true, "#e2e6ff"); + vym.statusMessage(status); } //! Macro Shift + F5: Frame background light grey function macro_shift_f5() { map = vym.currentMap(); + b = map.selectedBranch(); status = "Background off"; - if (map.getFrameType() == "NoFrame") { + if (b.getFrameType(true) == "NoFrame") { status = "Background light grey"; } - toggle_frame ( map ); - map.setFrameBrushColor("#d6d6d6"); - statusMessage(status); + toggle_frame_branch ( map ); + b.setFrameBrushColor(true, "#d6d6d6"); + vym.statusMessage(status); } //! Macro Shift + F6: Frame background purple function macro_shift_f6() { map = vym.currentMap(); + b = map.selectedBranch(); status = "Background off"; - if (map.getFrameType() == "NoFrame") { + if (b.getFrameType(true) == "NoFrame") { status = "Background purple"; } - toggle_frame ( map ); - map.setFrameBrushColor("#ffaaff"); - statusMessage(status); + toggle_frame_branch ( map ); + b.setFrameBrushColor(true, "#ffaaff"); + vym.statusMessage(status); } //! Macro Shift + F7: Frame background white function macro_shift_f7() { map = vym.currentMap(); + b = map.selectedBranch(); status = "Background off"; - if (map.getFrameType() == "NoFrame") { + if (b.getFrameType() == "NoFrame") { status = "Background white"; } - toggle_frame ( map ); - map.setFrameBrushColor("#ffffff"); - statusMessage(status); + toggle_frame_branch ( map ); + b.setFrameBrushColor("#ffffff"); + vym.statusMessage(status); } //! Macro Shift + F8: Frame background black function macro_shift_f8() { map = vym.currentMap(); + b = map.selectedBranch(); status = "Background off"; - if (map.getFrameType() == "NoFrame") { + if (b.getFrameType(true) == "NoFrame") { status = "Background black"; } - toggle_frame ( map ); - map.setFrameBrushColor("#000000"); - statusMessage(status); + toggle_frame_branch ( map ); + b.setFrameBrushColor(true, "#000000"); + vym.statusMessage(status); } -//! Macro Shift + F9: Toggle frame to include children +// Macro Shift + F9: function macro_shift_f9() { - map = vym.currentMap(); - map.toggleFrameIncludeChildren(); } //! Macro Shift + F10: // Useful for timestamps created on last entry function macro_shift_f10() -{ +{ } //! Macro Shift + F11: Replace "@..." by mutt aliases @@ -275,151 +316,216 @@ function macro_shift_f11() //! Macro Shift + F12: function macro_shift_f12() { - statusMessage("Macro F12 + Shift triggered"); + vym.statusMessage("Macro F12 + Shift triggered"); } // New ///////////////////////////////////// -//! Macro Ctrl + F1: +//! Macro Ctrl + F1: Subtree background light red function macro_ctrl_f1() { - statusMessage("Macro F1 + Ctrl triggered"); + map = vym.currentMap(); + b = map.selectedBranch(); + status = "Subtree background off"; + if (b.getFrameType(false) == "NoFrame") { + status = "Subtree background light red"; + } + toggle_frame_subtree ( map ); + b.setFrameBrushColor(false, "#ffb3b4"); + vym.statusMessage(status); } -//! Macro Ctrl + F2: +//! Macro Ctrl + F2: Subtree background light green + function macro_ctrl_f2() { - statusMessage("Macro F2 + Ctrl triggered"); + map = vym.currentMap(); + b = map.selectedBranch(); + status = "Subtree background off"; + if (b.getFrameType(true) == "NoFrame") { + status = "Subtree background light green"; + } + toggle_frame_branch ( map ); + b.setFrameBrushColor(true, "#bdffd6"); + vym.statusMessage(status); } -//! Macro Ctrl + F3: +//! Macro Ctrl + F3: Subtree background light yellow function macro_ctrl_f3() { - statusMessage("Macro F3 + Ctrl triggered"); + map = vym.currentMap(); + b = map.selectedBranch(); + status = "Subtree background off"; + if (b.getFrameType(true) == "NoFrame") { + status = "SUbtree background light yellow"; + } + toggle_frame_branch ( map ); + b.setFrameBrushColor(true, "#efefb3"); + vym.statusMessage(status); } -//! Macro Ctrl + F4: +//! Macro Ctrl + F4: Subtree background light blue function macro_ctrl_f4() { - statusMessage("Macro F4 + Ctrl triggered"); + map = vym.currentMap(); + b = map.selectedBranch(); + status = "Subtree background off"; + if (b.getFrameType(true) == "NoFrame") { + status = "SUbtree background light yellow"; + } + toggle_frame_branch ( map ); + b.setFrameBrushColor(true, "#efefb3"); + vym.statusMessage(status); } -//! Macro Ctrl + F5: +//! Macro Ctrl + F5: Subtree background light grey function macro_ctrl_f5() { - statusMessage("Macro F5 + Ctrl triggered"); + map = vym.currentMap(); + b = map.selectedBranch(); + status = "Subtree background off"; + if (b.getType(true) == "NoFrame") { + status = "Subtree background light grey"; + } + toggle_frame_branch ( map ); + b.setFrameBrushColor(true, "#d6d6d6"); + vym.statusMessage(status); } -//! Macro Ctrl + F6: +//! Macro Ctrl + F6: Subtree background purple function macro_ctrl_f6() { - statusMessage("Macro F6 + Ctrl triggered"); + map = vym.currentMap(); + b = map.selectedBranch(); + status = "Subtree background off"; + if (b.getFrameType(true) == "NoFrame") { + status = "Subtree background purple"; + } + toggle_frame_branch ( map ); + b.setFrameBrushColor(true, "#ffaaff"); + vym.statusMessage(status); } -//! Macro Ctrl + F7: +//! Macro Ctrl + F7: Subtree background white function macro_ctrl_f7() { - statusMessage("Macro F7 + Ctrl triggered"); + map = vym.currentMap(); + b = map.selectedBranch(); + status = "Subtree background off"; + if (b.getFrameType() == "NoFrame") { + status = "Subtree background white"; + } + toggle_frame_branch ( map ); + b.setFrameBrushColor("#ffffff"); + vym.statusMessage(status); } -//! Macro Ctrl + F8: +//! Macro Ctrl + F8: Subtree background black function macro_ctrl_f8() { - statusMessage("Macro F8 + Ctrl triggered"); + map = vym.currentMap(); + b = map.selectedBranch(); + status = "Subtree background off"; + if (b.getFrameType(true) == "NoFrame") { + status = "Subtree background black"; + } + toggle_frame_branch ( map ); + b.setFrameBrushColor(true, "#000000"); + vym.statusMessage(status); } //! Macro Ctrl + F9: function macro_ctrl_f9() { - statusMessage("Macro F9 + Ctrl triggered"); + vym.statusMessage("Macro F9 + Ctrl triggered"); } //! Macro Ctrl + F10: function macro_ctrl_f10() { - statusMessage("Macro F10 + Ctrl triggered"); + vym.statusMessage("Macro F10 + Ctrl triggered"); } //! Macro Ctrl + F11: function macro_ctrl_f11() { - statusMessage("Macro F11 + Ctrl triggered"); + vym.statusMessage("Macro F11 + Ctrl triggered"); } //! Macro Ctrl + F12: function macro_ctrl_f12() { - statusMessage("Macro F12 + Ctrl triggered"); + vym.statusMessage("Macro F12 + Ctrl triggered"); } //! Macro Ctrl + Shift + F1: function macro_ctrl_shift_f1() { - statusMessage("Macro F1 + Ctrl + Shift triggered"); + vym.statusMessage("Macro F1 + Ctrl + Shift triggered"); } //! Macro Ctrl + Shift + F2: function macro_ctrl_shift_f2() { - statusMessage("Macro F2 + Ctrl + Shift triggered"); + vym.statusMessage("Macro F2 + Ctrl + Shift triggered"); } //! Macro Ctrl + Shift + F3: function macro_ctrl_shift_f3() { - statusMessage("Macro F3 + Ctrl + Shift triggered"); + vym.statusMessage("Macro F3 + Ctrl + Shift triggered"); } //! Macro Ctrl + Shift + F4: function macro_ctrl_shift_f4() { - statusMessage("Macro F4 + Ctrl + Shift triggered"); + vym.statusMessage("Macro F4 + Ctrl + Shift triggered"); } //! Macro Ctrl + Shift + F5: function macro_ctrl_shift_f5() { - statusMessage("Macro F5 + Ctrl + Shift triggered"); + vym.statusMessage("Macro F5 + Ctrl + Shift triggered"); } //! Macro Ctrl + Shift + F6: function macro_ctrl_shift_f6() { - statusMessage("Macro F6 + Ctrl + Shift triggered"); + vym.statusMessage("Macro F6 + Ctrl + Shift triggered"); } //! Macro Ctrl + Shift + F7: function macro_ctrl_shift_f7() { - statusMessage("Macro F7 + Ctrl + Shift triggered"); + vym.statusMessage("Macro F7 + Ctrl + Shift triggered"); } //! Macro Ctrl + Shift + F8: function macro_ctrl_shift_f8() { - statusMessage("Macro F8 + Ctrl + Shift triggered"); + vym.statusMessage("Macro F8 + Ctrl + Shift triggered"); } //! Macro Ctrl + Shift + F9: function macro_ctrl_shift_f9() { - statusMessage("Macro F9 + Ctrl + Shift triggered"); + vym.statusMessage("Macro F9 + Ctrl + Shift triggered"); } //! Macro Ctrl + Shift + F10: function macro_ctrl_shift_f10() { - statusMessage("Macro F10 + Ctrl + Shift triggered"); + vym.statusMessage("Macro F10 + Ctrl + Shift triggered"); } //! Macro Ctrl + Shift + F11: function macro_ctrl_shift_f11() { - statusMessage("Macro F11 + Ctrl + Shift triggered"); + vym.statusMessage("Macro F11 + Ctrl + Shift triggered"); } //! Macro Ctrl + Shift + F12: function macro_ctrl_shift_f12() { - statusMessage("Macro F12 + Ctrl + Shift triggered"); + vym.statusMessage("Macro F12 + Ctrl + Shift triggered"); } \ No newline at end of file diff --git a/macros/slideeditor-snapshot.vys b/macros/slideeditor-snapshot.vys index 80ba102..02b0639 100644 --- a/macros/slideeditor-snapshot.vys +++ b/macros/slideeditor-snapshot.vys @@ -1,6 +1,6 @@ // Template for taking snapshots in slideeditor map = vym.currentMap(); -map.setMapZoom(CURRENT_ZOOM); -map.setMapRotation(CURRENT_ANGLE); +map.setZoom(CURRENT_ZOOM); +map.setRotationView(CURRENT_ANGLE); map.centerOnID(CURRENT_ID); diff --git a/scripts/vivym b/scripts/vivym index 69befe0..1e1382c 100755 --- a/scripts/vivym +++ b/scripts/vivym @@ -43,14 +43,19 @@ for MAP in $*; do cp $DIR/$BASE.xml $BAK # Edit - $EDITOR $DIR/$BASE.xml + if [ -z "$EDITOR" ] ; then + echo "\$EDITOR is not set" + else + $EDITOR $DIR/$BASE.xml + fi # Compare if cmp $DIR/$BASE.xml $DIR/$BASE.xml.bak &> /dev/null ; then echo "Map not changed." else # Missing: Zip again - #rm $BAK + echo Removing Backup: $BAK + rm $BAK cd $DIR zip -r $MAP . diff --git a/scripts/vym-ruby.rb b/scripts/vym-ruby.rb index bf91f0b..c99724d 100644 --- a/scripts/vym-ruby.rb +++ b/scripts/vym-ruby.rb @@ -1,7 +1,7 @@ require 'dbus' require 'pp' -$debug = false +$debug = true class Vym def initialize (name) @@ -24,7 +24,7 @@ class Vym # No parameters com = "vym.#{c}();" puts " * Calling vym: \"#{com}\":" if $debug - ret = @main.execute( com ) + ret = @main.runScript( com ) else # with parameters p = ""; @@ -37,13 +37,14 @@ class Vym end end com = "vym.#{c} (#{a.join(',')});" - puts " ** Calling vym: \"#{com}\":" if $debug - ret = @main.execute( com ) + puts " * Calling vym: \"#{com}\":" if $debug + ret = @main.runScript( com ) end - #FIXME-2 err = m.errorLevel[0] + #FIXME err = m.errorLevel[0] if $debug puts " Returned: #{ret[0]}" if ret[0] != "" + pp ret # puts " Error: #{err}" if err > 0 end ret[0] @@ -60,7 +61,6 @@ class Vym end def map (n) - #puts "def map: @service.object(\"/vymmodel_#{n}\")" map = @service.object("/vymmodel_#{n}") map.introspect map.default_iface = "org.insilmaril.vym.model.adaptor" @@ -87,7 +87,6 @@ class VymMap # Getting commands for model via DBUS #if mapCount() > 0 - # m = model(1) s = @map.listCommands puts "VymMap::initialize Retrieving commands via dbus..." if $debug @model_commands = s[0].split "," @@ -98,7 +97,7 @@ class VymMap # No parameters com = "vym.currentMap().#{c}();" puts " * Calling model: \"#{com}\":" if $debug - ret = @map.execute( com ) + ret = @main.runScript( com ) else # Build string with parameters p = ""; @@ -113,11 +112,11 @@ class VymMap # com = "vym.clearConsole(); print( vym.currentMap().#{c} (#{a.join(',')}));" com = " vym.currentMap().#{c} (#{a.join(',')});" puts " ** Calling model: \"#{com}\":" if $debug - ret = @map.execute( com ) + ret = @main.runScript( com ) puts "Done calling" if $debug end - #FIXME-2 err = m.errorLevel[0] + #FIXME err = m.errorLevel[0] if $debug puts " Returned: #{ret[0]}" if ret[0] != "" #puts " Error: #{err}" if err > 0 diff --git a/src/aboutdialog.cpp b/src/aboutdialog.cpp index 67ff08a..1442522 100644 --- a/src/aboutdialog.cpp +++ b/src/aboutdialog.cpp @@ -7,7 +7,7 @@ #include "settings.h" extern Settings settings; -extern QString iconPath; // FIXME-4 embed vym logo as ressource? +extern QString iconPath; extern QString vymVersion; extern QString vymBuildDate; extern QString vymCodeName; @@ -73,6 +73,7 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent) "
  • Croatian: Damir BraÅ¡nić
  • " "
  • Czech: Vít Pelčák, Pavel Fric
  • " "
  • French: Marc Sert, Philippe Caillaud and Claude
  • " + "
  • German: Uwe Drechsel (with typo fixes by Herbert Reiter)
  • " "
  • Greek: Yannis Kaskamanidis
  • " "
  • Interlingua: Giovanni Sora
  • " "
  • Italian: Albano Battistella, Giovanni Sora, Seyed Puria Nafisi Azizi
  • " @@ -86,6 +87,7 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent) "" "
  • Patches" "
      " + "
    • Bleyddyn: "Clear" button in "Recent files" menu and improving remembering last directory
    • " "
    • Sven Höxter: Various patches to fix typos and especiall for Debian packaging
    • " "
    • Edward Wang: adding close tab buttons
    • " "
    • p0llox (Pierre): various patches for Debian packaging
    • " @@ -116,7 +118,7 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent) "
    • Packaging" "
    • " "
        " - "
      • Jon Ciesla: Sourceforge file releases
      • " + "
      • Gwyn Ciesla: Fedora packaging
      • " "
      • Xavier Oswald, Christoph Thielecke, Pierre, and Steffen " "Joeris: Debian packaging
      • " "
      " diff --git a/src/actionlog-dialog.cpp b/src/actionlog-dialog.cpp new file mode 100644 index 0000000..845e340 --- /dev/null +++ b/src/actionlog-dialog.cpp @@ -0,0 +1,77 @@ +#include "actionlog-dialog.h" + +#include + +#include "file.h" +#include "mainwindow.h" + +extern Main *mainWindow; +extern QString vymName; + +extern QString iconTheme; + +extern bool useActionLog; +extern QString actionLogPath; + +ActionLogDialog::ActionLogDialog() +{ + ui.setupUi(this); + + QDialog::setWindowTitle( vymName + + tr("Logfile settings", "Dialog to set if and where logfile is used")); + + updateControls(); + + ui.setPathButton->setIcon(QPixmap(QString(":/document-open-%1.svg").arg(iconTheme))); + connect(ui.setPathButton, SIGNAL(pressed()), this, SLOT(selectLogPathDialog())); + + connect(ui.useLogFileCheckbox, SIGNAL(clicked()), this, SLOT(toggleUseLogFile())); + connect(ui.logFilePathLineEdit, SIGNAL(textEdited(const QString &)), + this, SLOT(pathChanged(const QString &))); +} + +int ActionLogDialog::exec() +{ + int r = QDialog::exec(); + /* + if (ui.useBackgroundImageCheckbox->isChecked()) + model->setBackgroundImageName(ui.imageNameLineEdit->text()); + */ + return r; +} + +void ActionLogDialog::toggleUseLogFile() +{ + useActionLog = ui.useLogFileCheckbox->isChecked(); + updateControls(); +} + +void ActionLogDialog::pathChanged(const QString &s) +{ + actionLogPath = ui.logFilePathLineEdit->text(); +} + +void ActionLogDialog::selectLogPathDialog() +{ + QStringList filters; + filters << tr("Logfiles") + " (*.log)"; + QFileDialog fd; + fd.setFileMode(QFileDialog::AnyFile); + fd.setNameFilters(filters); + fd.setWindowTitle(vymName + " - " + tr("Set path to logfile")); + fd.setDirectory(dirname(actionLogPath)); + fd.setAcceptMode(QFileDialog::AcceptOpen); + + if (fd.exec() == QDialog::Accepted && !fd.selectedFiles().isEmpty()) { + actionLogPath = fd.selectedFiles().first(); + updateControls(); + } +} + +void ActionLogDialog::updateControls() +{ + ui.logFilePathLineEdit->setText(actionLogPath); + ui.useLogFileCheckbox->setChecked(useActionLog); + ui.logFilePathLineEdit->setEnabled(useActionLog); + ui.setPathButton->setEnabled(useActionLog); +} diff --git a/src/actionlog-dialog.h b/src/actionlog-dialog.h new file mode 100644 index 0000000..2dfadf7 --- /dev/null +++ b/src/actionlog-dialog.h @@ -0,0 +1,25 @@ +#ifndef ACTIONLOG_DIALOG_H +#define ACTIONLOG_DIALOG_H + +#include "ui_actionlog-dialog.h" + +class VymModel; + +class ActionLogDialog : public QDialog { + Q_OBJECT + + public: + ActionLogDialog(); + int exec(); + + public slots: + void toggleUseLogFile(); + void pathChanged(const QString &); + void selectLogPathDialog(); + + private: + void updateControls(); + Ui::ActionLogDialog ui; +}; + +#endif diff --git a/src/animpoint.cpp b/src/animpoint.cpp index 66dd0fa..8120c02 100644 --- a/src/animpoint.cpp +++ b/src/animpoint.cpp @@ -60,6 +60,8 @@ void AnimPoint::copy(AnimPoint other) void AnimPoint::setStart(const QPointF &p) { startPos = p; + setX(startPos.x()); + setY(startPos.y()); initVector(); } @@ -90,6 +92,13 @@ bool AnimPoint::animate() { if (!animated) return false; + + // Some math to slow down the movement in the end + qreal f = 1 - n / (qreal)animTicks; + qreal ff = 1 - f * f * f; + setX(startPos.x() + vector.x() * ff); + setY(startPos.y() + vector.y() * ff); + n++; if (n > animTicks) { vector = QPointF(0, 0); @@ -99,12 +108,6 @@ bool AnimPoint::animate() return false; } - // Some math to slow down the movement in the end - qreal f = 1 - n / (qreal)animTicks; - qreal ff = 1 - f * f * f; - setX(startPos.x() + vector.x() * ff); - setY(startPos.y() + vector.y() * ff); - return animated; } diff --git a/src/animpoint.h b/src/animpoint.h index 91bfeaa..740da68 100644 --- a/src/animpoint.h +++ b/src/animpoint.h @@ -29,7 +29,7 @@ class AnimPoint : public QPointF { QPointF startPos; QPointF destPos; QPointF vector; - qreal n; + uint n; uint animTicks; bool animated; }; diff --git a/src/arrowobj.cpp b/src/arrowobj.cpp index b4e36c7..f89d07a 100644 --- a/src/arrowobj.cpp +++ b/src/arrowobj.cpp @@ -1,5 +1,5 @@ #include "arrowobj.h" -#include "misc.h" +#include "geometry.h" #include #include @@ -23,12 +23,11 @@ void ArrowObj::init() pen.setStyle(Qt::SolidLine); arrowBegin = scene()->addPolygon(QPolygonF(), pen); - arrowBegin->setZValue(dZ_XLINK); + arrowBegin->setParentItem(this); arrowEnd = scene()->addPolygon(QPolygonF(), pen); - arrowEnd->setZValue(dZ_XLINK); + arrowEnd->setParentItem(this); line = scene()->addLine(QLineF(), pen); - line->setZValue(dZ_XLINK); arrowSize = 4; useFixedLength = false; @@ -71,7 +70,7 @@ void ArrowObj::hide() { setVisibility(false); } void ArrowObj::setVisibility(bool b) { - MapObj::setVisibility(b); + //qDebug() << "AO::setVis b=" << b; if (b) { if (styleEnd != None) arrowEnd->show(); @@ -92,12 +91,10 @@ void ArrowObj::setEndPoint(QPointF p) { endPoint = p; - line->setLine(absPos.x(), absPos.y(), p.x(), p.y()); - arrowEnd->setPos(absPos); + line->setLine(pos().x(), pos().y(), p.x(), p.y()); - qreal a = getAngle(endPoint - absPos); + qreal a = getAngle(pos() - endPoint); arrowEnd->setRotation(-a / 6.28 * 360); - arrowEnd->setPos(endPoint); } QPointF ArrowObj::getEndPoint() { return endPoint; } diff --git a/src/attribute-wrapper.cpp b/src/attribute-wrapper.cpp new file mode 100644 index 0000000..8ab4188 --- /dev/null +++ b/src/attribute-wrapper.cpp @@ -0,0 +1,63 @@ +#include "attribute-wrapper.h" + +#include "attributeitem.h" + +#include "mainwindow.h" +#include "vymmodel.h" + +extern Main *mainWindow; + +AttributeWrapper::AttributeWrapper(AttributeItem *ai) +{ + //qDebug() << "Constr AttributeWrapper (ii)"; + attributeItemInt = ai; +} + +AttributeWrapper::~AttributeWrapper() +{ + //qDebug() << "Destr AttributeWrapper"; +} + +VymModel* AttributeWrapper::model() {return attributeItemInt->getModel();} + +AttributeItem* AttributeWrapper::attributeItem() {return attributeItemInt;} + +bool AttributeWrapper::hasRichTextHeading() +{ + bool r = attributeItemInt->heading().isRichText(); + mainWindow->setScriptResult(r); + return r; +} + +QString AttributeWrapper::headingText() +{ + QString r = attributeItemInt->headingPlain(); + mainWindow->setScriptResult(r); + return r; +} + +bool AttributeWrapper::selectParent() +{ + bool r = model()->selectParent(attributeItemInt); + if (!r) + mainWindow->abortScript( + QJSValue::GenericError, + "Couldn't select parent item"); + mainWindow->setScriptResult(r); + return r; +} + +void AttributeWrapper::setHeadingRichText(const QString &text) +{ + /* + VymText vt; + vt.setRichText(text); + model()->setHeading(vt, attributeItemInt); + */ +} + +void AttributeWrapper::setHeadingText(const QString &text) +{ + model()->setHeadingPlainText(text, attributeItemInt); +} + diff --git a/src/attribute-wrapper.h b/src/attribute-wrapper.h new file mode 100644 index 0000000..e8733e0 --- /dev/null +++ b/src/attribute-wrapper.h @@ -0,0 +1,28 @@ +#ifndef ATTRIBUTE_WRAPPER_H +#define ATTRIBUTE_WRAPPER_H + +class AttributeItem; +class VymModel; + +#include + +class AttributeWrapper : public QObject { + Q_OBJECT + public: + AttributeWrapper(AttributeItem*); + ~AttributeWrapper(); + VymModel* model(); + AttributeItem* attributeItem(); + + public slots: + bool hasRichTextHeading(); + QString headingText(); + bool selectParent(); + void setHeadingRichText(const QString &); + void setHeadingText(const QString &); + + private: + AttributeItem *attributeItemInt; +}; + +#endif diff --git a/src/attributeitem.cpp b/src/attributeitem.cpp index d4961d0..a43a039 100644 --- a/src/attributeitem.cpp +++ b/src/attributeitem.cpp @@ -1,26 +1,26 @@ #include "attributeitem.h" +#include "attribute-wrapper.h" + +#include #include extern bool debug; AttributeItem::AttributeItem(TreeItem *parent) - : BranchItem(parent) + : MapItem(parent) { //qDebug() << "Constr. AttrItem (parent)"; - TreeItem::setType(Attribute); - internal = false; - attrType = Undefined; + init(); } -AttributeItem::AttributeItem(const QString &k, const QString &v, TreeItem *parent) - : BranchItem(parent) +AttributeItem::AttributeItem(const QString &k, const QVariant &v, TreeItem *parent) + : MapItem(parent) { //qDebug() << "Constr. AttrItem (k, v, parent)"; - TreeItem::setType(Attribute); - internal = false; - - set(k, v); + init(); + keyInt = k; + setValue(v); } AttributeItem::~AttributeItem() { @@ -29,87 +29,44 @@ AttributeItem::~AttributeItem() { void AttributeItem::copy(AttributeItem *other) { - key = other->key; - value = other->value; - attrType = other->attrType; -} - -void AttributeItem::set(const QString &k, const QString &v) -{ - key = k; - value = QVariant(v); - attrType = String; - createHeading(); -} - -void AttributeItem::get(QString &k, QString &v, Type &t) // FIXME-3 Better use return tuple - // https://stackoverflow.com/questions/321068/returning-multiple-values-from-a-c-function -{ - k = key; - v = value.toString(); - t = attrType; -} - -void AttributeItem::setKey(const QString &k) // FIXME-3 Check if key aready exists in branch? -{ - key = k; - createHeading(); -} - -QString AttributeItem::getKey() -{ - return key; + keyInt = other->keyInt; + valueInt = other->valueInt; } -void AttributeItem::setValue(const QString &v) -{ - value = v; - attrType = String; - createHeading(); +void AttributeItem::init() { + TreeItem::setType(Attribute); + internal = false; + attributeWrapperInt = nullptr; } -void AttributeItem::setValue(const qlonglong &n) +AttributeWrapper* AttributeItem::attributeWrapper() { - value = n; - attrType = Integer; - createHeading(); -} + if (!attributeWrapperInt) + attributeWrapperInt = new AttributeWrapper(this); -void AttributeItem::setValue(const QDateTime &dt) -{ - value = dt; - attrType = DateTime; - createHeading(); + return attributeWrapperInt; } -QVariant AttributeItem::getValue() +QString AttributeItem::key() { - return value; + return keyInt; } -void AttributeItem::setAttributeType(const Type &t) +void AttributeItem::setValue(const QVariant &v) { - attrType = t; + valueInt = v; + updateHeading(); } -AttributeItem::Type AttributeItem::getAttributeType() +QVariant AttributeItem::value() { - return attrType; + return valueInt; } -QString AttributeItem::getAttributeTypeString() +void AttributeItem::updateHeading() { - switch (attrType) { - case Integer: - return "Integer"; - case String: - return "String"; - case DateTime: - return "DateTime"; - default: - break; - } - return "Undefined"; + setHeadingPlainText( + QString("[Attr] %1: %2").arg(keyInt).arg(valueInt.toString())); } void AttributeItem::setInternal(bool b) { internal = b; } @@ -119,14 +76,8 @@ bool AttributeItem::isInternal() { return internal; } QString AttributeItem::getDataXML() { QString a; - a = attribut("key", getKey()); - a += attribut("value", getValue().toString()); - a += attribut("type", getAttributeTypeString()); + a = attribute("key", keyInt); + a += attribute("value", valueInt.toString()); + a += attribute("type", valueInt.typeName()); return singleElement("attribute", a); } - -void AttributeItem::createHeading() // FIXME-3 Visible in TreeEditor, should not go to MapEditor -{ - setHeadingPlainText( - QString("[Attr] %1: %2").arg(key).arg(value.toString())); -} diff --git a/src/attributeitem.h b/src/attributeitem.h index 69c5f62..c03d105 100644 --- a/src/attributeitem.h +++ b/src/attributeitem.h @@ -4,48 +4,37 @@ #include #include -#include "branchitem.h" +#include "mapitem.h" + +class AttributeWrapper; /*! \brief A key and a value The data itself is stored in Attribute Definitions (AttributeDef). A list of these tables AttributeTable is maintained for every MapEditor. */ -class AttributeItem : public BranchItem { +class AttributeItem : public MapItem { public: - enum Type { - Undefined, //!< Undefined type - Integer, //!< Integer - DateTime, //!< DateTime - String //!< String - }; - AttributeItem(TreeItem *parent = nullptr); - AttributeItem(const QString &k, const QString &v, TreeItem *parent = nullptr); + AttributeItem(const QString &k, const QVariant &v, TreeItem *parent = nullptr); virtual ~AttributeItem(); void copy(AttributeItem *other); - void set(const QString &k, const QString &v); - void get(QString &k, QString &v, Type &t); + void init(); + AttributeWrapper* attributeWrapper(); void setKey(const QString &k); - QString getKey(); - void setValue(const QString &v); - void setValue(const qlonglong &n); - void setValue(const QDateTime &dt); - QVariant getValue(); - QDateTime getValueDateTime(); - using BranchItem::setType; - virtual void setAttributeType(const Type &t); - AttributeItem::Type getAttributeType(); - QString getAttributeTypeString(); + QString key(); + void setValue(const QVariant &v); + QVariant value(); + void updateHeading(); +// using BranchItem::setType; void setInternal(bool b); bool isInternal(); QString getDataXML(); protected: - void createHeading(); bool internal; //!< Internal attributes cannot be edited by user - QString key; - QVariant value; - Type attrType; + QString keyInt; + QVariant valueInt; + AttributeWrapper *attributeWrapperInt; }; #endif diff --git a/src/background-dialog.cpp b/src/background-dialog.cpp new file mode 100644 index 0000000..43752c1 --- /dev/null +++ b/src/background-dialog.cpp @@ -0,0 +1,103 @@ +#include "background-dialog.h" + +#include +#include +#include + +#include "mainwindow.h" +#include "mapeditor.h" +#include "vymmodel.h" + +extern QDir lastImageDir; +extern Main *mainWindow; +extern QString vymName; + +BackgroundDialog::BackgroundDialog(VymModel *m) +{ + ui.setupUi(this); + + model = m; + + QDialog::setWindowTitle( + "VYM - " + tr("Set background", "Dialog to set background color or image")); + + updateBackgroundColorButton(); + updateBackgroundImageControls(); + + //ui.selectImageButton->setIcon(QIcon::fromTheme("document-new")); + ui.selectImageButton->setIcon(style()->standardIcon(QStyle::SP_DialogOpenButton)); + connect(ui.selectImageButton, SIGNAL(pressed()), this, SLOT(selectBackgroundImage())); + connect(ui.backgroundColorButton, SIGNAL(pressed()), this, SLOT(selectBackgroundColor())); + + connect(ui.useBackgroundImageCheckbox, SIGNAL(clicked()), this, SLOT(toggleBackgroundImage())); +} + +int BackgroundDialog::exec() +{ + int r = QDialog::exec(); + if (ui.useBackgroundImageCheckbox->isChecked()) + model->setBackgroundImageName(ui.imageNameLineEdit->text()); + return r; +} + +void BackgroundDialog::selectBackgroundColor() +{ + QColor orgCol = model->getMapEditor()->getScene()->backgroundBrush().color(); + + QColorDialog colorDialog(orgCol); + colorDialog.setOption(QColorDialog::ShowAlphaChannel); + colorDialog.setWindowTitle( tr("Map backgroundcolor","Map background dialog")); + + //colorDialog.disconnect(); + + connect(&colorDialog, SIGNAL(currentColorChanged(QColor)), this, SLOT(colorChanged(QColor))); + + if (colorDialog.exec() != QDialog::Accepted) { + model->setBackgroundColor(orgCol); + return; + } + + // Update local and maybe also global color button + updateBackgroundColorButton(); + updateBackgroundImageControls(); + mainWindow->updateActions(); +} + +void BackgroundDialog::toggleBackgroundImage() +{ + if (!ui.useBackgroundImageCheckbox->isChecked()) { + model->unsetBackgroundImage(); + updateBackgroundImageControls(); + } else + selectBackgroundImage(); +} + +void BackgroundDialog::selectBackgroundImage() +{ + QStringList images = openImageDialog( tr("Load background image")); + if (!images.isEmpty() && model->loadBackgroundImage(images.first())) + updateBackgroundImageControls(); +} + +void BackgroundDialog::colorChanged(QColor col) +{ + model->setBackgroundColor(col); +} + +void BackgroundDialog::updateBackgroundColorButton() +{ + QPixmap pix(16, 16); + pix.fill(model->mapDesign()->backgroundColor()); + ui.backgroundColorButton->setIcon(pix); +} + +void BackgroundDialog::updateBackgroundImageControls() +{ + if (model->hasBackgroundImage()) { + ui.imageNameLineEdit->setText(model->backgroundImageName()); + ui.useBackgroundImageCheckbox->setChecked(true); + } else { + ui.imageNameLineEdit->setText(""); + ui.useBackgroundImageCheckbox->setChecked(false); + } +} diff --git a/src/background-dialog.h b/src/background-dialog.h new file mode 100644 index 0000000..482b8bb --- /dev/null +++ b/src/background-dialog.h @@ -0,0 +1,30 @@ +#ifndef BACKGROUND_DIALOG_H +#define BACKGROUND_DIALOG_H + +#include "ui_background-dialog.h" + +class VymModel; + +class BackgroundDialog : public QDialog { + Q_OBJECT + + public: + BackgroundDialog(VymModel *m); + int exec(); + + public slots: + void selectBackgroundColor(); + void toggleBackgroundImage(); + void selectBackgroundImage(); + + private slots: + void colorChanged(QColor); + + private: + void updateBackgroundColorButton(); + void updateBackgroundImageControls(); + VymModel *model; + Ui::BackgroundDialog ui; +}; + +#endif // BACKGROUND_DIALOG_H diff --git a/src/branch-container-base.cpp b/src/branch-container-base.cpp new file mode 100644 index 0000000..bbe0a2a --- /dev/null +++ b/src/branch-container-base.cpp @@ -0,0 +1,101 @@ +#include "branch-container-base.h" + +#include "branch-container.h" + +#define qdbg() qDebug().nospace().noquote() + +BranchContainerBase::BranchContainerBase() +{ + // qDebug() << "* Const BranchContainerBase begin this = " << this; + init(); +} + +void BranchContainerBase::init() +{ + // General defaults, also used by BranchContainer + orientation = UndefinedOrientation; + + imagesContainer = nullptr; + branchesContainer = nullptr; + imagesAndBranchesContainer = nullptr; + + setBrush(Qt::NoBrush); + setPen(QPen(Qt::NoPen)); + + horizontalDirection = Container::LeftToRight; +} + +void BranchContainerBase::setOrientation(const Orientation &o) +{ + orientation = o; +} + +BranchContainerBase::Orientation BranchContainerBase::getOrientation() +{ + return orientation; +} + +int BranchContainerBase::childrenCount() +{ + return branchCount() + imageCount(); +} + +int BranchContainerBase::branchCount() +{ + if (!branchesContainer) + return 0; + else + return branchesContainer->childItems().count(); +} + +void BranchContainerBase::addToBranchesContainer(BranchContainer *bc) {} + +Container* BranchContainerBase::getBranchesContainer() +{ + return branchesContainer; +} + +int BranchContainerBase::imageCount() +{ + if (!imagesContainer) + return 0; + else + return imagesContainer->childItems().count(); +} + +void BranchContainerBase::createImagesContainer() {} + +void BranchContainerBase::addToImagesContainer(Container *c) {} + +Container* BranchContainerBase::getImagesContainer() +{ + return imagesContainer; +} + +QList BranchContainerBase::childBranches() +{ + QList list; + + if (!branchesContainer) return list; + + foreach (QGraphicsItem *g_item, branchesContainer->childItems()) + list << (BranchContainer*)g_item; + + return list; +} + +QList BranchContainerBase::childImages() +{ + QList list; + + if (!imagesContainer) return list; + + foreach (QGraphicsItem *g_item, imagesContainer->childItems()) + list << (ImageContainer*)g_item; + + return list; +} + + +void BranchContainerBase::reposition() {} + diff --git a/src/branch-container-base.h b/src/branch-container-base.h new file mode 100644 index 0000000..71d8cee --- /dev/null +++ b/src/branch-container-base.h @@ -0,0 +1,61 @@ +#ifndef BRANCH_CONTAINER_BASE_H +#define BRANCH_CONTAINER_BASE_H + + +#include "container.h" +#include "selectable-container.h" + +class BranchContainerBase : public Container, public SelectableContainer { + friend class SelectableContainer; + + public: + /*! Orientation relative to parent branch container */ + enum Orientation { + UndefinedOrientation, + LeftOfParent, + RightOfParent + }; + + BranchContainerBase (); + virtual void init(); + + void setOrientation(const Orientation &); + Orientation getOrientation(); + + public: + int childrenCount(); //! Sum of branch and image children + + int branchCount(); + + /*! branchesContainer exists only, if there are children branches + * + * branchesContainer and linkSpaceContainer are children of innerContainer. + * The linkSpaceContainer is existing, only if a !Floating layout is used AND + * there is a branchesContainer + */ + virtual void addToBranchesContainer(BranchContainer *); + Container* getBranchesContainer(); + + int imageCount(); + virtual void createImagesContainer(); + virtual void addToImagesContainer(Container *c); + Container* getImagesContainer(); + + // Convenience functions to access children + QList childBranches(); + QList childImages(); + + public: + virtual void reposition(); + + protected: + Container::HorizontalAlignment branchesContainerHorizontalAlignment; + + Container *branchesContainer; // Container with children branches + Container *imagesContainer; // Container with children images + Container *imagesAndBranchesContainer; // Container, which contains both of above in special cases + + Orientation orientation; +}; + +#endif diff --git a/src/branch-container.cpp b/src/branch-container.cpp new file mode 100644 index 0000000..9f3e912 --- /dev/null +++ b/src/branch-container.cpp @@ -0,0 +1,1514 @@ +#include +#include + +#include "branch-container.h" + +#include "branchitem.h" +#include "flag-container.h" +#include "flag.h" +#include "flagrow-container.h" +#include "flagrow-master.h" +#include "frame-container.h" +#include "heading-container.h" +#include "link-container.h" +#include "linkobj.h" +#include "mapdesign.h" +#include "misc.h" + +#include "xlinkobj.h" + +#define qdbg() qDebug().nospace().noquote() + +extern FlagRowMaster *standardFlagsMaster; +extern FlagRowMaster *userFlagsMaster; +extern FlagRowMaster *systemFlagsMaster; + +qreal BranchContainer::linkWidth = 20; // FIXME-5 testing + +BranchContainer::BranchContainer( + QGraphicsScene *scene, + BranchItem *bi) // FIXME-3 scene and addItem should not be required, only + // for mapCenters without parent: setParentItem + // automatically sets scene! +{ + // qDebug() << "* Const BranchContainer begin this = " << this << " + // branchitem = " << bi; + scene->addItem(this); + branchItem = bi; + init(); +} + +BranchContainer::~BranchContainer() +{ + // qDebug() << "* Destr BranchContainer" << getName() << this; + + if (branchItem) { + // Unlink all containers in my own subtree, which will be deleted + // when tree of QGraphicsItems is deleted. + // In every destructor tell the linked BranchItem to longer consider + // deleting containers + // when the BranchItem will be deleted later + branchItem->unlinkBranchContainer(); + } +} + +void BranchContainer::init() +{ + // BranchContainer defaults + // partially overwriting MinimalBranchContainer + // can be overwritten by MapDesign later + containerType = Container::Branch; + + setLayout(Container::Horizontal); + + imagesContainerAutoLayout = true; + imagesContainerLayoutInt = Container::GridColumns; + + branchesContainerAutoLayout = true; + branchesContainerLayoutInt = Container::Vertical; + branchesContainerAndOrnamentsVerticalInt = false; + + scrollOpacity = 1; + + columnWidthAutoDesignInt = true; + + rotationsAutoDesignInt = true; + rotationHeadingInt = 0; + rotationSubtreeInt = 0; + + scaleAutoDesignInt = true; + scaleHeadingInt = 1; + scaleSubtreeInt = 1; + + autoDesignInnerFrame = true; + autoDesignOuterFrame = true; + + // BranchContainers inherit FrameContainer, reset overlay + overlay = false; + + // Setup children containers + headingContainer = new HeadingContainer; + headingContainer->setHeading(VymText(" ")); + + innerFrame = nullptr; + outerFrame = nullptr; + + ornamentsContainer = new Container; + ornamentsContainer->containerType = OrnamentsContainer; + + linkContainer = new LinkContainer; + + innerContainer = new Container; + innerContainer->containerType = InnerContainer; + + standardFlagRowContainer = nullptr; + systemFlagRowContainer = nullptr; + + listContainer = nullptr; + bulletPointContainer = nullptr; + + ornamentsContainer->addContainer(headingContainer, Z_HEADING); + + ornamentsContainer->setCentralContainer(headingContainer); + + innerContainer->addContainer(linkContainer, Z_LINK); + innerContainer->addContainer(ornamentsContainer, Z_ORNAMENTS); + + linkSpaceContainer = nullptr; + + outerContainer = nullptr; + + addContainer(innerContainer); + + // Center of whole mainBranches should be the heading + setCentralContainer(headingContainer); + + // Elastic layout experiments FIXME-3 + v_anim = QPointF(0, 0); + v.setParentItem(this); + v.setPen(QPen(Qt::red)); + v.setVisible(false); + + /* Uncomment for testing + QGraphicsEllipseItem *center = new QGraphicsEllipseItem (0, 0, 5, 5, this); + center->setPen(QPen(Qt::blue)); + setPen(QPen(Qt::blue)); + */ +} + +BranchContainer *BranchContainer::parentBranchContainer() +{ + if (SelectableContainer::movingStateInt == SelectableContainer::TemporaryLinked && tmpLinkedParentContainer) + return tmpLinkedParentContainer; + + if (SelectableContainer::movingStateInt == Moving) + // Parent is tmpParentContainer, which technically is not a + // BranchContainer, so don't return it here + return nullptr; + + if (!branchItem) + return nullptr; + + // For MapCenters parentBranch is rootItem and will return nullptr + return branchItem->parentBranch()->getBranchContainer(); +} + +void BranchContainer::setBranchItem(BranchItem *bi) { branchItem = bi; } + +BranchItem *BranchContainer::getBranchItem() const { return branchItem; } + +QString BranchContainer::getName() +{ + if (branchItem) + return Container::getName() + " '" + branchItem->headingPlain() + "'"; + else + return Container::getName() + " - ?"; +} + +void BranchContainer::setOriginalOrientation() +{ + originalOrientation = orientation; + originalParentBranchContainer = parentBranchContainer(); + if (parentItem()) { + if (parentBranchContainer()) + originalParentPos = parentBranchContainer()->downLinkPos(); + else + originalParentPos = pos(); + } +} + +BranchContainer::Orientation BranchContainer::getOriginalOrientation() +{ + return originalOrientation; +} + +QPointF BranchContainer::getOriginalParentPos() { return originalParentPos; } + +void BranchContainer::setOriginalScenePos() +{ + // qDebug() << "BC::sOSCP of " << info(); + originalPos = scenePos(); +} + +void BranchContainer::updateVisibility() +{ + if (branchItem) { + // Check own visibility for hidden export mode + if (branchItem->isHidden()) { + // Hide myself (and potential child branches or images) completely + setVisible(false); + upLink->setVisible(false); + return; + } + + if (branchItem->hideLinkUnselected()) { + if (!SelectableContainer::isSelected()) + upLink->setVisible(false); + else + upLink->setVisible(true); + } else + upLink->setVisible(true); + + // Ensure I am visible myself + setVisible(true); + if (!branchesContainer) + return; + + // We have children now + if (branchItem->isScrolled()) { + branchesContainer->setVisible(false); + linkContainer->setVisible(false); + } + else { + branchesContainer->setVisible(true); + linkContainer->setVisible(true); + } + + // Images of *this* branch may still stay visible, + // deeper down in the tree they will be hidden due to + // parent branch already being hidden + } +} + +#include +void BranchContainer::setScrollOpacity( + qreal o) // FIXME-4 testing for potential later animation +{ + scrollOpacity = o; + // headingContainer->setScrollOpacity(a); + headingContainer->setOpacity(o); + if (standardFlagRowContainer) + standardFlagRowContainer->setOpacity(o); + QTransform t; + t.scale(1, o); + setTransform(t); + + qDebug() << "BC::sSO o=" << o << " flags=" << flags(); // FIXME-4 playing only + setOpacity(o); +} + +qreal BranchContainer::getScrollOpacity() { return scrollOpacity; } + +void BranchContainer::updateBranchesContainerParent() +{ + if (listContainer) + listContainer->addContainer(branchesContainer); + else + innerContainer->addContainer(branchesContainer); +} + +void BranchContainer::addToBranchesContainer(BranchContainer *bc) +{ + // Overloaded for real BranchContainers compared to MinimalBranchContainer + + if (!branchesContainer) { + // Create branchesContainer before adding to it + // (It will be deleted later in updateChildrenStructure(), if there + // are no children) + branchesContainer = new Container(); + branchesContainer->containerType = Container::BranchesContainer; + branchesContainer->zPos = Z_BRANCHES; + branchesContainer->setLayout(branchesContainerLayoutInt); + branchesContainer->setVerticalAlignment( + branchesContainerVerticalAlignmentInt); + branchesContainer->setHorizontalAlignment( + branchesContainerHorizontalAlignmentInt); + + updateBranchesContainerParent(); + + branchesContainer->addContainer(bc); + updateChildrenStructure(); + updateVisibility(); // children might be scrolled and invisible + } + else + branchesContainer->addContainer(bc); +} + +void BranchContainer::updateImagesContainer() +{ + if (imagesContainer && imagesContainer->childItems().count() == 0) { + delete imagesContainer; + imagesContainer = nullptr; + } +} + +void BranchContainer::createOuterContainer() +{ + if (!outerContainer) { + outerContainer = new Container; + outerContainer->containerType = OuterContainer; + outerContainer->setLayout(BoundingFloats); + addContainer(outerContainer); + + // Children structure is updated in updateChildrenStructure(), which is + // anyway calling this method + } +} + +void BranchContainer::deleteOuterContainer() +{ + if (outerContainer) { + // Before outerContainer get's deleted, it's children need to be + // reparented + if (outerFrame) + outerFrame->addContainer(innerContainer); + else + addContainer(innerContainer); + if (imagesContainer) + innerContainer->addContainer(imagesContainer); + + delete outerContainer; + outerContainer = nullptr; + } +} + +void BranchContainer::updateTransformations() +{ + MapDesign *md = nullptr; + int depth = 0; + if (branchItem) { + md = branchItem->mapDesign(); + depth = branchItem->depth(); + } + else + return; + + if (!md) + return; + + // Rotation of heading + if (innerFrame) + innerFrame->setRotation(rotationHeadingInt); + else if (ornamentsContainer) + ornamentsContainer->setRotation(rotationHeadingInt); + + // Scale of heading + headingContainer->setScale(scaleHeadingInt); + + // Rotation and scaling of subtree + if (outerFrame) { + outerFrame->setRotation(rotationSubtreeInt); + outerFrame->setScale(scaleSubtreeInt); + if (outerContainer) { + outerContainer->setRotation(0); + outerContainer->setScale(1); + } + else { + innerContainer->setRotation(0); + innerContainer->setScale(1); + } + } + else { + if (outerContainer) { + outerContainer->setRotation(rotationSubtreeInt); + outerContainer->setScale(scaleSubtreeInt); + } + else { + innerContainer->setRotation(rotationSubtreeInt); + innerContainer->setScale(scaleSubtreeInt); + } + } +} + +void BranchContainer::updateChildrenStructure() +{ + if (branchesContainerLayoutInt == List) { + if (!listContainer) { + // Create and setup a listContainer *below* the ornamentsContainer + innerContainer->setLayout(Vertical); + innerContainer->setHorizontalAlignment(HorAlignedLeft); + + // listContainer has one linkSpaceContainer left of + // branchesContainer + listContainer = new Container; + listContainer->containerType = Container::ListContainer; + listContainer->setLayout(Horizontal); + if (linkSpaceContainer) + listContainer->addContainer(linkSpaceContainer); + if (branchesContainer) + listContainer->addContainer(branchesContainer); + + // Insert at end, especially behind innerFrame or ornamentsContainer + innerContainer->addContainer(listContainer, Z_LIST); + // qDebug() << "... Created listContainer in branch " << + // branchItem->headingPlain(); + } + } + else { + // Switch back from listContainer to regular setup with innerContainer + if (listContainer) { + innerContainer->setLayout(Horizontal); + if (linkSpaceContainer) + innerContainer->addContainer(linkSpaceContainer); + if (branchesContainer) + innerContainer->addContainer(branchesContainer); + delete listContainer; + listContainer = nullptr; + } + } + + // The structure of subcontainers within a BranchContainer + // depends on layouts of imagesContainer and branchesContainer: + // + // Usually both inagesContainer and branchesContainer are children of + // innerContainer. The layout of innerContainer is either Horizontal or + // BoundingFloats. outerContainer is only needed in corner case d) + // + // a) No FloatingBounded children + // - No outerContainer + // - innerContainer is Horizontal + // - branchesContainer is not FloatingBounded + // - if imagesContainer is not floating: + // - Check imagesPosition(), where images should be relative to + // children branches + // + // b) Only branches are FloatingBounded + // - No outerContainer + // - innerContainer BoundingFloats + // - branchesContainer is FloatingBounded + // - imagesContainer is FloatingFree + // + // c) images and branches are FloatingBounded + // - No outerContainer + // - innerContainer BoundingFloats + // - branchesContainer is FloatingBounded + // - imagesContainer is FloatingBounded + // + // d) Only images are FloatingBounded + // - outerContainer contains + // - innerContainer + // - imagesContainer + // - innerContainer is Horizontal + // - branchesContainer is Vertical + // - imagesContainer is FloatingBounded + + // qDebug() << "BC::updateChildrenStructure() of " << info(); + + if (branchesContainerLayoutInt != FloatingBounded && + imagesContainerLayoutInt != FloatingBounded) { + // a) No FloatingBounded images or branches + deleteOuterContainer(); + if (listContainer) + innerContainer->setLayout(Vertical); + else { + if (branchesContainerAndOrnamentsVerticalInt) + innerContainer->setLayout(Vertical); + else { + innerContainer->setLayout(Horizontal); + if (imagesContainer && branchesContainer && + branchesContainerLayoutInt != FloatingFree && + imagesContainerLayoutInt != FloatingFree) { + // Align images relative to branches subtree by using + // imagesAndBranchesContainer + + bool imagesFirst = true; // FIXME-3 get from MapDesign + Container::Layout ibcl = + Container::Vertical; // FIXME-3 get from MapDesign + if (!imagesAndBranchesContainer) { + imagesAndBranchesContainer = new Container; + imagesAndBranchesContainer->containerType = + Container::ImagesAndBranchesContainer; + innerContainer->addContainer(imagesAndBranchesContainer, + Z_IMAGE); + imagesAndBranchesContainer->addContainer( + imagesContainer); + imagesAndBranchesContainer->addContainer( + branchesContainer); + } + imagesAndBranchesContainer->setLayout(ibcl); + if (imagesFirst) // FIXME-3 Check for imagesPosition + // relative to branches, hardcoded for now + imagesContainer->stackBefore(branchesContainer); + else + branchesContainer->stackBefore(imagesContainer); + } + else { + // No imagesAndBranchesContainer required + // + // TODO Remove imagesAndBranchesCont, relink imagesCont and + // branchesCont + if (imagesAndBranchesContainer) { + updateImagesContainerParent(); + updateBranchesContainerParent(); + delete imagesAndBranchesContainer; + imagesAndBranchesContainer = nullptr; + } + } + } + } + } + else if (branchesContainerLayoutInt == FloatingBounded && + imagesContainerLayoutInt != FloatingBounded) { + // b) Only branches are FloatingBounded + deleteOuterContainer(); + innerContainer->setLayout(BoundingFloats); + } + else if (branchesContainerLayoutInt == FloatingBounded && + imagesContainerLayoutInt == FloatingBounded) { + // c) images and branches are FloatingBounded + deleteOuterContainer(); + innerContainer->setLayout(BoundingFloats); + } + else if (branchesContainerLayoutInt != FloatingBounded && + imagesContainerLayoutInt == FloatingBounded) { + // d) Only images are FloatingBounded + createOuterContainer(); + if (listContainer) + innerContainer->setLayout(Vertical); + else + innerContainer->setLayout(Horizontal); + } + else { + // e) remaining cases + deleteOuterContainer(); + innerContainer->setLayout(FloatingBounded); + } + + updateTransformations(); + + // Update structure of outerContainer + if (outerContainer) { + // outerContainer should be child of outerFrame, if this is used + if (outerFrame) + outerFrame->addContainer(outerContainer); + else + outerContainer->setParentItem(this); + outerContainer->addContainer(innerContainer); + if (imagesContainer) + outerContainer->addContainer(imagesContainer); + } + + // Structure for bullet point list layouts + BranchContainer *pbc = parentBranchContainer(); + if (pbc && pbc->branchesContainerLayoutInt == List) { + // Parent has list layout + if (!bulletPointContainer) { + // qDebug() << "... Creating bulletPointContainer"; + bulletPointContainer = + new HeadingContainer; // FIXME-3 create new type or re-use + // LinkObj and set type + // See also + // https://www.w3schools.com/charsets/ref_utf_punctuation.asp + VymText vt(" • "); + // vt.setColor(branchItem->headingColor()); + bulletPointContainer->setHeading(vt); + bulletPointContainer->setColor(branchItem->headingColor()); + if (ornamentsContainer) + ornamentsContainer->addContainer(bulletPointContainer, + Z_BULLETPOINT); + } + } + else { + // Parent has no list layout + if (bulletPointContainer) { + delete bulletPointContainer; + bulletPointContainer = nullptr; + } + } + + updateImagesContainer(); + + if (branchCount() == 0) { + // no children branches, remove unused containers + if (linkSpaceContainer) { + delete linkSpaceContainer; + linkSpaceContainer = nullptr; + } + if (branchesContainer) { + delete branchesContainer; + branchesContainer = nullptr; + } + } + else { + // Space for links depends on layout and scrolled state: + if (linkSpaceContainer) { + if (hasFloatingBranchesLayout() || !branchItem || + branchItem->isScrolled()) { + delete linkSpaceContainer; + linkSpaceContainer = nullptr; + } + } + else { + if (!hasFloatingBranchesLayout() && + (!branchItem || !branchItem->isScrolled())) { + linkSpaceContainer = new HeadingContainer(); + linkSpaceContainer->setContainerType(LinkSpace); + linkSpaceContainer->zPos = Z_LINKSPACE; + linkSpaceContainer->setHeading(VymText( + " ")); // FIXME-3 introduce minWidth later in Container + // instead of a pseudo heading here see oc.pos + + if (listContainer) + listContainer->addContainer(linkSpaceContainer); + else + innerContainer->addContainer(linkSpaceContainer); + + if (!imagesAndBranchesContainer) + linkSpaceContainer->stackBefore(branchesContainer); + } + } + } +} + +void BranchContainer::updateImagesContainerParent() +{ + if (outerContainer) + outerContainer->addContainer(imagesContainer); + else + innerContainer->addContainer(imagesContainer, Z_IMAGE); +} + +void BranchContainer::createImagesContainer() +{ + // imagesContainer is created when images are added to branch + // The destructor of ImageItem calls + // updateChildrenStructure() in parentBranch() + imagesContainer = new Container(); + imagesContainer->containerType = ImagesContainer; + imagesContainer->setLayout(imagesContainerLayoutInt); + + updateImagesContainerParent(); +} + +void BranchContainer::addToImagesContainer(Container *c) +{ + bool updateStructure = false; + if (!imagesContainer) { + createImagesContainer(); + updateStructure = true; + } + + QPointF sp = c->scenePos(); + imagesContainer->addContainer(c, Z_IMAGE); + + + c->setPos(imagesContainer->sceneTransform().inverted().map(sp)); + + if (updateStructure) + updateChildrenStructure(); +} + +HeadingContainer *BranchContainer::getHeadingContainer() +{ + return headingContainer; +} + +LinkContainer *BranchContainer::getLinkContainer() { return linkContainer; } + +void BranchContainer::linkTo(BranchContainer *pbc) +{ + + if (!pbc) + return; + + originalParentBranchContainer = nullptr; + + pbc->linkContainer->addLink(upLink); +} + +QPointF BranchContainer::getPositionHintNewChild(Container *c) +{ + // Should we put new child c on circle around myself? + bool useCircle = false; + int n = 0; + qreal radius; + if (c->containerType == Branch && hasFloatingBranchesLayout()) { + useCircle = true; + radius = 190; + n = branchCount(); + } + else if (c->containerType == Image && hasFloatingImagesLayout()) { + useCircle = true; + radius = 100; + n = imageCount(); + } + + if (useCircle) { + // Mapcenter, suggest to put image or mainbranch on circle around center + qreal a = 5 * M_PI_4 + M_PI_2 * n + (M_PI_4 / 2) * (n / 4 % 4); + return QPointF(radius * cos(a), radius * sin(a)); + } + + QRectF r = headingContainer->rect(); + + switch (orientation) { + case LeftOfParent: + return QPointF(r.left() - c->rect().width(), r.center().y()); + break; + case RightOfParent: + return QPointF(r.right(), r.center().y()); + break; + default: + return QPointF(r.left(), r.center().y()); + break; + } +} + +QPointF BranchContainer::downLinkPos() { return downLinkPos(orientation); } + +QPointF BranchContainer::downLinkPos(const Orientation &orientationChild) +{ + if (branchesContainerAndOrnamentsVerticalInt) + return ornamentsContainer->mapToScene( + ornamentsContainer->bottomCenter()); + + if (frameType(true) != FrameContainer::NoFrame) { + if (!parentBranchContainer()) + // Framed MapCenter: Use center of frame // FIXME-3 downLinkPos should depend on layout, not depth + return ornamentsContainer->mapToScene(ornamentsContainer->center()); + else { + // Framed branch: Use left or right edge + switch (orientationChild) { + case RightOfParent: + return ornamentsContainer->mapToScene( + ornamentsContainer->rightCenter()); + case LeftOfParent: + return ornamentsContainer->mapToScene( + ornamentsContainer->leftCenter()); + default: // Shouldn't happen... + return ornamentsContainer->mapToScene( + ornamentsContainer->bottomLeft()); + } + } + } + + // No frame, return bottom left/right corner + switch (orientationChild) { + case RightOfParent: + return ornamentsContainer->mapToScene( + ornamentsContainer->bottomRight()); + case LeftOfParent: + return ornamentsContainer->mapToScene(ornamentsContainer->bottomLeft()); + default: + return ornamentsContainer->mapToScene( + ornamentsContainer->bottomRight()); + } +} + +QPointF BranchContainer::upLinkPos(const Orientation &orientationChild) +{ + if (branchesContainerAndOrnamentsVerticalInt) + return ornamentsContainer->mapToScene(ornamentsContainer->topCenter()); + + if (frameType(true) != FrameContainer::NoFrame || + frameType(false) != FrameContainer::NoFrame) { + if (!parentBranchContainer() && movingStateInt != Moving) { + // Framed MapCenter: Use center of frame // FIXME-3 should depend + // on layout, not depth + return ornamentsContainer->mapToScene(ornamentsContainer->center()); + } + else { + // Framed branch: Use left or right edge + switch (orientationChild) { + case RightOfParent: + return ornamentsContainer->mapToScene( + ornamentsContainer->leftCenter()); + case LeftOfParent: + return ornamentsContainer->mapToScene( + ornamentsContainer->rightCenter()); + default: // mapcenter is moved, use bottomLeft corner + // qWarning() << "BC::upLinkPos a) framed undefined orientation + // in " << info(); + return ornamentsContainer->mapToScene( + ornamentsContainer->bottomLeft()); + } + } + } + + // For branches without frames, return bottom left/right corner + switch (orientationChild) { + case RightOfParent: + return ornamentsContainer->mapToScene(ornamentsContainer->bottomLeft()); + case LeftOfParent: + return ornamentsContainer->mapToScene( + ornamentsContainer->bottomRight()); + default: + // qWarning() << "BC::upLinkPos b) not framed undefined orientation in " + // << info() << branchItem->depth(); + return ornamentsContainer->mapToScene(ornamentsContainer->bottomLeft()); + } +} + +void BranchContainer::updateUpLink() +{ + // Sets geometry and color of upLink and bottomline. + // Called from MapEditor e.g. during animation or + // from VymModel, when colors change + + // MapCenters still might have upLinks: The bottomLine is part of upLink! + + if (!isVisible()) + return; + + QPointF upLinkSelf_sp = upLinkPos(orientation); + QPointF downLink_sp = downLinkPos(); + + BranchContainer *pbc = nullptr; + + if (tmpLinkedParentContainer) { + // I am temporarily linked to tmpLinkedParentContainer + pbc = tmpLinkedParentContainer; + } + else if (originalParentBranchContainer) + // I am moving with tmpParent, use original parent for link + pbc = originalParentBranchContainer; + else + // Regular update, e.g. when linkStyle changes + pbc = parentBranchContainer(); + + BranchItem *tmpParentBI = nullptr; + + if (pbc) { + tmpParentBI = pbc->getBranchItem(); + QPointF upLinkParent_sp; + + upLinkParent_sp = pbc->downLinkPos(orientation); + + QGraphicsItem *upLinkParent = upLink->parentItem(); + if (!upLinkParent) + return; + + upLink->setUpLinkPosParent( + upLinkParent->sceneTransform().inverted().map(upLinkParent_sp)); + upLink->setUpLinkPosSelf( + upLinkParent->sceneTransform().inverted().map(upLinkSelf_sp)); + upLink->setDownLinkPos( + upLinkParent->sceneTransform().inverted().map(downLink_sp)); + } + else { + // I am a MapCenter without parent. Add LinkObj to my own LinkContainer, + // so that at least positions are updated and bottomLine can be drawn + linkContainer->addLink(upLink); + + upLink->setLinkStyle(LinkObj::NoLink); + + upLink->setUpLinkPosSelf( + linkContainer->sceneTransform().inverted().map(upLinkSelf_sp)); + upLink->setDownLinkPos( + linkContainer->sceneTransform().inverted().map(downLink_sp)); + } + + // Color of link (depends on current parent) + if (upLink->linkColorHint() == LinkObj::HeadingColor) + upLink->setLinkColor(branchItem->headingColor()); + else { + if (branchItem) + upLink->setLinkColor(branchItem->mapDesign()->defaultLinkColor()); + } + + // Style of link + if (tmpParentBI) { + if (pbc && pbc->branchesContainerLayoutInt == List) + upLink->setLinkStyle(LinkObj::NoLink); + else { + upLink->setLinkStyle( + tmpParentBI->mapDesign()->linkStyle(tmpParentBI->depth())); + } + } + + // Create/delete bottomline, depends on frame and (List-)Layout + if (frameType(true) != FrameContainer::NoFrame || + branchesContainerAndOrnamentsVerticalInt || + (pbc && pbc->branchesContainerLayoutInt == List)) { + if (upLink->hasBottomLine()) + upLink->deleteBottomLine(); + } + else { + if (!upLink->hasBottomLine()) + upLink->createBottomLine(); + } + + // Finally update geometry + upLink->updateLinkGeometry(); +} + +void BranchContainer::setLayout(const Layout &l) +{ + if (containerType != Branch && containerType != TmpParent) + qWarning() << "BranchContainer::setLayout (...) called for non-branch: " + << info(); + Container::setLayout(l); +} + +void BranchContainer::setImagesContainerLayout(const Layout <ype) +{ + if (imagesContainerLayoutInt == ltype) + return; + + imagesContainerLayoutInt = ltype; + + if (imagesContainer) + imagesContainer->setLayout(imagesContainerLayoutInt); + + updateChildrenStructure(); +} + +Container::Layout BranchContainer::imagesContainerLayout() +{ + return imagesContainerLayoutInt; +} + +bool BranchContainer::hasFloatingImagesLayout() +{ + if (imagesContainer) + return imagesContainer->hasFloatingLayout(); + + if (imagesContainerLayoutInt == FloatingBounded || + imagesContainerLayoutInt == FloatingFree) + return true; + else + return false; +} + +void BranchContainer::setBranchesContainerLayout(const Layout &layoutNew) +{ + branchesContainerLayoutInt = layoutNew; + + if (branchesContainer) + branchesContainer->setLayout(branchesContainerLayoutInt); + updateChildrenStructure(); +} + +Container::Layout BranchContainer::branchesContainerLayout() +{ + return branchesContainerLayoutInt; +} + +bool BranchContainer::hasFloatingBranchesLayout() +{ + if (branchesContainer) + return branchesContainer->hasFloatingLayout(); + + if (branchesContainerLayoutInt == FloatingBounded || + branchesContainerLayoutInt == FloatingFree) + return true; + else + return false; +} + +void BranchContainer::setBranchesContainerHorizontalAlignment( + const HorizontalAlignment &a) +{ + branchesContainerHorizontalAlignmentInt = a; + if (branchesContainer) + branchesContainer->setHorizontalAlignment( + branchesContainerHorizontalAlignmentInt); +} + +void BranchContainer::setBranchesContainerVerticalAlignment( + const VerticalAlignment &a) +{ + branchesContainerVerticalAlignmentInt = a; + if (branchesContainer) + branchesContainer->setVerticalAlignment( + branchesContainerVerticalAlignmentInt); +} + +void BranchContainer::setBranchesContainerBrush( + const QBrush &b) +{ + branchesContainerBrushInt = b; + if (branchesContainer) + branchesContainer->setBrush(branchesContainerBrushInt); +} + +void BranchContainer::setBranchesContainerAndOrnamentsVertical(bool b) +{ + branchesContainerAndOrnamentsVerticalInt = b; +} + +QRectF BranchContainer::headingRect() +{ + // Returns scene coordinates of bounding rectanble + return headingContainer->mapToScene(headingContainer->rect()) + .boundingRect(); +} + +QRectF BranchContainer::ornamentsRect() +{ + // Returns scene coordinates of bounding rectanble + return ornamentsContainer->mapToScene(headingContainer->rect()) + .boundingRect(); +} + +void BranchContainer::setColumnWidthAutoDesign(const bool &b) +{ + columnWidthAutoDesignInt = b; +} + +bool BranchContainer::columnWidthAutoDesign() +{ + return columnWidthAutoDesignInt; +} + +void BranchContainer::setColumnWidth(const int &i) +{ + headingContainer->setColumnWidth(i); + headingContainer->setHeading(branchItem->heading()); +} + +int BranchContainer::columnWidth() { return headingContainer->columnWidth(); } + +void BranchContainer::setRotationsAutoDesign(const bool &b, const bool &update) +{ + rotationsAutoDesignInt = b; + + if (update) + updateTransformations(); +} + +bool BranchContainer::rotationsAutoDesign() { return rotationsAutoDesignInt; } + +void BranchContainer::setRotationHeading(const int &a) +{ + rotationHeadingInt = a; + updateTransformations(); +} + +int BranchContainer::rotationHeading() { return qRound(rotationHeadingInt); } + +int BranchContainer::rotationHeadingInScene() +{ + qreal r = rotationHeadingInt + rotationSubtreeInt; + + BranchContainer *pbc = parentBranchContainer(); + while (pbc) { + r += pbc->rotationSubtree(); + pbc = pbc->parentBranchContainer(); + } + + return qRound(r); +} + +void BranchContainer::setScaleAutoDesign(const bool &b, const bool &update) +{ + scaleAutoDesignInt = b; + if (update) + updateTransformations(); +} + +bool BranchContainer::scaleAutoDesign() { return scaleAutoDesignInt; } + +void BranchContainer::setScaleHeading(const qreal &f) +{ + scaleHeadingInt = f; + updateTransformations(); +} + +qreal BranchContainer::scaleHeading() { return scaleHeadingInt; } + +void BranchContainer::setRotationSubtree(const int &a) +{ + rotationSubtreeInt = a; + updateTransformations(); +} + +int BranchContainer::rotationSubtree() { return qRound(rotationSubtreeInt); } + +void BranchContainer::setScaleSubtree(const qreal &f) +{ + scaleSubtreeInt = f; + updateTransformations(); +} + +qreal BranchContainer::scaleSubtree() { return scaleSubtreeInt; } + +void BranchContainer::setColor(const QColor &col) +{ + headingContainer->setColor(col); + if (bulletPointContainer) // FIXME-3 duplicated code in + // updateChildrenStructure + bulletPointContainer->setColor(col); +} + +QUuid BranchContainer::findFlagByPos(const QPointF &p) +{ + QUuid uid; + + if (systemFlagRowContainer) { + uid = systemFlagRowContainer->findFlagByPos(p); + if (!uid.isNull()) + return uid; + } + + if (standardFlagRowContainer) + uid = standardFlagRowContainer->findFlagByPos(p); + + return uid; +} + +bool BranchContainer::isInClickBox(const QPointF &p) +{ + return ornamentsContainer->rect().contains( + ornamentsContainer->mapFromScene(p)); +} + +QRectF BranchContainer::getBBoxURLFlag() +{ + Flag *f = systemFlagsMaster->findFlagByName("system-url"); + if (f) { + QUuid u = f->getUuid(); + FlagContainer *fc = systemFlagRowContainer->findFlagContainerByUid(u); + if (fc) + return fc->mapRectToScene(fc->rect()); + } + return QRectF(); +} + +void BranchContainer::select() +{ + SelectableContainer::select(ornamentsContainer, + branchItem->mapDesign()->selectionPen(), + branchItem->mapDesign()->selectionBrush()); +} + +bool BranchContainer::frameAutoDesign(const bool &useInnerFrame) +{ + if (useInnerFrame) + return autoDesignInnerFrame; + else + return autoDesignOuterFrame; +} + +void BranchContainer::setFrameAutoDesign(const bool &useInnerFrame, + const bool &b) +{ + if (useInnerFrame) + autoDesignInnerFrame = b; + else + autoDesignOuterFrame = b; +} + +FrameContainer::FrameType BranchContainer::frameType(const bool &useInnerFrame) +{ + if (useInnerFrame) { + if (innerFrame) + return innerFrame->frameType(); + else + return FrameContainer::NoFrame; + } + + if (outerFrame) + return outerFrame->frameType(); + else + return FrameContainer::NoFrame; +} + +QString BranchContainer::frameTypeString(const bool &useInnerFrame) +{ + if (useInnerFrame) { + if (innerFrame) + return innerFrame->frameTypeString(); + } + else if (outerFrame) + return outerFrame->frameTypeString(); + + return "NoFrame"; +} + +void BranchContainer::setFrameType(const bool &useInnerFrame, + const FrameContainer::FrameType &ftype) +{ + if (useInnerFrame) { + // Inner frame around ornamentsContainer + if (ftype == FrameContainer::NoFrame) { + if (innerFrame) { + innerContainer->addContainer(ornamentsContainer, Z_ORNAMENTS); + ornamentsContainer->setRotation(innerFrame->rotation()); + ornamentsContainer->setPos(innerFrame->pos()); + delete innerFrame; + innerFrame = nullptr; + } + } + else { + if (!innerFrame) { + innerFrame = new FrameContainer; + innerFrame->setUsage(FrameContainer::InnerFrame); + innerFrame->setParentBranchContainer(this); + innerFrame->addContainer(ornamentsContainer, Z_ORNAMENTS); + innerFrame->setRotation(ornamentsContainer->rotation()); + innerFrame->setPos(ornamentsContainer->pos()); + innerContainer->addContainer(innerFrame, Z_INNER_FRAME); + ornamentsContainer->setRotation(0); + } + innerFrame->setFrameType(ftype); + } + } + else { + // Outer frame around whole branchContainer including children + if (ftype == FrameContainer::NoFrame) { + // Remove outerFrame + if (outerFrame) { + int a = rotationSubtree(); + Container *c; + if (outerContainer) + c = outerContainer; + else + c = innerContainer; + addContainer(c); + delete outerFrame; + outerFrame = nullptr; + setRotationSubtree(a); + } + } + else { + // Set outerFrame + if (!outerFrame) { + outerFrame = new FrameContainer; + outerFrame->setUsage(FrameContainer::OuterFrame); + outerFrame->setParentBranchContainer(this); + Container *c; + if (outerContainer) + c = outerContainer; + else + c = innerContainer; + outerFrame->addContainer(c); + addContainer(outerFrame, Z_OUTER_FRAME); + } + outerFrame->setFrameType(ftype); + } + } + updateChildrenStructure(); +} + +void BranchContainer::setFrameType(const bool &useInnerFrame, const QString &s) +{ + FrameContainer::FrameType ftype = FrameContainer::frameTypeFromString(s); + setFrameType(useInnerFrame, ftype); +} + +int BranchContainer::framePadding(const bool &useInnerFrame) +{ + if (useInnerFrame) { + if (innerFrame) + return innerFrame->framePadding(); + } + else { + if (outerFrame) + return outerFrame->framePadding(); + } + + return 0; +} + +void BranchContainer::setFramePadding(const bool &useInnerFrame, const int &p) +{ + if (useInnerFrame) { + if (innerFrame) + innerFrame->setFramePadding(p); + } + else { + if (outerFrame) + outerFrame->setFramePadding(p); + } +} + +int BranchContainer::framePenWidth(const bool &useInnerFrame) +{ + if (useInnerFrame) { + if (innerFrame) + return innerFrame->framePenWidth(); + } + else { + if (outerFrame) + return outerFrame->framePenWidth(); + } + + return 0; +} + +void BranchContainer::setFramePenWidth(const bool &useInnerFrame, const int &w) +{ + if (useInnerFrame) { + if (innerFrame) + innerFrame->setFramePenWidth(w); + } + else { + if (outerFrame) + outerFrame->setFramePenWidth(w); + } +} + +QColor BranchContainer::framePenColor(const bool &useInnerFrame) +{ + if (useInnerFrame) { + if (innerFrame) + return innerFrame->framePenColor(); + } + else { + if (outerFrame) + return outerFrame->framePenColor(); + } + + return QColor(); +} + +void BranchContainer::setFramePenColor(const bool &useInnerFrame, + const QColor &c) +{ + if (useInnerFrame) { + if (innerFrame) + innerFrame->setFramePenColor(c); + } + else { + if (outerFrame) + outerFrame->setFramePenColor(c); + } +} + +QColor BranchContainer::frameBrushColor(const bool &useInnerFrame) +{ + if (useInnerFrame) { + if (innerFrame) + return innerFrame->frameBrushColor(); + } + else { + if (outerFrame) + return outerFrame->frameBrushColor(); + } + + return QColor(); +} + +void BranchContainer::setFrameBrushColor(const bool &useInnerFrame, + const QColor &c) +{ + if (useInnerFrame) { + if (innerFrame) + innerFrame->setFrameBrushColor(c); + } + else { + if (outerFrame) + outerFrame->setFrameBrushColor(c); + } +} + +QString BranchContainer::saveFrame() +{ + QString r; + if (innerFrame && innerFrame->frameType() != FrameContainer::NoFrame) + r = innerFrame->saveFrame(); + + if (outerFrame && outerFrame->frameType() != FrameContainer::NoFrame) + r += outerFrame->saveFrame(); + return r; +} + +void BranchContainer::updateVisuals() +{ + // Update heading + if (!branchItem) + return; + + headingContainer->setHeading(branchItem->heading()); + + // Update standard flags active in TreeItem + QList TIactiveFlagUids = branchItem->activeFlagUids(); + if (TIactiveFlagUids.count() == 0) { + if (standardFlagRowContainer) { + delete standardFlagRowContainer; + standardFlagRowContainer = nullptr; + } + } + else { + if (!standardFlagRowContainer) { + standardFlagRowContainer = new FlagRowContainer; + ornamentsContainer->addContainer(standardFlagRowContainer, + Z_STANDARD_FLAGS); + } + standardFlagRowContainer->updateActiveFlagContainers( + TIactiveFlagUids, standardFlagsMaster, userFlagsMaster); + } + + // Add missing system flags active in TreeItem + TIactiveFlagUids = branchItem->activeSystemFlagUids(); + if (TIactiveFlagUids.count() == 0) { + if (systemFlagRowContainer) { + delete systemFlagRowContainer; + systemFlagRowContainer = nullptr; + } + } + else { + if (!systemFlagRowContainer) { + systemFlagRowContainer = new FlagRowContainer; + ornamentsContainer->addContainer(systemFlagRowContainer, + Z_SYSTEM_FLAGS); + } + systemFlagRowContainer->updateActiveFlagContainers(TIactiveFlagUids, + systemFlagsMaster); + } +} + +void BranchContainer::reposition() +{ + // Set orientation based layout or + // in the process of being (temporary) relinked + BranchContainer *pbc = parentBranchContainer(); + + if (movingStateInt == Moving || movingStateInt == TemporaryLinked) + // I am currently attached to tmpParentContainer + orientation = + ((BranchContainerBase *)(parentContainer()->parentContainer())) + ->getOrientation(); + else { + // pbc is now either the temporary parent or the original one, depending + // on MovingState + if (pbc) { + if (pbc->hasFloatingBranchesLayout()) { + if (pos().x() > 0) + orientation = RightOfParent; + else + orientation = LeftOfParent; + } + else + orientation = pbc->getOrientation(); + } + else + orientation = BranchContainerBase::UndefinedOrientation; + } + + /* + qdbg() << ind() << "BC::reposition bc=" << info() << " orientation=" << orientation; + if (pbc) + qdbg() << ind() << " pbc=" << pbc->info() << " pbc->orientation=" << pbc->orientation; + else + qdbg() << ind() << " pbc=0 children=" << branchItem->branchCount(); + */ + //qdbg() << ind() << " state=" << movingStateInt; + + // Settings depending on depth + uint depth = 0; + if (branchItem) + depth = branchItem->depth(); + + if (depth == 0) { + // MapCenter + setHorizontalDirection(LeftToRight); + // FIXME-3 set in updateChildrenStructure: + // innerContainer->setHorizontalDirection(LeftToRight); + + // FIXME-3 set in updateChildrenStructure: + // innerContainer->setLayout(BoundingFloats); + } + else { + // Branch or mainbranch + switch (orientation) { + case LeftOfParent: + setHorizontalDirection(RightToLeft); + innerContainer->setHorizontalDirection(RightToLeft); + if (branchesContainerAndOrnamentsVerticalInt) { + setBranchesContainerHorizontalAlignment(HorAlignedCentered); + innerContainer->setHorizontalAlignment(HorAlignedCentered); + } + else { + setBranchesContainerHorizontalAlignment(HorAlignedRight); + } + break; + case RightOfParent: + setHorizontalDirection(LeftToRight); + innerContainer->setHorizontalDirection(LeftToRight); + + // Playing... + if (branchesContainerAndOrnamentsVerticalInt) { + setBranchesContainerHorizontalAlignment(HorAlignedCentered); + innerContainer->setHorizontalAlignment(HorAlignedCentered); + } + else { + setBranchesContainerHorizontalAlignment(HorAlignedLeft); + } + break; + case UndefinedOrientation: + qWarning() << "BC::reposition - Undefined orientation in " + << info(); + break; + default: + qWarning() << "BC::reposition - Unknown orientation " << orientation + << " in " << info(); + break; + } + } + + Container::reposition(); + + // Update links of children + if (branchesContainer && branchCount() > 0) { + foreach (Container *c, branchesContainer->childContainers()) { + BranchContainer *bc = (BranchContainer *)c; + bc->updateUpLink(); + } + } + + // Update my own bottomLine, in case I am a MapCenter + if (depth == 0) + updateUpLink(); + + // Update XLinks + if (branchItem) { + XLinkObj *xlo; + for (int i = 0; i < branchItem->xlinkCount(); ++i) { + xlo = branchItem->getXLinkObjNum(i); + if (xlo) + xlo->updateGeometry(); + } + } +} diff --git a/src/branch-container.h b/src/branch-container.h new file mode 100644 index 0000000..da6683a --- /dev/null +++ b/src/branch-container.h @@ -0,0 +1,214 @@ +#ifndef BRANCH_CONTAINER_H +#define BRANCH_CONTAINER_H + +#include + +#include "branch-container-base.h" +#include "container.h" +#include "mapdesign.h" +#include "linkable-container.h" + +class BranchItem; +class FlagRowContainer; +class HeadingContainer; +class LinkContainer; + +class BranchContainer : public BranchContainerBase, public LinkableContainer { + public: + BranchContainer( + QGraphicsScene *scene, + BranchItem *bi = nullptr); + virtual ~BranchContainer(); + virtual void init(); + + BranchContainer* parentBranchContainer(); + + void setBranchItem(BranchItem *); + BranchItem *getBranchItem() const; + + virtual QString getName(); + + void setOriginalOrientation(); + Orientation getOriginalOrientation(); + QPointF getOriginalParentPos(); + + void setOriginalScenePos(); //! Saves current scene position for later restoring + void updateVisibility(); // consider scroll hidden state for branchesCont and imagesCont + + void setScrolled(bool b); + void setScrollOpacity(qreal a); + qreal getScrollOpacity(); + private: + qreal scrollOpacity; + + private: + void updateBranchesContainerParent(); + + public: + void addToBranchesContainer(BranchContainer *bc); + + private: + void updateImagesContainer(); //! Remove unused containers and add needed ones + void createOuterContainer(); //! Used if only images have FloatingBounded layout + void deleteOuterContainer(); + void updateTransformations(); //! Update rotation and scaling + + public: + void updateChildrenStructure(); //! Depending on layouts of children, rearrange structure + + private: + void updateImagesContainerParent(); //! Set parent depending on outerContainer + + public: + void createImagesContainer(); + void addToImagesContainer(Container *c); + + HeadingContainer* getHeadingContainer(); + LinkContainer* getLinkContainer(); + void linkTo(BranchContainer *); + + /*! Get suggestion where new child could be positioned (scene coord) */ + QPointF getPositionHintNewChild(Container*); + + /*! Get scene positions for links depending on frameType and orientation*/ + QPointF downLinkPos(); + QPointF downLinkPos(const Orientation &orientationChild); + QPointF upLinkPos(const Orientation &orientationChild); + + private: + LinkObj::PosHint upLinkPosHintInt; + LinkObj::PosHint downLinkPosHintInt; + + public: + /*! Update "upwards" links in LinkContainer */ + void updateUpLink(); + + void setLayout(const Layout &l); + + bool imagesContainerAutoLayout; + void setImagesContainerLayout(const Layout &l); + Container::Layout imagesContainerLayout(); + bool hasFloatingImagesLayout(); //! Checks, if children images are or should be floating + + bool branchesContainerAutoLayout; + void setBranchesContainerLayout(const Layout &l); + Container::Layout branchesContainerLayout(); + bool hasFloatingBranchesLayout(); //! Checks, if children branches are or should be floating + void setBranchesContainerHorizontalAlignment(const HorizontalAlignment &); + void setBranchesContainerVerticalAlignment(const VerticalAlignment &); + void setBranchesContainerBrush(const QBrush &b); + + void setBranchesContainerAndOrnamentsVertical(bool); + + QRectF headingRect(); //! Return rectangle of HeadingContainer in absolute coordinates + QRectF ornamentsRect(); //! Return rectangle of ornamentsContainer in absolute coordinates + + void setColumnWidthAutoDesign(const bool &); + bool columnWidthAutoDesign(); + + void setColumnWidth(const int &); + int columnWidth(); + + void setRotationsAutoDesign(const bool &, const bool &update = true); + bool rotationsAutoDesign(); + void setRotationHeading(const int &); + int rotationHeading(); + int rotationHeadingInScene(); + + void setRotationSubtree(const int &); + int rotationSubtree(); + + void setScaleAutoDesign(const bool &, const bool &update = true); + bool scaleAutoDesign(); + void setScaleHeading(const qreal &); + qreal scaleHeading(); + void setScaleSubtree(const qreal &); + qreal scaleSubtree(); + + void setColor(const QColor &); + + protected: + bool columnWidthAutoDesignInt; + bool rotationsAutoDesignInt; + qreal rotationHeadingInt; + qreal rotationSubtreeInt; + bool scaleAutoDesignInt; + qreal scaleHeadingInt; + qreal scaleSubtreeInt; + + public: + QUuid findFlagByPos(const QPointF &p); + bool isInClickBox(const QPointF &p); + QRectF getBBoxURLFlag(); + + virtual void select(); // Overloads SelectableContainer::select + + private: + bool autoDesignInnerFrame; + bool autoDesignOuterFrame; + + public: + // FrameContainer interfaces + bool frameAutoDesign(const bool &useInnerFrame); + void setFrameAutoDesign(const bool &userInnerFrame, const bool &); + FrameContainer::FrameType frameType(const bool &useInnerFrame); + QString frameTypeString(const bool &useInnerFrame); + void setFrameType(const bool &useInnerFrame, const FrameContainer::FrameType &); + void setFrameType(const bool &useInnerFrame, const QString &); + + int framePadding(const bool &useInnerFrame = true); + void setFramePadding(const bool &useInnerFrame, const int &); + int framePenWidth(const bool &useInnerFrame); + void setFramePenWidth(const bool &useInnerFrame, const int &); + QColor framePenColor(const bool &useInnerFrame); + void setFramePenColor(const bool &useInnerFrame, const QColor &); + QColor frameBrushColor(const bool &useInnerFrame); + void setFrameBrushColor(const bool &useInnerFrame, const QColor&); + + QString saveFrame(); + + public: + /*! Update flags and heading */ + void updateVisuals(); + + void reposition(); + + protected: + static qreal linkWidth; + BranchItem *branchItem; //! Crossreference to "parent" BranchItem + + // Save layout, alignment and brush of children containers + // even before containers are created on demand + Layout imagesContainerLayoutInt; + Layout branchesContainerLayoutInt; + HorizontalAlignment branchesContainerHorizontalAlignmentInt; + VerticalAlignment branchesContainerVerticalAlignmentInt; + QBrush branchesContainerBrushInt; + + bool branchesContainerAndOrnamentsVerticalInt; // Position branchesContainer e.g. for orgcharts + // Affects layout if innerContainer in BC + FrameContainer *innerFrame; // Frame container around ornamentsContainer + FrameContainer *outerFrame; // Frame container around whole BranchContainer + HeadingContainer *headingContainer; // Heading of this branch + HeadingContainer *linkSpaceContainer; // space for downLinks + LinkContainer *linkContainer; // Container with upLinks from child images and branches to myself + Container *listContainer; // Container for bullet point lists, if used + HeadingContainer *bulletPointContainer; // if lists are used, contains bulletpoint + Container *ornamentsContainer; // Flags and heading + Container *innerContainer; // Ornaments (see above) and children branches + Container *outerContainer; // Used only with FloatingBounded images and vertical branches + + FlagRowContainer *standardFlagRowContainer; + FlagRowContainer *systemFlagRowContainer; + + private: + Orientation originalOrientation; //! Save orientation before move for undo + bool originalFloating; //! Save, if floating before linked temporary + QPointF originalParentPos; // used in ME to determine orientation during move: scene coord of orig, parent + + public: // FIXME-3 v_anim public only for experimenting + QPointF v_anim; // Animation vector. Added to current pos in each animation step + QGraphicsLineItem v; +}; + +#endif diff --git a/src/branch-wrapper.cpp b/src/branch-wrapper.cpp new file mode 100644 index 0000000..ea2f498 --- /dev/null +++ b/src/branch-wrapper.cpp @@ -0,0 +1,895 @@ +#include "branch-wrapper.h" + +#include + +#include "attributeitem.h" +#include "branchitem.h" +#include "branch-container.h" + +#include "misc.h" +#include "scripting-xlink-wrapper.h" +#include "task.h" +#include "vymmodel.h" +#include "mainwindow.h" +#include "xlink.h" +#include "xlinkitem.h" + +extern Main *mainWindow; + +BranchWrapper::BranchWrapper(BranchItem *bi) +{ + //std:cout << "Constr BranchWrapper (BI) " << this << endl; + QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); + branchItemInt = bi; +} + +BranchWrapper::~BranchWrapper() +{ + //std:cout << "Destr BranchWrapper " << this << endl; +} + +BranchItem* BranchWrapper::branchItem() +{ + return branchItemInt; +} + +VymModel* BranchWrapper::model() +{ + return branchItemInt->getModel(); +} + +QPointF BranchWrapper::v_anim() // FIXME-3 experimental, no highlighting +{ + return branchItemInt->getBranchContainer()->v_anim; +} + +qreal BranchWrapper::v_animX() // FIXME-3 experimental, no highlighting +{ + return branchItemInt->getBranchContainer()->v_anim.x(); +} + +qreal BranchWrapper::v_animY() // FIXME-3 experimental, no highlighting +{ + return branchItemInt->getBranchContainer()->v_anim.y(); +} + +void BranchWrapper::setV_anim(qreal x, qreal y) // FIXME-3 playing with elastic animation +{ + branchItemInt->getBranchContainer()->v_anim = QPointF(x, y); + branchItemInt->getBranchContainer()->v.setLine(0, 0, x * 40, y * 40); + branchItemInt->getBranchContainer()->v.setVisible(true); +} + +BranchWrapper* BranchWrapper::addBranch() +{ + BranchItem* newbi = model()->addNewBranch(branchItemInt, -2); + if (!newbi) { + mainWindow->abortScript(QJSValue::GenericError,"Couldn't add branch to map"); + return nullptr; + } else + return newbi->branchWrapper(); +} + +BranchWrapper* BranchWrapper::addBranchAt(int pos) +{ + BranchItem* newbi = model()->addNewBranch(branchItemInt, -2); + if (!newbi) { + mainWindow->abortScript(QJSValue::GenericError,"Couldn't add branch to map"); + return nullptr; + } else + return newbi->branchWrapper(); +} + +BranchWrapper* BranchWrapper::addBranchBefore() +{ + BranchItem* newbi = model()->addNewBranchBefore(branchItemInt); + if (!newbi) { + mainWindow->abortScript( + QJSValue::GenericError, + "Couldn't add branch before selection to map"); + return nullptr; + } else + return newbi->branchWrapper(); +} + +XLinkWrapper* BranchWrapper::addXLink(BranchWrapper *bwEnd, + int width, const QString &color, + const QString &penstyle) +{ + BranchItem *biEnd = bwEnd->branchItem(); + XLink *li = new XLink(model()); + li->setBeginBranch(branchItemInt); + li->setEndBranch(biEnd); + + model()->createXLink(li); + QPen pen = li->getPen(); + if (width > 0) + pen.setWidth(width); + QColor col(color); + if (col.isValid()) + pen.setColor(col); + else { + mainWindow->abortScript( + QJSValue::GenericError, + QString("Could not set color to %1").arg(color)); + return nullptr; + } + + bool ok; + Qt::PenStyle st1 = penStyle(penstyle, ok); + if (ok) { + pen.setStyle(st1); + li->setPen(pen); + } else { + mainWindow->abortScript( + QJSValue::GenericError, + QString("Couldn't set penstyle %1").arg(penstyle)); + return nullptr; + } + return li->xlinkWrapper(); +} + +int BranchWrapper::attributeAsInt(const QString &key) +{ + QVariant v; + AttributeItem *ai = model()->getAttributeByKey(key, branchItemInt); + if (ai) { + v = ai->value(); + } else { + mainWindow->abortScript( + QJSValue::GenericError, + QString("No attribute found with key '%1'").arg(key)); + } + + bool ok; + int i = v.toInt(&ok); + if (ok) { + mainWindow->setScriptResult(i); + return i; + } else { + mainWindow->abortScript( + QJSValue::GenericError, + QString("Could not convert attribute with key '%1' to int.").arg(key)); + return -314; + } +} + +QString BranchWrapper::attributeAsString(const QString &key) +{ + QVariant v; + AttributeItem *ai = model()->getAttributeByKey(key, branchItemInt); + if (ai) { + v = ai->value(); + } else { + mainWindow->abortScript( + QJSValue::GenericError, + QString("No attribute found with key '%1'").arg(key)); + } + // + // Returned string will be empty for unsupported variant types + QString r = v.toString(); + mainWindow->setScriptResult(r); + return r; +} + +int BranchWrapper::branchCount() +{ + int r = branchItemInt->branchCount(); + mainWindow->setScriptResult(r); + return r; +} + +void BranchWrapper::clearFlags() { model()->clearFlags(branchItemInt); } + +void BranchWrapper::colorBranch(const QString &color) +{ + QColor col(color); + if (!col.isValid()) + mainWindow->abortScript( + QJSValue::GenericError, + QString("Could not set color to %1").arg(color)); + else + model()->colorBranch(col, branchItemInt); +} + +void BranchWrapper::colorSubtree(const QString &color) +{ + QColor col(color); + if (!col.isValid()) + mainWindow->abortScript( + QJSValue::GenericError, + QString("Could not set color to %1").arg(color)); + else + model()->colorSubtree(col, branchItemInt); +} + +bool BranchWrapper::cycleTask(bool reverse) +{ + bool r = model()->cycleTaskStatus(branchItemInt, reverse); + + mainWindow->setScriptResult(r); + return r; +} + +void BranchWrapper::deleteAttribute(const QString &key) +{ + model()->deleteAttribute(branchItemInt, key); +} + +#include "confluence-agent.h" +void BranchWrapper::deleteConfluencePageLabel(const QString &labelName) +{ + // qDebug() << __func__ << "called!"; + AttributeItem *ai = model()->getAttributeByKey("Confluence.pageID", branchItemInt); + if (ai) { + QString pageID = ai->value().toString(); + // qDebug() << " Found pageID in branch attributes: " << pageID; + ConfluenceAgent *ca_setHeading = new ConfluenceAgent(branchItemInt); + ca_setHeading->setPageID(pageID); + ca_setHeading->setLabelName(labelName); + ca_setHeading->setJobType(ConfluenceAgent::DeletePageLabel); + ca_setHeading->startJob(); + } else { + // qDebug() << " No pageID in branch attributes"; + mainWindow->abortScript( + QJSValue::GenericError, + "No pageID found in attributes of branch. Run getConfluencePageDetails first."); + return; + } +} + +int BranchWrapper::depth() +{ + int r = branchItemInt->depth(); + mainWindow->setScriptResult(r); + return r; +} + +void BranchWrapper::detach() +{ + model()->detach(branchItemInt); +} + +bool BranchWrapper::getFrameAutoDesign(const bool &useInnerFrame) +{ + bool r = branchItemInt->getBranchContainer()->frameAutoDesign(useInnerFrame); + mainWindow->setScriptResult(r); + return r; +} + +QString BranchWrapper::getFrameBrushColor(const bool &useInnerFrame) +{ + QString r = branchItemInt->getBranchContainer()->frameBrushColor(useInnerFrame).name(QColor::HexArgb); + mainWindow->setScriptResult(r); + return r; +} + +int BranchWrapper::getFramePadding(const bool &useInnerFrame) +{ + int r = branchItemInt->getBranchContainer()->framePadding(useInnerFrame); + mainWindow->setScriptResult(r); + return r; +} + +QString BranchWrapper::getFramePenColor(const bool &useInnerFrame) +{ + QString r = branchItemInt->getBranchContainer()->framePenColor(useInnerFrame).name(QColor::HexArgb); + mainWindow->setScriptResult(r); + return r; +} + +int BranchWrapper::getFramePenWidth(const bool &useInnerFrame) +{ + int r = branchItemInt->getBranchContainer()->framePenWidth(useInnerFrame); + mainWindow->setScriptResult(r); + return r; +} + +QString BranchWrapper::getFrameType(const bool &useInnerFrame) +{ + QString r = branchItemInt->getBranchContainer()->frameTypeString(useInnerFrame); + mainWindow->setScriptResult(r); + return r; +} + +QString BranchWrapper::getHeading() +{ + QString r = branchItemInt->heading().getText(); + mainWindow->setScriptResult(r); + return r; +} + +QString BranchWrapper::getHeadingXML() +{ + QString r = branchItemInt->heading().saveToDir(); + mainWindow->setScriptResult(r); + return r; +} + +void BranchWrapper::getJiraData(bool subtree) +{ + model()->getJiraData(subtree, branchItemInt); +} + +QString BranchWrapper::getNoteText() +{ + QString r = branchItemInt->getNote().getTextASCII(); + mainWindow->setScriptResult(r); + return r; +} + +QString BranchWrapper::getNoteXML() +{ + QString r = branchItemInt->getNote().saveToDir(); + mainWindow->setScriptResult(r); + return r; +} + +int BranchWrapper::getNum() +{ + int r = branchItemInt->num(); + mainWindow->setScriptResult(r); + return r; +} + +qreal BranchWrapper::getPosX() +{ + qreal r = branchItemInt->getBranchContainer()->pos().x(); + mainWindow->setScriptResult(r); + return r; +} + +qreal BranchWrapper::getPosY() +{ + qreal r = branchItemInt->getBranchContainer()->pos().y(); + mainWindow->setScriptResult(r); + return r; +} + +int BranchWrapper::getRotationHeading() +{ + int r = branchItemInt->getBranchContainer()->rotationHeading(); + mainWindow->setScriptResult(r); + return r; +} + +int BranchWrapper::getRotationSubtree() +{ + int r = branchItemInt->getBranchContainer()->rotationSubtree(); + mainWindow->setScriptResult(r); + return r; +} + +QPointF BranchWrapper::getScenePos() +{ + QPointF r = branchItemInt->getBranchContainer()->scenePos(); + mainWindow->setScriptResult(r); + return r; +} + +qreal BranchWrapper::getScenePosX() +{ + qreal r = branchItemInt->getBranchContainer()->scenePos().x(); + mainWindow->setScriptResult(r); + return r; +} + +qreal BranchWrapper::getScenePosY() +{ + qreal r = branchItemInt->getBranchContainer()->scenePos().y(); + mainWindow->setScriptResult(r); + return r; +} + +int BranchWrapper::getTaskPriorityDelta() +{ + int r = model()->getTaskPriorityDelta(branchItemInt); + mainWindow->setScriptResult(r); + return r; +} + +QString BranchWrapper::getTaskSleep() +{ + QString r; + Task *task = branchItemInt->getTask(); + if (task) + r = task->alarmTime().toString(Qt::ISODate); + else + mainWindow->abortScript( + QJSValue::GenericError, + "Branch has no task"); + mainWindow->setScriptResult(r); + return r; +} + +int BranchWrapper::getTaskSleepDays() +{ + int r = -1; + Task *task = branchItemInt->getTask(); + if (task) + r = task->getDaysSleep(); + else + mainWindow->abortScript(QJSValue::GenericError, "Branch has no task"); + mainWindow->setScriptResult(r); + return r; +} + +QString BranchWrapper::getTaskStatus() +{ + QString r; + Task *task = branchItemInt->getTask(); + if (task) + r = task->getStatusString(); + else + mainWindow->abortScript(QJSValue::GenericError, "Branch has no task"); + + mainWindow->setScriptResult(r); + return r; +} + +QString BranchWrapper::getUid() +{ + QString r = branchItemInt->getUuid().toString(); + mainWindow->setScriptResult(r); + return r; +} + +QString BranchWrapper::getUrl() +{ + QString r = branchItemInt->url(); + mainWindow->setScriptResult(r); + return r; +} + +QString BranchWrapper::getVymLink() +{ + QString r = branchItemInt->vymLink(); + mainWindow->setScriptResult(r); + return r; +} + +bool BranchWrapper::hasActiveFlag(const QString &flag) +{ + bool r = branchItemInt->hasActiveFlag(flag); + mainWindow->setScriptResult(r); + return r; +} + +bool BranchWrapper::hasAttributeWithKey(const QString &key) +{ + QVariant v; + AttributeItem *ai = model()->getAttributeByKey(key, branchItemInt); + if (ai) + return true; + else + return false; +} + +bool BranchWrapper::hasNote() +{ + bool r = !branchItemInt->getNote().isEmpty(); + mainWindow->setScriptResult(r); + return r; +} + +bool BranchWrapper::hasRichTextHeading() +{ + bool r = branchItemInt->heading().isRichText(); + mainWindow->setScriptResult(r); + return r; +} + +bool BranchWrapper::hasRichTextNote() +{ + bool r = branchItemInt->getNote().isRichText(); + mainWindow->setScriptResult(r); + return r; +} + +bool BranchWrapper::hasTask() +{ + bool r = false; + Task *task = branchItemInt->getTask(); + if (task) + r = true; + + mainWindow->setScriptResult(r); + return r; +} + +QString BranchWrapper::headingText() +{ + QString r = branchItemInt->headingPlain(); + mainWindow->setScriptResult(r); + return r; +} + +int BranchWrapper::imageCount() +{ + int r = branchItemInt->imageCount(); + mainWindow->setScriptResult(r); + return r; +} + +void BranchWrapper::importDir(const QString &path) // FIXME-5 error handling missing (in vymmodel and here) +{ + model()->importDir(path, branchItemInt); +} + +bool BranchWrapper::loadBranchInsert(QString fileName, int pos) +{ + if (QDir::isRelativePath(fileName)) + fileName = QDir::currentPath() + "/" + fileName; + + bool r = model()->addMapInsert(fileName, pos, branchItemInt); + mainWindow->setScriptResult(r); + return r; +} + +bool BranchWrapper::loadImage(const QString &filename) +{ + bool r; + ImageItem *ii = model()->loadImage(branchItemInt, filename); + r = (ii) ? true : false; + mainWindow->setScriptResult(r); + if (ii) + return true; + else + return false; +} + +bool BranchWrapper::loadNote(const QString &filename) +{ + bool r = model()->loadNote(filename, branchItemInt); + mainWindow->setScriptResult(r); + return r; +} + +void BranchWrapper::moveDown() +{ + model()->moveDown(branchItemInt); +} + +void BranchWrapper::moveUp() +{ + model()->moveUp(branchItemInt); +} + +void BranchWrapper::note2URLs() +{ + model()->note2URLs(branchItemInt); +} + +BranchWrapper* BranchWrapper::parentBranch() +{ + return branchItemInt->parentBranch()->branchWrapper(); +} + +bool BranchWrapper::isScrolled() +{ + bool r = branchItemInt->isScrolled(); + mainWindow->setScriptResult(r); + return r; +} + +bool BranchWrapper::relinkToBranch(BranchWrapper *dst) +{ + bool r = model()->relinkBranch(branchItemInt, dst->branchItemInt); + mainWindow->setScriptResult(r); + return r; +} + +bool BranchWrapper::relinkToBranchAt(BranchWrapper *dst, int pos) +{ + bool r = model()->relinkBranch(branchItemInt, dst->branchItemInt, pos); + mainWindow->setScriptResult(r); + return r; +} + +void BranchWrapper::removeChildren() +{ + model()->deleteChildren(branchItemInt); +} + +void BranchWrapper::removeChildrenBranches() +{ + model()->deleteChildrenBranches(branchItemInt); +} + +bool BranchWrapper::saveNote(const QString &filename) +{ + bool r = model()->saveNote(filename); + mainWindow->setScriptResult(r); + return r; +} + +void BranchWrapper::scroll() +{ + model()->scrollBranch(branchItemInt); +} + +void BranchWrapper::select() +{ + model()->select(branchItemInt); +} + +bool BranchWrapper::selectFirstBranch() +{ + bool r = model()->selectFirstBranch(branchItemInt); + mainWindow->setScriptResult(r); + return r; +} + +bool BranchWrapper::selectFirstChildBranch() +{ + bool r = model()->selectFirstChildBranch(branchItemInt); + mainWindow->setScriptResult(r); + return r; +} + +bool BranchWrapper::selectLastChildBranch() +{ + bool r = model()->selectLastChildBranch(branchItemInt); + mainWindow->setScriptResult(r); + return r; +} + +bool BranchWrapper::selectLastBranch() +{ + bool r = model()->selectLastBranch(branchItemInt); + mainWindow->setScriptResult(r); + return r; +} +bool BranchWrapper::selectParent() +{ + bool r = model()->selectParent(branchItemInt); + if (!r) + mainWindow->abortScript( + QJSValue::GenericError, + "Couldn't select parent item"); + mainWindow->setScriptResult(r); + return r; +} + +bool BranchWrapper::selectXLink(int n) +{ + bool r = false; + XLinkItem *xli = branchItemInt->getXLinkItemNum(n); + if (!xli) + mainWindow->abortScript(QJSValue::RangeError, + QString("Selected branch has no xlink with index %1").arg(n)); + else + r = model()->select((TreeItem*)xli); + mainWindow->setScriptResult(r); + return r; +} + +bool BranchWrapper::selectXLinkOtherEnd(int n) +{ + bool r = false; + XLinkItem *xli = branchItemInt->getXLinkItemNum(n); + if (!xli) { + mainWindow->abortScript( + QJSValue::RangeError, + QString("Selected branch has no xlink with index %1").arg(n)); + } else { + BranchItem *bi = xli->getPartnerBranch(); + if (!bi) { + mainWindow->abortScript( + QJSValue::RangeError, + "Selected xlink has no other end ?!"); + } else + r = model()->select(bi); + } + mainWindow->setScriptResult(r); + return r; +} + +void BranchWrapper::setAttribute(const QString &key, const QString &value) +{ + model()->setAttribute(branchItemInt, key, value); +} + +void BranchWrapper::setFlagByName(const QString &s) +{ + model()->setFlagByName(s, branchItemInt); +} + +void BranchWrapper::setFrameAutoDesign(const bool useInnerFrame, const bool b) +{ + model()->setFrameAutoDesign(useInnerFrame, b, branchItemInt); +} + +void BranchWrapper::setFrameBrushColor(const bool &useInnerFrame, const QString &color) +{ + model()->setFrameBrushColor(useInnerFrame, color, branchItemInt); +} + +void BranchWrapper::setFramePadding(const bool &useInnerFrame, int padding) +{ + model()->setFramePadding(useInnerFrame, padding, branchItemInt); +} + +void BranchWrapper::setFramePenColor(const bool &useInnerFrame, const QString &color) +{ + model()->setFramePenColor(useInnerFrame, color, branchItemInt); +} + +void BranchWrapper::setFramePenWidth(const bool &useInnerFrame, int width) +{ + model()->setFramePenWidth(useInnerFrame, width, branchItemInt); +} + +void BranchWrapper::setFrameType(const bool &useInnerFrame, const QString &type) +{ + model()->setFrameType(useInnerFrame, type, branchItemInt); +} + +void BranchWrapper::setHeadingColumnWidth(const int &w) +{ + model()->setHeadingColumnWidth(w, branchItemInt); +} + +void BranchWrapper::setHeadingColumnWidthAutoDesign(const bool b) +{ + model()->setHeadingColumnWidthAutoDesign(b, branchItemInt); +} + +void BranchWrapper::setHeadingConfluencePageName() +{ + model()->setConfluencePageDetails(false, branchItemInt); +} + +void BranchWrapper::setHeadingRichText(const QString &text) +{ + // Set plaintext heading + VymText vt; + vt.setRichText(text); + model()->setHeading(vt, branchItemInt); +} + +void BranchWrapper::setHeadingText(const QString &text) +{ + // Set plaintext heading + model()->setHeadingPlainText(text, branchItemInt); +} + +void BranchWrapper::setHideExport(bool b) +{ + model()->setHideExport(b, branchItemInt); +} + +void BranchWrapper::setHideLinkUnselected(bool b) +{ + model()->setHideLinkUnselected(b, branchItemInt); +} + +void BranchWrapper::setNoteRichText(const QString &s) +{ + VymNote vn; + vn.setRichText(s); + model()->setNote(vn, branchItemInt); +} + +void BranchWrapper::setNoteText(const QString &s) +{ + VymNote vn; + vn.setPlainText(s); + model()->setNote(vn, branchItemInt); +} + +void BranchWrapper::setOnlyFlags(QJSValueList args) +{ + QList uids; + foreach (QJSValue v, args) + uids << QUuid(v.toString()); + model()->setOnlyFlags(uids, branchItemInt); +} + +void BranchWrapper::setPos(qreal x, qreal y) +{ + model()->setPos(QPointF(x, y), branchItemInt); +} + +void BranchWrapper::setRotationAutoDesign(const bool b) +{ + model()->setRotationAutoDesign(b, branchItemInt); +} + +void BranchWrapper::setRotationHeading(const int &i) +{ + model()->setRotationHeading(i, branchItemInt); +} + +void BranchWrapper::setRotationSubtree(const int &i) +{ + model()->setRotationSubtree(i, branchItemInt); +} + +void BranchWrapper::setScaleAutoDesign(const bool b) +{ + model()->setScaleAutoDesign(b, branchItemInt); +} + +void BranchWrapper::setScaleHeading(qreal f) { model()->setScaleHeading(f, false, branchItemInt); } + +void BranchWrapper::setScaleSubtree(qreal f) { model()->setScaleSubtree(f, branchItemInt); } + +void BranchWrapper::setTaskPriorityDelta(const int &n) +{ + model()->setTaskPriorityDelta(n, branchItemInt); +} + +bool BranchWrapper::setTaskSleep(const QString &s) +{ + bool r = model()->setTaskSleep(s, branchItemInt); + mainWindow->setScriptResult(r); + return r; +} + +void BranchWrapper::setUrl(const QString &s) +{ + model()->setUrl(s, true, branchItemInt); +} + +void BranchWrapper::setVymLink(const QString &s) +{ + model()->setVymLink(s, branchItemInt); +} + +void BranchWrapper::sortChildren(bool b) +{ + model()->sortChildren(b, branchItemInt); +} + +void BranchWrapper::sortChildren() +{ + sortChildren(false); +} + +void BranchWrapper::toggleFlagByName(const QString &s) +{ + model()->toggleFlagByName(s, branchItemInt); +} + +void BranchWrapper::toggleFlagByUid(const QString &s) +{ + model()->toggleFlagByUid(QUuid(s), branchItemInt); +} + +void BranchWrapper::toggleScroll() +{ + model()->toggleScroll(branchItemInt); +} + +void BranchWrapper::toggleTarget() +{ + model()->toggleTarget(branchItemInt); +} + +void BranchWrapper::toggleTask() { + model()->toggleTask(branchItemInt); +} + +void BranchWrapper::unscroll() +{ + model()->unscrollBranch(branchItemInt); +} + +void BranchWrapper::unscrollSubtree() +{ + model()->unscrollSubtree(branchItemInt); +} + +void BranchWrapper::unsetFlagByName(const QString &s) +{ + model()->unsetFlagByName(s, branchItemInt); +} + + +int BranchWrapper::xlinkCount() +{ + int r = branchItemInt->xlinkCount(); + mainWindow->setScriptResult(r); + return r; +} diff --git a/src/branch-wrapper.h b/src/branch-wrapper.h new file mode 100644 index 0000000..aad3390 --- /dev/null +++ b/src/branch-wrapper.h @@ -0,0 +1,143 @@ +#ifndef BRANCH_WRAPPER_H +#define BRANCH_WRAPPER_H + +#include +#include + +class BranchItem; +class VymModel; +class XLinkWrapper; + +class BranchWrapper : public QObject { + Q_OBJECT + public: + Q_INVOKABLE BranchWrapper(BranchItem*); + ~BranchWrapper(); + BranchItem* branchItem(); + VymModel* model(); + + public slots: + QPointF v_anim(); + qreal v_animX(); + qreal v_animY(); + void setV_anim(qreal, qreal); + + Q_INVOKABLE BranchWrapper* addBranch(); + Q_INVOKABLE BranchWrapper* addBranchAt(int pos); + Q_INVOKABLE BranchWrapper* addBranchBefore(); + Q_INVOKABLE XLinkWrapper* addXLink(BranchWrapper *bwEnd, int width, + const QString &color, const QString &penstyle); + int attributeAsInt(const QString &key); + QString attributeAsString(const QString &key); + int branchCount(); + void clearFlags(); + void colorBranch(const QString &color); + void colorSubtree(const QString &color); + bool cycleTask(bool reverse = false); + void deleteAttribute(const QString &key); + void deleteConfluencePageLabel(const QString &labelName); + int depth(); + void detach(); + bool getFrameAutoDesign(const bool & useInnerFrame); + QString getFrameBrushColor(const bool & useInnerFrame); + int getFramePadding(const bool & useInnerFrame); + QString getFramePenColor(const bool & useInnerFrame); + int getFramePenWidth(const bool & useInnerFrame); + QString getFrameType(const bool & useInnerFrame); + QString getHeading(); + QString getHeadingXML(); + void getJiraData(bool subtree); + QString getNoteText(); + QString getNoteXML(); + int getNum(); + qreal getPosX(); + qreal getPosY(); + int getRotationHeading(); + int getRotationSubtree(); + QPointF getScenePos(); + qreal getScenePosX(); + qreal getScenePosY(); + int getTaskPriorityDelta(); + QString getTaskSleep(); + int getTaskSleepDays(); + QString getTaskStatus(); + QString getUid(); + QString getUrl(); + QString getVymLink(); + bool hasActiveFlag(const QString &flag); + bool hasAttributeWithKey(const QString &key); + bool hasNote(); + bool hasRichTextHeading(); + bool hasRichTextNote(); + bool hasTask(); + QString headingText(); + int imageCount(); + void importDir(const QString &path); + bool isScrolled(); + bool loadBranchInsert(QString filename, int pos); + bool loadImage(const QString &filename); + bool loadNote(const QString &filename); + void moveDown(); + void moveUp(); + void note2URLs(); + Q_INVOKABLE BranchWrapper* parentBranch(); + bool relinkToBranch(BranchWrapper*); + bool relinkToBranchAt(BranchWrapper*, int pos); + void removeChildren(); + void removeChildrenBranches(); + bool saveNote(const QString &filename); + void scroll(); + void select(); + bool selectFirstBranch(); + bool selectFirstChildBranch(); + bool selectLastBranch(); + bool selectLastChildBranch(); + bool selectParent(); + bool selectXLink(int n); + bool selectXLinkOtherEnd(int n); + void setAttribute(const QString &key, const QString &value); + void setFlagByName(const QString &); + void setFrameAutoDesign(const bool, const bool); + void setFrameBrushColor(const bool & useInnerFrame, const QString &color); + void setFramePadding(const bool & useInnerFrame, int padding); + void setFramePenColor(const bool & useInnerFrame, const QString &color); + void setFramePenWidth(const bool & useInnerFrame, int w); + void setFrameType(const bool & useInnerFrame, const QString &type); + void setHeadingColumnWidth(const int &w); + void setHeadingColumnWidthAutoDesign(const bool); + void setHeadingConfluencePageName(); + void setHeadingRichText(const QString &); + void setHeadingText(const QString &); + void setHideExport(bool b); + void setHideLinkUnselected(bool b); + void setNoteRichText(const QString &); + void setNoteText(const QString &); + void setOnlyFlags(QJSValueList args); + void setPos(qreal x, qreal y); + void setRotationAutoDesign(const bool b); + void setRotationHeading(const int &i); + void setRotationSubtree(const int &i); + void setScaleAutoDesign(const bool b); + void setScaleHeading(qreal f); + void setScaleSubtree(qreal f); + void setTaskPriorityDelta(const int &n); + bool setTaskSleep(const QString &s); + void setUrl(const QString &s); + void setVymLink(const QString &s); + void sortChildren(bool b); + void sortChildren(); + void toggleFlagByName(const QString &); + void toggleFlagByUid(const QString &); + void toggleScroll(); + void toggleTarget(); + void toggleTask(); + void unscroll(); + void unscrollSubtree(); + void unsetFlagByName(const QString &); + int xlinkCount(); + + private: + BranchItem *branchItemInt; +}; + +#endif diff --git a/src/branchitem.cpp b/src/branchitem.cpp index 91a71be..a518573 100644 --- a/src/branchitem.cpp +++ b/src/branchitem.cpp @@ -1,7 +1,11 @@ #include "branchitem.h" #include "attributeitem.h" -#include "branchobj.h" +#include "branch-container.h" +#include "branch-wrapper.h" +#include "frame-container.h" +#include "heading-container.h" +#include "image-container.h" #include "task.h" #include "taskmodel.h" #include "vymmodel.h" @@ -10,8 +14,6 @@ extern TaskModel *taskModel; -//#include - BranchItem::BranchItem(TreeItem *parent) : MapItem(parent) { @@ -27,31 +29,37 @@ BranchItem::BranchItem(TreeItem *parent) scrolled = false; tmpUnscrolled = false; - includeImagesVer = false; - includeImagesHor = false; - includeChildren = false; - childrenLayout = BranchItem::AutoPositioning; - lastSelectedBranchNum = 0; lastSelectedBranchNumAlt = 0; - task = NULL; -} + task = nullptr; -BranchItem::~BranchItem() -{ - // qDebug()<< "Destr. BranchItem this="<isBranchLikeType() && + // save area, if not scrolled + // FIXME-5 we could check if _any_ of parents is scrolled + if (exportBoundingBoxes && branchContainer && parentItem->hasTypeBranch() && !((BranchItem *)parentItem)->isScrolled()) { - qreal x = mo->getAbsPos().x(); - qreal y = mo->getAbsPos().y(); - areaAttr = - attribut("x1", QString().setNum(x - offset.x())) + - attribut("y1", QString().setNum(y - offset.y())) + - attribut("x2", QString().setNum(x + mo->width() - offset.x())) + - attribut("y2", QString().setNum(y + mo->height() - offset.y())); + QRectF r_bc = branchContainer->mapToScene(branchContainer->rect()).boundingRect(); + attr += + attribute("x1", QString().setNum(r_bc.topLeft().x() - offset.x())) + + attribute("y1", QString().setNum(r_bc.topLeft().y() - offset.y())) + + attribute("x2", QString().setNum(r_bc.bottomRight().x() - offset.x())) + + attribute("y2", QString().setNum(r_bc.bottomRight().y() - offset.y())); } - else - areaAttr = ""; QString elementName; if (parentItem == rootItem) @@ -125,42 +159,55 @@ QString BranchItem::saveToDir(const QString &tmpdir, const QString &prefix, elementName = "branch"; // Free positioning of children - QString layoutAttr; - if (childrenLayout == BranchItem::FreePositioning) - layoutAttr += attribut("childrenFreePos", "true"); - - // Save rotation - QString rotAttr; - if (mo && mo->getRotation() != 0) - rotAttr = attribut("rotation", QString().setNum(mo->getRotation())); - - s = beginElement(elementName + getMapAttr() + getGeneralAttr() + - scrolledAttr + getIncludeImageAttr() + rotAttr + - layoutAttr + idAttr); + if (!branchContainer->branchesContainerAutoLayout) + // Save the manually set layout for children branches + attr += attribute("branchesLayout", branchContainer->layoutString(branchContainer->branchesContainerLayout())); + + if (!branchContainer->imagesContainerAutoLayout) + // Save the manually set layout for children Images + attr += attribute("imagesLayout", branchContainer->Container::layoutString(branchContainer->imagesContainerLayout())); + + if (!branchContainer->rotationsAutoDesign()) { + attr += attribute("rotHeading", QString("%1").arg(branchContainer->rotationHeading())); + + attr += attribute("rotSubtree", QString("%1").arg(branchContainer->rotationSubtree())); + } + + if (!branchContainer->scaleAutoDesign()) { + attr += attribute("scaleHeading", QString("%1").arg(branchContainer->scaleHeading())); + + attr += attribute("scaleSubtree", QString("%1").arg(branchContainer->scaleSubtree())); + } + + // width of heading + if (!branchContainer->columnWidthAutoDesign()) + attr += attribute("colWidth", QString("%1").arg(branchContainer->getHeadingContainer()->columnWidth())); + + if (parentItem == rootItem || branchContainer->isFloating()) + attr += getPosAttr(); + + QString s = beginElement(elementName + " " + attr); incIndent(); // save heading - s += heading.saveToDir(); + s += headingInt.saveToDir(); // save note if (!note.isEmpty()) s += note.saveToDir(); - // Save frame // not saved if there is no MO - if (mo) { - // Avoid saving NoFrame for objects other than MapCenter - if (depth() == 0 || ((OrnamentedObj *)mo)->getFrame()->getFrameType() != - FrameObj::NoFrame) - s += ((OrnamentedObj *)mo)->getFrame()->saveToDir(); - } + // Save frame + if (branchContainer->frameType(true) != FrameContainer::NoFrame || + branchContainer->frameType(false) != FrameContainer::NoFrame) + s += branchContainer->saveFrame(); - // save names of flags set + // save names of flag set s += standardFlags.saveState(); s += userFlags.saveState(); // Save Images for (int i = 0; i < imageCount(); ++i) - s += getImageNum(i)->saveToDir(tmpdir, prefix); + s += getImageNum(i)->saveToDir(tmpdir); // save attributes for (int i = 0; i < attributeCount(); ++i) @@ -174,38 +221,26 @@ QString BranchItem::saveToDir(const QString &tmpdir, const QString &prefix, int i = 0; TreeItem *ti = getBranchNum(i); while (ti) { - s += getBranchNum(i)->saveToDir(tmpdir, prefix, offset, tmpLinks); + s += getBranchNum(i)->saveToDir(tmpdir, prefix, offset, tmpXLinks, exportBoundingBoxes); i++; ti = getBranchNum(i); } // Mark Links for save for (int i = 0; i < xlinkCount(); ++i) { - Link *l = getXLinkItemNum(i)->getLink(); - if (l && !tmpLinks.contains(l)) - tmpLinks.append(l); + XLink *xl = getXLinkItemNum(i)->getXLink(); + if (xl && !tmpXLinks.contains(xl)) + tmpXLinks.append(xl); } decIndent(); s += endElement(elementName); return s; } -void BranchItem::updateVisibility() -{ - // Needed to hide relinked branch, if parent is scrolled - if (mo) { - if (hasScrolledParent(this) || hidden) - mo->setVisibility(false); - else - mo->setVisibility(true); - } -} - void BranchItem::setHeadingColor(QColor color) { TreeItem::setHeadingColor(color); - if (mo) - ((BranchObj *)mo)->setColor(color); + branchContainer->setColor(color); } void BranchItem::updateTaskFlag() @@ -249,27 +284,17 @@ bool BranchItem::toggleScroll() if (depth() == 0) return false; - BranchObj *bo; if (scrolled) { scrolled = false; systemFlags.deactivate(QString("system-scrolledright")); - if (branchCounter > 0) - for (int i = 0; i < branchCounter; ++i) { - bo = (BranchObj *)(getBranchNum(i)->getMO()); - if (bo) - bo->setVisibility(true); // Recursively! - } } else { scrolled = true; systemFlags.activate(QString("system-scrolledright")); - if (branchCounter > 0) - for (int i = 0; i < branchCounter; ++i) { - bo = (BranchObj *)(getBranchNum(i)->getMO()); - if (bo) - bo->setVisibility(false); // Recursively! - } } + + branchContainer->updateChildrenStructure(); // needed to insert linkSpaceContainer + branchContainer->updateVisibility(); return true; } @@ -303,7 +328,7 @@ bool BranchItem::tmpUnscroll(BranchItem *start) // Unscroll parent (recursivly) BranchItem *pi = (BranchItem *)parentItem; - if (pi && pi->isBranchLikeType()) + if (pi && pi->hasTypeBranch()) result = pi->tmpUnscroll(start); // Unscroll myself @@ -323,7 +348,7 @@ bool BranchItem::resetTmpUnscroll() // Unscroll parent (recursivly) BranchItem *pi = (BranchItem *)parentItem; - if (pi && pi->isBranchLikeType()) + if (pi && pi->hasTypeBranch()) result = pi->resetTmpUnscroll(); // Unscroll myself @@ -337,98 +362,21 @@ bool BranchItem::resetTmpUnscroll() return result; } -void BranchItem::sortChildren( - bool inverse) // FIXME-4 optimize by not using moveUp/Down -{ - int childCount = branchCounter; - int curChildIndex; - bool madeChanges = false; - do { - madeChanges = false; - for (curChildIndex = 1; curChildIndex < childCount; curChildIndex++) { - BranchItem *curChild = getBranchNum(curChildIndex); - BranchItem *prevChild = getBranchNum(curChildIndex - 1); - if (inverse) { - if (prevChild->getHeadingPlain().compare( - curChild->getHeadingPlain(), Qt::CaseInsensitive) < 0) { - model->moveUp(curChild); - madeChanges = true; - } - } - else if (prevChild->getHeadingPlain().compare( - curChild->getHeadingPlain(), Qt::CaseInsensitive) > - 0) { - model->moveUp(curChild); - madeChanges = true; - } - } - } while (madeChanges); -} - -void BranchItem::setChildrenLayout(BranchItem::LayoutHint layoutHint) -{ - childrenLayout = layoutHint; -} - -BranchItem::LayoutHint BranchItem::getChildrenLayout() +void BranchItem::setBranchesLayout(const QString &s) { - return childrenLayout; + branchContainer->setBranchesContainerLayout(Container::layoutFromString(s)); } -void BranchItem::setIncludeImagesVer(bool b) { includeImagesVer = b; } - -bool BranchItem::getIncludeImagesVer() { return includeImagesVer; } - -void BranchItem::setIncludeImagesHor(bool b) { includeImagesHor = b; } - -bool BranchItem::getIncludeImagesHor() { return includeImagesHor; } - -QString BranchItem::getIncludeImageAttr() +void BranchItem::setImagesLayout(const QString &s) { - QString a; - if (includeImagesVer) - a = attribut("incImgV", "true"); - if (includeImagesHor) - a += attribut("incImgH", "true"); - return a; -} - -BranchItem *BranchItem::getFramedParentBranch(BranchItem *start) -{ - BranchObj *bo = getBranchObj(); - if (bo && bo->getFrameType() != FrameObj::NoFrame) { - if (bo->getFrame()->getFrameIncludeChildren()) - return this; - if (this == start) - return this; - } - BranchItem *bi = (BranchItem *)parentItem; - if (bi && bi != rootItem) - return bi->getFramedParentBranch(start); - else - return NULL; -} - -void BranchItem::setFrameIncludeChildren(bool b) -{ - includeChildren = b; // FIXME-4 ugly: same information stored in FrameObj - BranchObj *bo = getBranchObj(); - if (bo) - bo->getFrame()->setFrameIncludeChildren(b); -} - -bool BranchItem::getFrameIncludeChildren() -{ - BranchObj *bo = getBranchObj(); - if (bo) - return bo->getFrame()->getFrameIncludeChildren(); - else - return includeChildren; + branchContainer->setImagesContainerLayout(Container::layoutFromString(s)); } QColor BranchItem::getBackgroundColor(BranchItem *start, bool checkInnerFrame) { - /* + if (!branchContainer) + return QColor(); + // Determine background color in taskEditor, first try inner frame if (checkInnerFrame && branchContainer->frameType(true) != FrameContainer::NoFrame) return branchContainer->frameBrushColor(true); @@ -442,13 +390,8 @@ QColor BranchItem::getBackgroundColor(BranchItem *start, bool checkInnerFrame) // Recursively try parents and check for frames there return pb->getBackgroundColor(start, false); else - */ - BranchItem *bi = getFramedParentBranch(start); - if (bi) - return bi->getBranchObj()->getFrameBrushColor(); - // No frame found - return model->getMapBackgroundColor(); + return model->mapDesign()->backgroundColor(); } void BranchItem::setLastSelectedBranch() @@ -459,12 +402,14 @@ void BranchItem::setLastSelectedBranch() // Hack to save an additional lastSelected for mapcenters in // MapEditor depending on orientation this allows to go both left // and right from there - if (mo && ((BranchObj *)mo)->getOrientation() == - LinkableMapObj::LeftOfCenter) { + + if (branchContainer->getOrientation() == + BranchContainer::LeftOfParent) { ((BranchItem *)parentItem)->lastSelectedBranchNumAlt = parentItem->num(this); return; } + ((BranchItem *)parentItem)->lastSelectedBranchNum = parentItem->num(this); } @@ -485,90 +430,146 @@ BranchItem *BranchItem::getLastSelectedBranchAlt() return getBranchNum(lastSelectedBranchNumAlt); } -TreeItem *BranchItem::findMapItem(QPointF p, TreeItem *excludeTI) +TreeItem *BranchItem::findMapItem(QPointF p, QList excludedItems) { // Search branches - TreeItem *ti; - for (int i = 0; i < branchCount(); ++i) { - ti = getBranchNum(i)->findMapItem(p, excludeTI); - if (ti != NULL) - return ti; + if (!isScrolled()) { + TreeItem *ti; + for (int i = 0; i < branchCounter; ++i) { + ti = getBranchNum(i)->findMapItem(p, excludedItems); + if (ti != nullptr) + return ti; + } } // Search images ImageItem *ii; + ImageContainer *ic; for (int i = 0; i < imageCount(); ++i) { ii = getImageNum(i); - MapObj *mo = ii->getMO(); - if (mo && mo->isInClickBox(p) && (ii != excludeTI) && - this != excludeTI && mo->isVisibleObj()) - return ii; + ic = ii->getImageContainer(); + if (!excludedItems.contains(ii) && ic->isVisible() && ic->mapToScene(ic->rect()).containsPoint(p, Qt::OddEvenFill)) return ii; } - // Search myself - if (getBranchObj()->isInClickBox(p) && (this != excludeTI) && - getBranchObj()->isVisibleObj()) + // Search my container + if (branchContainer->isVisible() && branchContainer->isInClickBox(p) && !excludedItems.contains(this) ) // && + //getBranchObj()->isVisibleObj()) return this; - // Search attributes - AttributeItem *ai; - for (int i = 0; i < attributeCount(); ++i) { - ai = getAttributeNum(i); - MapObj *mo = ai->getMO(); - if (mo && mo->isInClickBox(p) && (ai != excludeTI) && - this != excludeTI && mo->isVisibleObj()) - return ai; - } - return NULL; + return nullptr; +} + +void BranchItem::setHideMode(HideTmpMode mode) +{ + TreeItem::setHideMode(mode); + branchContainer->updateVisibility(); +} + +void BranchItem::updateVisuals() +{ + branchContainer->updateVisuals(); } -void BranchItem::updateStyles(const bool &keepFrame) +BranchContainer *BranchItem::createBranchContainer(QGraphicsScene *scene) { - // Update styles when relinking branches - if (mo) { - BranchObj *bo = getBranchObj(); - if (parentItem != rootItem) - bo->setParObj((LinkableMapObj *)(((MapItem *)parentItem)->getMO())); - else - bo->setParObj(NULL); - bo->setDefAttr(BranchObj::MovedBranch, keepFrame); + branchContainer = new BranchContainer(scene, this); + + if (parentBranch() != rootItem) { + // For floating branches get a position hint + parentBranch()->addToBranchesContainer(branchContainer); + BranchContainer *pbc = branchContainer->parentBranchContainer(); + if (pbc->hasFloatingBranchesLayout()) + branchContainer->setPos(pbc->getPositionHintNewChild(branchContainer)); + + // Link to parent branch visually by + // adding my upLink to parents linkContainer + branchContainer->linkTo(parentBranch()->getBranchContainer()); } + + return branchContainer; +} + +BranchContainer* BranchItem::getBranchContainer() +{ + return branchContainer; } -BranchObj *BranchItem::getBranchObj() { return (BranchObj *)mo; } +void BranchItem::unlinkBranchContainer() +{ + //qDebug() << "BI::unlinkBC in " << this << headingPlain(); + + // Called from destructor of containers to + // avoid double deletion + branchContainer = nullptr; +} -BranchObj *BranchItem::createMapObj(QGraphicsScene *scene) +Container* BranchItem::getBranchesContainer() { - BranchObj *newbo; + return branchContainer->getBranchesContainer(); +} + +Container* BranchItem::getImagesContainer() +{ + return branchContainer->getImagesContainer(); +} + +void BranchItem::updateContainerStackingOrder() +{ + // After relinking branches (also moving up/down), the order of the + // BranchContainers does not match the order of BranchItems any longer and + // needs to be adjusted. Or the BranchContainer has (temporarily) been linked to + // a completely different parent. + // + // It seems the QGraphicsItem::stackBefore only works, if an item is moved up. + // For moving below (or into another subtree), we have to reparent first :-( + + // For simplicity we always reparent. The absolute position will not be changed here - if (parentItem == rootItem) { - newbo = new BranchObj(NULL, this); - mo = newbo; - scene->addItem(newbo); + int n = num(); + + QPointF sp = branchContainer->scenePos(); + + branchContainer->setParentItem(nullptr); + + if (parentBranch() == rootItem) { + // I am a MapCenter + branchContainer->setPos(sp); + return; } - else { - newbo = new BranchObj(((MapItem *)parentItem)->getMO(), this); - mo = newbo; - // Set visibility depending on parents - if (parentItem != rootItem && - (((BranchItem *)parentItem)->scrolled || - !((MapItem *)parentItem)->getLMO()->isVisibleObj())) - newbo->setVisibility(false); - if (depth() == 1) { - qreal r = 190; - qreal a = - -M_PI_4 + M_PI_2 * (num()) + (M_PI_4 / 2) * (num() / 4 % 4); - QPointF p(r * cos(a), r * sin(a)); - newbo->setRelPos(p); + + parentBranch()->addToBranchesContainer(branchContainer); + + while (n < parentBranch()->branchCount() - 1) { + // Insert container of this branch above others + + // The next sibling container might currently still be temporarily + // linked to tmpParentContainer, in that case it is not a sibling and + // cannot be inserted using QGraphicsItem::stackBefore + // + // We try the next sibling then, if this fails, just append at the end. + if ( (parentBranch()->getBranchNum(n + 1))->getContainer()->parentItem() != parentBranch()->getBranchesContainer() ) + n++; + else { + branchContainer->stackBefore( (parentBranch()->getBranchNum(n + 1))->getContainer() ); + break; } } - newbo->setDefAttr(BranchObj::NewBranch); - initLMO(); - if (!getHeading().isEmpty()) { - newbo->updateVisuals(); - newbo->setColor(heading.getColor()); - } + branchContainer->setPos(branchContainer->parentItem()->sceneTransform().inverted().map(sp)); +} - return newbo; +void BranchItem::addToBranchesContainer(BranchContainer *bc) +{ + branchContainer->addToBranchesContainer(bc); +} + +void BranchItem::addToImagesContainer(ImageContainer *ic) +{ + // Keep scene position while relinking image container + branchContainer->addToImagesContainer(ic); +} + +void BranchItem::repositionContainers() +{ + branchContainer->reposition(); } diff --git a/src/branchitem.h b/src/branchitem.h index c545aa1..7d01281 100644 --- a/src/branchitem.h +++ b/src/branchitem.h @@ -2,32 +2,34 @@ #define BRANCHITEM_H #include "mapitem.h" -#include "task.h" #include class QString; class QGraphicsScene; -class BranchObj; -class Link; -class XLinkItem; + +class BranchContainer; +class BranchWrapper; +class HeadingContainer; +class ImageContainer; +class Task; +class XLink; class BranchItem : public MapItem { public: - enum LayoutHint { AutoPositioning, FreePositioning }; - BranchItem(TreeItem *parent = nullptr); virtual ~BranchItem(); - virtual void clear(); virtual void copy(BranchItem *item); virtual BranchItem *parentBranch(); + BranchWrapper *branchWrapper(); + virtual void insertBranch(int pos, BranchItem *branch); + virtual void insertImage (int pos, ImageItem *image); virtual QString saveToDir(const QString &tmpdir, const QString &prefix, - const QPointF &offset, QList &tmpLinks); - - virtual void updateVisibility(); + const QPointF &offset, QList &tmpXLinks, + const bool &exportBoundingBoxes); virtual void setHeadingColor( QColor color); //! Overloaded from TreeItem to update QGraphicsView @@ -43,6 +45,7 @@ class BranchItem : public MapItem { private: Task *task; + BranchWrapper *branchWrapperInt; public: virtual void scroll(); @@ -50,32 +53,16 @@ class BranchItem : public MapItem { virtual bool toggleScroll(); // scroll or unscroll virtual bool isScrolled(); // returns scroll state virtual bool hasScrolledParent( - BranchItem *start = NULL); // true, if any of the parents is scrolled + BranchItem *start = nullptr); // true, if any of the parents is scrolled virtual bool tmpUnscroll( - BranchItem *start = NULL); // unscroll scrolled parents temporary e.g. + BranchItem *start = nullptr); // unscroll scrolled parents temporary e.g. // during "find" process virtual bool resetTmpUnscroll(); // scroll all tmp scrolled parents again // e.g. when unselecting - virtual void sortChildren(bool inverse = false); //! Sort children - virtual void setChildrenLayout(BranchItem::LayoutHint layoutHint); - virtual BranchItem::LayoutHint getChildrenLayout(); - - protected: - bool includeImagesVer; //! include floatimages in bbox vertically - bool includeImagesHor; //! include floatimages in bbox horizontally - bool includeChildren; //! include children in frame - LayoutHint childrenLayout; //! should children be positioned freely? public: - void setIncludeImagesVer(bool); - bool getIncludeImagesVer(); - void setIncludeImagesHor(bool); - bool getIncludeImagesHor(); - QString getIncludeImageAttr(); - BranchItem *getFramedParentBranch(BranchItem *start); - void setFrameIncludeChildren(bool); - bool getFrameIncludeChildren(); - + void setBranchesLayout(const QString &); + void setImagesLayout(const QString &); QColor getBackgroundColor(BranchItem *start, bool checkInnerFrame = true); protected: @@ -96,15 +83,29 @@ class BranchItem : public MapItem { public: TreeItem *findMapItem( QPointF p, - TreeItem *excludeTI); //! search map for branches or images. Ignore - //! excludeTI, where search is started + QList excludedItems); //! search map for branches or images. Ignore + //! excludeItems, where search is started or which are selected - virtual void - updateStyles(const bool &keepFrame = - false); //! update related fonts, parObjects, links, ... - virtual BranchObj *getBranchObj(); - virtual BranchObj *createMapObj( + + void setHideMode(HideTmpMode mode); + void updateVisuals(); + + BranchContainer *createBranchContainer( QGraphicsScene *scene); //! Create classic object in GraphicsView + + BranchContainer* getBranchContainer(); + void unlinkBranchContainer(); + Container* getBranchesContainer(); + Container* getImagesContainer(); + + private: + BranchContainer *branchContainer; + + public: + void updateContainerStackingOrder(); + void addToBranchesContainer(BranchContainer*); + void addToImagesContainer(ImageContainer*); + void repositionContainers(); }; #endif diff --git a/src/branchobj.cpp b/src/branchobj.cpp deleted file mode 100644 index ffae47b..0000000 --- a/src/branchobj.cpp +++ /dev/null @@ -1,672 +0,0 @@ -#include - -#include "branchobj.h" - -#include "attributeitem.h" -#include "branchitem.h" -#include "geometry.h" -#include "mainwindow.h" -#include "mapeditor.h" -#include "misc.h" - -extern FlagRowMaster *standardFlagsMaster; -extern FlagRowMaster *userFlagsMaster; -extern FlagRowMaster *systemFlagsMaster; -extern bool debug; -extern bool usingDarkTheme; - -///////////////////////////////////////////////////////////////// -// BranchObj -///////////////////////////////////////////////////////////////// - -BranchObj::BranchObj(QGraphicsItem *parent, TreeItem *ti) - : OrnamentedObj(parent, ti) -{ - // qDebug ()<< "Const BranchObj (s,ti) ti="<parent()); - if (pi && pi != ti->getModel()->getRootItem()) - parObj = pi->getLMO(); - else - parObj = NULL; - init(); -} - -BranchObj::~BranchObj() -{ - // qDebug()<< "Destr BranchObj of "<getModel(); - model->stopAnimation(this); - } - - clear(); -} - -void BranchObj::init() -{ - if (parObj) - absPos = parObj->getChildRefPos(); -} - -void BranchObj::copy(BranchObj *other) -{ - OrnamentedObj::copy(other); - - setVisibility(other->visible); - - positionBBox(); -} - -void BranchObj::clear() {} - -void BranchObj::setParObjTmp(LinkableMapObj *dst, QPointF m, int off) -{ - // Temporary link to dst - // m is position of mouse pointer - // offset 0: default 1: below dst -1 above dst (if possible) - - BranchItem *dsti = (BranchItem *)(dst->getTreeItem()); - - BranchItem *pi = (BranchItem *)(dsti->parent()); - int pi_depth = pi->depth(); - BranchObj *bodst = (BranchObj *)dst; - - if (!tmpParent) { - tmpParent = true; - parObjTmpBuf = parObj; - } - - if (pi_depth < 1) - off = 0; - if (off == 0) - link2ParPos = false; - else - link2ParPos = true; - parObj = bodst; - - setLinkStyle(dst->getDefLinkStyle(dsti)); - - // Move temporary to new position at destination - // Usually the positioning would be done by reposition(), - // but then also the destination branch would "Jump" around... - // Better just do it approximately - if (dsti->depth() == 0) { // new parent is a mapcenter - Vector v = (m - bodst->getChildRefPos()); - v.normalize(); - v.scale(150); - move2RelPos(v.toQPointF()); - } - else { - qreal y; - if (off == 0) { - // Below is needed e.g. in a freshly loaded map, - // bboxTotal seems not to be correct yet - // relinking positions too far below then - calcBBoxSizeWithChildren(); - - // new parent is just a branch, link to it - bodst->calcBBoxSizeWithChildren(); - QRectF t = bodst->getTotalBBox(); - if (dsti->getLastBranch()) - // Move below children of destination - y = t.y() + t.height(); - else - // Move left or right to destination - y = t.y(); - } - else { - if (off < 0) - // we want to link above dst - y = bodst->y() - height() + 12; - else - // we want to link below dst - // Bottom of sel should be 5 pixels above - // the bottom of the branch _below_ the target: - // Don't try to find that branch, guess 12 pixels - y = bodst->getChildRefPos().y() - height() + 12; - } - if (bodst->getOrientation() == LinkableMapObj::LeftOfCenter) - move(bodst->getChildRefPos().x() - linkwidth - bboxTotal.width(), - y); - else - move(bodst->getChildRefPos().x() + linkwidth, y); - } - - // updateLinkGeometry is called implicitly in move - requestReposition(); -} - -void BranchObj::unsetParObjTmp() -{ - if (tmpParent) { - tmpParent = false; - link2ParPos = false; - parObj = parObjTmpBuf; - parObjTmpBuf = NULL; - setLinkStyle(getDefLinkStyle(treeItem->parent())); - updateLinkGeometry(); - } -} - -void BranchObj::setVisibility(bool v, int toDepth) -{ - BranchItem *bi = (BranchItem *)treeItem; - if (bi->depth() <= toDepth) { - frame->setVisibility(v); - heading->setVisibility(v); - systemFlagRowObj->setVisibility(v); - standardFlagRowObj->setVisibility(v); - LinkableMapObj::setVisibility(v); - int i; - for (i = 0; i < treeItem->imageCount(); ++i) - treeItem->getImageObjNum(i)->setVisibility(v); - for (i = 0; i < treeItem->xlinkCount(); ++i) - treeItem->getXLinkObjNum(i)->setVisibility(); - - // Only change children, if I am not scrolled - if (!bi->isScrolled() && (bi->depth() < toDepth)) { - // Now go recursivly through all children - for (i = 0; i < treeItem->branchCount(); ++i) - treeItem->getBranchObjNum(i)->setVisibility(v, toDepth); - } - } -} - -void BranchObj::setVisibility(bool v) { setVisibility(v, MAX_DEPTH); } - -void BranchObj::positionContents() -{ - OrnamentedObj::positionContents(); - updateLinkGeometry(); // required before positioning images - for (int i = 0; i < treeItem->imageCount(); ++i) - treeItem->getImageObjNum(i)->reposition(); -} - -void BranchObj::move(double x, double y) { OrnamentedObj::move(x, y); } - -void BranchObj::move(QPointF p) { move(p.x(), p.y()); } - -void BranchObj::moveBy(double x, double y) -{ - OrnamentedObj::moveBy(x, y); - for (int i = 0; i < treeItem->branchCount(); ++i) - treeItem->getBranchObjNum(i)->moveBy(x, y); - positionBBox(); -} - -void BranchObj::moveBy(QPointF p) { moveBy(p.x(), p.y()); } - -void BranchObj::positionBBox() // FIXME-3 consider dimensions of frame - // (thickness, geometry, padding... -{ - QPointF ap = getAbsPos(); - bbox.moveTopLeft(ap); - positionContents(); // this positions FIOs - - // Update links to other branches - XLinkObj *xlo; - for (int i = 0; i < treeItem->xlinkCount(); ++i) { - xlo = treeItem->getXLinkObjNum(i); - if (xlo) - xlo->updateXLink(); - } -} - -void BranchObj::calcBBoxSize() -{ - QSizeF heading_r = heading->getSize(); - qreal heading_w = (qreal)heading_r.width(); - qreal heading_h = (qreal)heading_r.height(); - QSizeF sysflags_r = systemFlagRowObj->getSize(); - qreal sysflags_h = sysflags_r.height(); - qreal sysflags_w = sysflags_r.width(); - QSizeF stanflags_r = standardFlagRowObj->getSize(); - qreal stanflags_h = stanflags_r.height(); - qreal stanflags_w = stanflags_r.width(); - qreal w; - qreal h; - - // set width to sum of all widths - w = heading_w + sysflags_w + stanflags_w; - - // set height to maximum needed height - h = max(sysflags_h, stanflags_h); - h = max(h, heading_h); - - // Save the dimension of flags and heading - ornamentsBBox.setSize(QSizeF(w, h)); - - // clickBox includes Flags and Heading - clickPoly = QPolygonF(ornamentsBBox); - - // Floatimages - QPointF rp; - - topPad = botPad = leftPad = rightPad = 0; - bool incV = ((BranchItem *)treeItem)->getIncludeImagesVer(); - bool incH = ((BranchItem *)treeItem)->getIncludeImagesHor(); - if (incH || incV) { - FloatImageObj *fio; - for (int i = 0; i < treeItem->imageCount(); ++i) { - fio = treeItem->getImageObjNum(i); - rp = fio->getRelPos(); - if (incV) { - qreal y; - if (rp.y() > 0) { - y = rp.y() + fio->height() / 2 - ornamentsBBox.height() / 2; - botPad = max(botPad, y); - } - else { - y = -rp.y() + fio->height() / 2 - - ornamentsBBox.height() / 2; - topPad = max(topPad, y); - } - } - if (incH) { - qreal x; - if (rp.x() > 0) { - x = rp.x() + fio->width() / 2 - ornamentsBBox.width() / 2; - rightPad = max(rightPad, x); - } - else { - x = -rp.x() + fio->width() / 2 - ornamentsBBox.width() / 2; - leftPad = max(leftPad, x); - } - } - } - h += topPad + botPad; - w += leftPad + rightPad; - } - - // Frame thickness - w += frame->getTotalPadding() * 2; - h += frame->getTotalPadding() * 2; - - // Finally set size - bbox.setSize(QSizeF(w, h)); - // if (debug) qDebug()<<"BO: calcBBox "<getHeading()<<" - // bbox="<getType() == TreeItem::MapCenter) { - // set childRefPos to middle of MapCenterObj - QRectF r = clickPoly.boundingRect(); - childRefPos.setX(r.topLeft().x() + r.width() / 2); - childRefPos.setY(r.topLeft().y() + r.height() / 2); - parPos = childRefPos; - for (int i = 0; i < treeItem->branchCount(); ++i) - treeItem->getBranchObjNum(i)->updateLinkGeometry(); - } - else { - if (orientation == LinkableMapObj::LeftOfCenter) { - // Left of center - if (((BranchItem *)treeItem)->getFrameIncludeChildren()) { - childRefPos = QPointF(ornamentsBBox.bottomLeft().x() - leftPad, - bottomlineY); - parPos = QPointF(bboxTotal.bottomRight().x() - - frame->getPadding() / 2, - bottomlineY); - } - else { - childRefPos = QPointF(ornamentsBBox.bottomLeft().x() - - frame->getPadding(), - bottomlineY); - parPos = QPointF(ornamentsBBox.bottomRight().x(), bottomlineY); - } - } - else { - // Right of center - if (((BranchItem *)treeItem)->getFrameIncludeChildren()) { - childRefPos = QPointF( - ornamentsBBox.bottomRight().x() + rightPad, bottomlineY); - parPos = QPointF(bboxTotal.bottomLeft().x() + - frame->getPadding() / 2, - bottomlineY); - } - else { - childRefPos = QPointF(ornamentsBBox.bottomRight().x() + - frame->getPadding(), - bottomlineY); - parPos = QPointF(ornamentsBBox.bottomLeft().x(), bottomlineY); - } - } - } -} - -void BranchObj::updateVisuals() -{ - if (!treeItem) { - qWarning("BranchObj::udpateHeading treeItem==NULL"); - return; - } - QString s = treeItem->getHeadingText(); - if (s != heading->text()) - heading->setText(s); - - // Update standard flags active in TreeItem - QList TIactiveFlagUids = treeItem->activeFlagUids(); - standardFlagRowObj->updateActiveFlagObjs( - TIactiveFlagUids, standardFlagsMaster, userFlagsMaster); - - // Add missing system flags active in TreeItem - TIactiveFlagUids = treeItem->activeSystemFlagUids(); - systemFlagRowObj->updateActiveFlagObjs(TIactiveFlagUids, systemFlagsMaster); - - calcBBoxSize(); -} - -void BranchObj::setDefAttr(BranchModification mod, bool keepFrame) -{ - - // Note: not needed in 3.x.0 versions, - // where MapDesign will be used - QFont font = treeItem->getModel()->getMapDefaultFont(); - qreal fontsize = font.pointSizeF(); - switch (treeItem->depth()) { - case 0: - break; - case 1: - fontsize = fontsize - 2; - break; - case 2: - fontsize = fontsize - 4; - break; - default: - fontsize = fontsize - 6; - break; - } - setLinkStyle(getDefLinkStyle(treeItem->parent())); - setLinkColor(); - font.setPointSizeF(fontsize); - heading->setFont(font); - - if (mod == NewBranch && !keepFrame) { - if (treeItem->depth() == 0) { - setFrameType(FrameObj::RoundedRectangle); - setFrameBorderWidth(2); - if (usingDarkTheme) { - setFramePenColor(QColor(Qt::white)); - setFrameBrushColor(QColor(85, 85, 127)); - treeItem->setHeadingColor(QColor(Qt::white)); - } else { - setFramePenColor(QColor(Qt::black)); - setFrameBrushColor(QColor(Qt::white)); - } - } else - setFrameType(FrameObj::NoFrame); - } - if (mod == NewBranch) - setColor(treeItem->getHeadingColor()); - else { - // Relinked mapcenters - if (!keepFrame && getFrameType() != FrameObj::NoFrame) - setFrameType(FrameObj::NoFrame); - - // Also set styles for children - for (int i = 0; i < treeItem->branchCount(); ++i) - treeItem->getBranchObjNum(i)->setDefAttr(MovedBranch, keepFrame); - } - calcBBoxSize(); -} - -void BranchObj::alignRelativeTo(QPointF ref, bool alignSelf) -{ - // Define some heights - qreal th = bboxTotal.height(); - qreal ch = 0; // Sum of childrens heights - for (int i = 0; i < treeItem->branchCount(); ++i) - ch += treeItem->getBranchObjNum(i)->getTotalBBox().height(); - - int depth = 0; - BranchItem::LayoutHint layoutHint = BranchItem::AutoPositioning; - if (parObj) { - TreeItem *pi = parObj->getTreeItem(); - depth = 1 + pi->depth(); - layoutHint = - ((BranchItem *)treeItem)->parentBranch()->getChildrenLayout(); - } - - // set useRelPos, depending on layout - if (depth > 1) { - if (layoutHint == BranchItem::FreePositioning) { - if (!useRelPos) { - useRelPos = true; - // if we used relPos before, set known positions - // "known" means any position != (0,0) - if (relPos == QPointF(0, 0)) - // use current position to get relPos() - setRelPos(); - } - } - else - useRelPos = false; - } - - // TODO testing - /* - if (debug) - { - QString o; - switch (orientation) - { - case UndefinedOrientation: o = "UndefOrientation"; break; - case LeftOfCenter: o = "LeftOfCenter"; break; - case RightOfCenter: o = "RightOfCenter"; break; - } - - QString h=QString (depth+1,' '); - h += treeItem->getHeadingPlain(); - h += QString (25,' '); - h.truncate (25); - QPointF pp; - if (parObj) pp = parObj->getChildRefPos(); - qDebug() << "BO::alignRelTo for "<
    " "Please allow vym to check for updates :-)"); - QMessageBox mb(vymName, infotext, QMessageBox::Information, - QMessageBox::Yes | QMessageBox::Default, - QMessageBox::No | QMessageBox::Escape, - QMessageBox::NoButton); - - mb.setButtonText(QMessageBox::Yes, tr("Allow")); - mb.setButtonText(QMessageBox::No, tr("Do not allow")); - switch (mb.exec()) { - case QMessageBox::Yes: { + QMessageBox mb(QMessageBox::Information, vymName, infotext); + QPushButton *allowButton = mb.addButton(tr("Allow"), QMessageBox::AcceptRole); + mb.addButton(tr("Do not allow"), QMessageBox::RejectRole); + mb.setDefaultButton(allowButton); + mb.exec(); + if (mb.clickedButton() == allowButton) { result = true; QMessageBox msgBox; msgBox.setText(tr("Thank you for enabling downloads!")); msgBox.setStandardButtons(QMessageBox::Close); msgBox.setIconPixmap(QPixmap(":/flag-face-smile.svg")); msgBox.exec(); - break; - } - default: + } else { result = false; QMessageBox msgBox; msgBox.setText(tr("That's ok, though I would be happy to see many users working with vym and also on which platforms.")); msgBox.setStandardButtons(QMessageBox::Close); msgBox.setIconPixmap(QPixmap(":/flag-face-sad.svg")); msgBox.exec(); - break; } - } - else + } else result = false; actionSettingsToggleDownloads->setChecked(result); settings.setValue("/downloads/enabled", result); @@ -7371,7 +8007,6 @@ bool Main::downloadsEnabled(bool userTriggered) void Main::downloadUpdatesFinished(bool userTriggered) { DownloadAgent *agent = static_cast(sender()); - QString s; if (agent->isSuccess()) { ShowTextDialog dia; @@ -7493,4 +8128,13 @@ void Main::togglePresentationMode() } menuBar()->show(); } + +} + +void Main::toggleHideTmpMode() +{ + VymModel *m = currentModel(); + if (m) + m->toggleHideTmpMode(); } + diff --git a/src/mainwindow.h b/src/mainwindow.h index 22cb89c..37ee69b 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -1,23 +1,27 @@ #ifndef MAINWINDOW_H #define MAINWINDOW_H +#include +#include #include -#include #include -#include -#include -#include #include -#include "branchpropeditor.h" -#include "extrainfodialog.h" #include "file.h" #include "flag.h" -#include "historywindow.h" -#include "mapeditor.h" -#include "scripting.h" -#include "texteditor.h" -#include "vymview.h" + +#include "settings.h" + +class QPrinter; +class QJSEngine; + +class HistoryWindow; +class MapEditor; +class TreeItem; +class VymText; +class VymModel; +class VymView; +class VymWrapper; class Main : public QMainWindow { Q_OBJECT @@ -45,7 +49,8 @@ class Main : public QMainWindow { int progressCounterTotal; public: - void statusMessage(const QString &); + void logInfo(const QString &comment, const QString &caller = ""); + void statusMessage(const QString &, int timeout = 10000); void setProgressMaximum(int max); void addProgressValue(float v); void initProgressCounter(uint n = 1); @@ -100,12 +105,12 @@ class Main : public QMainWindow { public: MapEditor *currentMapEditor() const; VymModel *currentModel() const; - uint currentMapID() const; + uint currentMapId() const; int currentMapIndex() const; VymModel *getModel(uint); - void gotoModel(VymModel *m); - void gotoModelWithID(uint id); - bool closeModelWithID(uint id); + bool gotoModel(VymModel *m); + bool gotoModelWithId(uint id); + bool closeModelWithId(uint id); int modelCount(); void updateTabName(VymModel *vm); @@ -113,8 +118,8 @@ class Main : public QMainWindow { void editorChanged(); public slots: - File::ErrorCode fileLoad(QString, const LoadMode &, const FileType &ftype); - void fileLoad(const LoadMode &); + bool fileLoad(QString, const File::LoadMode &, const File::FileType &ftype); + void fileLoad(const File::LoadMode &); private slots: void fileLoad(); void fileSaveSession(); @@ -122,17 +127,19 @@ class Main : public QMainWindow { void fileRestoreSession(); private slots: void fileLoadRecent(); + void fileClearRecent(); void addRecentMap(const QString &); - void fileSave(VymModel *, const SaveMode &); + void fileSave(VymModel *, const File::SaveMode &); void fileSave(); public slots: void fileSave(VymModel *); // autosave from MapEditor private slots: void fileSaveAs(); - void fileSaveAs(const SaveMode &); + void fileSaveAs(const File::SaveMode &); void fileSaveAsDefault(); void fileImportFirefoxBookmarks(); void fileImportFreemind(); + void fileImportIThoughts(); void fileImportMM(); void fileImportDir(); void fileExportAO(); @@ -149,7 +156,7 @@ class Main : public QMainWindow { void fileExportOrgMode(); void fileExportPDF(); void fileExportSVG(); - void fileExportTaskjuggler(); + void fileExportTaskJuggler(); void fileExportXML(); void fileExportLast(); bool fileCloseMap(int i = -1); // Optionally pass number of tab @@ -179,8 +186,10 @@ class Main : public QMainWindow { void editURL(); void editLocalURL(); void editHeading2URL(); + void setJiraQuery(); void getJiraDataSubtree(); - void setHeadingConfluencePageName(); + void getConfluencePageDetails(); + void getConfluencePageDetailsRecursively(); void getConfluenceUser(); void openVymLinks(const QStringList &, bool background = false); void editVymLink(); @@ -211,16 +220,15 @@ class Main : public QMainWindow { void editExpandOneLevel(); void editCollapseOneLevel(); void editCollapseUnselected(); - void editUnscrollChildren(); + void editUnscrollSubtree(); void editGrowSelectionSize(); void editShrinkSelectionSize(); void editResetSelectionSize(); - void editAddAttribute(); void editAddMapCenter(); - void editNewBranch(); - void editNewBranchBefore(); - void editNewBranchAbove(); - void editNewBranchBelow(); + void editAddBranch(); + void editAddBranchBefore(); + void editAddBranchAbove(); + void editAddBranchBelow(); void editImportAdd(); void editImportReplace(); void editSaveBranch(); @@ -267,8 +275,7 @@ class Main : public QMainWindow { void formatLinkStyleParabel(); void formatLinkStylePolyLine(); void formatLinkStylePolyParabel(); - void formatSelectBackColor(); - void formatSelectBackImage(); + void formatBackground(); void formatSelectLinkColor(); void formatSelectSelectionColor(); void formatSelectFont(); @@ -283,14 +290,15 @@ class Main : public QMainWindow { void viewRotateClockwise(); void viewCenter(); void viewCenterScaled(); + void viewCenterRotated(); public slots: void networkStartServer(); void networkConnect(); void downloadFinished(); - bool settingsPDF(); - bool settingsURL(); - void settingsZipTool(); + void settingsPDF(); + void settingsURL(); + void settingsActionLog(); void settingsMacroPath(); void settingsUndoLevels(); void settingsDefaultMapPath(); @@ -315,9 +323,11 @@ class Main : public QMainWindow { bool settingsJIRA(); void windowToggleNoteEditor(); - void windowToggleTreeEditor(); + void windowToggleTreeEditors(); + void windowSetTreeEditorsVisibility(bool); void windowToggleTaskEditor(); - void windowToggleSlideEditor(); + void windowToggleSlideEditors(); + void windowSetSlideEditorsVisibility(bool); void windowToggleScriptEditor(); void windowToggleScriptOutput(); void windowToggleHistory(); @@ -333,7 +343,7 @@ class Main : public QMainWindow { void updateHeading(const VymText &vt); void updateNoteText(const VymText &vt); void updateNoteEditor(TreeItem *ti); - void updateHeadingEditor(BranchItem *bi = nullptr); + void updateHeadingEditor(TreeItem *ti = nullptr); void selectInNoteEditor(QString s, int i); void setFocusMapEditor(); void changeSelection(VymModel *model, const QItemSelection &newSel, @@ -343,7 +353,18 @@ class Main : public QMainWindow { void updateActions(); ModMode getModMode(); bool autoSelectNewBranch(); + + void scriptPrint(const QString &, const QString &color = ""); QVariant runScript(const QString &); + void abortScript(const QJSValue::ErrorType &err, const QString &msg); + void abortScript(const QString &msg); + QVariant setScriptResult(const QVariant &r); + + private: + QJSEngine *scriptEngine; + QVariant scriptResult; + + public slots: QObject *getCurrentModelWrapper(); bool gotoWindow(const int &n); @@ -365,11 +386,13 @@ class Main : public QMainWindow { void helpDemo(); void helpShortcuts(); void helpMacros(); + public: + QString scriptingCommands(); + private slots: void helpScriptingCommands(); void helpDebugInfo(); void helpAbout(); void helpAboutQT(); - void callMacro(); void downloadReleaseNotesFinished(); @@ -389,6 +412,7 @@ class Main : public QMainWindow { void checkUpdates(); void escapePressed(); void togglePresentationMode(); + void toggleHideTmpMode(); private: QString shortcutScope; //! For listing shortcuts @@ -397,9 +421,7 @@ class Main : public QMainWindow { QStringList imageTypes; - QScriptEngine scriptEngine; - - QString prevSelection; + QUuid prevSelection; HistoryWindow *historyWindow; @@ -422,6 +444,7 @@ class Main : public QMainWindow { QList actionListFiles; //! File related actions, e.g. load, save, //! restore session QList actionListBranches; + QList actionListImages; QList actionListItems; int xLinkMenuWidth; @@ -429,6 +452,7 @@ class Main : public QMainWindow { QMenu *recentFilesMenu; enum { MaxRecentFiles = 20 }; QAction *recentFileActions[MaxRecentFiles]; + QAction *actionRecentFilesClear; QAction *macroActions[48]; QStringList macro; @@ -436,6 +460,7 @@ class Main : public QMainWindow { QList quickColors; QMenu *toolbarsMenu; + QMenu *windowsMenu; QToolBar *fileToolbar; QToolBar *clipboardToolbar; QToolBar *editActionsToolbar; @@ -455,9 +480,12 @@ class Main : public QMainWindow { QAction *actionFileNew; QAction *actionFileNewCopy; QAction *actionFileOpen; + QAction *actionFileClose; QAction *actionFileRestoreSession; QAction *actionFileSave; QAction *actionFilePrint; + QAction *actionFileExitVym; + QAction *actionClearRecent; QAction *actionMapProperties; QAction *actionFileExportLast; QAction *actionFileExportConfluence; @@ -487,7 +515,8 @@ class Main : public QMainWindow { QAction *actionLocalURL; QAction *actionHeading2URL; QAction *actionGetJiraDataSubtree; - QAction *actionGetConfluencePageName; + QAction *actionGetConfluencePageDetails; + QAction *actionGetConfluencePageDetailsRecursively; QAction *actionOpenVymLink; QAction *actionOpenVymLinkBackground; QAction *actionOpenMultipleVymLinks; @@ -496,6 +525,7 @@ class Main : public QMainWindow { QAction *actionAddTimestamp; QAction *actionToggleTask; QAction *actionTogglePresentationMode; + QAction *actionToggleHideTmpMode; QAction *actionCycleTaskStatus; QAction *actionTaskResetDeltaPrio; QAction *actionTaskSleep0; @@ -513,7 +543,6 @@ class Main : public QMainWindow { QAction *actionHeading; QAction *actionDelete; QAction *actionDeleteAlt; - QAction *actionAddAttribute; public: QAction *actionAddMapCenter; @@ -549,8 +578,7 @@ class Main : public QMainWindow { QAction *actionFormatColorBranch; QAction *actionFormatColorSubtree; QAction *actionFormatLinkColorHint; - QAction *actionFormatBackColor; - QAction *actionFormatBackImage; + QAction *actionFormatBackground; QAction *actionFormatLinkColor; QAction *actionFormatSelectionColor; QAction *actionFormatFont; @@ -561,7 +589,8 @@ class Main : public QMainWindow { QAction *actionRotateCounterClockwise; QAction *actionRotateClockwise; QAction *actionCenterOn; - QAction *actionFitToSelection; + QAction *actionCenterOnScaled; + QAction *actionCenterOnRotated; QActionGroup *actionGroupModModes; QAction *actionModModePoint; @@ -586,9 +615,13 @@ class Main : public QMainWindow { QAction *actionViewToggleNoteEditor; QAction *actionViewToggleHeadingEditor; - QAction *actionViewToggleTreeEditor; QAction *actionViewToggleTaskEditor; + + public: // Allow VymView class to check visibility + QAction *actionViewToggleTreeEditor; QAction *actionViewToggleSlideEditor; + + private: QAction *actionViewToggleScriptEditor; QAction *actionViewToggleScriptOutput; QAction *actionViewToggleHistoryWindow; diff --git a/src/mapdesign.cpp b/src/mapdesign.cpp new file mode 100644 index 0000000..bdba73a --- /dev/null +++ b/src/mapdesign.cpp @@ -0,0 +1,718 @@ +#include "mapdesign.h" + +#include +#include + +#include "branch-container.h" +#include "branchitem.h" +#include "file.h" +#include "heading-container.h" +#include "misc.h" + +extern bool usingDarkTheme; + +template ConfigList & ConfigList::operator<<(const T &other) { + qlist << other; + return *this; +} + +template T & ConfigList::operator[](int i) { + if (i >= 0 && i < qlist.count()) + return qlist.at(i); +} + +template T ConfigList::tryAt(int i) { + if (i >= qlist.count()) + return qlist.last(); + else + return qlist.at(i); +} + +template void ConfigList::setAt(int i, const T &val) { + if (i <= 0) { + // Set val for first level and clear all others + qlist.clear(); + qlist << val; + } else if (i >= qlist.count()) { + // Fill all values between last and new one with last one + for (int j = qlist.count(); j < i; j++) + qlist << qlist.last(); + qlist << val; + } else + qlist.replace(i, val); + +} + +template int ConfigList::count() { + return qlist.count(); +} + +template void ConfigList::clear() { + qlist.clear(); +} + +template QString ConfigList::save( + const QString &attrName, + QString (&f)(int)) { + XMLObj xml; + QString s; + for (int i = 0; i < qlist.size(); ++i) + s += xml.singleElement("md", + xml.attribute( "key", attrName) + + xml.attribute( "d", QString("%1").arg(i)) + + xml.attribute( "val", f(qlist.at(i))) + ); + return s; +} + +template QString ConfigList::saveBool( + const QString &attrName) { + XMLObj xml; + QString s; + for (int i = 0; i < qlist.size(); ++i) + s += xml.singleElement("md", + xml.attribute( "key", attrName) + + xml.attribute( "d", QString("%1").arg(i)) + + xml.attribute( "val", toS(qlist.at(i))) + ); + return s; +} + +template QString ConfigList::saveColor( + const QString &attrName) { + XMLObj xml; + QString s; + for (int i = 0; i < qlist.size(); ++i) + s += xml.singleElement("md", + xml.attribute( "key", attrName) + + xml.attribute( "d", QString("%1").arg(i)) + + xml.attribute( "val", qlist.at(i).name(QColor::HexArgb)) + ); + return s; +} + +template QString ConfigList::saveInt( + const QString &attrName) { + XMLObj xml; + QString s; + for (int i = 0; i < qlist.size(); ++i) + s += xml.singleElement("md", + xml.attribute( "key", attrName) + + xml.attribute( "d", QString("%1").arg(i)) + + xml.attribute( "val", QString("%1").arg(qlist.at(i))) + ); + return s; +} + +/* +FIXME-3 currently not used template void ConfigList::setDefault(const T &d) { + defaultValue = d; +} +*/ + +///////////////////////////////////////////////////////////////// +// MapDesign +///////////////////////////////////////////////////////////////// + +MapDesign::MapDesign() // FIXME-1 add options to update styles when relinking (Triggers, Actors) + // Triggers: Never, DepthChanged, Always + // Actors: Inner/Outer-Frames,Fonts,HeadingColor,Rotation Heading/Subtree, ... +{ + // qDebug() << "Constr. MapDesign"; + init(); +} + +void MapDesign::init() +{ + // + // Design elements not depending on depth, incl. legacy map attributes + // + + // Background + usesBackgroundImage = false; + + innerFramePenWidths << 2; + outerFramePenWidths << 2; + + // Colors + if (usingDarkTheme) { + QPalette palette = qApp->palette(); + backgroundColorInt = QColor(palette.color(QPalette::Base)); + + innerFramePenColors << QColor(Qt::white); + innerFrameBrushColors << QColor(85, 85, 127); + + innerFramePenColors << QColor(Qt::blue); + innerFrameBrushColors << QColor(25, 25, 127); + + outerFramePenColors << QColor(Qt::green); + outerFramePenColors << QColor(Qt::red); + outerFramePenColors << QColor(Qt::green); + outerFramePenColors << QColor(Qt::red); + outerFrameBrushColors << QColor(85, 85, 127); + outerFrameBrushColors << QColor(25, 25, 117); + outerFrameBrushColors << QColor(85, 85, 127); + outerFrameBrushColors << QColor(25, 25, 117); + } else { + backgroundColorInt = QColor(Qt::white); + innerFramePenColors << QColor(Qt::black); + innerFrameBrushColors << QColor(Qt::white); + outerFramePenColors << QColor(Qt::green); + outerFrameBrushColors << QColor(85, 85, 127); + } + + // Font + fontInt.setPointSizeF(16); + + // Dimensions + headingColumnWidths << 42; + + // Selection + selectionPenInt = QPen(QColor(255,255,0,255), 3); + selectionBrushInt = QBrush(QColor(255,255,0,120)); + + // Should links of branches use a default color or the color of heading? + linkColorHintInt = LinkObj::DefaultColor; + defaultLinkCol = Qt::blue; + + // XLinks + defXLinkPenInt.setWidth(1); + defXLinkPenInt.setColor(QColor(50, 50, 255)); + defXLinkPenInt.setStyle(Qt::DashLine); + defXLinkStyleBeginInt = "HeadFull"; + defXLinkStyleEndInt = "HeadFull"; + + // + // Design elements depending on depth + // + + // Layout of children branches + branchesContainerLayouts << Container::FloatingBounded; + branchesContainerLayouts << Container::Vertical; + + // Layout of children images + imagesContainerLayouts << Container::GridColumns; + imagesPositionsInt << ImagesPositionHint::VerticalAboveBranches; + + // Layout children branches above/below heading or side by side? + branchesContainerAndOrnamentsVerticalInt << false; + branchesContainerVerticalAlignmentsInt << Container::VertAlignedCentered; + + // Heading colors + headingColorHints << MapDesign::SpecificColor; // Specific for MapCenter + headingColorHints << MapDesign::InheritedColor; // Use color of parent + headingColorUpdateWhenRelinking << false; + + headingColors << QColor(Qt::white); + headingColors << QColor(Qt::green); + + // Frames + innerFrameTypes << FrameContainer::RoundedRectangle; + innerFrameTypes << FrameContainer::Rectangle; + innerFrameTypes << FrameContainer::NoFrame; + innerFramePenWidths << 2; + innerFrameUpdateWhenRelinking << true; // MapCenters inner frame + innerFrameUpdateWhenRelinking << true; // Mainbranches inner frame + innerFrameUpdateWhenRelinking << false; + + outerFrameTypes << FrameContainer::NoFrame; + /* + outerFrameTypes << FrameContainer::Rectangle; + outerFrameTypes << FrameContainer::RoundedRectangle; + outerFrameTypes << FrameContainer::Rectangle; + outerFrameTypes << FrameContainer::Rectangle; + outerFrameTypes << FrameContainer::NoFrame; + */ + outerFrameUpdateWhenRelinking << true; // MapCenters outer frame + outerFrameUpdateWhenRelinking << false; + + outerFrameTypes << FrameContainer::NoFrame; + /* + outerFramePenColors; + outerFrameBrushColors; + outerFramePenWidths; + */ + + // Transformations + rotationHeadingInt << 0; + //rotationHeadingInt << 20; + //rotationHeadingInt << 20; + + rotationSubtreeInt << 0; + + scaleHeadingInt << 1.3; + scaleHeadingInt << 1.0; + scaleHeadingInt << 0.8; + + scaleSubtreeInt << 1.0; + + // Links + linkStyles << LinkObj::NoLink; + linkStyles << LinkObj::PolyParabel; + linkStyles << LinkObj::Parabel; +} + +void MapDesign::setName(const QString &s) +{ + name = s; +} + +QString MapDesign::getName() +{ + return name; +} + +QString MapDesign::updateModeString(const UpdateMode &mode) +{ + switch (mode) { + case Undefined: + return "Update mode Undefined!"; + case LoadingMap: + return "LoadingMap"; + case CreatedByUser: + return "CreatedByUser"; + case RelinkedByUser: + return "RelinkedByUser"; + case LayoutChanged: + return "LayoutChanged"; + case LinkStyleChanged: + return "LinkStyleChanged"; + case StyleChanged: + return "StyleChanged"; + case AutoDesign: + return "AutoDesign"; + default: + return QString("Unknown update mode: %1").arg(mode); + } +} + +bool MapDesign::setElement(const QString &key, const QString &val, const QString &d) // FIXME-3 should also return undo/redo commands to VymModel, if called from there? +{ + //qDebug() << "MD::setElement k=" << key << " v=" << val << " d=" << d; + + int depth; + bool ok; + + depth = d.toInt(&ok); + if (!ok) { + qWarning() << "MD::setElement k=" << key << " v=" << val << " Failed to parse d=" << d; + return false; + } + + if (key == "branchesLayout") { + branchesContainerLayouts.setAt(depth, Container::layoutFromString(val)); + return true; + } else if (key == "childrenAndHeadingVertical") { + branchesContainerAndOrnamentsVerticalInt.setAt(depth, QVariant(val).toBool()); + return true; + } else if (key == "childrenVertAlignment") { + branchesContainerVerticalAlignmentsInt.setAt(depth, Container::verticalAlignmentFromString(val)); + return true; + } else if (key == "imagesLayout") { + imagesContainerLayouts.setAt(depth, Container::layoutFromString(val)); + return true; + } else if (key == "innerFrameType") { + innerFrameTypes.setAt(depth, FrameContainer::frameTypeFromString(val)); + return true; + } else if (key == "innerFrameBrushColor") { + innerFrameBrushColors.setAt(depth, QColor(val)); + return true; + } else if (key == "innerFramePenColor") { + innerFramePenColors.setAt(depth, QColor(val)); + return true; + } else if (key == "innerFramePenWidth") { + innerFramePenWidths.setAt(depth, val.toInt()); + return true; + } else if (key == "innerFrameUpdateWhenRelinking") { + innerFrameUpdateWhenRelinking.setAt(depth, QVariant(val).toBool()); + return true; + } else if (key == "outerFrameType") { + outerFrameTypes.setAt(depth, FrameContainer::frameTypeFromString(val)); + return true; + } else if (key == "outerFrameBrushColor") { + outerFrameBrushColors.setAt(depth, QColor(val)); + return true; + } else if (key == "outerFramePenColor") { + outerFramePenColors.setAt(depth, QColor(val)); + return true; + } else if (key == "outerFramePenWidth") { + outerFramePenWidths.setAt(depth, val.toInt()); + return true; + } else if (key == "outerFrameUpdateWhenRelinking") { + outerFrameUpdateWhenRelinking.setAt(depth, QVariant(val).toBool()); + return true; + } else if (key == "linkStyle") { + auto style = LinkObj::styleFromString(val); + linkStyles.setAt(depth, style); + return true; + } + + return false; +} + +Container::Layout MapDesign::branchesContainerLayout(int depth) +{ + return branchesContainerLayouts.tryAt(depth); +} + +Container::VerticalAlignment MapDesign::branchesContainerVerticalAlignment(int depth) +{ + return branchesContainerVerticalAlignmentsInt.tryAt(depth); +} + +Container::Layout MapDesign::imagesContainerLayout(int depth) +{ + return imagesContainerLayouts.tryAt(depth); +} + +bool MapDesign::branchesContainerAndOrnamentsVertical(int depth) +{ + return branchesContainerAndOrnamentsVerticalInt.tryAt(depth); +} + +MapDesign::ImagesPositionHint MapDesign::imagesPosition(int depth) +{ + return imagesPositionsInt.tryAt(depth); +} + +LinkObj::ColorHint MapDesign::linkColorHint() +{ + return linkColorHintInt; +} + +void MapDesign::setLinkColorHint(const LinkObj::ColorHint &lch) +{ + linkColorHintInt = lch; +} + +QColor MapDesign::defaultLinkColor() +{ + return defaultLinkCol; +} + +void MapDesign::setDefaultLinkColor(const QColor &col) +{ + defaultLinkCol = col; +} + +LinkObj::Style MapDesign::linkStyle(int depth) +{ + return linkStyles.tryAt(depth); +} + +void MapDesign::setLinkStyle(LinkObj::Style style, int depth) +{ + linkStyles.setAt(depth, style); +} + +qreal MapDesign::linkWidth() +{ + return 20; +} + +void MapDesign::setDefXLinkPen(const QPen &p) +{ + defXLinkPenInt = p; +} + +QPen MapDesign::defXLinkPen() +{ + return defXLinkPenInt; +} + +void MapDesign::setDefXLinkStyleBegin(const QString &s) +{ + defXLinkStyleBeginInt = s; +} + +QString MapDesign::defXLinkStyleBegin() +{ + return defXLinkStyleBeginInt; +} + +void MapDesign::setDefXLinkStyleEnd(const QString &s) +{ + defXLinkStyleEndInt = s; +} + +QString MapDesign::defXLinkStyleEnd() +{ + return defXLinkStyleEndInt; +} + + +void MapDesign::setBackgroundColor(const QColor &col) +{ + backgroundColorInt = col; + usesBackgroundImage = false; +} + +QColor MapDesign::backgroundColor() +{ + return backgroundColorInt; +} + +bool MapDesign::loadBackgroundImage(const QString &fileName) +{ + backgroundImage.load(fileName); + if (backgroundImage.isNull()) { + usesBackgroundImage = false; + return false; + } + + usesBackgroundImage = true; + backgroundImageBrushInt.setTextureImage(backgroundImage); + + return true; +} + +bool MapDesign::saveBackgroundImage(const QString &imagePath) +{ + return backgroundImage.save(imagePath, "PNG", 100); +} + +void MapDesign::setBackgroundImageName(const QString &n) +{ + backgroundImageNameInt = n; +} + +void MapDesign::unsetBackgroundImage() +{ + usesBackgroundImage = false; + backgroundImageNameInt.clear(); +} + +bool MapDesign::hasBackgroundImage() +{ + return usesBackgroundImage; +} + +QString MapDesign::backgroundImageName() +{ + return backgroundImageNameInt; +} + +QBrush MapDesign::backgroundImageBrush() +{ + return backgroundImageBrushInt; +} + + +QFont MapDesign::font() +{ + return fontInt; +} + +void MapDesign::setFont(const QFont &f) +{ + fontInt = f; +} + +int MapDesign::headingColumnWidth(const int &depth) +{ + return headingColumnWidths.tryAt(depth); +} + +QColor MapDesign::headingColor( + const MapDesign::UpdateMode &updateMode, + BranchItem *branchItem, + bool &updateRequired) +{ + updateRequired = false; + QColor col; + + if (!branchItem) return col; + + int depth = branchItem->depth(); + if (updateMode == CreatedByUser || + (updateMode == RelinkedByUser && headingColorUpdateWhenRelinking.tryAt(depth))) + { + HeadingColorHint colHint = headingColorHints.tryAt(depth); + + switch (colHint) { + case InheritedColor: { + BranchItem *pbi = branchItem->parentBranch(); + if (pbi) { + col = pbi->headingColor(); + //qDebug() << " - Inherited color: " << col.name(); + break; + } + // If there is no parent branch, mapCenter should + // have a specific color, thus continue + } + case SpecificColor: { + col = headingColors.tryAt(depth); + //qDebug() << " - SpecificColor:" << col.name(); + break; + } + case UnchangedColor: + //qDebug() << " - UnchangedColor"; + break; + default: + qWarning() << "MapDesign::branchHeadingColor no branchHeadingColorHint defined"; + } + if (col != branchItem->headingColor()) + updateRequired = true; + } + return col; +} + +FrameContainer::FrameType MapDesign::frameType(bool useInnerFrame, const int &depth) +{ + if (useInnerFrame) + return innerFrameTypes.tryAt(depth); + else + return outerFrameTypes.tryAt(depth); +} + +QColor MapDesign::frameBrushColor( bool useInnerFrame, const int &depth) +{ + if (useInnerFrame) + return innerFrameBrushColors.tryAt(depth); + else + return outerFrameBrushColors.tryAt(depth); +} + +QColor MapDesign::framePenColor( bool useInnerFrame, const int &depth) +{ + if (useInnerFrame) + return innerFramePenColors.tryAt(depth); + else + return outerFramePenColors.tryAt(depth); +} + +int MapDesign::framePenWidth( bool useInnerFrame, const int &depth) +{ + if (useInnerFrame) + return innerFramePenWidths.tryAt(depth); + else + return outerFramePenWidths.tryAt(depth); +} + +bool MapDesign::updateFrameWhenRelinking(bool useInnerFrame, const int &depth) +{ + if (useInnerFrame) + return innerFrameUpdateWhenRelinking.tryAt(depth); + else + return outerFrameUpdateWhenRelinking.tryAt(depth); +} + +QPen MapDesign::selectionPen() +{ + return selectionPenInt; +} + +void MapDesign::setSelectionPen(const QPen &p) +{ + selectionPenInt = p; +} + +QBrush MapDesign::selectionBrush() +{ + return selectionBrushInt; +} + +void MapDesign::setSelectionBrush(const QBrush &b) +{ + selectionBrushInt = b; +} + +int MapDesign::rotationHeading(const int &depth) +{ + return rotationHeadingInt.tryAt(depth); +} + +int MapDesign::rotationSubtree(const int &depth) +{ + return rotationSubtreeInt.tryAt(depth); +} + +qreal MapDesign::scaleHeading(const int &depth) +{ + return scaleHeadingInt.tryAt(depth); +} + +qreal MapDesign::scaleSubtree(const int &depth) +{ + return scaleSubtreeInt.tryAt(depth); +} + +QString MapDesign::saveToDir(const QString &tmpdir, const QString &prefix) +{ + XMLObj xml; + QString s; + + xml.incIndent(); + s += xml.beginElement("mapdesign"); + + xml.incIndent(); + s += xml.singleElement("md", + xml.attribute("backgroundColor", backgroundColorInt.name())); + + // Save background image + if (usesBackgroundImage && !backgroundImage.isNull()) { + QString img_path = "images/0-background"; + QString img_fullpath = tmpdir + "/" + img_path; + if (!saveBackgroundImage(img_fullpath)) + qWarning() << "md::saveToDir failed to save background image to " << img_fullpath; + else + s += xml.singleElement("md", + xml.attribute("backgroundImage", "file:" + img_path) + + xml.attribute("backgroundImageName", backgroundImageNameInt)); + } + + s += xml.singleElement("md", + xml.attribute("font", fontInt.toString())); + + s += xml.singleElement("md", + xml.attribute("selectionPenColor", selectionPenInt.color().name(QColor::HexArgb))); + s += xml.singleElement("md", + xml.attribute("selectionPenWidth", QString().setNum(selectionPenInt.width()))); + s += xml.singleElement("md", + xml.attribute("selectionBrushColor", selectionBrushInt.color().name(QColor::HexArgb))); + + if (linkColorHintInt == LinkObj::HeadingColor) + s += xml.singleElement("md", + xml.attribute("linkColorHint", "HeadingColor")); + + s += xml.singleElement("md", + xml.attribute("linkColor", defaultLinkColor().name())); + + s += xml.singleElement("md", + xml.attribute("defXLinkColor", defXLinkPenInt.color().name())); + s += xml.singleElement("md", + xml.attribute("defXLinkWidth", + QString().setNum(defXLinkPenInt.width(), 10))); + s += xml.singleElement("md", + xml.attribute("defXLinkPenStyle", + penStyleToString(defXLinkPenInt.style()))); + s += xml.singleElement("md", + xml.attribute("defXLinkStyleBegin", defXLinkStyleBeginInt)); + s += xml.singleElement("md", + xml.attribute("defXLinkStyleEnd", defXLinkStyleEndInt)); + + s += linkStyles.save("linkStyle", LinkObj::styleString); + s += imagesContainerLayouts.save("imagesLayout", Container::layoutString); + + s += branchesContainerLayouts.save("branchesLayout", Container::layoutString); + s += branchesContainerAndOrnamentsVerticalInt.saveBool("childrenAndHeadingVertical"); + s += branchesContainerVerticalAlignmentsInt.save("childrenVertAlignment", Container::verticalAlignmentString); + + s += innerFrameTypes.save("innerFrameType", FrameContainer::frameTypeString); + s += innerFrameBrushColors.saveColor("innerFrameBrushColor"); + s += innerFramePenColors.saveColor("innerFramePenColor"); + s += innerFramePenWidths.saveInt("innerFramePenWidth"); + s += innerFrameUpdateWhenRelinking.saveBool("innerFrameUpdateWhenRelinking"); + + s += outerFrameTypes.save("outerFrameType", FrameContainer::frameTypeString); + s += outerFrameBrushColors.saveColor("outerFrameBrushColor"); + s += outerFramePenColors.saveColor("outerFramePenColor"); + s += outerFramePenWidths.saveInt("outerFramePenWidth"); + s += outerFrameUpdateWhenRelinking.saveBool("outerFrameUpdateWhenRelinking"); + + xml.decIndent(); + s += xml.endElement("mapdesign"); + xml.decIndent(); + + return s; +} diff --git a/src/mapdesign.h b/src/mapdesign.h new file mode 100644 index 0000000..9fc5ac4 --- /dev/null +++ b/src/mapdesign.h @@ -0,0 +1,248 @@ +#ifndef MAPDESIGN_H +#define MAPDESIGN_H + +#include +#include + +//#include "branch-container.h" +//#include "branchitem.h" +#include "container.h" +#include "frame-container.h" +#include "linkobj.h" + +///////////////////////////////////////////////////////////////////////////// + +// Extended QList, which allows to access element at position n or, if n does not exist, +// the last existing element before n +template class ConfigList { + public: + QList qlist; + ConfigList & operator<<(const T &other); + T & operator[](int i); + T tryAt(int); + void setAt(int i, const T &val); + int count(); + void clear(); + QString save(const QString &attrName, QString (&f)(int)); + QString saveBool(const QString &attrName); + QString saveColor(const QString &attrName); + QString saveInt(const QString &attrName); + + protected: + T defaultValue; +}; + +///////////////////////////////////////////////////////////////////////////// +/*! \brief A MapDesign defines the visual appearance of a map, e.g. how branches, frames, links look. Settings depend on + - depth + - Mode: NewBranch, RelinkBranch + Settings may be overriden locallay and locally also depend on other settings, + e.g. links may depend on frames +*/ + +class BranchContainer; +class BranchItem; + +class MapDesign { + public: + enum HeadingColorHint { + SpecificColor, + InheritedColor, + UnchangedColor, + UndefinedColor}; + + enum UpdateMode : unsigned int { + Undefined = 0x0000, + LoadingMap = 0x0001, + //MapImport = 0x0002 + CreatedByUser = 0x0004, + RelinkedByUser = 0x0008, + LayoutChanged = 0x0010, + LinkStyleChanged = 0x0020, + StyleChanged = 0x0040, // e.g. heading color, which could change link color, too + AutoDesign = 0x0080 + }; + + // Defines where imagesContainer in non-floating + // layouts are relative to branchesContainer + enum ImagesPositionHint { + HorizontalInsideBranches, + HorizontalOutsideBranches, + VerticalAboveBranches, + VerticalBelowBranches + }; + + /* + constexpr RelinkMode operator|(RelinkMode X, RelinkMode Y) { + return static_cast( + static_cast(X) | static_cast(Y)); + } + + RelinkMode& operator|=(RelinkMode& X, RelinkMode Y) { + X = X | Y; return X; + } + */ + + MapDesign(); + void init(); + +// Basic data of MapDesign + public: + void setName(const QString &); + QString getName(); + static QString updateModeString(const UpdateMode &mode); + + private: + QString name; + +// Parse MapDesign when read from map file or undo/redo command + public: + bool setElement(const QString &k, const QString &v, const QString &d); + +// Container layouts + public: + Container::Layout branchesContainerLayout(int depth); + Container::VerticalAlignment branchesContainerVerticalAlignment(int depth); + + Container::Layout imagesContainerLayout(int depth); + bool branchesContainerAndOrnamentsVertical(int depth); + ImagesPositionHint imagesPosition(int depth); + + private: + ConfigList branchesContainerLayouts; + ConfigList imagesContainerLayouts; + ConfigList branchesContainerAndOrnamentsVerticalInt; + ConfigList branchesContainerVerticalAlignmentsInt; + ConfigList imagesPositionsInt; + +// Links + public: + LinkObj::ColorHint linkColorHint(); + void setLinkColorHint(const LinkObj::ColorHint &lch); + QColor defaultLinkColor(); + void setDefaultLinkColor(const QColor &col); + + LinkObj::Style linkStyle(int depth); + void setLinkStyle(LinkObj::Style style, int depth); + + qreal linkWidth(); + + private: + LinkObj::ColorHint linkColorHintInt; + QColor defaultLinkCol; + ConfigList linkStyles; + +// XLinks + public: + void setDefXLinkPen(const QPen &p); + QPen defXLinkPen(); + void setDefXLinkStyleBegin(const QString &s); + QString defXLinkStyleBegin(); + void setDefXLinkStyleEnd(const QString &s); + QString defXLinkStyleEnd(); + + private: + QPen defXLinkPenInt; // default pen for xlinks + QString defXLinkStyleBeginInt; // default style begin + QString defXLinkStyleEndInt; + +// Background + public: + void setBackgroundColor(const QColor &); + QColor backgroundColor(); + + bool loadBackgroundImage(const QString &fileName); + bool saveBackgroundImage(const QString &imagePath); + void setBackgroundImageName(const QString &); + void unsetBackgroundImage(); + bool hasBackgroundImage(); + QString backgroundImageName(); + QBrush backgroundImageBrush(); + + private: + QColor backgroundColorInt; + bool usesBackgroundImage; + QString backgroundImageNameInt; + QImage backgroundImage; + QBrush backgroundImageBrushInt; + +// Heading & Fonts + public: + QFont font(); + void setFont(const QFont &f); + int headingColumnWidth(const int &depth); + + QColor headingColor( + const MapDesign::UpdateMode &updateMode, + BranchItem *branchItem, + bool &updateRequired); + + private: + QFont fontInt; + + ConfigList headingColumnWidths; + ConfigList headingColorHints; + ConfigList headingColors; + ConfigList headingColorUpdateWhenRelinking; + +// Frames + public: + FrameContainer::FrameType frameType(bool useInnerFrame, const int &depth); + QColor frameBrushColor(bool useInnerFrame, const int &depth); + QColor framePenColor(bool useInnerFrame, const int &depth); + int framePenWidth(bool useInnerFrame, const int &depth); + bool updateFrameWhenRelinking(bool useInnerFrame, const int &depth); + + private: + ConfigList innerFrameTypes; + ConfigList innerFramePenColors; + ConfigList innerFrameBrushColors; + ConfigList innerFramePenWidths; + ConfigList innerFrameUpdateWhenRelinking; + + ConfigList outerFrameTypes; + ConfigList outerFramePenColors; + ConfigList outerFrameBrushColors; + ConfigList outerFramePenWidths; + ConfigList outerFrameUpdateWhenRelinking; + +// Selections + public: + QPen selectionPen(); + void setSelectionPen(const QPen &); + QBrush selectionBrush(); + void setSelectionBrush(const QBrush &); + + private: + QPen selectionPenInt; + QBrush selectionBrushInt; + +// Transformations + public: + int rotationHeading(const int &depth); + int rotationSubtree(const int &depth); + qreal scaleHeading(const int &depth); + qreal scaleSubtree(const int &depth); + + private: + ConfigList rotationHeadingInt; + ConfigList rotationSubtreeInt; + ConfigList scaleHeadingInt; + ConfigList scaleSubtreeInt; + + public: + QString saveToDir(const QString &tmpdir, const QString &prefix); +}; + +///////////////////////////////////////////////////////////////////////////// +inline MapDesign::UpdateMode operator|(MapDesign::UpdateMode a, MapDesign::UpdateMode b) +{ + return static_cast(static_cast(a) | static_cast(b)); +} + +inline MapDesign::UpdateMode operator|=(MapDesign::UpdateMode &a, MapDesign::UpdateMode b) +{ + a = a | b; return a; +} + +#endif diff --git a/src/mapeditor.cpp b/src/mapeditor.cpp index b8904ef..2bedeae 100644 --- a/src/mapeditor.cpp +++ b/src/mapeditor.cpp @@ -1,5 +1,6 @@ #include "mapeditor.h" +#include #include #include #include @@ -7,14 +8,18 @@ #include #include +#include "animpoint.h" #include "branchitem.h" #include "geometry.h" +#include "heading-container.h" +#include "image-container.h" #include "mainwindow.h" #include "misc.h" #include "shortcuts.h" -#include "warningdialog.h" #include "winter.h" +#include "xlink.h" #include "xlinkitem.h" +#include "xlinkobj.h" extern Main *mainWindow; extern QString clipboardDir; @@ -43,20 +48,61 @@ MapEditor::MapEditor(VymModel *vm) // qDebug() << "Constructor ME " << this; QString shortcutScope = tr("Map Editor", "Shortcut scope"); - mapScene = new QGraphicsScene(NULL); + mapScene = new QGraphicsScene(nullptr); mapScene->setBackgroundBrush(QBrush(Qt::white, Qt::SolidPattern)); - mapScene->setItemIndexMethod(QGraphicsScene::NoIndex); // FIXME-2 Avoiding crashes... + //mapScene->setItemIndexMethod(QGraphicsScene::NoIndex); // FIXME-3 Avoiding crashes... // Alternatively call removeFromIndex() in destructor // or maybe also prepareGeometryChange() - zoomFactor = zoomFactorTarget = 1; - angle = angleTarget = 0; + // Origin for view transformations (rotation, scaling) + setTransformationAnchor(QGraphicsView::AnchorViewCenter); + transformationOrigin = QPointF(0, 0); + useTransformationOrigin = false; + zoomDelta = 0.20; + + if (debug) { + // Add cross in origin for debugging + QPointF p; + qreal size = 100; + QGraphicsRectItem *x_axis = new QGraphicsRectItem(p.x() - size, p.y(), size * 2, 1 ); + QGraphicsRectItem *y_axis = new QGraphicsRectItem(p.x(), p.y() - size, 1, size * 2); + x_axis->setBrush(Qt::NoBrush); + y_axis->setBrush(Qt::NoBrush); + x_axis->setPen(QColor(Qt::blue)); + y_axis->setPen(QColor(Qt::blue)); + + mapScene->addItem(x_axis); + mapScene->addItem(y_axis); + + // Add another cross + /* + p = QPointF(200,0); + size = 20; + QGraphicsRectItem *x_axis2 = new QGraphicsRectItem(p.x() - size, p.y(), size * 2, 1 ); + QGraphicsRectItem *y_axis2 = new QGraphicsRectItem(p.x(), p.y() - size, 1, size * 2); + x_axis2->setBrush(Qt::NoBrush); + y_axis2->setBrush(Qt::NoBrush); + x_axis2->setPen(QColor(Qt::gray)); + y_axis2->setPen(QColor(Qt::gray)); + + mapScene->addItem(x_axis2); + mapScene->addItem(y_axis2); + */ + } + + zoomFactorInt = zoomFactorTargetInt = 1; + rotationInt = rotationTargetInt = 0; model = vm; model->registerMapEditor(this); setScene(mapScene); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + + selectionMode = AutoSelection; + setStyleSheet("QGraphicsView:focus {" + editorFocusStyle + "}"); // Create bitmap cursors, platform dependant @@ -64,13 +110,21 @@ MapEditor::MapEditor(VymModel *vm) PickColorCursor = QCursor(QPixmap(":/cursorcolorpicker.png"), 5, 27); XLinkCursor = QCursor(QPixmap(":/cursorxlink.png"), 1, 7); - editingBO = NULL; + editingBO = nullptr; printFrame = true; printFooter = true; setAcceptDrops(true); + // Container used for temporary moving and relinking branches + tmpParentContainer = new TmpParentContainer (); + mapScene->addItem(tmpParentContainer); + tmpParentContainer->setName("tmpParentContainer"); + + // When moving objects, draw then on top of everything else + tmpParentContainer->setZValue(10000); + // Shortcuts and actions QAction *a; @@ -81,7 +135,7 @@ MapEditor::MapEditor(VymModel *vm) addAction(a); a = new QAction("Add upper branch to selection", this); - a->setShortcut(Qt::Key_Up + Qt::SHIFT); + a->setShortcut(Qt::Key_Up | Qt::SHIFT); a->setShortcutContext(Qt::WidgetShortcut); addAction(a); connect(a, SIGNAL(triggered()), this, SLOT(cursorUpToggleSelection())); @@ -93,7 +147,7 @@ MapEditor::MapEditor(VymModel *vm) connect(a, SIGNAL(triggered()), this, SLOT(cursorDown())); a = new QAction("Add lower branch to selection", this); - a->setShortcut(Qt::Key_Down + Qt::SHIFT); + a->setShortcut(Qt::Key_Down | Qt::SHIFT); a->setShortcutContext(Qt::WidgetShortcut); addAction(a); connect(a, SIGNAL(triggered()), this, SLOT(cursorDownToggleSelection())); @@ -123,7 +177,7 @@ MapEditor::MapEditor(VymModel *vm) connect(a, SIGNAL(triggered()), this, SLOT(cursorLast())); // Action to embed LineEdit for heading in Scene - lineEdit = NULL; + lineEdit = nullptr; a = new QAction(tr("Edit heading", "MapEditor"), this); a->setShortcut(Qt::Key_Return); // Edit heading @@ -136,10 +190,6 @@ MapEditor::MapEditor(VymModel *vm) addAction(a); connect(a, SIGNAL(triggered()), this, SLOT(editHeading())); - // Selections - selectionPen = QPen(QColor(255,255,0), 1); - selectionBrush = QBrush(QColor(255,255,0)); - // Panning panningTimer = new QTimer(this); vPan = QPointF(); @@ -156,7 +206,16 @@ MapEditor::MapEditor(VymModel *vm) setState(Neutral); - winter = NULL; + winter = nullptr; + + // animations + animationUse = settings.value("/animation/use", true) .toBool(); + animationTicks = settings.value("/animation/snapback/ticks", 50).toInt(); + animationInterval = settings.value("/animation/snapback/interval", 15).toInt(); + animatedContainers.clear(); + animationTimer = new QTimer(this); + connect(animationTimer, SIGNAL(timeout()), this, SLOT(animate())); + } MapEditor::~MapEditor() @@ -165,8 +224,11 @@ MapEditor::~MapEditor() if (winter) { delete winter; - winter = NULL; + winter = nullptr; } + + stopViewAnimations(); + stopContainerAnimations(); } VymModel *MapEditor::getModel() { return model; } @@ -194,7 +256,7 @@ void MapEditor::panView() QRectF r = QRectF(q, QPointF(q.x() + 1, q.y() + 1)); // Expand view if necessary - setScrollBarPosTarget(r); // FIXME-2 mapToScene first? + setScrollBarPosTarget(r); // Stop possible other animations if (scrollBarPosAnimation.state() == QAbstractAnimation::Running) @@ -204,13 +266,14 @@ void MapEditor::panView() horizontalScrollBar()->setValue(horizontalScrollBar()->value() + vPan.x()); verticalScrollBar()->setValue(verticalScrollBar()->value() + vPan.y()); - - // Update currently moving object - moveObject(); } } -void MapEditor::ensureAreaVisibleAnimated(const QRectF &area, bool maximizeArea) // FIXME-2 zooming in not working yet (fit to selection) +void MapEditor::ensureAreaVisibleAnimated( + const QRectF &area, + bool scaled, + bool rotated, + qreal new_rotation) { // Changes viewCenter to make sure that // r is within the margins of the viewport @@ -232,9 +295,12 @@ void MapEditor::ensureAreaVisibleAnimated(const QRectF &area, bool maximizeArea) QRect visibleViewCoord = rect(); visibleViewCoord -= QMargins(xmargin, ymargin, xmargin, ymargin); + if (!rotated) + // Use current view rotation, if we do not plan to rotate + new_rotation = rotationInt; // Calculate required width and height considering rotation of view - qreal a = angle / 180 * M_PI; + qreal a = new_rotation / 180 * M_PI; qreal area_w_viewCoord = abs(sin(a) * area.height()) + abs(cos(a) * area.width()); qreal area_h_viewCoord = abs(sin(a) * area.width()) + abs(cos(a) * area.height()); qreal z_x = 1.0 * visibleViewCoord.width() / area_w_viewCoord; @@ -245,18 +311,22 @@ void MapEditor::ensureAreaVisibleAnimated(const QRectF &area, bool maximizeArea) bool zoomOutRequired = (visibleViewCoord.width() < areaViewCoord.width() || visibleViewCoord.height() < areaViewCoord.height()); - bool zoomInRequired = - (visibleViewCoord.width() > areaViewCoord.width() && - visibleViewCoord.height() > areaViewCoord.height()); + int animDuration = 2000; + QEasingCurve easingCurve = QEasingCurve::OutQuint; + //qDebug() << " zoom out: " << zoomOutRequired; - //qDebug() << " zoom in: " << zoomInRequired << " zoomFactor=" << zoomFactor << " zf=" << zf; - if (zoomOutRequired || maximizeArea) { - setViewCenterTarget(area.center(), zf, angle); + //qDebug() << " zoom in: " << zoomInRequired << " zoomFactor=" << zoomFactorInt << " zf=" << zf; + if (zoomOutRequired || scaled) { + setViewCenterTarget( + area.center(), + zf, + new_rotation, + animDuration, + easingCurve); return; } - // After zooming bbox would fit into margins of viewport long view_dx = 0; long view_dy = 0; @@ -274,16 +344,16 @@ void MapEditor::ensureAreaVisibleAnimated(const QRectF &area, bool maximizeArea) // move down view_dy = areaViewCoord.y() + areaViewCoord.height() - viewport()->height() + ymargin; - if (abs(view_dx) > 5 || abs(view_dy) > 5) + if (abs(view_dx) > 5 || abs(view_dy) > 5 || rotated) setViewCenterTarget( mapToScene(viewport()->geometry().center() + QPoint (view_dx, view_dy)), - zoomFactor, - angle, - 2000, - QEasingCurve::OutQuint); + zoomFactorInt, + new_rotation, + animDuration, + easingCurve); } -void MapEditor::ensureSelectionVisibleAnimated(bool maximizeArea) +void MapEditor::ensureSelectionVisibleAnimated(bool scaled, bool rotated) { // Changes viewCenter to make sure that bounding box of all currently // selected items is within the margins of the viewport @@ -304,34 +374,46 @@ void MapEditor::ensureSelectionVisibleAnimated(bool maximizeArea) bool firstIteration = true; foreach (TreeItem *ti, selis) { - LinkableMapObj *lmo = nullptr; - if (ti->getType() == TreeItem::Image || ti->isBranchLikeType()) - lmo = ((MapItem *)ti)->getLMO(); - if (lmo) { - if (firstIteration) { - bbox = lmo->getBBox(); - firstIteration = false; - } else - bbox = bbox.united(lmo->getBBox()); + Container *c = nullptr; + QRectF c_bbox; + if (ti->hasTypeAttribute()) + ti = ti->parent(); + if (ti->hasTypeBranch()) { + c = ((BranchItem*)ti)->getBranchContainer()->getHeadingContainer(); + c_bbox = c->mapToScene(c->rect()).boundingRect(); + } else if (ti->getType() == TreeItem::Image) { + c = ((ImageItem*)ti)->getImageContainer(); + c_bbox = c->mapToScene(c->rect()).boundingRect(); + } else if (ti->hasTypeXLink()) { + XLinkObj *xlo = ((XLinkItem*)ti)->getXLinkObj(); + if (xlo) + c_bbox = xlo->boundingRect(); } + + if (firstIteration) { + bbox = c_bbox; + firstIteration = false; + } else + bbox = bbox.united(c_bbox); } + int new_rotation = round_int(rotationInt) % 360; - ensureAreaVisibleAnimated(bbox, maximizeArea); -} + if (rotated && selis.count() == 1) { + if (selis.first()->hasTypeBranch()) { + BranchContainer *bc = ((BranchItem*)selis.first())->getBranchContainer(); -void MapEditor::scrollTo(const QModelIndex &index) -{ - if (index.isValid()) { - LinkableMapObj *lmo = NULL; - TreeItem *ti = static_cast(index.internalPointer()); - if (ti->getType() == TreeItem::Image || ti->isBranchLikeType()) - lmo = ((MapItem *)ti)->getLMO(); - if (lmo) { - QRectF r = lmo->getBBox(); - setScrollBarPosTarget(r); - animateScrollBars(); + // Avoid rotations > 360 + setRotation(new_rotation); + + qreal rotScene = bc->rotationHeadingInScene(); + int d_rotation = new_rotation + round_int(rotScene) % 360; + if (d_rotation > 180) + d_rotation = d_rotation - 360; + new_rotation = new_rotation - d_rotation; } } + + ensureAreaVisibleAnimated(bbox, scaled, rotated, new_rotation); } void MapEditor::setScrollBarPosTarget(QRectF rect) @@ -346,7 +428,9 @@ void MapEditor::setScrollBarPosTarget(QRectF rect) // Prepare scrolling qreal width = viewport()->width(); qreal height = viewport()->height(); - QRectF viewRect = transform().scale(zoomFactorTarget, zoomFactorTarget).mapRect(rect); + QRectF viewRect = transform(). + scale(zoomFactorTargetInt, zoomFactorTargetInt). + mapRect(rect); qreal left = horizontalScrollBar()->value(); qreal right = left + width; @@ -392,6 +476,7 @@ QPointF MapEditor::getScrollBarPos() void MapEditor::animateScrollBars() { + qDebug() << "ME::animateScrollBars"; if (scrollBarPosAnimation.state() == QAbstractAnimation::Running) scrollBarPosAnimation.stop(); @@ -410,18 +495,109 @@ void MapEditor::animateScrollBars() setScrollBarPos(scrollBarPosTarget); } +void MapEditor::animate() +{ + animationTimer->stop(); + foreach (Container *c, animatedContainers) { + c->animate(); + + if (c->getContainerType() == Container::Branch) + ((BranchContainer*)c)->updateUpLink(); + + if (!c->isAnimated()) + animatedContainers.removeAll(c); + } + + if (!animatedContainers.isEmpty()) + animationTimer->start(animationInterval); + + model->repositionXLinks(); +} + +void MapEditor::startAnimation(Container *c, const QPointF &v) // FIXME-3 only used in ME::autoLayout +{ + if (!c) return; + + startAnimation(c, c->pos(), c->pos() + v); +} + +void MapEditor::startAnimation(Container *c, const QPointF &start, + const QPointF &dest) +{ + if (start == dest) return; + + if (c) { + c->setPos(start); + AnimPoint ap; + ap.setStart(start); + ap.setDest(dest); + ap.setTicks(animationTicks); + ap.setAnimated(true); + c->setAnimation(ap); + if (!animatedContainers.contains(c)) + animatedContainers.append(c); + animationTimer->setSingleShot(true); + animationTimer->start(animationInterval); + } +} + +void MapEditor::stopContainerAnimation(Container *c) +{ + int i = animatedContainers.indexOf(c); + if (i >= 0) + animatedContainers.removeAt(i); +} + +void MapEditor::stopContainerAnimations() +{ + animationTimer->stop(); + + Container *c; + while (!animatedContainers.isEmpty()) { + c = animatedContainers.takeFirst(); + c->stopAnimation(); + } +} + +void MapEditor::stopViewAnimations() +{ + if (viewCenterAnimation.state() == QAbstractAnimation::Running) + viewCenterAnimation.stop(); + if (rotationAnimation.state() == QAbstractAnimation::Running) + rotationAnimation.stop(); + if (zoomAnimation.state() == QAbstractAnimation::Running) + zoomAnimation.stop(); +} + +void MapEditor::zoomIn() +{ + qreal f_zf = 1 + zoomDelta; // view transformation grows + + useTransformationOrigin = false; + setZoomFactorTarget(zoomFactorTargetInt * f_zf); +} + +void MapEditor::zoomOut() +{ + qreal f_zf = 1 - zoomDelta; // view transformation grows + + useTransformationOrigin = false; + setZoomFactorTarget(zoomFactorTargetInt * f_zf); +} + void MapEditor::setZoomFactorTarget(const qreal &zft) { - zoomFactorTarget = zft; + zoomFactorTargetInt = zft; if (zoomAnimation.state() == QAbstractAnimation::Running) zoomAnimation.stop(); + if (settings.value("/animation/use/", true).toBool()) { zoomAnimation.setTargetObject(this); - zoomAnimation.setPropertyName("zoomFactor"); + zoomAnimation.setPropertyName("zoomFactorInt"); zoomAnimation.setDuration( settings.value("/animation/duration/zoom", 2000).toInt()); zoomAnimation.setEasingCurve(QEasingCurve::OutQuint); - zoomAnimation.setStartValue(zoomFactor); + zoomAnimation.setStartValue(zoomFactorInt); zoomAnimation.setEndValue(zft); zoomAnimation.start(); } @@ -429,63 +605,58 @@ void MapEditor::setZoomFactorTarget(const qreal &zft) setZoomFactor(zft); } -qreal MapEditor::getZoomFactorTarget() { return zoomFactorTarget; } +qreal MapEditor::zoomFactorTarget() { return zoomFactorTargetInt; } void MapEditor::setZoomFactor(const qreal &zf) { - zoomFactor = zf; + zoomFactorInt = zf; updateMatrix(); } -qreal MapEditor::getZoomFactor() { return zoomFactor; } +qreal MapEditor::zoomFactor() { return zoomFactorInt; } -void MapEditor::setAngleTarget(const qreal &at) +void MapEditor::setRotationTarget(const qreal &at) { - angleTarget = at; + rotationTargetInt = at; if (rotationAnimation.state() == QAbstractAnimation::Running) rotationAnimation.stop(); if (settings.value("/animation/use/", true).toBool()) { rotationAnimation.setTargetObject(this); - rotationAnimation.setPropertyName("angle"); + rotationAnimation.setPropertyName("rotationInt"); rotationAnimation.setDuration( settings.value("/animation/duration/rotation", 2000).toInt()); rotationAnimation.setEasingCurve(QEasingCurve::OutQuint); - rotationAnimation.setStartValue(angle); + rotationAnimation.setStartValue(rotationInt); rotationAnimation.setEndValue(at); rotationAnimation.start(); } else - setAngle(angleTarget); + setRotation(rotationTargetInt); } -qreal MapEditor::getAngleTarget() { return angleTarget; } +qreal MapEditor::rotationTarget() { return rotationTargetInt; } -void MapEditor::setAngle(const qreal &a) +void MapEditor::setRotation(const qreal &a) { - angle = a; + rotationInt = a; updateMatrix(); if (winter) winter->updateView(); } -qreal MapEditor::getAngle() { return angle; } +qreal MapEditor::rotation() { return rotationInt; } void MapEditor::setViewCenterTarget(const QPointF &p, const qreal &zft, const qreal &at, const int duration, const QEasingCurve &easingCurve) { viewCenterTarget = p; - zoomFactorTarget = zft; - angleTarget = at; + zoomFactorTargetInt = zft; + rotationTargetInt = at; viewCenter = mapToScene(viewport()->geometry()).boundingRect().center(); - if (viewCenterAnimation.state() == QAbstractAnimation::Running) - viewCenterAnimation.stop(); - if (rotationAnimation.state() == QAbstractAnimation::Running) - rotationAnimation.stop(); - if (zoomAnimation.state() == QAbstractAnimation::Running) - zoomAnimation.stop(); + stopViewAnimations(); if (settings.value("/animation/use/", true).toBool()) { viewCenterAnimation.setTargetObject(this); @@ -498,25 +669,24 @@ void MapEditor::setViewCenterTarget(const QPointF &p, const qreal &zft, viewCenterAnimation.start(); rotationAnimation.setTargetObject(this); - rotationAnimation.setPropertyName("angle"); + rotationAnimation.setPropertyName("rotationInt"); rotationAnimation.setDuration( settings.value("/animation/duration/rotation", duration).toInt()); rotationAnimation.setEasingCurve(easingCurve); - rotationAnimation.setStartValue(angle); - rotationAnimation.setEndValue(angleTarget); + rotationAnimation.setStartValue(rotationInt); + rotationAnimation.setEndValue(rotationTargetInt); rotationAnimation.start(); zoomAnimation.setTargetObject(this); - zoomAnimation.setPropertyName("zoomFactor"); + zoomAnimation.setPropertyName("zoomFactorInt"); zoomAnimation.setDuration( settings.value("/animation/duration/zoom", duration).toInt()); zoomAnimation.setEasingCurve(easingCurve); - zoomAnimation.setStartValue(zoomFactor); - zoomAnimation.setEndValue(zoomFactorTarget); + zoomAnimation.setStartValue(zoomFactorInt); + zoomAnimation.setEndValue(zoomFactorTargetInt); zoomAnimation.start(); - } - else { - setAngle(angleTarget); + } else { + setRotation(rotationTargetInt); setZoomFactor(zft); setViewCenter(viewCenterTarget); } @@ -526,34 +696,52 @@ void MapEditor::setViewCenterTarget() { MapItem *selti = (MapItem *)(model->getSelectedItem()); if (selti) { - LinkableMapObj *lmo = selti->getLMO(); - if (lmo) - setViewCenterTarget(lmo->getBBox().center(), 1, 0); + Container *c = nullptr; + if (selti->hasTypeBranch()) + c = ((BranchItem*)selti)->getBranchContainer()->getHeadingContainer(); + else if (selti->hasTypeImage()) + c = ((ImageItem*)selti)->getImageContainer(); + else + return; + setViewCenterTarget(c->mapToScene(c->rect().center()), 1, 0); } } QPointF MapEditor::getViewCenterTarget() { return viewCenterTarget; } -void MapEditor::setViewCenter(const QPointF &vc) { centerOn(vc); } +void MapEditor::setViewCenter(const QPointF &vc) { + // For wheel events // useTransFormationOrigin == true + // and thus we will need vp_center in updateMatrix() later + vp_center = vc; + centerOn(vc); +} QPointF MapEditor::getViewCenter() { return viewCenter; } void MapEditor::updateMatrix() { - QTransform t_zoom; - t_zoom.scale(zoomFactor, zoomFactor); - QTransform t_rot; - t_rot.rotate(angle); - setTransform(t_zoom * t_rot); + if (useTransformationOrigin) { + //qDebug() << " vp_center=" << toS(vp_center); + centerOn(transformationOrigin); + } + + QTransform t; + t.rotate(rotationInt); + t.scale(zoomFactorInt, zoomFactorInt); + setTransform(t); + + if (useTransformationOrigin) + centerOn(vp_center); } void MapEditor::minimizeView() { - // If we only would set scene rectangle to existing items, then - // view fould "jump", when Qt automatically tries to center. + // If we only would set scene rectangle to existing items, then + // view would "jump", when Qt automatically tries to center. // Better consider the currently visible viewport (with slight offset) QRectF r = mapToScene(viewport()->geometry()).boundingRect(); r.translate(-2,-3); setSceneRect(scene()->itemsBoundingRect().united(r)); + // Used to be called also from VymModel::reposition() } void MapEditor::print() @@ -586,7 +774,7 @@ void MapEditor::print() model->unselectAll(); QRectF mapRect = totalBBox; - QGraphicsRectItem *frame = NULL; + QGraphicsRectItem *frame = nullptr; if (printFrame) { // Print frame around map @@ -594,7 +782,6 @@ void MapEditor::print() totalBBox.width() + 20, totalBBox.height() + 20); frame = mapScene->addRect(mapRect, QPen(Qt::black), QBrush(Qt::NoBrush)); - frame->setZValue(0); frame->show(); } @@ -639,28 +826,34 @@ void MapEditor::print() } } -QRectF MapEditor::getTotalBBox() // FIXME-2 really needed? Overlaps with scene and VM... +QRectF MapEditor::getTotalBBox() // return (minimal) size of view before printing or creating pdfs { - minimizeView(); + minimizeView(); // Before returning size of view, minimize view return sceneRect(); } QImage MapEditor::getImage(QPointF &offset) { - QRectF mapRect = getTotalBBox(); // minimized sceneRect + QRectF sceneRect = scene()->itemsBoundingRect(); + + int d = 0; // border around sceneRect + + QRect imageRect; + imageRect.setWidth(sceneRect.width() + 2 * d - 2); + imageRect.setHeight(sceneRect.height() + 2 * d); - int d = 10; // border - offset = QPointF(mapRect.x() - d / 2, mapRect.y() - d / 2); - QImage pix(mapRect.width() + d, mapRect.height() + d, QImage::Format_RGB32); + offset = QPointF(sceneRect.left() - d, sceneRect.top() - d); + QImage pix(imageRect.width(), imageRect.height(), QImage::Format_ARGB32); + //qDebug() << "ME::getImage offset="<< offset << " imageRect=" << toS(imageRect,0) << " sceneRect=" << toS(sceneRect,0); QPainter pp(&pix); pp.setRenderHints(renderHints()); mapScene->render(&pp, // Destination: - QRectF(0, 0, mapRect.width() + d, mapRect.height() + d), + QRectF(0, 0, imageRect.width(), imageRect.height()), // Source in scene: - QRectF(mapRect.x() - d / 2, mapRect.y() - d / 2, - mapRect.width() + d, mapRect.height() + d)); + QRectF(sceneRect.x() - d, sceneRect.y() - d, + sceneRect.width() + 2 * d, sceneRect.height() + 2 * d )); return pix; } @@ -674,21 +867,22 @@ void MapEditor::setSmoothPixmap(bool b) setRenderHint(QPainter::SmoothPixmapTransform, b); } -void MapEditor::autoLayout() +void MapEditor::autoLayout() // FIXME-3 not ported yet to containers. Review use case ("brainstorming") { + /* // Create list with all bounding polygons QList mapobjects; QList polys; ConvexPolygon p; QList vectors; QList orgpos; - QStringList headings; // FIXME-3 testing only + QStringList headings; // FIXME testing only Vector v; BranchItem *bi; BranchItem *bi2; BranchObj *bo; - // Outer loop: Iterate until we no more changes in orientation + // Outer loop: Iterate until we have no more changes in orientation bool orientationChanged = true; while (orientationChanged) { BranchItem *ri = model->getRootItem(); @@ -702,7 +896,7 @@ void MapEditor::autoLayout() polys.append(p); vectors.append(QPointF(0, 0)); orgpos.append(p.at(0)); - headings.append(bi->getHeadingPlain()); + headings.append(bi->headingPlain()); } for (int j = 0; j < bi->branchCount(); ++j) { bi2 = bi->getBranchNum(j); @@ -714,7 +908,7 @@ void MapEditor::autoLayout() polys.append(p); vectors.append(QPointF(0, 0)); orgpos.append(p.at(0)); - headings.append(bi2->getHeadingPlain()); + headings.append(bi2->headingPlain()); } } } @@ -747,7 +941,7 @@ void MapEditor::autoLayout() vectors[j] = v * 10000 / polys.at(j).weight(); vectors[i] = v * 10000 / polys.at(i).weight(); vectors[i].invert(); - // FIXME-3 outer loop, "i" get's changed several + // FIXME outer loop, "i" get's changed several // times... // Better not move away from centroid of 2 colliding // polys, but from centroid of _all_ @@ -776,13 +970,13 @@ void MapEditor::autoLayout() << headings[i]; // mapobjects[i]->moveBy(v.x(),v.y() ); // mapobjects[i]->setRelPos(); - model->startAnimation((BranchObj *)mapobjects[i], v); + startAnimation((BranchObj *)mapobjects[i], v); if (debug) qDebug() << i << " Weight: " << polys.at(i).weight() << " " << v << " " << headings.at(i); } } - /* + / * model->reposition(); orientationChanged=false; for (int i=0;iemitSelectionChanged(); + */ } -TreeItem *MapEditor::findMapItem(QPointF p, TreeItem *exclude) +TreeItem *MapEditor::findMapItem( + QPointF p, + const QList &excludedItems, + bool findNearCenter) { // Search XLinks - Link *link; + XLink *xlink; for (int i = 0; i < model->xlinkCount(); i++) { - link = model->getXLinkNum(i); - if (link) { - XLinkObj *xlo = link->getXLinkObj(); - if (xlo && xlo->isInClickBox(p)) { - // Found XLink, now return the nearest XLinkItem of p - qreal d0 = Geometry::distance(p, xlo->getBeginPos()); - qreal d1 = Geometry::distance(p, xlo->getEndPos()); - if (d0 > d1) - return link->getBeginLinkItem(); - else - return link->getEndLinkItem(); + xlink = model->getXLinkNum(i); + if (xlink) { + XLinkObj *xlo = xlink->getXLinkObj(); + if (xlo) { + XLinkObj::SelectionType xlinkSelection = xlo->couldSelect(p); + if (xlinkSelection == XLinkObj::Path) { + // Found path of XLink, now return the nearest XLinkItem of p + qreal d0 = Geometry::distance(p, xlo->getBeginPos()); + qreal d1 = Geometry::distance(p, xlo->getEndPos()); + if (d0 < d1) + return xlink->beginXLinkItem(); + else + return xlink->endXLinkItem(); + } + if (xlinkSelection == XLinkObj::C0) + return xlink->beginXLinkItem(); + if (xlinkSelection == XLinkObj::C1) + return xlink->endXLinkItem(); } } } // Search branches (and their childs, e.g. images // Start with mapcenter, no images allowed at rootItem + BranchItem *nearestFloatingCenter = nullptr; + qreal d = 0; int i = 0; BranchItem *bi = model->getRootItem()->getFirstBranch(); - TreeItem *found = NULL; + TreeItem *found = nullptr; while (bi) { - found = bi->findMapItem(p, exclude); + found = bi->findMapItem(p, excludedItems); if (found) return found; + + if (findNearCenter) { + // Try to find nearest MapCenter // FIXME-3 or branch with floating layout. + // Currently only MapCenters are searched + Container *hc = bi->getBranchContainer()->getHeadingContainer(); + QPointF q = hc->mapToScene(hc->center()); + if (!nearestFloatingCenter) { + nearestFloatingCenter = bi; + d = Geometry::distance(p, q); + } else { + qreal d2 = Geometry::distance(p, q); + if (d2 < d) { + d = d2; + nearestFloatingCenter = bi; + } + } + } + i++; bi = model->getRootItem()->getBranchNum(i); } - return NULL; + + if (nearestFloatingCenter && d < 80 && !excludedItems.contains(nearestFloatingCenter)) + return nearestFloatingCenter; + + return nullptr; } -void MapEditor::testFunction1() {} +BranchItem *MapEditor::findMapBranchItem( + QPointF p, + const QList &excludedItems, + bool findNearCenter) +{ + TreeItem *ti = findMapItem(p, excludedItems, findNearCenter); + if (ti && ti->hasTypeBranch()) + return (BranchItem*)ti; + else + return nullptr; +} -void MapEditor::testFunction2() { autoLayout(); } +void MapEditor::testFunction1() +{ + //autoLayout(); + qDebug() << "ME::test"; + qDebug() << " hor_scrollbar=" << horizontalScrollBar()->value(); + qDebug() << " ver_scrollbar=" << verticalScrollBar()->value(); + qDebug() << " rect=" << toS(rect()); + qDebug() << " sceneRect=" << toS(sceneRect()); + qDebug() << " tf=" << zoomFactorInt; + qDebug() << " pageStep=" << horizontalScrollBar()->pageStep(); +} + +void MapEditor::testFunction2() +{ + TreeItem *selti = model->getSelectedItem(); + if (selti) + { + if (selti->hasTypeBranch()) { + BranchContainer *bc = ((BranchItem*)selti)->getBranchContainer(); + bc->setScrollOpacity(bc->getScrollOpacity() * 0.9); // FIXME-3 animation test + } else if (selti->hasTypeImage()) { + ImageContainer *ic = ((ImageItem*)selti)->getImageContainer(); + qDebug() << ic->info() << ic; + } else + qDebug() << "Unknown type"; + } else + qWarning() << "Nothing selected"; +} void MapEditor::toggleWinter() { if (winter) { delete winter; - winter = NULL; + winter = nullptr; } else { winter = new Winter(this); QList obstacles; - BranchObj *bo; - BranchItem *cur = NULL; - BranchItem *prev = NULL; + BranchContainer *bc; + BranchItem *cur = nullptr; + BranchItem *prev = nullptr; model->nextBranch(cur, prev); while (cur) { - if (!cur->hasHiddenExportParent()) { + if (!cur->hasHiddenParent()) { // FIXME-3 avoid recursive calls here in winter // Branches - bo = (BranchObj *)(cur->getLMO()); - if (bo && bo->isVisibleObj()) - obstacles.append(bo->getBBox()); + bc = cur->getBranchContainer(); + if (bc->isVisible()) { + HeadingContainer *hc = bc->getHeadingContainer(); + obstacles.append(hc->mapRectToScene(hc->boundingRect())); + } } model->nextBranch(cur, prev); } @@ -866,239 +1132,337 @@ void MapEditor::toggleWinter() } } -BranchItem *MapEditor::getBranchDirectAbove(BranchItem *bi) +bool MapEditor::isContainerCloserInDirection(Container *c1, Container *c2, const qreal &d_min, const QPoint &v, RadarDirection radarDir) { - if (bi) { - int i = bi->num(); - if (i > 0) - return bi->parent()->getBranchNum(i - 1); + qreal d = c1->distance(c2); + + switch(radarDir) { + case UpDirection: + if (v.y() < 0 && (d_min < 0 || d < d_min)) + return true; + break; + + case DownDirection: + if (v.y() > 0 && (d_min < 0 || d < d_min)) + return true; + break; + + case LeftDirection: + if (v.x() < 0 && (d_min < 0 || d < d_min)) + return true; + break; + + case RightDirection: + if (v.x() > 0 && (d_min < 0 || d < d_min)) + return true; + break; + default: + qWarning() << "MapEditor::isContainerCloserInDirection undefined radar"; } - return NULL; + return false; } -BranchItem *MapEditor::getBranchAbove(BranchItem *selbi) +TreeItem* MapEditor::getItemInDirection(TreeItem *ti, RadarDirection radarDir) { - if (selbi) { - int dz = selbi->depth(); // original depth - bool invert = false; - if (selbi->getLMO()->getOrientation() == LinkableMapObj::LeftOfCenter) - invert = true; + SelectionMode selMode = currentSelectionMode(ti); - BranchItem *bi; + //qDebug() << "ME::getItemInDir selMode=" << selMode; + if (selMode == GeometricSelection) + return getItemFromGeometry(ti, radarDir); - // Look for branch with same parent but directly above - if (dz == 1 && invert) - bi = getBranchDirectBelow(selbi); - else - bi = getBranchDirectAbove(selbi); + if (selMode == OrgChartSelection) + return getItemFromOrgChart(ti, radarDir); - if (bi) - // direct predecessor - return bi; + return getItemFromClassicMap(ti, radarDir); +} - // Go towards center and look for predecessor - while (selbi->depth() > 0) { - selbi = (BranchItem *)(selbi->parent()); - if (selbi->depth() == 1 && invert) - bi = getBranchDirectBelow(selbi); - else - bi = getBranchDirectAbove(selbi); - if (bi) { - // turn - selbi = bi; - while (selbi->depth() < dz) { - // try to get back to original depth dz - bi = selbi->getLastBranch(); - if (!bi) { - return selbi; +TreeItem* MapEditor::getItemFromGeometry(TreeItem *ti, RadarDirection radarDir) // FIXME-3 does not really work +{ + TreeItem *nearestItem = nullptr; + if (ti) { + // Calculate reference points: Nearest corners of selected towards radarDir + QPoint rp_view; + Container *c = nullptr; + if (ti->hasTypeBranch()) + c = ((BranchItem*)ti)->getBranchContainer()->getHeadingContainer(); + else if (ti->hasTypeImage()) + c = ((ImageItem*)ti)->getImageContainer(); + + if (!c) { + qWarning() << __func__ << "No container found"; + return nullptr; + } + + rp_view = mapFromScene(c->mapToScene(c->center())); + + qreal d_min = -1; + qreal d; + BranchItem *cur = nullptr; + BranchItem *prev = nullptr; + model->nextBranch(cur, prev); + while (cur) { + // Interate over all branches in map + BranchContainer *bc; + bc = cur->getBranchContainer(); + if (bc && bc->isVisible()) { + HeadingContainer *hc = bc->getHeadingContainer(); + + QPointF p_scene = hc->mapToScene(hc->center()); + QPoint v = mapFromScene(p_scene) - rp_view; // Direction between centers + d = c->distance(hc); + if (cur != ti && isContainerCloserInDirection(c, hc, d_min, v, radarDir)) { + d_min = d; + nearestItem = cur; + } + + // Iterate over images + for (int i = 0; i < cur->imageCount(); i++) { + ImageItem *ii = cur->getImageNum(i); + ImageContainer *ic = ii->getImageContainer(); + p_scene = ic->mapToScene(ic->center()); + v = mapFromScene(p_scene) - rp_view; + d = c->distance(ic); + if (ii != ti && isContainerCloserInDirection(c, ic, d_min, v, radarDir)) { + d_min = d; + nearestItem = ii; } - selbi = bi; } - return selbi; } + model->nextBranch(cur, prev); } } - return NULL; + + return nearestItem; } -BranchItem *MapEditor::getBranchDirectBelow(BranchItem *bi) +TreeItem* MapEditor::getItemFromOrgChart(TreeItem *ti, RadarDirection radarDir) { - if (bi) { - int i = bi->num(); - if (i + 1 < bi->parent()->branchCount()) - return bi->parent()->getBranchNum(i + 1); - } - return NULL; + BranchItem *bi = nullptr; + if (ti->hasTypeBranch()) + bi = (BranchItem*)ti; + + if (!bi) + return nullptr; + + if (radarDir == UpDirection) + return bi->parentBranch(); + else if (radarDir == DownDirection) + return bi->getLastSelectedBranch(); + else if (radarDir == LeftDirection) + return getItemFromClassicMap(ti, UpDirection); + else if (radarDir == RightDirection) + return getItemFromClassicMap(ti, DownDirection); + + return nullptr; } -BranchItem *MapEditor::getBranchBelow(BranchItem *selbi) +TreeItem* MapEditor::getItemFromClassicMap(TreeItem *selti, RadarDirection radarDir) { - if (selbi) { - BranchItem *bi; - int dz = selbi->depth(); // original depth - bool invert = false; - if (selbi->getLMO()->getOrientation() == LinkableMapObj::LeftOfCenter) - invert = true; - - // Look for branch with same parent but directly below - if (dz == 1 && invert) - bi = getBranchDirectAbove(selbi); - else - bi = getBranchDirectBelow(selbi); - if (bi) - // direct successor - return bi; - - // Go towards center and look for neighbour - while (selbi->depth() > 0) { - selbi = (BranchItem *)(selbi->parent()); - if (selbi->depth() == 1 && invert) - bi = getBranchDirectAbove(selbi); - else - bi = getBranchDirectBelow(selbi); - if (bi) { + if (!selti) + return nullptr; + + BranchItem * bi = nullptr; + if (selti->hasTypeBranch()) + bi = (BranchItem*)selti; + + int d = selti->depth(); // original depth + + if (radarDir == UpDirection) { + TreeItem *ti = getItemDirectAbove(selti); + + if (ti) + // direct predecessor + return ti; + + // Go towards center and look for predecessor + while (selti->depth() > 0) { + selti = selti->parent(); + ti = getItemDirectAbove(selti); + + if (ti) { // turn - selbi = bi; - while (selbi->depth() < dz) { + selti = ti; + while (selti->depth() < d) { // try to get back to original depth dz - bi = selbi->getFirstBranch(); - if (!bi) { - return selbi; - } - selbi = bi; + ti = selti->getLastItem(); + if (!ti) + return selti; + + selti = ti; } - return selbi; + return selti; } } - } - return NULL; -} -BranchItem *MapEditor::getLeftBranch(TreeItem *ti) -{ - if (!ti) - return NULL; + } else if (radarDir == DownDirection) { + TreeItem *ti = getItemDirectBelow(selti); - if (ti->isBranchLikeType()) { - BranchItem *bi = (BranchItem *)ti; - if (bi->depth() == 0) { - // Special case: use alternative selection index - BranchItem *newbi = bi->getLastSelectedBranchAlt(); - if (!newbi) { - BranchObj *bo; - // Try to find a mainbranch left of center - for (int i = 0; i < bi->branchCount(); i++) { - newbi = bi->getBranchNum(i); - bo = newbi->getBranchObj(); - if (bo && - bo->getOrientation() == LinkableMapObj::LeftOfCenter) - break; + if (ti) return ti; + + // Go towards center and look for siblings + while (selti->depth() > 0) { + selti = selti->parent(); + ti = getItemDirectBelow(selti); + + if (ti) { + // turn + selti = ti; + while (selti->depth() < d) { + // try to get back to original depth d + ti = selti->getFirstItem(); + if (!ti) + return selti; + + selti = ti; } + return selti; } - return newbi; } - if (bi->getBranchObj()->getOrientation() == - LinkableMapObj::RightOfCenter) - // right of center - return (BranchItem *)(bi->parent()); - else - // left of center - if (bi->getType() == TreeItem::Branch) - return bi->getLastSelectedBranch(); - } - - if (ti->parent() && ti->parent()->isBranchLikeType()) - return (BranchItem *)(ti->parent()); - return NULL; -} - -BranchItem *MapEditor::getRightBranch(TreeItem *ti) -{ - if (!ti) - return NULL; - - if (ti->isBranchLikeType()) { - BranchItem *bi = (BranchItem *)ti; - if (bi->depth() == 0) { - // Special case: use alternative selection index - BranchItem *newbi = bi->getLastSelectedBranch(); - if (!newbi) { - BranchObj *bo; - // Try to find a mainbranch right of center - for (int i = 0; i < bi->branchCount(); i++) { - newbi = bi->getBranchNum(i); - bo = newbi->getBranchObj(); - if (bo && - bo->getOrientation() == LinkableMapObj::RightOfCenter) - qDebug() - << "BI found right: " << newbi->getHeadingPlain(); + + } else if (radarDir == LeftDirection) { + if (bi) { + // Branch selected + if (d == 0) { + // Special case: use alternative selection index + BranchItem *newbi = bi->getLastSelectedBranchAlt(); + if (!newbi) { + BranchContainer *bc; + // Try to find a mainbranch left of center + for (int i = 0; i < bi->branchCount(); i++) { + newbi = bi->getBranchNum(i); + bc = newbi->getBranchContainer(); + if (bc && bc->getOrientation() == BranchContainer::LeftOfParent) + break; + } } + return newbi; + } + if (bi->getBranchContainer()->getOrientation() == + BranchContainer::RightOfParent) + // right of center + return bi->parentBranch(); + else { + // left of center + TreeItem *ri = bi->getLastSelectedBranch(); + if (ri) + // Return last selected branch + return ri; + else + // Look for image + return getItemFromGeometry(bi, LeftDirection); + } + } + } else if (radarDir == RightDirection) { + if (bi) { + // Branch selected + if (d == 0) { + // Special case: use alternative selection index + BranchItem *newbi = bi->getLastSelectedBranch(); + if (!newbi) { + BranchContainer *bc; + // Try to find a mainbranch right of center + for (int i = 0; i < bi->branchCount(); i++) { + newbi = bi->getBranchNum(i); + bc = newbi->getBranchContainer(); + if (bc && bc->getOrientation() == BranchContainer::RightOfParent) + break; + } + } + return newbi; + } + if (bi->getBranchContainer()->getOrientation() == BranchContainer::LeftOfParent) + // left of center + return bi->parentBranch(); + else { + // right of center + TreeItem *ri = bi->getLastSelectedBranch(); + if (ri) + // Return last selected branch + return ri; + else + // Look for image + return getItemFromGeometry(bi, RightDirection); } - return newbi; } - if (bi->getBranchObj()->getOrientation() == - LinkableMapObj::LeftOfCenter) - // left of center - return (BranchItem *)(bi->parent()); - else - // right of center - if (bi->getType() == TreeItem::Branch) - return (BranchItem *)bi->getLastSelectedBranch(); } + return nullptr; +} - if (ti->parent() && ti->parent()->isBranchLikeType()) - return (BranchItem *)(ti->parent()); +TreeItem *MapEditor::getItemDirectAbove(TreeItem *ti) +{ + if (ti) { + if (ti->hasTypeBranch()) { + BranchItem *bi = (BranchItem*)ti; + + int i = bi->num(); + if (i > 0) + return bi->parent()->getBranchNum(i - 1); + } else if (ti->hasTypeImage()) { + ImageItem *ii = (ImageItem*)ti; + + int i = ii->num(); + if (i > 0) + return ii->parent()->getImageNum(i - 1); + } + } + return nullptr; +} - return NULL; +TreeItem *MapEditor::getItemDirectBelow(TreeItem *ti) +{ + if (ti) { + if (ti->hasTypeBranch()) { + BranchItem *bi = (BranchItem*)ti; + int i = bi->num(); + if (i + 1 < bi->parent()->branchCount()) + return bi->parent()->getBranchNum(i + 1); + } else if (ti->hasTypeImage()) { + ImageItem *ii = (ImageItem*)ti; + int i = ii->num(); + if (i + 1 < ii->parent()->imageCount()) + return ii->parent()->getImageNum(i + 1); + } + } + return nullptr; } void MapEditor::cursorUp() { - if (state == MapEditor::EditingHeading) + if (editorState == MapEditor::EditingHeading) return; - BranchItem *selbi = model->getSelectedBranch(); - BranchItem *bi; - if (selbi) { - // Exactly one branch is currently selected - bi = getBranchAbove(selbi); - if (bi) { - model->select(bi); - } - } else { - // Nothing selected or already multiple selections - TreeItem *ti = model->lastToggledItem(); - if (ti && ti->isBranchLikeType()) { - bi = getBranchAbove( (BranchItem*)ti); - if (bi) - model->select(bi); - } + TreeItem *selti = model->getSelectedItem(); + if (selti) { + selti = getItemInDirection(selti, UpDirection); + if (selti) + model->select(selti); } } void MapEditor::cursorUpToggleSelection() { - if (state == MapEditor::EditingHeading) + if (editorState == MapEditor::EditingHeading) return; - BranchItem *selbi = model->getSelectedBranch(); - BranchItem *bi; + QList seltis = model->getSelectedItems(); + TreeItem *ti; - if (selbi) { - // Exactly one branch is currently selected - bi = getBranchAbove(selbi); - if (bi) model->selectToggle(bi); + if (seltis.size() == 0) + return; + else if (seltis.size() == 1) { + ti = getItemInDirection(seltis.first(), UpDirection); + if (ti) model->selectToggle(ti); } else { // Nothing selected or already multiple selections - TreeItem *ti = model->lastToggledItem(); - if (ti && ti->isBranchLikeType()) { + TreeItem *last_ti = model->lastToggledItem(); + if (last_ti && (last_ti->hasTypeBranch() || last_ti->hasTypeImage())) { if (lastToggleDirection == toggleUp) - bi = getBranchAbove( (BranchItem*)ti); + ti = getItemInDirection(last_ti, UpDirection); else - bi = (BranchItem*)ti; + ti = last_ti; - if (bi) - model->selectToggle(bi); + if (ti) + model->selectToggle(ti); } } lastToggleDirection = toggleUp; @@ -1106,53 +1470,40 @@ void MapEditor::cursorUpToggleSelection() void MapEditor::cursorDown() { - if (state == MapEditor::EditingHeading) + if (editorState == MapEditor::EditingHeading) return; - BranchItem *selbi = model->getSelectedBranch(); - BranchItem *bi; - if (selbi) { - // Exactly one branch is currently selected - bi = getBranchBelow(selbi); - if (bi) { - model->select(bi); - } - } else { - // Nothing selected or already multiple selections - TreeItem *ti = model->lastToggledItem(); - if (ti && ti->isBranchLikeType()) { - bi = getBranchBelow( (BranchItem*)ti); - - if (bi) - model->select(bi); - } + TreeItem *selti = model->getSelectedItem(); + if (selti) { + selti = getItemInDirection(selti, DownDirection); + if (selti) + model->select(selti); } } void MapEditor::cursorDownToggleSelection() { - if (state == MapEditor::EditingHeading) + if (editorState == MapEditor::EditingHeading) return; - BranchItem *selbi = model->getSelectedBranch(); - BranchItem *bi; - if (selbi) { - // Exactly one branch is currently selected - bi = getBranchBelow(selbi); - if (bi) { - model->selectToggle(bi); - } + TreeItem *selti = model->getSelectedItem(); + TreeItem *ti; + if (selti) { + ti = getItemInDirection(selti, DownDirection); + if (ti) { + model->selectToggle(ti); + } } else { // Nothing selected or already multiple selections - TreeItem *ti = model->lastToggledItem(); - if (ti && ti->isBranchLikeType()) { + TreeItem *last_ti = model->lastToggledItem(); + if (last_ti && (last_ti->hasTypeBranch() || last_ti->hasTypeImage())) { if (lastToggleDirection == toggleDown) - bi = getBranchBelow( (BranchItem*)ti); + ti = getItemInDirection(last_ti, DownDirection); else - bi = (BranchItem*)ti; + ti = last_ti; - if (bi) - model->selectToggle(bi); + if (ti) + model->selectToggle(ti); } } lastToggleDirection = toggleDown; @@ -1160,56 +1511,53 @@ void MapEditor::cursorDownToggleSelection() void MapEditor::cursorLeft() { - TreeItem *ti = model->getSelectedItem(); - if (!ti) { - ti = model->lastToggledItem(); - if (!ti) return; + TreeItem *selti = model->getSelectedItem(); + if (!selti) { + // If multiple items are selected, select the next to last toggled one + selti = model->lastToggledItem(); + if (!selti) return; } - BranchItem *bi = getLeftBranch(ti); - if (bi) - model->select(bi); - else { - ImageItem *ii = ti->getFirstImage(); - if (ii) - model->select(ii); - } + TreeItem *ti = getItemInDirection(selti, LeftDirection); + if (ti) + model->select(ti); } void MapEditor::cursorRight() { - TreeItem *ti = model->getSelectedItem(); - if (!ti) { - ti = model->lastToggledItem(); - if (!ti) return; + TreeItem *selti = model->getSelectedItem(); + + if (!selti) { + // If multiple items are selected, select the next to last toggled one + selti = model->lastToggledItem(); + if (!selti) return; } - BranchItem *bi = getRightBranch(ti); - if (bi) - model->select(bi); + TreeItem *ti = getItemInDirection(selti, RightDirection); + if (ti) + model->select(ti); else { - ImageItem *ii = ti->getFirstImage(); + ImageItem *ii = selti->getFirstImage(); if (ii) model->select(ii); } } -void MapEditor::cursorFirst() { model->selectFirstBranch(); } +void MapEditor::cursorFirst() { model->selectFirstBranch(); } // FIXME-3 adapt for images and container layouts -void MapEditor::cursorLast() { model->selectLastBranch(); } +void MapEditor::cursorLast() { model->selectLastBranch(); } // FIXME-3 adapt for images and container layouts -void MapEditor::editHeading() +void MapEditor::editHeading(BranchItem *selbi) { - if (state == EditingHeading) { + if (editorState == EditingHeading) { editHeadingFinished(); return; } - BranchObj *bo = model->getSelectedBranchObj(); - BranchItem *bi = model->getSelectedBranch(); - if (bo && bi) { - VymText heading = bi->getHeading(); - if (heading.isRichText() || bi->getHeadingPlain().contains("\n")) { + if (!selbi) selbi = model->getSelectedBranch(); + if (selbi) { + VymText heading = selbi->heading(); + if (heading.isRichText() || selbi->headingPlain().contains("\n")) { mainWindow->windowShowHeadingEditor(); ensureSelectionVisibleAnimated(); return; @@ -1217,10 +1565,11 @@ void MapEditor::editHeading() model->setSelectionBlocked(true); lineEdit = new QLineEdit; - QGraphicsProxyWidget *pw = mapScene->addWidget(lineEdit); - pw->setZValue(Z_LINEEDIT); + QGraphicsProxyWidget *proxyWidget = mapScene->addWidget(lineEdit); + // FIXME-3-FT get total rotation XXX for BC in scene and do "proxyWidget->setRotation(XXX); lineEdit->setCursor(Qt::IBeamCursor); lineEdit->setCursorPosition(1); + lineEdit->grabKeyboard(); #if defined(Q_OS_WINDOWS) QFont font = lineEdit->font(); @@ -1232,19 +1581,24 @@ void MapEditor::editHeading() QPointF br; qreal w = 230; qreal h = 30; - if (bo->getOrientation() != LinkableMapObj::LeftOfCenter) { - tl = bo->getOrnamentsBBox().topLeft(); + + BranchContainer *bc = selbi->getBranchContainer(); + if (bc->getOrientation() == BranchContainer::RightOfParent) { + tl = bc->headingRect().topLeft(); br = tl + QPointF(w, h); } else { - br = bo->getOrnamentsBBox().bottomRight(); + br = bc->headingRect().bottomRight(); tl = br - QPointF(w, h); } + // Qt bug when using QProxyWdiget in scaled QGraphicsView + // https://bugreports.qt.io/browse/QTBUG-48681 + // Still present in Qt 6.5 QRectF r(tl, br); lineEdit->setGeometry(r.toRect()); - pw->setGeometry(r.toRect()); + proxyWidget->setGeometry(r.toRect()); - minimizeView(); + minimizeView(); // LineEdit might exceed current view size, enlarge view if required // Set focus to MapEditor first // To avoid problems with Cursor up/down @@ -1265,20 +1619,19 @@ void MapEditor::editHeading() void MapEditor::editHeadingFinished() { - if (state != EditingHeading || !lineEdit ) { + if (editorState != EditingHeading || !lineEdit ) { qWarning() << "ME::editHeadingFinished not editing heading!"; } else { lineEdit->clearFocus(); + lineEdit->releaseKeyboard(); QString s = lineEdit->text(); - s.replace(QRegExp("\\n"), " "); // Don't paste newline chars + s.replace(QRegularExpression("\\n"), " "); // Don't paste newline chars if (s.length() == 0) s = " "; // Don't allow empty lines, which would screw up drawing model->setHeadingPlainText(s); delete (lineEdit); lineEdit = nullptr; - // FIXME-2 ensureAreaVisible like in starting editing? - // Maybe reselect previous branch mainWindow->editHeadingFinished(model); @@ -1297,20 +1650,17 @@ void MapEditor::contextMenuEvent(QContextMenuEvent *e) // mouseEvent, we don't need to close here. QPointF p = mapToScene(e->pos()); - TreeItem *ti = findMapItem(p, NULL); + TreeItem *ti = findMapItem(p); - if (ti) { // MapObj was found + if (ti) { model->select(ti); - LinkableMapObj *lmo = NULL; BranchItem *selbi = model->getSelectedBranch(); - if (ti) - lmo = ((MapItem *)ti)->getLMO(); // Context Menu - if (lmo && selbi) { + if (selbi) { QString sysFlagName; - QUuid uid = ((BranchObj *)lmo)->findSystemFlagUidByPos(p); + QUuid uid = selbi->getBranchContainer()->findFlagByPos(p); if (!uid.isNull()) { Flag *flag = systemFlagsMaster->findFlagByUid(uid); if (flag) @@ -1335,7 +1685,7 @@ void MapEditor::contextMenuEvent(QContextMenuEvent *e) } } } - else { // No MapObj found, we are on the Canvas itself + else { // No object or container found, we are on the Canvas itself // Context Menu on scene // Open context menu synchronously to position new mapcenter @@ -1352,49 +1702,27 @@ void MapEditor::keyPressEvent(QKeyEvent *e) // Ignore PageUP/Down to avoid scrolling with keys return; - if (e->modifiers() & Qt::ShiftModifier) { - switch (mainWindow->getModMode()) { - case Main::ModModePoint: - setCursor(Qt::ArrowCursor); - break; - case Main::ModModeColor: - setCursor(PickColorCursor); - break; - case Main::ModModeXLink: - setCursor(XLinkCursor); - break; - case Main::ModModeMoveObject: - setCursor(Qt::PointingHandCursor); - break; - case Main::ModModeMoveView: - setCursor(QPixmap(":/mode-move-view.png")); - break; - default: - setCursor(Qt::ArrowCursor); - break; - } - } + if (e->modifiers() & Qt::ShiftModifier) + updateCursor(); QGraphicsView::keyPressEvent(e); } void MapEditor::keyReleaseEvent(QKeyEvent *e) { - if (!(e->modifiers() & Qt::ControlModifier)) + if (!(e->modifiers() & Qt::ShiftModifier)) setCursor(Qt::ArrowCursor); } -void MapEditor::startMovingView(QMouseEvent *e) +void MapEditor::startPanningView(QMouseEvent *e) { - setState(MovingView); - movingObj = NULL; // move Content not Obj - movingObj_offset = e->globalPos(); - movingCont_start = - QPointF(horizontalScrollBar()->value(), verticalScrollBar()->value()); - movingVec = QPointF(0, 0); - setCursor(HandOpenCursor); + setState(PanningView); + panning_initialPointerPos = e->globalPosition().toPoint(); + panning_initialScrollBarValues = // Used for scrollbars when moving view + QPoint(horizontalScrollBar()->value(), verticalScrollBar()->value()); + setCursor(Qt::ClosedHandCursor); } -void MapEditor::mousePressEvent(QMouseEvent *e) +void MapEditor::mousePressEvent(QMouseEvent *e) // FIXME-3 Drop down dialog, if multiple tree items are found to select the "right" one { // Ignore right clicks if (e->button() == Qt::RightButton) { @@ -1404,18 +1732,16 @@ void MapEditor::mousePressEvent(QMouseEvent *e) } // Check if we need to reset zoomFactor for middle button + Ctrl - if (e->button() == Qt::MidButton && e->modifiers() & Qt::ControlModifier) { + if (e->button() == Qt::MiddleButton && e->modifiers() & Qt::ControlModifier) { setZoomFactorTarget(1); - setAngleTarget(0); + setRotationTarget(0); return; } - QPointF p = mapToScene(e->pos()); - TreeItem *ti_found = findMapItem(p, NULL); - LinkableMapObj *lmo_found = NULL; - if (ti_found) - lmo_found = ((MapItem *)ti_found)->getLMO(); + // Initial position of pointer in scene coordinates. See also e->globalPos (!) + movingObj_initialScenePos = mapToScene(e->pos()); + TreeItem *ti_found = findMapItem(movingObj_initialScenePos); // Allow selecting text in QLineEdit if necessary if (model->isSelectionBlocked()) { @@ -1425,196 +1751,182 @@ void MapEditor::mousePressEvent(QMouseEvent *e) } // Stop editing in LineEdit - if (state == EditingHeading) editHeadingFinished(); - - QString sysFlagName; - QUuid uid; - if (lmo_found) { - uid = ((BranchObj *)lmo_found)->findSystemFlagUidByPos(p); - if (!uid.isNull()) { - Flag *flag = systemFlagsMaster->findFlagByUid(uid); - if (flag) - sysFlagName = flag->getName(); - } - } + if (editorState == EditingHeading) editHeadingFinished(); /* qDebug() << "ME::mouse pressed\n"; - qDebug() << " lmo_found=" << lmo_found; qDebug() << " ti_found=" << ti_found; - //if (ti_found) qDebug() << " ti_found="<getHeading(); - qDebug() << " flag=" << sysFlagName; */ + //if (ti_found) qDebug() << " ti_found="<heading(); - // Check modifier key (before selecting object!) - if (ti_found && (e->modifiers() & Qt::ShiftModifier)) { - if (mainWindow->getModMode() == Main::ModModeColor) { - setState(PickingColor); - mainWindow->setCurrentColor(ti_found->getHeadingColor()); - if (e->modifiers() & Qt::ControlModifier) - model->colorBranch(ti_found->getHeadingColor()); - else - model->colorSubtree(ti_found->getHeadingColor()); - return; - } - - if (mainWindow->getModMode() == Main::ModModeMoveView) { - startMovingView(e); - return; - } - } - - // Check vymlink modifier (before selecting object!) - if (ti_found && sysFlagName == "system-vymLink") { - model->select(ti_found); - if (e->modifiers() & Qt::ControlModifier) { - if (e->modifiers() & Qt::ShiftModifier) - model->deleteVymLink(); - else - mainWindow->editOpenVymLink(true); - } else - mainWindow->editOpenVymLink(false); + // If Modifier mode "view" is set, all other clicks can be ignored, + // nothing will be selected + if ((e->modifiers() & Qt::ShiftModifier) && + mainWindow->getModMode() == Main::ModModeMoveView) { + startPanningView(e); return; } - // Select the clicked object, if not moving without linking - if (ti_found && (e->modifiers() & Qt::ShiftModifier)) { - if (mainWindow->getModMode() == Main::ModModePoint) { - model->selectToggle(ti_found); - lastToggleDirection = toggleUndefined; + BranchItem *selbi = model->getSelectedBranch(); + BranchContainer *selbc = nullptr; + if (selbi) { + selbc = selbi->getBranchContainer(); + + // XLink modifier, create new XLink + if (mainWindow->getModMode() == Main::ModModeXLink && + (e->modifiers() & Qt::ShiftModifier)) { + setState(CreatingXLink); + tmpXLink = new XLink(model); + tmpXLink->setBeginBranch(selbi); + tmpXLink->createXLinkObj(); + tmpXLink->setStyleBegin("None"); + tmpXLink->setStyleEnd("None"); + tmpXLink->setEndPoint(movingObj_initialScenePos); + tmpXLink->updateXLink(); + return; } } - else - model->select(ti_found); - e->accept(); + QString sysFlagName; - // Take care of remaining system flags _or_ modifier modes - if (lmo_found) { - if (!sysFlagName.isEmpty()) { - // systemFlag clicked - if (sysFlagName.contains("system-url")) { + if (ti_found) { + // Check modifier key (before selecting object!) + if (e->modifiers() & Qt::ShiftModifier) { + if (mainWindow->getModMode() == Main::ModModeColor) { + setState(PickingColor); + mainWindow->setCurrentColor(ti_found->headingColor()); if (e->modifiers() & Qt::ControlModifier) - mainWindow->editOpenURLTab(); + model->colorBranch(ti_found->headingColor()); else - mainWindow->editOpenURL(); + model->colorSubtree(ti_found->headingColor()); + return; } - else if (sysFlagName == "system-note") - mainWindow->windowToggleNoteEditor(); - else if (sysFlagName == "hideInExport") - model->toggleHideExport(); - else if (sysFlagName.startsWith("system-task-")) - model->cycleTaskStatus(); + + } + + // Check for flags on MousePress + if (selbc) { + QUuid uid = selbc->findFlagByPos(movingObj_initialScenePos); + if (!uid.isNull()) { + Flag *flag = systemFlagsMaster->findFlagByUid(uid); + if (flag) + sysFlagName = flag->getName(); + } + } + + // Check vymlink modifier (before selecting object!) + if (sysFlagName == "system-vymLink") { + model->select(ti_found); + if (e->modifiers() & Qt::ControlModifier) { + if (e->modifiers() & Qt::ShiftModifier) + model->deleteVymLink(); + else + mainWindow->editOpenVymLink(true); + } else + mainWindow->editOpenVymLink(false); return; } - else { - // Take care of xLink: Open context menu with targets - // if clicked near to begin of xlink - if (ti_found->xlinkCount() > 0 && - ti_found->getType() != TreeItem::MapCenter && - lmo_found->getBBox().width() > 30) { - if ((lmo_found->getOrientation() != - LinkableMapObj::RightOfCenter && - p.x() < lmo_found->getBBox().left() + 10) || - (lmo_found->getOrientation() != - LinkableMapObj::LeftOfCenter && - p.x() > lmo_found->getBBox().right() - 10)) { - // FIXME-4 similar code in mainwindow::updateActions - QMenu menu; - QList alist; - QList blist; - for (int i = 0; i < ti_found->xlinkCount(); i++) { - XLinkItem *xli = ti_found->getXLinkItemNum(i); - BranchItem *bit = xli->getPartnerBranch(); - if (bit) - alist.append( - new QAction(ti_found->getXLinkItemNum(i) - ->getPartnerBranch() - ->getHeadingPlain(), - &menu)); - } - menu.addActions(alist); - QAction *ra = menu.exec(e->globalPos()); - if (ra) - model->select(blist.at(alist.indexOf(ra))); - while (!alist.isEmpty()) { - QAction *a = alist.takeFirst(); - delete a; - } - return; - } + + // Select the clicked object, if not moving without linking + if (e->modifiers() & Qt::ShiftModifier) { + if (mainWindow->getModMode() == Main::ModModePoint) { + lastToggleDirection = toggleUndefined; + + model->selectToggle(ti_found); } + } else { + if (model->getSelectedItems().count() < 2 || !model->getSelectedItems().contains(ti_found)) + // Only add ti_found, if we don't have multi-selection yet, which we + // want to move around. In that case we would ignore the "pressed" event + model->select(ti_found); } - } + movingItems = model->getSelectedItemsReduced(); - // XLink modifier, create new XLink - BranchItem *selbi = model->getSelectedBranch(); - if (selbi && mainWindow->getModMode() == Main::ModModeXLink && - (e->modifiers() & Qt::ShiftModifier)) { - setState(DrawingLink); - tmpLink = new Link(model); - tmpLink->setBeginBranch(selbi); - tmpLink->createMapObj(); - tmpLink->setStyleBegin("None"); - tmpLink->setStyleEnd("None"); - tmpLink->setEndPoint(mapToScene(e->pos())); - tmpLink->updateLink(); - return; - } + // Make sure currently clicked item is first in list + int i = movingItems.indexOf(ti_found); + if (i > 0) + movingItems.move(i, 0); - // Start moving around - if (lmo_found) { // Left Button Move Branches if (e->button() == Qt::LeftButton) { // No system flag clicked, take care of moving modes or simply - // moving - movingObj_offset.setX(p.x() - lmo_found->x()); - movingObj_offset.setY(p.y() - lmo_found->y()); - movingObj_orgPos.setX(lmo_found->x()); - movingObj_orgPos.setY(lmo_found->y()); - if (ti_found->depth() > 0) { - lmo_found->setRelPos(); - movingObj_orgRelPos = lmo_found->getRelPos(); + // start moving + if (ti_found->hasTypeBranch()) + { + BranchContainer *bc = ((BranchItem*)ti_found)->getBranchContainer(); + movingObj_initialContainerOffset = movingObj_initialScenePos - bc->getHeadingContainer()->mapToScene(QPointF(0,0)); } if (mainWindow->getModMode() == Main::ModModeMoveObject && - e->modifiers() & Qt::ShiftModifier) { + e->modifiers() & Qt::ShiftModifier) { setState(MovingObjectWithoutLinking); } else setState(MovingObject); - movingObj = model->getSelectedLMO(); + // Set initial position and size of tmpParentContainer + // Required when ONLY moving images. + tmpParentContainer->setPos(movingObj_initialScenePos - movingObj_initialContainerOffset); + if (movingItems.count() > 0) { + qreal w = 0; + qreal h = 0; + BranchContainer *bc_first = nullptr; + foreach (TreeItem *ti, movingItems) { + if (ti->hasTypeBranch()) { + BranchContainer* bc = ((BranchItem*)ti)->getBranchContainer(); + if (!bc_first) + bc_first = bc; + w = max(w, bc->rect().width()); + h += bc->rect().height(); + } + } + if (bc_first) tmpParentContainer->setRect(bc_first->rect().left(), bc_first->rect().top(), w, h); + } } else - // Middle Button Toggle Scroll + // Middle Button - Toggle Scroll + // // (On Mac OS X this won't work, but we still have // a button in the toolbar) - if (e->button() == Qt::MidButton) - model->toggleScroll(); + if (e->button() == Qt::MiddleButton) + model->toggleScroll(); + } else { + // No ti_found, we are on the scene itself + // Left Button move Pos of sceneView + if (e->button() == Qt::LeftButton || + e->button() == Qt::MiddleButton) { + startPanningView(e); + return; + } } - else { // No lmo found, check XLinks - if (ti_found) { - if (ti_found->getType() == TreeItem::XLink) { - XLinkObj *xlo = (XLinkObj *)((MapItem *)ti_found)->getMO(); - if (xlo) { - setState(DrawingXLink); - int i = xlo->ctrlPointInClickBox(p); - if (i >= 0) - xlo->setSelection(i); - movingObj_offset.setX(p.x() - xlo->x()); - movingObj_offset.setY(p.y() - xlo->y()); - movingObj_orgPos.setX(xlo->x()); - movingObj_orgPos.setY(xlo->y()); - } - } + + e->accept(); + + // Take care of remaining system flags _or_ modifier modes + if (selbc) { + if (!sysFlagName.isEmpty()) { + // systemFlag clicked + if (sysFlagName.contains("system-url") || + sysFlagName.contains("system-jira") ) { + if (e->modifiers() & Qt::ControlModifier) + mainWindow->editOpenURLTab(); + else + mainWindow->editOpenURL(); + } else if (sysFlagName == "system-note") + mainWindow->windowToggleNoteEditor(); + else if (sysFlagName == "hideInExport") + model->toggleHideExport(); + else if (sysFlagName.startsWith("system-task-")) + model->cycleTaskStatus(); + return; } - else { // No MapObj found, we are on the scene itself - // Left Button move Pos of sceneView - if (e->button() == Qt::LeftButton || - e->button() == Qt::MiddleButton) { - startMovingView(e); - return; + } // system flags or modModes + else { // No selbc found, check XLinks + if (ti_found) { + if (ti_found->getType() == TreeItem::XLinkItemType) { + XLinkObj *xlo = ((XLinkItem *)ti_found)->getXLink()->getXLinkObj(); + if (xlo) + setState(EditingXLink); } } } @@ -1622,12 +1934,13 @@ void MapEditor::mousePressEvent(QMouseEvent *e) void MapEditor::mouseMoveEvent(QMouseEvent *e) { + QPointF p_event = mapToScene(e->pos()); + // Show mouse position for debugging in statusBar if (debug && e->modifiers() & Qt::ControlModifier) mainWindow->statusMessage( - QString("ME::mousePressEvent Scene: %1 widget: %2") - .arg(qpointFToString(mapToScene(e->pos()))) - .arg(qpointFToString(e->pos()))); + QString("ME::mouseMoveEvent Scene: %1 - Viewport: %2") + .arg(toS(p_event, 0), toS(e->pos()))); // Allow selecting text in QLineEdit if necessary if (model->isSelectionBlocked()) { @@ -1636,203 +1949,396 @@ void MapEditor::mouseMoveEvent(QMouseEvent *e) return; } - // Move sceneView - if (state == MovingView && - (e->buttons() == Qt::LeftButton || e->buttons() == Qt::MiddleButton)) { - QPointF p = e->globalPos(); - movingVec.setX(-p.x() + movingObj_offset.x()); - movingVec.setY(-p.y() + movingObj_offset.y()); + // Pan view + if (editorState == PanningView) { + QPointF pg = e->globalPosition(); + QPoint v_pan; + v_pan.setX(-pg.x() + panning_initialPointerPos.x()); + v_pan.setY(-pg.y() + panning_initialPointerPos.y()); horizontalScrollBar()->setSliderPosition( - (int)(movingCont_start.x() + movingVec.x())); + (int)(panning_initialScrollBarValues.x() + v_pan.x())); verticalScrollBar()->setSliderPosition( - (int)(movingCont_start.y() + movingVec.y())); + (int)(panning_initialScrollBarValues.y() + v_pan.y())); + // Avoid flickering scrollBarPosAnimation.stop(); viewCenterAnimation.stop(); - rotationAnimation.stop(); + // rotationAnimation.stop(); // zoomAnimation.stop(); return; } - TreeItem *seli = model->getSelectedItem(); - - MapObj *mosel = NULL; - if (seli) - mosel = ((MapItem *)seli)->getMO(); - - // If not already happened during mousepress, we might need to switch state + // After clicking object shift might have been pressed, adjust state then if (mainWindow->getModMode() == Main::ModModeMoveObject && - e->modifiers() & Qt::ShiftModifier && e->buttons() == Qt::LeftButton) { - state = MovingObjectWithoutLinking; - } + e->modifiers() & Qt::ShiftModifier && editorState == MovingObject) { + setState(MovingObjectWithoutLinking); + } + + // Move the selected items + if (movingItems.count() > 0 && + (editorState == MovingObject || + editorState == MovingObjectTmpLinked || + editorState == MovingObjectWithoutLinking || + editorState == EditingXLink)) { + + if (!(e->buttons() & Qt::LeftButton)) { + // Sometimes at least within a VM there might be a + // release event lost, while still the mousePress event is processed + // + // So moving without a pressed left button is considered a "release" + mouseReleaseEvent(e); + return; + } - // Move the selected MapObj - if (mosel && - (state == MovingObject || state == MovingObjectWithoutLinking || - state == DrawingXLink)) { int margin = 50; // Check if we have to scroll + QPointF p = e->position(); vPan.setX(0); vPan.setY(0); - if (e->y() >= 0 && e->y() <= margin) - vPan.setY(e->y() - margin); - else if (e->y() <= height() && e->y() > height() - margin) - vPan.setY(e->y() - height() + margin); - if (e->x() >= 0 && e->x() <= margin) - vPan.setX(e->x() - margin); - else if (e->x() <= width() && e->x() > width() - margin) - vPan.setX(e->x() - width() + margin); - - pointerPos = e->pos(); - pointerMod = e->modifiers(); - moveObject(); + if (p.y() >= 0 && p.y() <= margin) + vPan.setY(p.y() - margin); + else if (p.y() <= height() && p.y() > height() - margin) + vPan.setY(p.y() - height() + margin); + if (p.x() >= 0 && p.x() <= margin) + vPan.setX(p.x() - margin); + else if (p.x() <= width() && p.x() > width() - margin) + vPan.setX(p.x() - width() + margin); + + moveObject(e, p_event); } // selection && moving_obj // Draw a link from one branch to another - if (state == DrawingLink) { - tmpLink->setEndPoint(mapToScene(e->pos())); - tmpLink->updateLink(); + if (editorState == CreatingXLink) { + tmpXLink->setEndPoint(p_event); + tmpXLink->updateXLink(); } } -void MapEditor::moveObject() +void MapEditor::moveObject(QMouseEvent *e, const QPointF &p_event) { + bool repositionRequired = false; + bool updateUpLinksRequired = false; + + // If necessary pan the view using animation if (!panningTimer->isActive()) panningTimer->start(50); - QPointF p = mapToScene(pointerPos); - TreeItem *seli = model->getSelectedItem(); - LinkableMapObj *lmosel = NULL; - if (seli) - lmosel = ((MapItem *)seli)->getLMO(); - - objectMoved = true; - // reset cursor if we are moving and don't copy - // Check if we could link - TreeItem *ti_found = findMapItem(p, seli); - BranchItem *bi_dst = NULL; - LinkableMapObj *lmo_dst = NULL; - if (ti_found && ti_found != seli && ti_found->isBranchLikeType()) { - bi_dst = (BranchItem *)ti_found; - lmo_dst = bi_dst->getLMO(); - } - else - bi_dst = NULL; - - if (lmosel) { - if (seli->getType() == TreeItem::Image) { - FloatImageObj *fio = (FloatImageObj *)lmosel; - fio->moveCenter(p.x() - movingObj_offset.x(), - p.y() - movingObj_offset.y()); - fio->setRelPos(); - fio->updateLinkGeometry(); // no need for reposition, if we update - // link here - model->emitSelectionChanged(); // position has changed - - // Relink float to new mapcenter or branch, if shift is pressed - // Only relink, if selection really has a new parent - if (pointerMod == Qt::ShiftModifier && bi_dst && - bi_dst != seli->parent()) { - // Also save the move which was done so far - QString pold = qpointFToString(movingObj_orgRelPos); - QString pnow = qpointFToString(fio->getRelPos()); - model->saveState(seli, "moveRel " + pold, seli, - "moveRel " + pnow, - QString("Move %1 to relative position %2") - .arg(model->getObjectName(lmosel)) - .arg(pnow)); - model->reposition(); - - model->relinkImage((ImageItem *)seli, bi_dst); - model->select(seli); + // Check if we could link (temporary). Consider also "near" mapCenters. + TreeItem *targetItem = findMapItem(p_event, movingItems, true); + + // Check, if targetItem is a child of one of the moving items + if (targetItem) { + foreach (TreeItem *ti, movingItems) { + if (targetItem->isChildOf(ti)) { + // qWarning() << "ME::moveObject " << targetItem->headingPlain() << "is child of " << ti->headingPlain(); + targetItem = nullptr; + break; } } - else if (seli->isBranchLikeType()) { // selection != a FloatObj - if (seli->depth() == 0) { - // Move mapcenter - lmosel->move(p - movingObj_offset); - if (pointerMod == Qt::ControlModifier) { - // Move only mapcenter, leave its children where they are - QPointF v; - v = lmosel->getAbsPos(); - for (int i = 0; i < seli->branchCount(); ++i) { - seli->getBranchObjNum(i)->setRelPos(); - seli->getBranchObjNum(i)->setOrientation(); + } + + // Add selected branches and images temporary to tmpParentContainer, + // if they are not there yet: + BranchContainer *bc_first = nullptr; + BranchContainer *bc_prev = nullptr; + if (movingItems.count() > 0 && (tmpParentContainer->childrenCount() == 0)) { + BranchContainer *bc; + foreach (TreeItem *ti, movingItems) + { + // The item structure in VymModel remaines untouched so far, + // only containers will be reparented temporarily! + if (ti->hasTypeBranch()) { + BranchItem *bi = (BranchItem*)ti; + bc = bi->getBranchContainer(); + + if (!bc_first) { + bc_first = bc; + + // Initially set orientation of tmpParentContainer to first BranchContainer + if (bc->getOrientation() == BranchContainerBase::UndefinedOrientation) { + // Orientation undefined for MapCenters, assume RightOfParent + tmpParentContainer->setOrientation(BranchContainerBase::RightOfParent); + } else + tmpParentContainer->setOrientation(bc->getOrientation()); + } + + if (tmpParentContainer->branchCount() == 0 || + bc->parentItem() != tmpParentContainer->getBranchesContainer()) { + + // Save position of children branches in case we only want to + // move this branch and keep children unchanged using CTRL modifier + if (bc->hasFloatingBranchesLayout()) { + foreach(BranchContainer *bc2, bc->childBranches()) + bc2->setOriginalScenePos(); } + + bc->setOriginalPos(); + bc->setOriginalOrientation(); // Also sets originalParentBranchContainer + tmpParentContainer->addToBranchesContainer(bc); + + } + + if (bc_first && bc_first != bc) { + QPointF p; + // Animate other items to position horizontally centered below first one + if (bc_first->getOriginalOrientation() == BranchContainer::RightOfParent) { + p = tmpParentContainer->mapFromItem(bc, + bc->alignTo(Container::TopLeft, bc_prev, Container::BottomLeft)); + } else if (bc_first->getOriginalOrientation() == BranchContainer::LeftOfParent) + p = tmpParentContainer->mapFromItem(bc, + bc->alignTo(Container::TopRight, bc_prev, Container::BottomRight)); + else + p = tmpParentContainer->mapFromItem(bc, + bc->alignTo(Container::TopCenter, bc_prev, Container::BottomCenter)); + + startAnimation ( bc, bc->pos(), p); + } + bc_prev = bc; + } else if (ti->hasTypeImage()) { + ImageContainer *ic = ((ImageItem*)ti)->getImageContainer(); + if (ic->parentItem() != tmpParentContainer->getImagesContainer()) { + ic->setOriginalPos(); + tmpParentContainer->addToImagesContainer(ic); + } + } + else if (ti->getType() == TreeItem::XLinkItemType) { + // Move XLink control point + XLinkObj *xlo = ((XLinkItem *)ti)->getXLinkObj(); + if (xlo) { + xlo->setSelectedCtrlPoint(p_event); // FIXME-3 Missing savestate + model->setChanged(); } } - else { - if (seli->depth() == 1) { - // Move mainbranch - if (!lmosel->hasParObjTmp()) - lmosel->move(p - movingObj_offset); - lmosel->setRelPos(); + else + qWarning("ME::moveObject Huh? I'm confused. No BC, IC or XLink moved"); + } + } // add to tmpParentContainer + + if (tmpParentContainer->childBranches().count() > 0) + // If ME::moveObject is called AFTER tPC has been filled previously, + // bc_first still might be unset here + bc_first = tmpParentContainer->childBranches().first(); + + BranchContainer *targetBranchContainer = nullptr; + + // Check if we are moving a branch and could relink. Position tmpParentContainer + if (targetItem && targetItem->hasTypeBranch() && bc_first && + !(mainWindow->getModMode() == Main::ModModeMoveObject && + (e->modifiers() & Qt::ShiftModifier))) { + setState(MovingObjectTmpLinked); + + targetBranchContainer = ((BranchItem*)targetItem)->getBranchContainer(); + + Container *targetRefContainer = targetBranchContainer->getHeadingContainer(); + Container *movingRefContainer = bc_first->getHeadingContainer(); + Container::PointName targetRefPointName; + Container::PointName movingRefPointName; + QPointF linkOffset; // Distance for temporary link + + BranchContainer *tbc = targetBranchContainer->parentBranchContainer(); + if (e->modifiers() & Qt::ShiftModifier && tbc) { + qreal dy = targetBranchContainer->rect().height() / 2; + targetBranchContainer = targetBranchContainer->parentBranchContainer(); + + if (targetBranchContainer->getOrientation() == BranchContainer::RightOfParent) { + // Shift modifier: Link right above + targetRefPointName = Container::BottomRight; + movingRefPointName = Container::BottomLeft; + linkOffset = QPointF(model->mapDesign()->linkWidth(), - dy); + } else if (targetBranchContainer->getOrientation() == BranchContainer::LeftOfParent) { + // Shift modifier: Link left above + targetRefPointName = Container::TopLeft; + movingRefPointName = Container::BottomRight; + linkOffset = QPointF(- model->mapDesign()->linkWidth(), dy); + } // else: Undefined orientation is handled with hasFloatingLayout() below! + } else if (e->modifiers() & Qt::ControlModifier && tbc) { + qreal dy = targetBranchContainer->rect().height() / 2; + targetBranchContainer = targetBranchContainer->parentBranchContainer(); + if (targetBranchContainer->getOrientation() == BranchContainer::RightOfParent) { + // Control modifier: Link right below + targetRefPointName = Container::TopRight; + movingRefPointName = Container::TopLeft; + linkOffset = QPointF(model->mapDesign()->linkWidth(), dy); + } else if (targetBranchContainer->getOrientation() == BranchContainer::LeftOfParent) { + // Control modifier: Link left below + targetRefPointName = Container::TopLeft; + movingRefPointName = Container::TopRight; + linkOffset = QPointF(- model->mapDesign()->linkWidth(), dy); + } // else: Undefined orientation is handled with hasFloatingLayout() below! + } else { + // No modifier used, temporary link to target itself + targetRefContainer = targetBranchContainer->getBranchesContainer(); + movingRefContainer = tmpParentContainer; + if (targetBranchContainer->getOrientation() == BranchContainer::RightOfParent) { + if (targetBranchContainer->branchCount() == 0) { + // vertically centered besides target + targetRefPointName = Container::RightCenter; + movingRefPointName = Container::LeftCenter; + linkOffset = QPointF(model->mapDesign()->linkWidth(), 0); + } else { + // Below target + targetRefPointName = Container::BottomLeft; + movingRefPointName = Container::TopLeft; } - else { - // d>1, move ordinary branch - if (lmosel->getOrientation() == - LinkableMapObj::LeftOfCenter) - // Add width of bbox here, otherwise alignRelTo will - // cause jumping around - lmosel->move(p.x() - movingObj_offset.x(), - p.y() - movingObj_offset.y() + - lmosel->getTopPad()); - else - lmosel->move(p.x() - movingObj_offset.x(), - p.y() - movingObj_offset.y() - - lmosel->getTopPad()); - BranchItem *selbi = ((BranchItem *)seli); - if (selbi->parentBranch()->getChildrenLayout() == - BranchItem::FreePositioning) - lmosel->setRelPos(); + } else if (targetBranchContainer->getOrientation() == BranchContainer::LeftOfParent) { + if (targetBranchContainer->branchCount() == 0) { + // vertically centered besides target + targetRefPointName = Container::LeftCenter; + movingRefPointName = Container::RightCenter; + linkOffset = QPointF(- model->mapDesign()->linkWidth(), 0); + } else { + // Below target + targetRefPointName = Container::BottomRight; + movingRefPointName = Container::TopRight; } + } // else: Undefined orientation is handled with hasFloatingLayout() below! + } - } // depth>0 + if (!targetRefContainer) + targetRefContainer = ((BranchItem*)targetItem)->getBranchContainer(); - // Maybe we can relink temporary? - if (bi_dst && state != MovingObjectWithoutLinking) { - if (pointerMod == Qt::ControlModifier) { - // Special case: CTRL to link below dst - lmosel->setParObjTmp(lmo_dst, p, +1); - } - else if (pointerMod == Qt::ShiftModifier) - lmosel->setParObjTmp(lmo_dst, p, -1); - else - lmosel->setParObjTmp(lmo_dst, p, 0); - } + // Align tmpParentContainer + if (targetBranchContainer->hasFloatingBranchesLayout()) { + // When temporary linking e.g. to MapCenter, position on a circle around MC + + qreal radius = 80; + + QPointF center_sp = targetBranchContainer->getHeadingContainer()->mapToScene(QPointF(0,0)); + qreal a = getAngle(p_event - center_sp); + QPointF p_hint = center_sp + QPointF (radius * cos(a), - radius * sin(a)); + + tmpParentContainer->setPos(p_hint); + } else + // Temporary link to branchContainers of targetRefContainer. Use position calculated above + tmpParentContainer->setPos( + linkOffset + movingRefContainer->mapToScene( + movingRefContainer->alignTo( + movingRefPointName, targetRefContainer, targetRefPointName))); + + // Set states of MapEditor and tPC + if (tmpParentContainer->movingState() != BranchContainerBase::TemporaryLinked) { + // Link tmpParentContainer temporarily to targetBranchContainer + + tmpParentContainer->setMovingState(SelectableContainer::TemporaryLinked, targetBranchContainer); + setState(MovingObjectTmpLinked); + } + + repositionRequired = true; + + } // tmp linking to target + else { + // Move without temporary relinking to a target + // + // Update state of MapEditor + if (mainWindow->getModMode() == Main::ModModeMoveObject && + e->modifiers() & Qt::ShiftModifier) + setState(MovingObjectWithoutLinking); + else + setState(MovingObject); + + if (tmpParentContainer->movingState() == BranchContainerBase::TemporaryLinked) + tmpParentContainer->setMovingState(SelectableContainer::Moving); + + updateUpLinksRequired = true; + } + + // Update states of children branch containers (for updating links later) + foreach (BranchContainer *bc, tmpParentContainer->childBranches()) { + if (tmpParentContainer->movingState() == BranchContainerBase::TemporaryLinked) + bc->setMovingState(SelectableContainer::TemporaryLinked, targetBranchContainer); + else + bc->setMovingState(SelectableContainer::Moving); + } + foreach (ImageContainer *ic, tmpParentContainer->childImages()) { + if (tmpParentContainer->movingState() == BranchContainerBase::TemporaryLinked) + ic->setMovingState(SelectableContainer::TemporaryLinked, targetBranchContainer); + else + ic->setMovingState(SelectableContainer::Moving); + } + + // Set orientation + BranchContainer::Orientation newOrientation; + Container *tpc_bc = tmpParentContainer->getBranchesContainer(); + if (targetBranchContainer && tpc_bc && !tpc_bc->childItems().contains(targetBranchContainer)) { + // tmpParentContainer has children and these do NOT contain targetBranchContainer + + if (targetBranchContainer->hasFloatingBranchesLayout()) { + if (p_event.x() > targetBranchContainer->getHeadingContainer()->mapToScene(QPointF(0,0)).x()) + newOrientation = BranchContainer::RightOfParent; else - lmosel->unsetParObjTmp(); - - // reposition subbranch - lmosel->reposition(); - - QItemSelection sel = model->getSelectionModel()->selection(); - updateSelection(sel, sel); // position has changed - - // In winter mode shake snow from heading - if (winter) - model->emitDataChanged(seli); - } // Moving branchLikeType - } // End of lmosel != NULL - else if (seli && seli->getType() == TreeItem::XLink) { - // Move XLink control point - MapObj *mosel = ((MapItem *)seli)->getMO(); - if (mosel) { - mosel->move(p - movingObj_offset); // FIXME-3 Missing savestate - model->setChanged(); - model->emitSelectionChanged(); + newOrientation = BranchContainer::LeftOfParent; + } else { + // Relinking to other branch + newOrientation = targetBranchContainer->getOrientation(); } + } else { + // No target branch + + if (bc_first) { + // Set new orientation for branches (not mapCenters): Consider pointer pos relative to first moving branch + if (p_event.x() > bc_first->getOriginalParentPos().x() && !(e->modifiers() & Qt::ControlModifier)) + newOrientation = BranchContainer::RightOfParent; + else + newOrientation = BranchContainer::LeftOfParent; + } else + // No target and no branch moving. No orientation change. + newOrientation = tmpParentContainer->getOrientation(); } - else - qWarning("ME::moveObject Huh? I'm confused."); - scene()->update(); + // Reposition if required + if (newOrientation != tmpParentContainer->getOrientation()) { + // tPC has BoundingFloats layout, still children need orientation + tmpParentContainer->setOrientation(newOrientation); + repositionRequired = true; + } + + if (repositionRequired) { + if (bc_first && targetBranchContainer && targetBranchContainer->hasFloatingBranchesLayout()) { + foreach(BranchContainer *bc, tmpParentContainer->childBranches()) + bc->setOrientation(newOrientation); + } + tmpParentContainer->reposition(); + } + + if (!targetBranchContainer) { + // Above tPC was positioned only if there is a target, so now tPC->setPos() is required if there is no target + // Since orientation might have changed and position depends on orientation, only do this now + if (bc_first) { + QPointF hc_center = tmpParentContainer->mapFromItem(bc_first->getHeadingContainer(), bc_first->getHeadingContainer()->pos()); + tmpParentContainer->setPos(p_event - hc_center - movingObj_initialContainerOffset); + + // When moving with Ctrl modifier, don't children branches (in scene) + if (e->modifiers() & Qt::ControlModifier) { + foreach(BranchContainer *bc, tmpParentContainer->childBranches()) { + if (bc->hasFloatingBranchesLayout()) { + foreach(BranchContainer *bc2, bc->childBranches()) { + QPointF q = bc->getHeadingContainer()->sceneTransform().inverted().map(bc2->getOriginalPos()); + bc2->setPos(q); + bc2->updateUpLink(); + } + } + } + } + + } else + // No branches, only image + tmpParentContainer->setPos(p_event - movingObj_initialContainerOffset); - return; + } + + if (updateUpLinksRequired) { + foreach(BranchContainer *bc, tmpParentContainer->childBranches()) + bc->updateUpLink(); + + foreach(ImageContainer *ic, tmpParentContainer->childImages()) + ic->updateUpLink(); + } + + model->repositionXLinks(); } void MapEditor::mouseReleaseEvent(QMouseEvent *e) @@ -1845,23 +2351,18 @@ void MapEditor::mouseReleaseEvent(QMouseEvent *e) } QPointF p = mapToScene(e->pos()); - TreeItem *seli = model->getSelectedItem(); - TreeItem *dsti = NULL; - if (seli) - dsti = findMapItem(p, seli); - LinkableMapObj *dst = NULL; - BranchItem *selbi = model->getSelectedBranch(); - if (dsti && dsti->isBranchLikeType()) - dst = ((MapItem *)dsti)->getLMO(); - else - dsti = NULL; + BranchItem *destinationBranch; + + destinationBranch = findMapBranchItem(p, movingItems, true); + + bool repositionNeeded = false; // Have we been picking color? - if (state == PickingColor) { + if (editorState == PickingColor) { setCursor(Qt::ArrowCursor); // Check if we are over another branch - if (dst) { + if (destinationBranch) { if (e->modifiers() & Qt::ShiftModifier) model->colorBranch(mainWindow->getCurrentColor()); else @@ -1872,173 +2373,172 @@ void MapEditor::mouseReleaseEvent(QMouseEvent *e) } // Have we been drawing a link? - if (state == DrawingLink) { + if (editorState == CreatingXLink) { setState(Neutral); + // Check if we are over another branch - if (dsti) { - tmpLink->setEndBranch(((BranchItem *)dsti)); - tmpLink->activate(); - tmpLink->updateLink(); - if (model->createLink(tmpLink)) { - model->saveState( - tmpLink->getBeginLinkItem(), "remove ()", seli, - QString("addXLink (\"%1\",\"%2\",%3,\"%4\",\"%5\")") - .arg(model->getSelectString(tmpLink->getBeginBranch())) - .arg(model->getSelectString(tmpLink->getEndBranch())) - .arg(tmpLink->getPen().width()) - .arg(tmpLink->getPen().color().name()) - .arg(penStyleToString(tmpLink->getPen().style())), - QString("Adding Link from %1 to %2") - .arg(model->getObjectName(seli)) - .arg(model->getObjectName(dsti))); - return; - } + if (destinationBranch) { + tmpXLink->setEndBranch(destinationBranch); + tmpXLink->activate(); + tmpXLink->updateXLink(); + if (model->createXLink(tmpXLink)) return; } - delete (tmpLink); - tmpLink = NULL; + delete (tmpXLink); + tmpXLink = nullptr; return; } // Have we been moving something? - if (seli && state == MovingObject) { + if (editorState == MovingObject || editorState == MovingObjectTmpLinked) { panningTimer->stop(); - if (seli->getType() == TreeItem::Image) { - FloatImageObj *fio = (FloatImageObj *)(((MapItem *)seli)->getLMO()); - if (fio) { - // Moved Image, we need to reposition - QString pold = qpointFToString(movingObj_orgRelPos); - QString pnow = qpointFToString(fio->getRelPos()); - model->saveState(seli, "moveRel " + pold, seli, - "moveRel " + pnow, - QString("Move %1 to relative position %2") - .arg(model->getObjectName(seli)) - .arg(pnow)); - - model->emitDataChanged( - seli->parent()); // Parent of image has changed - model->reposition(); - } - } - - if (selbi && selbi->depth() == 0) { - if (movingObj_orgPos != selbi->getBranchObj()->getAbsPos()) { - QString pold = qpointFToString(movingObj_orgPos); - QString pnow = - qpointFToString(selbi->getBranchObj()->getAbsPos()); - model->saveState(selbi, "move " + pold, selbi, "move " + pnow, - QString("Move mapcenter %1 to position %2") - .arg(model->getObjectName(selbi)) - .arg(pnow)); + // Check if we have a destination and should relink + if (destinationBranch && editorState != MovingObjectWithoutLinking) { + // Restore list of selected items later + + // Prepare relinking + BranchItem *dst_branch = destinationBranch; + int dst_num = -1; + + if (e->modifiers() & Qt::ShiftModifier && destinationBranch->parent()) { + // Link above dst + dst_branch = destinationBranch->parentBranch(); + dst_num = destinationBranch->num(); + } else if (e->modifiers() & Qt::ControlModifier && destinationBranch->parent()) { + // Link below dst + dst_branch = destinationBranch->parentBranch(); + dst_num = destinationBranch->num() + 1; } - } - - if (seli->isBranchLikeType()) //(seli->getType() == TreeItem::Branch ) - { // A branch was moved - LinkableMapObj *lmosel = NULL; - lmosel = ((MapItem *)seli)->getLMO(); - - // save the position in case we link to mapcenter - QPointF savePos = QPointF(lmosel->getAbsPos()); - - // Reset the temporary drawn link to the original one - lmosel->unsetParObjTmp(); - // For Redo we may need to save original selection - QString preSelStr = model->getSelectString(seli); + // Tell VymModel to relink + QList movingBranches; + foreach(BranchContainer *bc, tmpParentContainer->childBranches()) { + bc->setMovingState(SelectableContainer::NotMoving); + movingBranches << bc->getBranchItem(); + } - if (dsti && objectMoved && state != MovingObjectWithoutLinking) { - // We have a destination, relink to that - BranchObj *selbo = model->getSelectedBranchObj(); - QString preParStr = model->getSelectString(seli->parent()); - QString preNum = QString::number(seli->num(), 10); - QString preDstParStr; + if (!movingBranches.isEmpty()) + model->relinkBranches( + movingBranches, + dst_branch, + dst_num); + // If dst is scrolled, select it + if (dst_branch->isScrolled()) + model->select(dst_branch); - if (e->modifiers() & Qt::ShiftModifier && - dsti->parent()) { // Link above dst - preDstParStr = model->getSelectString(dsti->parent()); - model->relinkBranch((BranchItem *)seli, - (BranchItem *)dsti->parent(), - ((BranchItem *)dsti)->num(), true); - } - else if (e->modifiers() & Qt::ControlModifier && - dsti->parent()) { - // Link below dst - preDstParStr = model->getSelectString(dsti->parent()); - model->relinkBranch((BranchItem *)seli, - (BranchItem *)dsti->parent(), - ((BranchItem *)dsti)->num() + 1, true); - } - else { // Append to dst - preDstParStr = model->getSelectString(dsti); - model->relinkBranch((BranchItem *)seli, (BranchItem *)dsti, - -1, true, movingObj_orgPos); - if (dsti->depth() == 0) - selbo->move(savePos); - } + // Loop over images // FIXME-3 refactor in VM similar to relinkBranches + foreach(ImageContainer *ic, tmpParentContainer->childImages()) { + ImageItem *ii = ic->getImageItem(); + model->relinkImage(ii, destinationBranch); } - else { - // No destination, undo temporary move - - if (seli->depth() == 1) { - // The select string might be different _after_ moving - // around. Therefor reposition and then use string of old - // selection, too - model->reposition(); - - QPointF rp(lmosel->getRelPos()); - if (rp != movingObj_orgRelPos) { - QString ps = qpointFToString(rp); - model->saveState( - model->getSelectString(lmosel), - "moveRel " + qpointFToString(movingObj_orgRelPos), - preSelStr, "moveRel " + ps, - QString("Move %1 to relative position %2") - .arg(model->getObjectName(lmosel)) - .arg(ps)); - } - } - if (selbi->parentBranch()->getChildrenLayout() == - BranchItem::FreePositioning) { - lmosel->setRelPos(); - model->reposition(); + if (!tmpParentContainer->childImages().isEmpty()) { + foreach(ImageContainer *ic, tmpParentContainer->childImages()) { + ImageItem *ii = ic->getImageItem(); + model->selectToggle(ii); } - else { - - // Draw the original link, before selection was moved around - if (settings.value("/animation/use", true).toBool() && - seli->depth() > 1 - // && distance - //(lmosel->getRelPos(),movingObj_orgRelPos)<3 - ) { - lmosel->setRelPos(); // calc relPos first for starting - // point - - model->startAnimation((BranchObj *)lmosel, - lmosel->getRelPos(), - movingObj_orgRelPos); + } + } else { + // Branches moved, but not relinked + + QList childBranches = tmpParentContainer->childBranches(); + QList animationCurrentPositions; // After reposition start animations + QList animationContainers; + + if (!childBranches.isEmpty()) { + repositionNeeded = true; + + // We begin a saveStateScript. If nothing is really moved, this + // Script will be discarded later + model->saveStateBeginScript( + QString("Move %1 branch(es)").arg(childBranches.count()) + ); + + // Empty the tmpParentContainer, which is used for moving + // Updating the stacking order also resets the original parents + foreach(BranchContainer *bc, childBranches) { + BranchItem *bi = bc->getBranchItem(); + + bc->setMovingState(SelectableContainer::NotMoving); + + if (bc->isAnimated()) + bc->stopAnimation(); + + // Relink container to original parent container + // and keep (!) current absolute position + bi->updateContainerStackingOrder(); + + // Floating layout e.g. MapCenter + if (bc->isFloating()) + { + if (bi->depth() == 0) + // MapCenter + bc->setPos(bc->getHeadingContainer()->mapToScene(QPointF(0, 0))); + // Save position change + QString uc, rc; + uc = QString("setPos%1;").arg(toS(bc->getOriginalPos(), 5)); + rc = QString("setPos%1;").arg(toS(bc->pos(), 5)), + model->saveStateBranch(bi, uc, rc, QString("Move branch to %1").arg(toS(bc->pos()))); + } else { + if (!(e->modifiers() & Qt::ControlModifier)) { + // only animate snappack if not Ctrl-moving e.g. MC + animationContainers << bc; + animationCurrentPositions << bc->pos(); + } } - else - model->reposition(); + } // children of tmpParentContainer + model->saveStateEndScript(); + } // Empty tmpParenContainer + + if (animationUse && animationContainers.count() > 0) { + int i = 0; + foreach(BranchContainer *bc, animationContainers) { + startAnimation(bc, animationCurrentPositions.at(i), bc->getOriginalPos()); + i++; } } + } // Branches moved, but not relinked + + // Let's see if we moved images with tmpParentContainer + if (tmpParentContainer->childImages().count() > 0 ) { + repositionNeeded = true; } + + foreach(ImageContainer *ic, tmpParentContainer->childImages()) { + ImageItem *ii = ic->getImageItem(); + BranchItem *pi = ii->parentBranch(); + + // Update parent of moved container to original imageContainer + // in parent branch + pi->addToImagesContainer(ic); + + QString pold = toS(ic->getOriginalPos(), 5); + QString pnew = toS(ic->pos(), 5); + QString com = QString("Move image to %1").arg(pnew); + QString iv = model->setImageVar(ii); + QString uc = iv + QString("i.setPos%1;").arg(pold); + QString rc = iv + QString("i.setPos%1;").arg(pnew); + model->saveState(uc, rc, com); + } // Image moved, but not relinked + // Finally resize scene, if needed scene()->update(); - movingObj = NULL; - objectMoved = false; vPan = QPoint(); - } - else - // maybe we moved View: set old cursor - setCursor(Qt::ArrowCursor); + } // MovingObject or MovingObjecttmpXLinked - if (state != EditingHeading) + if (editorState != EditingHeading) { setState(Neutral); // Continue editing after double click! + } + // Restore cursor + updateCursor(); + + movingItems.clear(); QGraphicsView::mouseReleaseEvent(e); + + if (repositionNeeded) + model->reposition(); } void MapEditor::mouseDoubleClickEvent(QMouseEvent *e) @@ -2052,22 +2552,19 @@ void MapEditor::mouseDoubleClickEvent(QMouseEvent *e) if (e->button() == Qt::LeftButton) { QPointF p = mapToScene(e->pos()); - TreeItem *ti = findMapItem(p, NULL); - LinkableMapObj *lmo; + TreeItem *ti = findMapItem(p); if (ti) { - if (state == EditingHeading) + if (editorState == EditingHeading) editHeadingFinished(); model->select(ti); BranchItem *selbi = model->getSelectedBranch(); if (selbi) { - lmo = ((MapItem *)ti)->getLMO(); - if (lmo) { - QUuid uid = ((BranchObj *)lmo)->findSystemFlagUidByPos(p); + BranchContainer *bc = selbi->getBranchContainer(); + QUuid uid = bc->findFlagByPos(p); - // Don't edit heading when double clicking system flag: - if (!uid.isNull()) - return; - } + // Don't edit heading when double clicking flag: + if (!uid.isNull()) + return; } e->accept(); editHeading(); @@ -2079,16 +2576,34 @@ void MapEditor::wheelEvent(QWheelEvent *e) { if (e->modifiers() & Qt::ControlModifier && e->angleDelta().y() != 0) { - QPointF p = mapToScene(e->position().toPoint()); - if (e->angleDelta().y() > 0) - // setZoomFactorTarget (zoomFactorTarget*1.15); - setViewCenterTarget(p, zoomFactorTarget * 1.15, angleTarget); - else - // setZoomFactorTarget (zoomFactorTarget*0.85); - setViewCenterTarget(p, zoomFactorTarget * 0.85, angleTarget); + + qreal f_vp; + qreal f_zf; + if (e->angleDelta().y() > 0) { + // Zoom in + f_vp = 1 - zoomDelta; // vector to center of viewport shrinks + f_zf = 1 + zoomDelta + 0.046; // view transformation grows + } else { + // Zoom out + f_vp = 1 + zoomDelta; + f_zf = 1 - zoomDelta + 0.046; + } + + if (rotationAnimation.state() == QAbstractAnimation::Running) + rotationAnimation.stop(); + + transformationOrigin = mapToScene(e->position().toPoint()); + vp_center = mapToScene(viewport()->rect().center()); + + // Calculate center of scaled viewport with p as transformation origin + vp_center = (vp_center - transformationOrigin) * f_vp + transformationOrigin; + + useTransformationOrigin = true; + //setZoomFactorTarget(zoomFactorTargetInt * f_zf); + setViewCenterTarget(vp_center, zoomFactorTargetInt * f_zf, rotationTargetInt); } else { - scrollBarPosAnimation.stop(); + stopViewAnimations(); QGraphicsView::wheelEvent(e); } } @@ -2096,7 +2611,7 @@ void MapEditor::wheelEvent(QWheelEvent *e) void MapEditor::focusOutEvent(QFocusEvent *) { // qDebug()<<"ME::focusOutEvent"<reason(); - if (state == EditingHeading) + if (editorState == EditingHeading) editHeadingFinished(); } @@ -2130,11 +2645,11 @@ void MapEditor::dropEvent(QDropEvent *event) qDebug() << " enc:" << url.toEncoded(); qDebug() << " valid:" << url.isValid(); } - qDebug() << "============== mimeData ==================="; + qDebug() << "-------------- mimeData -------------------"; qDebug() << "has-img : " << event->mimeData()->hasImage(); qDebug() << "has-urls: " << event->mimeData()->hasUrls(); qDebug() << " text: " << event->mimeData()->text(); - qDebug() << "==========================================="; + qDebug() << "-------------------------------------------"; } if (event->mimeData()->hasUrls()) { @@ -2145,13 +2660,13 @@ void MapEditor::dropEvent(QDropEvent *event) QByteArray ba = event->mimeData()->urls().first().path().toLatin1(); QByteArray ba2; - for (int i = 0; i < ba.count(); i++) + for (int i = 0; i < ba.size(); i++) if (ba.at(i) != 0) ba2.append(ba.at(i)); url = ba2; } - BranchItem *bi = NULL; + BranchItem *bi = nullptr; // Workaround to avoid adding empty branches if (!url.isEmpty()) { if (url.startsWith("file://")) @@ -2179,7 +2694,7 @@ void MapEditor::dropEvent(QDropEvent *event) if (url.endsWith(".vym", Qt::CaseInsensitive)) model->setVymLink(url); else { - model->setURL(url); + model->setUrl(url); // Shorten long URLs for heading int i = url.indexOf("?"); @@ -2198,154 +2713,142 @@ void MapEditor::dropEvent(QDropEvent *event) event->acceptProposedAction(); } +void MapEditor::updateCursor() +{ + if (qApp->queryKeyboardModifiers() & Qt::ShiftModifier) { + switch (mainWindow->getModMode()) { + case Main::ModModePoint: + setCursor(Qt::ArrowCursor); + break; + case Main::ModModeColor: + setCursor(PickColorCursor); + break; + case Main::ModModeXLink: + setCursor(XLinkCursor); + break; + case Main::ModModeMoveObject: + setCursor(Qt::PointingHandCursor); + break; + case Main::ModModeMoveView: + setCursor(Qt::OpenHandCursor); + break; + default: + setCursor(Qt::ArrowCursor); + break; + } + } else { + setCursor(Qt::ArrowCursor); + } +} + void MapEditor::setState(EditorState s) { - if (state != Neutral && s != Neutral) - qWarning() << "MapEditor::setState switching directly from " << state - << " to " << s; - state = s; - /* if (debug) - { + editorState = s; + /* if (debug) { QString s; - switch (state) - { - case Neutral: - s = "Neutral"; - break; - case EditingHeading: - s = "EditingHeading"; - break; - case EditingLink: - s = "EditingLink"; - break; - case MovingObject: - s = "MovingObject"; - break; - case MovingObjectWithoutLinking: - s = "MovingObjectWithoutLinking"; - break; - case MovingView: - s = "MovingView"; - break; - case PickingColor: - s = "PickingColor"; - break; - case DrawingLink: - s = "DrawingLink"; - break; + switch (state) { + case Neutral: + s = "Neutral"; + break; + case EditingHeading: + s = "EditingHeading"; + break; + case EditingLink: + s = "EditingLink"; + break; + case MovingObject: + s = "MovingObject"; + break; + case MovingObjectWithoutLinking: + s = "MovingObjectWithoutLinking"; + break; + case MovingView: + s = "MovingView"; + break; + case PickingColor: + s = "PickingColor"; + break; + case CreatingXLink: + s = "CreatingXLink"; + break; + default: + s = "Unknown editor state"; + break; } qDebug() << "MapEditor: State " << s << " of " << model->getMapName(); } */ } -MapEditor::EditorState MapEditor::getState() { return state; } - -void MapEditor::updateSelection(QItemSelection nsel, QItemSelection dsel) -{ - Q_UNUSED(nsel); - - QList itemsSelected; - QList itemsDeselected; +MapEditor::EditorState MapEditor::state() { return editorState; } - QItemSelection sel = model->getSelectionModel()->selection(); - LinkableMapObj *lmo; - - // Add new selected objects - if (sel.indexes().count() > 1) - mainWindow->statusMessage( - tr("%1 items selected").arg(sel.indexes().count())); - - foreach (QModelIndex ix, sel.indexes()) { - MapItem *mi = static_cast(ix.internalPointer()); - if (mi->isBranchLikeType() || mi->getType() == TreeItem::Image || - mi->getType() == TreeItem::XLink) - if (!itemsSelected.contains(mi)) - itemsSelected.append(mi); - lmo = mi->getLMO(); - if (lmo) - mi->getLMO()->updateVisibility(); +MapEditor::SelectionMode MapEditor::currentSelectionMode(TreeItem *selti) +{ + // Selections should consider logical relations, e.g. siblings and parents + // but also geometric. Return the most appropriate mode depending on + // rotation of view and layout of selected item. + if (!selti) { + // qDebug() << "ME::selectionMode: Classic"; + return ClassicSelection; } - // Delete objects meanwhile removed from selection - foreach (QModelIndex ix, dsel.indexes()) { - MapItem *mi = static_cast(ix.internalPointer()); - if (mi->isBranchLikeType() || mi->getType() == TreeItem::Image || - mi->getType() == TreeItem::XLink) - if (!itemsDeselected.contains(mi)) - itemsDeselected.append(mi); - lmo = mi->getLMO(); // FIXME-2 xlink does return nullptr - if (lmo) - mi->getLMO()->updateVisibility(); + if (rotationInt != 0) { + // qDebug() << "ME::selectionMode: Geometric"; + return GeometricSelection; } - // Trim list of selection paths - while (itemsSelected.count() < selPathList.count()) - delete selPathList.takeFirst(); - - // Reduce polygons - while (itemsSelected.count() < selPathList.count()) - delete selPathList.takeFirst(); - - // Add additonal polygons - QGraphicsPathItem *sp; - while (itemsSelected.count() > selPathList.count()) { - sp = mapScene->addPath(QPainterPath()); - sp->show(); - selPathList.append(sp); + Container *c = nullptr; + if (selti->hasTypeBranch()) { + BranchContainer *bc = ((BranchItem*)selti)->getBranchContainer(); + if (bc->branchesContainerLayout() == Container::Horizontal) { + // qDebug() << "ME::selectionMode: OrgChart"; + return OrgChartSelection; + } + if (bc->isFloating()) { + // qDebug() << "ME::selectionMode: Geometric"; + return GeometricSelection; + } + } else if (selti->hasTypeImage()) { + // qDebug() << "ME::selectionMode: Geometric"; + return GeometricSelection; } - // Reposition polygons - for (int i = 0; i < itemsSelected.count(); ++i) { - MapObj *mo = itemsSelected.at(i)->getMO(); - sp = selPathList.at(i); - sp->setPath(mo->getSelectionPath()); - sp->setPen(selectionPen); - sp->setBrush(selectionBrush); - sp->setParentItem(mo); - sp->setZValue(dZ_SELBOX); + if (!c) { + // qDebug() << "ME::selectionMode: Classic"; + return ClassicSelection; + } - // Reposition also LineEdit for heading during animation - if (lineEdit) - lineEdit->move(mo->getAbsPos().toPoint()); + if (c->isFloating()) { + // qDebug() << "ME::selectionMode: Geometric"; + return GeometricSelection; } - scene()->update(); + qDebug() << "ME::selectionMode: Classic"; + return ClassicSelection; } void MapEditor::updateData(const QModelIndex &sel) { TreeItem *ti = static_cast(sel.internalPointer()); - /* testing - qDebug() << "ME::updateData"; - if (!ti) - { - qDebug() << " ti=NULL"; - return; - } - qDebug() << " ti="< animatedContainers; + + private slots: + void animate(); //!< Called by timer to animate stuff + public: + void startAnimation(Container *c, const QPointF &v); + void startAnimation(Container *c, const QPointF &start, const QPointF &dest); + void stopContainerAnimation(Container *c); + void stopContainerAnimations(); + void stopViewAnimations(); + // Animation of zoom - Q_PROPERTY(qreal zoomFactor READ getZoomFactor WRITE setZoomFactor) + Q_PROPERTY(qreal zoomFactorInt READ zoomFactor WRITE setZoomFactor) protected: - qreal zoomFactor; - qreal zoomFactorTarget; + qreal zoomDelta; + qreal zoomFactorInt; + qreal zoomFactorTargetInt; QPropertyAnimation zoomAnimation; public: + void zoomIn(); + void zoomOut(); void setZoomFactorTarget(const qreal &zf); - qreal getZoomFactorTarget(); + qreal zoomFactorTarget(); void setZoomFactor(const qreal &zf); - qreal getZoomFactor(); + qreal zoomFactor(); // Animation of rotation - Q_PROPERTY(qreal angle READ getAngle WRITE setAngle) + Q_PROPERTY(qreal rotationInt READ rotation WRITE setRotation) protected: - qreal angle; - qreal angleTarget; + qreal rotationInt; + qreal rotationTargetInt; QPropertyAnimation rotationAnimation; + bool useTransformationOrigin; + QPointF transformationOrigin; + QPointF vp_center; // Calculated before transformation to center on later + public: - void setAngleTarget(const qreal &a); - qreal getAngleTarget(); - void setAngle(const qreal &a); - qreal getAngle(); + void setRotationTarget(const qreal &a); + qreal rotationTarget(); + void setRotation(const qreal &a); + qreal rotation(); // Animation of viewCenter Q_PROPERTY(QPointF viewCenter READ getViewCenter WRITE setViewCenter) @@ -129,27 +155,38 @@ class MapEditor : public QGraphicsView { void testFunction2(); //! just testing new stuff public: - TreeItem *findMapItem(QPointF p, - TreeItem *exclude); //! find item in map at position - //! p. Ignore item exclude + TreeItem *findMapItem( + QPointF p, + const QList &excludedItems = QList(), + bool findNearCenter = false); //! find item in map at position + //! p. Ignore item exclude + BranchItem *findMapBranchItem( + QPointF p, + const QList &excludedItems = QList(), + bool findNearCenter = false); //! only return BranchItem void toggleWinter(); - BranchItem *getBranchDirectAbove( - BranchItem *bi); //! get branch direct above bi (in TreeView) - BranchItem * - getBranchAbove(BranchItem *bi); //! get branch above bi (in TreeView) - BranchItem *getBranchDirectBelow( - BranchItem *bi); //! bet branch direct below bi (in TreeView) - BranchItem * - getBranchBelow(BranchItem *bi); //! bet branch below bi (in TreeView) - BranchItem * - getLeftBranch(TreeItem *ti); //! bet branch left of bi (in TreeView) - BranchItem * - getRightBranch(TreeItem *ti); //! bet branch right of bi (in TreeView) + enum RadarDirection { + UpDirection, + DownDirection, + LeftDirection, + RightDirection + }; + + bool isContainerCloserInDirection(Container *c1, Container *c2, const qreal &d_min, const QPoint &v, RadarDirection radarDir); + TreeItem* getItemInDirection(TreeItem *ti, RadarDirection); + TreeItem* getItemFromGeometry(TreeItem *ti, RadarDirection); + TreeItem* getItemFromOrgChart(TreeItem *ti, RadarDirection); + TreeItem* getItemFromClassicMap(TreeItem *ti, RadarDirection); + + TreeItem* getItemDirectAbove(TreeItem *ti); + TreeItem* getItemDirectBelow( TreeItem *ti); private: - enum ToggleDirection {toggleUndefined, toggleUp, toggleDown}; - ToggleDirection lastToggleDirection; + // Toggle objects by moving the cursor up/down with shift modifier + // (needs to consider the current direction of movement) + enum ToggleDirection {toggleUndefined, toggleUp, toggleDown}; + ToggleDirection lastToggleDirection; public slots: void cursorUp(); @@ -160,7 +197,7 @@ class MapEditor : public QGraphicsView { void cursorRight(); void cursorFirst(); void cursorLast(); - void editHeading(); + void editHeading(BranchItem *selbi = nullptr); void editHeadingFinished(); private: @@ -170,10 +207,10 @@ class MapEditor : public QGraphicsView { void contextMenuEvent(QContextMenuEvent *e); void keyPressEvent(QKeyEvent *); void keyReleaseEvent(QKeyEvent *); - void startMovingView(QMouseEvent *); + void startPanningView(QMouseEvent *); void mousePressEvent(QMouseEvent *); void mouseMoveEvent(QMouseEvent *); - void moveObject(); + void moveObject(QMouseEvent *, const QPointF &p_event); // Called from mouseMoveEvent void mouseReleaseEvent(QMouseEvent *); void mouseDoubleClickEvent(QMouseEvent *); void wheelEvent(QWheelEvent *); @@ -185,6 +222,7 @@ class MapEditor : public QGraphicsView { void dragLeaveEvent(QDragLeaveEvent *); void dropEvent(QDropEvent *); + void updateCursor(); private: QGraphicsScene *mapScene; VymModel *model; //!< Vym Map, includding several mapCenters @@ -196,20 +234,29 @@ class MapEditor : public QGraphicsView { QCursor PickColorCursor; // cursor while picking color QCursor CopyCursor; // cursor while picking color QCursor XLinkCursor; // cursor while picking color - EditorState state; + + // Various states of the MapEditor + public: + MapEditor::EditorState state(); + + private: + EditorState editorState; void setState(EditorState); bool objectMoved; // true if object was not clicked, but moved with mouse // Temporary used for linkx - Link *tmpLink; + XLink *tmpXLink; + + // Temporary used for panning view + QPoint panning_initialPointerPos; // initial pos in pointer coordinates + QPoint panning_initialScrollBarValues; // inital values of scrollbars - MapObj *movingObj; // moving a MapObj - QPointF movingObj_orgPos; // org. pos of mouse before move - QPointF movingObj_orgRelPos; // org. relative pos of mouse before move - QPointF movingObj_offset; // offset of mousepointer to object - QPointF movingCont_start; // inital pos of moving Content or - QPointF movingVec; // how far has Content moved + // Moving containers + QList movingItems; // selected items which are currently moved + QPointF movingObj_initialScenePos; // coord when button was pressed + QPointF movingObj_initialContainerOffset; // offset from above coordinates to object + TmpParentContainer *tmpParentContainer; QPointF contextMenuPos; // position where context event was triggered @@ -219,24 +266,24 @@ class MapEditor : public QGraphicsView { QPoint exportOffset; // set before export, used in save //////////// Selection related - signals: - void selectionChanged(const QItemSelection &, const QItemSelection &); + public: + enum SelectionMode { + AutoSelection, + ClassicSelection, + OrgChartSelection, + GeometricSelection + }; + + SelectionMode currentSelectionMode(TreeItem *); private: - QList selPathList; - QColor selectionColor; - QPen selectionPen; - QBrush selectionBrush; + SelectionMode selectionMode; + + signals: + void selectionChanged(const QItemSelection &, const QItemSelection &); public slots: - void updateSelection(QItemSelection, QItemSelection); // update selection void updateData(const QModelIndex &); // update data void togglePresentationMode(); - - public: - void setSelectionPen(const QPen &p); - QPen getSelectionPen(); - void setSelectionBrush(const QBrush &p); - QBrush getSelectionBrush(); }; #endif diff --git a/src/mapitem.cpp b/src/mapitem.cpp index c639928..5b287be 100644 --- a/src/mapitem.cpp +++ b/src/mapitem.cpp @@ -1,12 +1,12 @@ #include "mapitem.h" -#include "linkablemapobj.h" -#include "ornamentedobj.h" +#include "branch-container.h" +#include "branchitem.h" +#include "image-container.h" +#include "imageitem.h" #include -extern FlagRowMaster *systemFlagsMaster; - MapItem::MapItem(TreeItem *parent) : TreeItem(parent) { @@ -16,156 +16,57 @@ MapItem::MapItem(TreeItem *parent) void MapItem::init() { - mo = NULL; - posMode = Unused; - hideLinkUnselected = false; + hideLinkUnselectedInt = false; } -void MapItem::appendChild(TreeItem *item) +Container* MapItem::getContainer() { - TreeItem::appendChild(item); - - // FIXME-4 maybe access parent in MapObjs directly via treeItem - // and remove this here... + if (hasTypeBranch()) + return ((BranchItem*)this)->getBranchContainer(); + else if (hasTypeImage()) + return ((ImageItem*)this)->getImageContainer(); - // If lmo exists, also set parObj there - LinkableMapObj *lmo = getLMO(); - if (lmo) { - LinkableMapObj *itemLMO = ((MapItem *)item)->getLMO(); - if (itemLMO) - itemLMO->setParObj(lmo); - } + return nullptr; } -void MapItem::setRelPos(const QPointF &p) +void MapItem::setPos(const QPointF &p) { - posMode = Relative; - pos = p; - LinkableMapObj *lmo = getLMO(); - if (lmo) { - ((OrnamentedObj *)lmo)->setUseRelPos(true); - ((OrnamentedObj *)lmo)->move2RelPos(p); + if (hasTypeBranch()) { + ((BranchItem*)this)->getBranchContainer()->setPos(p); + return; } -} -void MapItem::setAbsPos(const QPointF &p) -{ - posMode = Absolute; - pos = p; - if (mo) - mo->move(p); + if (hasTypeImage()) + ((ImageItem*)this)->getImageContainer()->setPos(p); } -void MapItem::setPositionMode(PositionMode mode) { posMode = mode; } - -MapItem::PositionMode MapItem::getPositionMode() { return posMode; } - void MapItem::setHideLinkUnselected(bool b) { - hideLinkUnselected = b; - LinkableMapObj *lmo = getLMO(); - if (lmo) { - // lmo->setHideLinkUnselected(); - lmo->setVisibility(lmo->isVisibleObj()); - lmo->updateLinkGeometry(); + hideLinkUnselectedInt = b; + if (hasTypeBranch()) { + ((BranchItem*)this)->getBranchContainer()->updateVisibility(); + return; } } -bool MapItem::getHideLinkUnselected() { return hideLinkUnselected; } +bool MapItem::hideLinkUnselected() { return hideLinkUnselectedInt; } -QString MapItem::getMapAttr() +QString MapItem::getPosAttr() { QString s; - LinkableMapObj *lmo = getLMO(); - - if (parentItem == rootItem) - posMode = Absolute; - else { - if (type == TreeItem::Image || depth() == 1 || (lmo && lmo->getUseRelPos())) - posMode = Relative; // FiXME-2 shouldn't this be replaced by relPos? - else - posMode = Unused; - } - - switch (posMode) { - case Relative: - if (lmo) - pos = lmo->getRelPos(); - s = attribut("relPosX", QString().setNum(pos.x())) + - attribut("relPosY", QString().setNum(pos.y())); - break; - case Absolute: - if (mo) - pos = mo->getAbsPos(); - s = attribut("absPosX", QString().setNum(pos.x())) + - attribut("absPosY", QString().setNum(pos.y())); - break; - default: - break; - } - if (hideLinkUnselected) - s += attribut("hideLink", "true"); - - // Rotation angle - MapObj *mo = getMO(); - if (mo) - angle = mo->getRotation(); - if (angle != 0) - s += attribut("rotation", QString().setNum(angle)); + QPointF pos = getContainer()->pos(); + s = attribute("posX", QString().setNum(pos.x())) + + attribute("posY", QString().setNum(pos.y())); return s; } -QRectF MapItem::getBBoxURLFlag() +QString MapItem::getLinkableAttr() { - QString s = "system-url"; - QStringList list = systemFlags.activeFlagNames().filter(s); - if (list.count() > 1) { - qWarning() << "MapItem::getBBoxURLFlag found more than one system-url*"; - return QRectF(); - } - - Flag *f = systemFlagsMaster->findFlagByName(s); - if (f) { - QUuid u = f->getUuid(); - LinkableMapObj *lmo = getLMO(); - if (lmo) - return ((OrnamentedObj *)lmo)->getBBoxSystemFlagByUid(u); - } - return QRectF(); -} - -void MapItem::setRotation(const qreal &a) -{ - angle = a; - MapObj *mo = getMO(); - if (mo) - mo->setRotation(a); -} - -MapObj *MapItem::getMO() { return mo; } + QString s; -LinkableMapObj *MapItem::getLMO() -{ - if (isBranchLikeType() || type == Image) - return (LinkableMapObj *)mo; - else - return NULL; -} + if (hideLinkUnselectedInt) + s += attribute("hideLink", "true"); -void MapItem::initLMO() -{ - LinkableMapObj *lmo = getLMO(); - if (!lmo) - return; - switch (posMode) { - case Relative: - lmo->setRelPos(pos); - break; - case Absolute: - lmo->move(pos); - break; - default: - break; - } + return s; } diff --git a/src/mapitem.h b/src/mapitem.h index be20fbc..a8c2285 100644 --- a/src/mapitem.h +++ b/src/mapitem.h @@ -5,70 +5,35 @@ #include "treeitem.h" -class MapObj; -class LinkableMapObj; - -/*! /brief MapItem is used to store information of MapObj and inherited - classes. - - This is done even while no QGraphicsView is availabe. This is useful - if e.g. on a small device like a cellphone the full map is not used, - but just a treeview instead. +class Container; +/*! /brief MapItem is used to maintain geometrical information of images and branches + * resp. their containers */ class MapItem : public TreeItem { public: - enum PositionMode { Unused, Absolute, Relative }; - - protected: - QPointF pos; - PositionMode posMode; - - public: - MapItem(TreeItem *parent = 0); + MapItem(TreeItem *parent = nullptr); void init(); - /*! Overloaded from TreeItem. Used to set parObj in LinkableMapObj */ - virtual void appendChild(TreeItem *item); - - /*! Used to save relative position while map is not in QGraphicsView */ - virtual void setRelPos(const QPointF &); + /*! Overloaded in BranchItem and ImageItem to retrieve the related container */ + virtual Container* getContainer(); - /*! Used to save absolute position while map is not in QGraphicsView */ - virtual void setAbsPos(const QPointF &); - - /*! Tell object to use e.g. absolute positioning for mapcenter. - Defaulst is MapItem::Unused */ - void setPositionMode(PositionMode mode); - PositionMode getPositionMode(); + /*! Used to save position while map is not in QGraphicsView */ + virtual void setPos(const QPointF &); protected: - bool hideLinkUnselected; + bool hideLinkUnselectedInt; public: /*! Hide link if item is not selected */ virtual void setHideLinkUnselected(bool); /*! Check if link is hidden for unselected items */ - virtual bool getHideLinkUnselected(); - - virtual QString getMapAttr(); //! Get attributes for saving as XML - - virtual QRectF getBBoxURLFlag(); //! get bbox of url flag - virtual void setRotation(const qreal &a); - - protected: - MapObj *mo; - qreal angle; - - public: - /*! Returns pointer to related LinkableMapObj in QGraphicsView */ - virtual MapObj *getMO(); - virtual LinkableMapObj *getLMO(); + virtual bool hideLinkUnselected(); - /*! Initialize LinkableMapObj with data in MapItem */ - virtual void initLMO(); + virtual QString getPosAttr(); //! Get position attributes shared by Images and Branches + virtual QString getLinkableAttr(); //! Get attributes shared by Images and Branches }; #endif diff --git a/src/mapobj.cpp b/src/mapobj.cpp index 8ade8ed..6cec54e 100644 --- a/src/mapobj.cpp +++ b/src/mapobj.cpp @@ -7,111 +7,19 @@ ///////////////////////////////////////////////////////////////// // MapObj ///////////////////////////////////////////////////////////////// -MapObj::MapObj(QGraphicsItem *parent, TreeItem *ti) : QGraphicsItem(parent) +MapObj::MapObj(QGraphicsItem *parent) : QGraphicsItem(parent) { - // qDebug() << "Const MapObj (this,ti)=("<setParentItem(NULL); -} - -void MapObj::init() -{ - absPos = QPointF(0, 0); - visible = true; -} - -void MapObj::copy(MapObj *other) -{ - absPos = other->absPos; - bbox.setX(other->bbox.x()); - bbox.setY(other->bbox.y()); - bbox.setSize(QSizeF(other->bbox.width(), other->bbox.height())); -} - -void MapObj::setTreeItem(TreeItem *ti) { treeItem = ti; } - -TreeItem *MapObj::getTreeItem() const { return treeItem; } - -qreal MapObj::x() { return getAbsPos().x(); } - -qreal MapObj::y() { return getAbsPos().y(); } - -qreal MapObj::width() { return bbox.width(); } - -qreal MapObj::height() { return bbox.height(); } - -QPointF MapObj::getAbsPos() { return absPos; } - -QString MapObj::getPos() { return qpointFToString(absPos); } - -void MapObj::move(double x, double y) { MapObj::move(QPointF(x, y)); } - -void MapObj::move(QPointF p) -{ - absPos = p; - bbox.moveTo(p); - clickPoly = QPolygonF(bbox); -} - -void MapObj::moveBy(double x, double y) -{ - QPointF v(x, y); - MapObj::move(absPos + v); - bbox.moveTo(bbox.topLeft() + v); - clickPoly.translate(v); + // Avoid that QGraphicsScene deletes children + i->setParentItem(nullptr); } QRectF MapObj::boundingRect() const { return QRectF(); } void MapObj::paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {} - -QRectF MapObj::getBBox() { return bbox; } - -ConvexPolygon MapObj::getBoundingPolygon() -{ - QPolygonF p; - p << bbox.topLeft() << bbox.topRight() << bbox.bottomRight() - << bbox.bottomLeft(); - return p; -} - -QPolygonF MapObj::getClickPoly() { return clickPoly; } - -QPainterPath MapObj::getSelectionPath() -{ - qreal d = 3; // Thickness of selection "border" - QPainterPath p; - QRectF br = clickPoly.boundingRect(); - p.moveTo(br.topLeft() + QPointF(-d, -d)); - p.lineTo(br.topRight() + QPointF(d, -d)); - p.lineTo(br.bottomRight() + QPointF(d, d)); - p.lineTo(br.bottomLeft() + QPointF(-d, d)); - p.lineTo(br.topLeft() + QPointF(-d, -d)); - return p; -} - -bool MapObj::isInClickBox(const QPointF &p) -{ - return clickPoly.containsPoint(p, Qt::OddEvenFill); -} - -QSizeF MapObj::getSize() { return bbox.size(); } - -void MapObj::setRotation(const qreal &a) { angle = a; } - -qreal MapObj::getRotation() { return angle; } - -bool MapObj::isVisibleObj() { return visible; } - -void MapObj::setVisibility(bool v) { visible = v; } - -void MapObj::positionBBox() {} -void MapObj::calcBBoxSize() {} diff --git a/src/mapobj.h b/src/mapobj.h index 66dee77..78b935d 100644 --- a/src/mapobj.h +++ b/src/mapobj.h @@ -5,73 +5,16 @@ #include "xmlobj.h" -#define dZ_BBOX 0 // testing -#define dZ_SELBOX 5 -#define dZ_FRAME_LOW 10 -#define dZ_LINK 20 -#define dZ_XLINK 40 -#define dZ_FLOATIMG 70 -#define dZ_ICON 80 -#define dZ_TEXT 90 -#define dZ_DEPTH 100 -#define Z_SNOW 2000 -#define Z_INIT 9999 -#define Z_LINEEDIT 10000 - -class ConvexPolygon; - -#include "treeitem.h" - /*! \brief Base class for all objects visible on a map */ -class MapObj : public XMLObj, public QGraphicsItem { +class MapObj : public QGraphicsItem { public: - MapObj(QGraphicsItem *parent = NULL, TreeItem *ti = NULL); + MapObj(QGraphicsItem *parent = nullptr); virtual ~MapObj(); - virtual void init(); - virtual void copy(MapObj *); - - virtual void setTreeItem(TreeItem *); - virtual TreeItem *getTreeItem() const; - - virtual qreal x(); - virtual qreal y(); - virtual qreal width(); - virtual qreal height(); - virtual QPointF getAbsPos(); - virtual QString getPos(); //! Return position as string (x,y) - virtual void move(double x, double y); //! move to absolute Position - virtual void move(QPointF p); - virtual void moveBy(double x, double y); //! move to relative Position - - virtual QRectF boundingRect() const; - virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); - - virtual QRectF getBBox(); //! returns bounding box - virtual ConvexPolygon - getBoundingPolygon(); //! return bounding convex polygon - virtual QPolygonF getClickPoly(); //! returns polygon to click - virtual QPainterPath getSelectionPath(); //! returns path for selection - virtual bool isInClickBox(const QPointF &p); //! Checks if p is in clickBox - virtual QSizeF getSize(); //! returns size of bounding box - - virtual void setRotation(const qreal &a); - virtual qreal getRotation(); - virtual bool isVisibleObj(); - virtual void setVisibility(bool); - virtual void positionBBox(); - virtual void calcBBoxSize(); - - protected: - QRectF bbox; // bounding box of MO itself - QPolygonF clickPoly; // area where mouseclicks are found - QPointF absPos; // Position on canvas - bool visible; - - qreal angle; //! Rotation angle - TreeItem *treeItem; //! Crossrefence to treemodel + QRectF boundingRect() const; + void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); }; #endif diff --git a/src/misc.cpp b/src/misc.cpp index c75b24b..07e65da 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -1,12 +1,15 @@ #include "misc.h" + #include "geometry.h" #include #include +#include #include #include +#include #include extern QString vymVersion; @@ -19,8 +22,8 @@ QString richTextToPlain(QString r, const QString &indent, const int &width) if (r.isEmpty()) return r; - QRegExp rx; - rx.setMinimal(true); + QRegularExpression rx; + rx.setPatternOptions(QRegularExpression::InvertedGreedinessOption); // Remove all ... rx.setPattern(".*"); @@ -61,19 +64,30 @@ QString richTextToPlain(QString r, const QString &indent, const int &width) return r; } -QString qpointToString(const QPoint &p) +QString toS(const bool &b) +{ + return b ? "true" : "false"; +} + +QString toS(const qreal &r, int d) +{ + return QString("%1") + .arg(QString::number(r,'f', d)); +} + +QString toS(const QPoint &p) { - return "(" + QString("%1").arg(p.x()) + "," + QString("%1").arg(p.y()) + - ")"; + return QString("(%1, %2)").arg(p.x()).arg(p.y()); } -QString qpointFToString(const QPointF &p) +QString toS(const QPointF &p, int d) { - return "(" + QString("%1").arg(p.x()) + "," + QString("%1").arg(p.y()) + - ")"; + return QString("(%1, %2)") + .arg(QString::number(p.x(),'f', d)) + .arg(QString::number(p.y(),'f', d)); } -QString qrectFToString(const QRectF &r, int d) +QString toS(const QRectF &r, int d) { return QString("(%1, %2 %3x%4)") .arg(QString::number(r.x(),'f', d)) @@ -82,21 +96,34 @@ QString qrectFToString(const QRectF &r, int d) .arg(QString::number(r.height(),'f', d)); } -QString VectorToString(const Vector &p) +QString toS(const Vector &p) { - return "(" + QString("%1").arg(p.x()) + "," + QString("%1").arg(p.y()) + - ")"; + return QString("(%1, %2)").arg(p.x()).arg(p.y()); +} + +QString toS(const QDate &d) +{ + return d.toString("yyyy-MM-dd"); +} + +QString pluralize(const QString &s, qsizetype count) +{ + // Very primitive implementation of pluralize :-/ + if (count > 1) + return s + "s"; + else + return s; } ostream &operator<<(ostream &stream, QPoint const &p) { - stream << "(" << p.x() << "," << p.y() << ")"; + stream << "(" << p.x() << ", " << p.y() << ")"; return stream; } ostream &operator<<(ostream &stream, QPointF const &p) { - stream << "(" << p.x() << "," << p.y() << ")"; + stream << "(" << p.x() << ", " << p.y() << ")"; return stream; } @@ -113,47 +140,6 @@ ostream &operator<<(ostream &stream, Vector const &p) return stream; } -qreal getAngle(const QPointF &p) -{ - // Calculate angle of vector to x-axis - if (p.x() == 0) { - if (p.y() >= 0) - return M_PI_2; - else - return 3 * M_PI_2; - } - else { - if (p.x() > 0) { - if (p.y() < 0) - return (qreal)(-atan((qreal)(p.y()) / (qreal)(p.x()))); - else - return (qreal)(2 * M_PI - - atan((qreal)(p.y()) / (qreal)(p.x()))); - } - else - return (qreal)(M_PI - atan((qreal)(p.y()) / (qreal)(p.x()))); - } - /* - // Calculate angle of vector to y-axis - if (p.y()==0) - { - if (p.x()>=0) - return M_PI_2; - else - return 3* M_PI_2; - } else - { - if (p.y()>0) - return (qreal)(M_PI - atan ( (qreal)(p.x()) / (qreal)(p.y()) ) ); - else - if (p.x()<0) - return (qreal)( 2*M_PI - atan ( (qreal)(p.x()) / (qreal)(p.y()) ) ); - else - return (qreal)( - atan ( (qreal)(p.x()) / (qreal)(p.y()) ) ); - } - */ -} - qreal min(qreal a, qreal b) { if (a < b) @@ -250,7 +236,7 @@ void centerDialog(QDialog *dia) // #include "version.h" // #include -// #include +// #include bool versionLowerThanVym(const QString &v) { @@ -278,30 +264,27 @@ bool versionLowerOrEqual(const QString &v, const QString &vstatic) int vs2 = 0; int vs3 = 0; - QRegExp rx("(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})"); - int pos = rx.indexIn(v); - if (pos > -1) { - v1 = rx.cap(1).toInt(&ok); + QRegularExpression re("(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})"); + QRegularExpressionMatch match = re.match(v); + if (match.hasMatch()) { + v1 = match.captured(1).toInt(&ok); if (ok) - v2 = rx.cap(2).toInt(&ok); + v2 = match.captured(2).toInt(&ok); if (ok) - v3 = rx.cap(3).toInt(&ok); + v3 = match.captured(3).toInt(&ok); } - pos = rx.indexIn(vstatic); - if (ok && pos > -1) { - vs1 = rx.cap(1).toInt(&ok); + match = re.match(vstatic); + if (match.hasMatch()) { + vs1 = match.captured(1).toInt(&ok); if (ok) - vs2 = rx.cap(2).toInt(&ok); + vs2 = match.captured(2).toInt(&ok); if (ok) - vs3 = rx.cap(3).toInt(&ok); + vs3 = match.captured(3).toInt(&ok); } if (!ok) { - qWarning() << QString( - "Warning: Checking version failed: v=%1 vstatic=%2") - .arg(v) - .arg(vstatic); + qWarning() << QString( "Warning: Checking version failed: v=%1 vstatic=%2").arg(v, vstatic); return false; } diff --git a/src/misc.h b/src/misc.h index dda38c8..e2c15b5 100644 --- a/src/misc.h +++ b/src/misc.h @@ -5,6 +5,7 @@ #include using namespace std; +class QDate; class QString; class QPoint; class QPointF; @@ -14,17 +15,21 @@ class QDialog; ///////////////////////////////////////////////////////////////////////////// QString richTextToPlain(QString r); -QString qpointToString(const QPoint &p); -QString qpointFToString(const QPointF &p); -QString qrectFToString(const QRectF &r, int d = 1); -QString VectorToString(const Vector &p); +QString toS(const bool &); +QString toS(const qreal &r, int d = 1); +QString toS(const QPoint &p); +QString toS(const QPointF &p, int d = 1); +QString toS(const QRectF &r, int d = 1); +QString toS(const Vector &p); +QString toS(const QDate &d); + +QString pluralize(const QString &, qsizetype count); extern ostream &operator<<(ostream &stream, QPoint const &p); extern ostream &operator<<(ostream &stream, QPointF const &p); extern ostream &operator<<(ostream &stream, QRectF const &r); extern ostream &operator<<(ostream &stream, Vector const &p); -qreal getAngle(const QPointF &); qreal min(qreal, qreal); qreal max(qreal, qreal); qreal roof(qreal x); diff --git a/src/mkdtemp.cpp b/src/mkdtemp.cpp index c74c925..836b918 100644 --- a/src/mkdtemp.cpp +++ b/src/mkdtemp.cpp @@ -27,7 +27,7 @@ QString mkdtemp(QString tmpl) return QString(); } - uint64_t random_time_bits = time(NULL); + uint64_t random_time_bits = time(nullptr); value += (random_time_bits ^ getpid()); diff --git a/src/mysortfilterproxymodel.cpp b/src/mysortfilterproxymodel.cpp deleted file mode 100644 index 923c84d..0000000 --- a/src/mysortfilterproxymodel.cpp +++ /dev/null @@ -1,38 +0,0 @@ -//#include - -#include "mysortfilterproxymodel.h" - -MySortFilterProxyModel::MySortFilterProxyModel(QObject *parent) - : QSortFilterProxyModel(parent) -{ -} -//! [0] - -/* -//! [1] -void MySortFilterProxyModel::setFilterMinimumDate(const QDate &date) -{ - minDate = date; - invalidateFilter(); -} -//! [1] - -//! [2] -void MySortFilterProxyModel::setFilterMaximumDate(const QDate &date) -{ - maxDate = date; - invalidateFilter(); -} -*/ - -bool MySortFilterProxyModel::filterAcceptsRow( - int sourceRow, // FIXME-3 find a way to show _all_ rows which match, - // independent of parent - const QModelIndex &sourceParent) const -{ - QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent); - QModelIndex index1 = sourceModel()->index(sourceRow, 1, sourceParent); - - return (sourceModel()->data(index0).toString().contains(filterRegExp()) || - sourceModel()->data(index1).toString().contains(filterRegExp())); -} diff --git a/src/mysortfilterproxymodel.h b/src/mysortfilterproxymodel.h deleted file mode 100644 index 546bce8..0000000 --- a/src/mysortfilterproxymodel.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef MYSORTFILTERPROXYMODEL_H -#define MYSORTFILTERPROXYMODEL_H - -//#include -#include - -//! [0] -class MySortFilterProxyModel : public QSortFilterProxyModel { - Q_OBJECT - - public: - MySortFilterProxyModel(QObject *parent = 0); - /* - - QDate filterMinimumDate() const { return minDate; } - void setFilterMinimumDate(const QDate &date); - - QDate filterMaximumDate() const { return maxDate; } - void setFilterMaximumDate(const QDate &date); - protected: - */ - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; - /* - bool lessThan(const QModelIndex &left, const QModelIndex &right) const; - -private: - bool dateInRange(const QDate &date) const; - - QDate minDate; - QDate maxDate; -*/ -}; - -#endif diff --git a/src/noteeditor.cpp b/src/noteeditor.cpp index 56927d5..b830571 100644 --- a/src/noteeditor.cpp +++ b/src/noteeditor.cpp @@ -15,7 +15,7 @@ NoteEditor::NoteEditor(QString scope) : TextEditor() menuBar()->show(); - setUseColorMapBackground(false); + setUseMapBackgroundColor(false); // Load Settings init(scope); diff --git a/src/options.cpp b/src/options.cpp index 719c08e..b046211 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -3,8 +3,6 @@ #include #include -using namespace std; - Option::Option() { name = ""; @@ -39,7 +37,7 @@ QString Option::getLong() { return lName; } Option::Type Option::getType() { return type; } void Option::setArg(const QString &s) { sarg = s; } QString Option::getArg() { return sarg; } -void Option::setActive() { active = true; } +void Option::setActive(bool b) { active = b; } bool Option::isActive() { return active; } /////////////////////////////////////////////////////////////// @@ -106,7 +104,16 @@ QString Options::getProgramName() { return progname; } QStringList Options::getFileList() { return filelist; } -bool Options::isOn(const QString &s) +void Options::setActive(const QString &s, bool b) +{ + for (int i = 0; i < optlist.size(); ++i) + if (optlist[i].getName() == s) { + optlist[i].setActive(b); + } + // FIXME-3 Create boolean option and set active (not used atm) +} + +bool Options::isActive(const QString &s) { for (int i = 0; i < optlist.size(); ++i) if (optlist[i].getName() == s && optlist[i].isActive()) diff --git a/src/options.h b/src/options.h index bc4f4cb..a097d17 100644 --- a/src/options.h +++ b/src/options.h @@ -21,7 +21,7 @@ class Option { Type getType(); void setArg(const QString &); QString getArg(); - void setActive(); + void setActive(bool b = true); bool isActive(); private: @@ -46,7 +46,8 @@ class Options { QString getHelpText(); QString getProgramName(); QStringList getFileList(); - bool isOn(const QString &); + bool isActive(const QString &); + void setActive(const QString &, bool b); QString getArg(const QString &); private: diff --git a/src/ornamentedobj.cpp b/src/ornamentedobj.cpp deleted file mode 100644 index acdb50c..0000000 --- a/src/ornamentedobj.cpp +++ /dev/null @@ -1,243 +0,0 @@ -#include - -#include "branchitem.h" -#include "linkablemapobj.h" -#include "ornamentedobj.h" -#include "vymmodel.h" - -extern bool debug; - -///////////////////////////////////////////////////////////////// -// OrnamentedObj -///////////////////////////////////////////////////////////////// - -OrnamentedObj::OrnamentedObj(QGraphicsItem *parent, TreeItem *ti) - : LinkableMapObj(parent, ti) -{ - // qDebug()<< "Const OrnamentedObj (s,ti) ti="<setTreeItem(treeItem); - heading->move(absPos.x(), absPos.y()); - - systemFlagRowObj = new FlagRowObj(this); - standardFlagRowObj = new FlagRowObj(this); - - frame = new FrameObj(this); - frame->setTreeItem(treeItem); - - angle = 0; -} - -void OrnamentedObj::copy(OrnamentedObj *other) -{ - LinkableMapObj::copy(other); - heading->copy(other->heading); - setColor(other->heading->getColor()); - - systemFlagRowObj->copy(other->systemFlagRowObj); - standardFlagRowObj->copy(other->standardFlagRowObj); - - ornamentsBBox = other->ornamentsBBox; -} - -void OrnamentedObj::setColor(QColor col) -{ - heading->setColor(col); - setLinkColor(); -} - -QColor OrnamentedObj::getColor() { return heading->getColor(); } - -QRectF OrnamentedObj::getBBoxHeading() { return heading->getBBox(); } - -void OrnamentedObj::setRotation(const qreal &a) -{ - MapObj::setRotation(a); - heading->setRotation(a); // FIXME-4 duplicated code... -} - -FrameObj *OrnamentedObj::getFrame() { return frame; } - -FrameObj::FrameType OrnamentedObj::getFrameType() -{ - return frame->getFrameType(); -} - -QString OrnamentedObj::getFrameTypeName() { return frame->getFrameTypeName(); } - -void OrnamentedObj::setFrameType(const FrameObj::FrameType &t) -{ - frame->setFrameType(t); - if (t == FrameObj::NoFrame) { - linkpos = LinkableMapObj::Bottom; - useBottomline = true; - } - else { - linkpos = LinkableMapObj::Middle; - useBottomline = false; - } - updateVisibility(); // Update bottomline - calcBBoxSize(); - positionBBox(); - requestReposition(); -} - -void OrnamentedObj::setFrameType(const QString &s) -{ - setFrameType(frame->getFrameType(s)); -} - -void OrnamentedObj::setFramePadding(const int &i) -{ - frame->setPadding(i); - calcBBoxSize(); - positionBBox(); - requestReposition(); -} - -int OrnamentedObj::getFramePadding() { return frame->getPadding(); } - -void OrnamentedObj::setFrameBorderWidth(const int &i) -{ - frame->setBorderWidth(i); - calcBBoxSize(); - positionBBox(); - requestReposition(); -} - -int OrnamentedObj::getFrameBorderWidth() { return frame->getBorderWidth(); } - -void OrnamentedObj::setFramePenColor(QColor col) { frame->setPenColor(col); } - -QColor OrnamentedObj::getFramePenColor() { return frame->getPenColor(); } - -void OrnamentedObj::setFrameBrushColor(QColor col) -{ - frame->setBrushColor(col); -} - -QColor OrnamentedObj::getFrameBrushColor() { return frame->getBrushColor(); } - -void OrnamentedObj::setFrameIncludeChildren(bool b) -{ - calcBBoxSizeWithChildren(); - frame->setFrameIncludeChildren(b); - requestReposition(); -} - -bool OrnamentedObj::getFrameIncludeChildren() -{ - return frame->getFrameIncludeChildren(); -} - -QRectF OrnamentedObj::getOrnamentsBBox() { return ornamentsBBox; } - -void OrnamentedObj::positionContents() -{ - double x = absPos.x(); - double y = absPos.y(); - double dp = frame->getTotalPadding(); - double dp2 = dp / 2; - double ox = leftPad + dp; - double oy = topPad + dp; - - // vertical align heading to bottom - heading->setZValue(dZ_TEXT); - heading->setTransformOriginPoint( - QPointF(ox + systemFlagRowObj->getBBox().width(), - oy + ornamentsBBox.height() - heading->getHeight())); - heading->move(ox + x + systemFlagRowObj->getBBox().width(), - oy + y + ornamentsBBox.height() - heading->getHeight()); - // Flags - systemFlagRowObj->move(ox + x, oy + y); - systemFlagRowObj->setZValue(dZ_ICON); - standardFlagRowObj->move(ox + x + heading->getWidth() + - systemFlagRowObj->getBBox().width(), - oy + y); - standardFlagRowObj->setZValue(dZ_ICON); - - ornamentsBBox.moveTopLeft(QPointF(ox + x, oy + y)); - clickPoly = QPolygonF(ornamentsBBox); - - // Update bboxTotal coordinate (size set already) - if (orientation == LinkableMapObj::LeftOfCenter) - bboxTotal.setRect(bbox.x() + (bbox.width() - bboxTotal.width()), - bbox.y() + bbox.height() / 2 - bboxTotal.height() / 2, - bboxTotal.width(), bboxTotal.height()); - else - bboxTotal.setRect(bbox.x(), - bbox.y() + bbox.height() / 2 - bboxTotal.height() / 2, - bboxTotal.width(), bboxTotal.height()); - - // Update frame - dp = frame->getXPadding(); - dp2 = dp / 2; - frame->setZValue(dZ_FRAME_LOW); - if (treeItem && treeItem->isBranchLikeType() && - ((BranchItem *)treeItem)->getFrameIncludeChildren()) - frame->setRect(QRectF(bboxTotal.x() + dp2, bboxTotal.y() + dp2, - bboxTotal.width() - dp, bboxTotal.height() - dp)); - else - frame->setRect(QRectF(bbox.x() + dp, bbox.y() + dp, - bbox.width() - 2 * dp, bbox.height() - 2 * dp)); -} - -void OrnamentedObj::move(double x, double y) -{ - MapObj::move(x, y); - positionBBox(); -} - -void OrnamentedObj::move(QPointF p) { move(p.x(), p.y()); } - -void OrnamentedObj::moveBy(double x, double y) -{ - MapObj::moveBy(x, y); - frame->moveBy(x, y); - systemFlagRowObj->moveBy(x, y); - standardFlagRowObj->moveBy(x, y); - heading->moveBy(x, y); - updateLinkGeometry(); - requestReposition(); -} - -void OrnamentedObj::moveBy(QPointF p) { moveBy(p.x(), p.y()); } - -void OrnamentedObj::move2RelPos(double x, double y) -{ - setRelPos(QPointF(x, y)); - if (parObj) { - QPointF p = parObj->getChildRefPos(); - move(p.x() + x, p.y() + y); - } -} - -void OrnamentedObj::move2RelPos(QPointF p) { move2RelPos(p.x(), p.y()); } - -QUuid OrnamentedObj::findSystemFlagUidByPos(const QPointF &p) -{ - return systemFlagRowObj->findFlagUidByPos(p); -} - -QRectF OrnamentedObj::getBBoxSystemFlagByUid(const QUuid &u) -{ - FlagObj *fo = systemFlagRowObj->findFlagObjByUid(u); - if (fo) - return fo->getBBox(); - - return QRectF(); -} diff --git a/src/ornamentedobj.h b/src/ornamentedobj.h deleted file mode 100644 index 786c118..0000000 --- a/src/ornamentedobj.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef ORNAMENTEDOBJ_H -#define ORNAMENTEDOBJ_H - -#include "frameobj.h" -#include "linkablemapobj.h" - -class TreeItem; - -/*! \brief Adds various ornaments and data to the class LinkableMapObj - -The ornaments are: - - frame - - note - - references - - flags - - standard flags - - system flags - */ -// - attributes (key/value pairs) - -class OrnamentedObj : public LinkableMapObj { - public: - OrnamentedObj(QGraphicsItem *parent, TreeItem *ti = NULL); - virtual ~OrnamentedObj(); - virtual void init(); - virtual void copy(OrnamentedObj *); - - //virtual void - virtual void setColor(QColor); // set the color of text and link - QColor getColor(); // get color of heading - QRectF getBBoxHeading(); - - virtual void setRotation(const qreal &a); - virtual FrameObj *getFrame(); - virtual FrameObj::FrameType getFrameType(); - virtual QString getFrameTypeName(); - virtual void setFrameType(const FrameObj::FrameType &); - virtual void setFrameType(const QString &); - virtual void setFramePadding(const int &); - virtual int getFramePadding(); - virtual void setFrameBorderWidth(const int &); - virtual int getFrameBorderWidth(); - virtual void setFramePenColor(QColor); - virtual QColor getFramePenColor(); - virtual void setFrameBrushColor(QColor); - virtual QColor getFrameBrushColor(); - virtual void setFrameIncludeChildren(bool); - virtual bool getFrameIncludeChildren(); - virtual QRectF getOrnamentsBBox(); - - virtual void positionContents(); - virtual void move(double, double); - virtual void move(QPointF); - virtual void moveBy(double, double); - virtual void moveBy(QPointF); - virtual void move2RelPos(QPointF); // move relativly to parent^ - virtual void move2RelPos(double, double); - - virtual QUuid findSystemFlagUidByPos(const QPointF &p); - virtual QRectF getBBoxSystemFlagByUid(const QUuid &u); - - protected: - HeadingObj *heading; // Heading - FlagRowObj *systemFlagRowObj; // System Flags - FlagRowObj *standardFlagRowObj; // Standard Flags - FrameObj *frame; // frame around object - QRectF ornamentsBBox; // bbox of flags and heading -}; - -#endif diff --git a/src/scripteditor.cpp b/src/scripteditor.cpp index a9b631d..d1322fb 100644 --- a/src/scripteditor.cpp +++ b/src/scripteditor.cpp @@ -16,9 +16,11 @@ #include "vymmodel.h" extern QString vymName; -extern QList modelCommands; extern QList vymCommands; -extern QDir lastMapDir; +extern QList modelCommands; +extern QList branchCommands; +extern QList imageCommands; +extern QDir lastScriptDir; extern Macros macros; extern Main *mainWindow; extern Options options; @@ -43,6 +45,7 @@ ScriptEditor::ScriptEditor(QWidget *parent) : QWidget(parent) connect(ui.fileRunButton, SIGNAL(clicked()), this, SLOT(runScript())); connect(ui.macroLoadButton, SIGNAL(clicked()), this, SLOT(reloadMacros())); connect(ui.macroSaveButton, SIGNAL(clicked()), this, SLOT(saveMacros())); + connect(ui.fileReloadButton, SIGNAL(clicked()), this, SLOT(reloadScript())); connect(ui.fileLoadButton, SIGNAL(clicked()), this, SLOT(loadScript())); connect(ui.fileSaveButton, SIGNAL(clicked()), this, SLOT(saveScript())); connect(ui.fileSaveAsButton, SIGNAL(clicked()), this, SLOT(saveScriptAs())); @@ -59,12 +62,11 @@ ScriptEditor::ScriptEditor(QWidget *parent) : QWidget(parent) codeEditor->setFont(font); // Define tab width - const int tabStop = 4; // 4 characters + const qreal d = 20; // unit is pixels QFontMetrics metrics(font); - int w = tabStop * metrics.width(' '); - codeEditor->setTabStopWidth(w); - slideEditor->setTabStopWidth(w); - macroEditor->setTabStopWidth(w); + codeEditor->setTabStopDistance(d); + slideEditor->setTabStopDistance(d); + macroEditor->setTabStopDistance(d); ui.modeTabWidget->setTabText(0, tr("Slide", "Mode in scriptEditor")); ui.modeTabWidget->setTabText(1, tr("Macro", "Mode in scriptEditor")); @@ -79,16 +81,20 @@ ScriptEditor::ScriptEditor(QWidget *parent) : QWidget(parent) highlighterSlide = new Highlighter(slideEditor->document()); highlighterFile = new Highlighter(codeEditor->document()); QStringList list; - foreach (Command *c, modelCommands) - list.append(c->getName()); foreach (Command *c, vymCommands) - list.append(c->getName()); + list.append(QString("\\b%1\\b").arg(c->name())); + foreach (Command *c, modelCommands) + list.append(QString("\\b%1\\b").arg(c->name())); + foreach (Command *c, branchCommands) + list.append(QString("\\b%1\\b").arg(c->name())); + foreach (Command *c, imageCommands) + list.append(QString("\\b%1\\b").arg(c->name())); highlighterMacro->addKeywords(list); highlighterSlide->addKeywords(list); highlighterFile->addKeywords(list); // QAction *a = new QAction( tr( "Save","ScriptEditor" ), ui.editor); - // a->setShortcut (Qt::CTRL + Qt::Key_S ); + // a->setShortcut (Qt::CTRL | Qt::Key_S ); // a->setShortcutContext (Qt::WidgetWithChildrenShortcut); // addAction (a); // connect( a, SIGNAL( triggered() ), this, SLOT( saveSlide() ) ); @@ -158,7 +164,7 @@ bool ScriptEditor::loadScript(QString fn) QString filter("VYM scripts (*.vys);;All (*)"); fn = QFileDialog::getOpenFileName(this, vymName + " - " + tr("Load script"), - lastMapDir.path(), filter); + lastScriptDir.path(), filter); } if (!fn.isEmpty()) { @@ -167,7 +173,7 @@ bool ScriptEditor::loadScript(QString fn) if (loadStringFromDisk(filename, s)) { codeEditor->setPlainText(s); ui.scriptPathLineEdit->setText(filename); - lastMapDir.setPath(filename.left(filename.lastIndexOf("/"))); + lastScriptDir.setPath(filename.left(filename.lastIndexOf("/"))); return true; } else { @@ -180,6 +186,28 @@ bool ScriptEditor::loadScript(QString fn) return false; } +bool ScriptEditor::reloadScript() +{ + if (filename.isEmpty()) + return false; + else { + QString s; + if (loadStringFromDisk(filename, s)) { + codeEditor->setPlainText(s); + ui.scriptPathLineEdit->setText(filename); + lastScriptDir.setPath(filename.left(filename.lastIndexOf("/"))); + return true; + } + else { + QString error(QObject::tr("Error")); + QString msg( + QObject::tr("Couldn't read script from \"%1\"\n.").arg(filename)); + QMessageBox::warning(0, error, msg); + } + } + return false; +} + void ScriptEditor::saveScript() { if (filename.isEmpty()) @@ -201,35 +229,15 @@ void ScriptEditor::saveScriptAs() QString filter("VYM scripts (*.vys *.js);;All (*)"); QString fn = QFileDialog::getSaveFileName( this, QString(vymName + " - " + tr("Save script")), QString(), - "VYM script (*js *.vys);;All files (*)", 0, - QFileDialog::DontConfirmOverwrite); + "VYM script (*js *.vys);;All files (*)"); if (!fn.isEmpty()) { QFile file(fn); - if (file.exists()) { - QMessageBox mb( - vymName, - tr("The file %1\nexists already.\nDo you want to overwrite it?", - "dialog 'save as'") - .arg(fn), - QMessageBox::Warning, QMessageBox::Yes | QMessageBox::Default, - QMessageBox::Cancel | QMessageBox::Escape, Qt::NoButton); - mb.setButtonText(QMessageBox::Yes, tr("Overwrite")); - mb.setButtonText(QMessageBox::No, tr("Cancel")); - switch (mb.exec()) { - case QMessageBox::Yes: - // save - filename = fn; - ui.scriptPathLineEdit->setText(filename); - lastMapDir.setPath(filename.left(filename.lastIndexOf("/"))); - saveScript(); - return; - case QMessageBox::Cancel: - // do nothing - return; - } - } + // Already tested in QFileDialog, if we may overwrite in case file exists already + filename = fn; + ui.scriptPathLineEdit->setText(filename); + lastScriptDir.setPath(filename.left(filename.lastIndexOf("/"))); saveScript(); } } diff --git a/src/scripteditor.h b/src/scripteditor.h index 07c6acc..948be36 100644 --- a/src/scripteditor.h +++ b/src/scripteditor.h @@ -31,6 +31,7 @@ class ScriptEditor : public QWidget { void reloadMacros(); void saveMacros(); bool loadScript(QString fn = ""); + bool reloadScript(); void saveScript(); void saveScriptAs(); diff --git a/src/scripting-xlink-wrapper.cpp b/src/scripting-xlink-wrapper.cpp new file mode 100644 index 0000000..87fe81f --- /dev/null +++ b/src/scripting-xlink-wrapper.cpp @@ -0,0 +1,92 @@ +#include "scripting-xlink-wrapper.h" + +#include "attributeitem.h" +#include "misc.h" +#include "vymmodel.h" +#include "mainwindow.h" +#include "xlink.h" +//#include "xlinkitem.h" + +extern Main *mainWindow; + +XLinkWrapper::XLinkWrapper(XLink *xl) +{ + //qDebug() << "Constr XLinkWrapper (ii)"; + xlinkInt = xl; +} + +XLinkWrapper::~XLinkWrapper() +{ + //qDebug() << "Destr XLinkWrapper"; +} + +VymModel* XLinkWrapper::model() {return xlinkInt->getModel();} + +XLink* XLinkWrapper::xlink() {return xlinkInt;} + +QString XLinkWrapper::getColor() +{ + QString r = xlinkInt->getPen().color().name(); + mainWindow->setScriptResult(r); + return r; +} + +int XLinkWrapper::getWidth() +{ + int r = xlinkInt->getPen().width(); + mainWindow->setScriptResult(r); + return r; +} + +QString XLinkWrapper::getPenStyle() +{ + QString r = penStyleToString(xlinkInt->getPen().style()); + mainWindow->setScriptResult(r); + return r; +} + +QString XLinkWrapper::getStyleBegin() +{ + QString r = xlinkInt->getStyleBeginString(); + mainWindow->setScriptResult(r); + return r; +} + +QString XLinkWrapper::getStyleEnd() +{ + QString r = xlinkInt->getStyleEndString(); + mainWindow->setScriptResult(r); + return r; +} + +void XLinkWrapper::setColor(const QString &color) +{ + QColor col(color); + if (!col.isValid()) + mainWindow->abortScript( + QJSValue::GenericError, + QString("Could not set color to %1").arg(color)); + else + model()->setXLinkColor(color, xlinkInt); +} + +void XLinkWrapper::setStyle(const QString &style) +{ + model()->setXLinkStyle(style, xlinkInt); +} + +void XLinkWrapper::setStyleBegin(const QString &style) +{ + model()->setXLinkStyleBegin(style, xlinkInt); +} + +void XLinkWrapper::setStyleEnd(const QString &style) +{ + model()->setXLinkStyleEnd(style, xlinkInt); +} + +void XLinkWrapper::setWidth(int w) +{ + model()->setXLinkWidth(w, xlinkInt); +} + diff --git a/src/scripting-xlink-wrapper.h b/src/scripting-xlink-wrapper.h new file mode 100644 index 0000000..caf7267 --- /dev/null +++ b/src/scripting-xlink-wrapper.h @@ -0,0 +1,35 @@ +#ifndef XLINK_WRAPPER_H +#define XLINK_WRAPPER_H + +#include + +class XLink; +class VymModel; + +class XLinkWrapper : public QObject { + Q_OBJECT + public: + Q_INVOKABLE XLinkWrapper(XLink*); + ~XLinkWrapper(); + VymModel* model(); + XLink* xlink(); + + public slots: + QString getColor(); + int getWidth(); + QString getPenStyle(); + QString getStyleBegin(); + QString getStyleEnd(); + void setColor(const QString &color); + void setStyle(const QString &styGle); + void setStyleBegin(const QString &style); + void setStyleEnd(const QString &style); + void setWidth(int w); + + private: + XLink *xlinkInt; +}; + +Q_DECLARE_METATYPE(XLinkWrapper) +Q_DECLARE_METATYPE(XLinkWrapper*) +#endif diff --git a/src/scripting.cpp b/src/scripting.cpp deleted file mode 100644 index 788d8df..0000000 --- a/src/scripting.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include "scripting.h" - -#include "branchitem.h" -#include "confluence-agent.h" -#include "imageitem.h" -#include "mainwindow.h" -#include "misc.h" -#include "vymmodelwrapper.h" -#include "vymtext.h" -#include "xlink.h" - -extern Main *mainWindow; -extern QString vymVersion; - -/////////////////////////////////////////////////////////////////////////// -void logError(QScriptContext *context, QScriptContext::Error error, - const QString &text) -{ - if (context) - context->throwError(error, text); - else - qDebug() << "VymWrapper: " << text; -} - -/////////////////////////////////////////////////////////////////////////// -VymScriptContext::VymScriptContext() {} - -QString VymScriptContext::setResult(const QString &r) -{ - context()->engine()->globalObject().setProperty("lastResult", r); - return r; -} - -bool VymScriptContext::setResult(bool r) -{ - context()->engine()->globalObject().setProperty("lastResult", r); - return r; -} - -int VymScriptContext::setResult(int r) -{ - context()->engine()->globalObject().setProperty("lastResult", r); - return r; -} - -uint VymScriptContext::setResult(uint r) -{ - context()->engine()->globalObject().setProperty("lastResult", r); - return r; -} - -/////////////////////////////////////////////////////////////////////////// -VymWrapper::VymWrapper() {} - -void VymWrapper::clearConsole() { mainWindow->clearScriptOutput(); } - -bool VymWrapper::isConfluenceAgentAvailable() -{ - return ConfluenceAgent::available(); -} - -QObject *VymWrapper::currentMap() -{ - return mainWindow->getCurrentModelWrapper(); -} - -void VymWrapper::editHeading() -{ - MapEditor *me = mainWindow->currentMapEditor(); - if (me) me->editHeading(); -} - -bool VymWrapper::loadMap(const QString &filename) -{ - bool r; - if (File::Success == mainWindow->fileLoad(filename, NewMap, VymMap)) - r = true; - else - r = false; - return setResult(r); -} - -int VymWrapper::mapCount() -{ - context()->engine()->globalObject().setProperty("lastResult", - mainWindow->modelCount()); - return setResult(mainWindow->modelCount()); -} - -void VymWrapper::gotoMap(uint n) -{ - if (!mainWindow->gotoWindow(n)) { - logError(context(), QScriptContext::RangeError, - QString("Map '%1' not available.").arg(n)); - } -} - -bool VymWrapper::closeMapWithID(uint n) -{ - bool r = mainWindow->closeModelWithID(n); - if (!r) - logError(context(), QScriptContext::RangeError, - QString("Map '%1' not available.").arg(n)); - return setResult(r); -} - -void VymWrapper::selectQuickColor(int n) -{ - mainWindow->selectQuickColor(n); -} - -QString VymWrapper::currentColor() -{ - return mainWindow->getCurrentColor().name(); -} - -uint VymWrapper::currentMapID() -{ - uint id = mainWindow->currentMapID(); - return setResult(id); -} - -void VymWrapper::toggleTreeEditor() { mainWindow->windowToggleTreeEditor(); } - -QString VymWrapper::loadFile( - const QString - &filename) // FIXME-3 error handling missing (in vymmodel and here) -{ - QString s; - loadStringFromDisk(filename, s); - return s; -} - -void VymWrapper::saveFile( - const QString &filename, - const QString &s) // FIXME-3 error handling missing (in vymmodel and here) -{ - saveStringToDisk(filename, s); -} - -QString VymWrapper::version() { return setResult(vymVersion); } - -// See also http://doc.qt.io/qt-5/qscriptengine.html#newFunction -Selection::Selection() { modelWrapper = NULL; } - -void Selection::test() -{ - qDebug() << "Selection::testSelection called"; // TODO debug - if (modelWrapper) - modelWrapper->setHeadingPlainText("huhu!"); -} - -void Selection::setModel(VymModelWrapper *mw) -{ - qDebug() << "Selection::setModel called: " << mw; // TODO debug - modelWrapper = mw; -} diff --git a/src/scripting.h b/src/scripting.h deleted file mode 100644 index c724512..0000000 --- a/src/scripting.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef SCRIPTING_H -#define SCRIPTING_H - -#include -#include -#include -#include -#include -#include - -class BranchItem; -class VymModelWrapper; - -void logError(QScriptContext *context, QScriptContext::Error error, - const QString &text); - -/////////////////////////////////////////////////////////////////////////// -class VymScriptContext : public QObject, protected QScriptable { - Q_OBJECT - public: - VymScriptContext(); - QString setResult(const QString &r); - bool setResult(bool r); - int setResult(int r); - uint setResult(uint r); -}; - -/////////////////////////////////////////////////////////////////////////// -class VymWrapper : public VymScriptContext { - Q_OBJECT - public: - VymWrapper(); - - public slots: - void clearConsole(); - bool isConfluenceAgentAvailable(); - QObject *currentMap(); - void editHeading(); - bool loadMap(const QString &filename); - int mapCount(); - void gotoMap(uint n); - bool closeMapWithID(uint n); - void selectQuickColor(int n); - QString currentColor(); - uint currentMapID(); - void toggleTreeEditor(); - QString loadFile(const QString &filename); - void saveFile(const QString &filename, const QString &s); - QString version(); -}; - -class Selection : public VymScriptContext { - Q_OBJECT - public: - Selection(); - - public slots: - void test(); - void setModel(VymModelWrapper *mw); - - private: - VymModelWrapper *modelWrapper; -}; - -#endif diff --git a/src/selectable-container.cpp b/src/selectable-container.cpp new file mode 100644 index 0000000..28c1ac5 --- /dev/null +++ b/src/selectable-container.cpp @@ -0,0 +1,59 @@ +#include "selectable-container.h" + +#include + +#include "container.h" + +SelectableContainer::SelectableContainer() +{ + selectionContainer = nullptr; + movingStateInt = NotMoving; + tmpLinkedParentContainer = nullptr; + originalParentBranchContainer = nullptr; +} + +void SelectableContainer::select(Container *parent, const QPen &pen, const QBrush &brush) +{ + if (!selectionContainer) + { + selectionContainer = new Container; + selectionContainer->setContainerType(Container::Selection); + selectionContainer->overlay = true; + } + selectionContainer->setPen(pen); + selectionContainer->setBrush(brush); + + parent->addContainer(selectionContainer, Z_SELECTION); + selectionContainer->setFlag(QGraphicsItem::ItemStacksBehindParent, true); + + // Initially set rectangle + selectionContainer->setRect(parent->rect()); +} + +void SelectableContainer::unselect() +{ + if (!selectionContainer) return; + + delete selectionContainer; + selectionContainer = nullptr; +} + +bool SelectableContainer::isSelected() +{ + if (selectionContainer) + return true; + else + return false; +} + +void SelectableContainer::setMovingState(const MovingState &ms, BranchContainer *tpc) +{ + movingStateInt = ms; + tmpLinkedParentContainer = tpc; +} + +SelectableContainer::MovingState SelectableContainer::movingState() +{ + return SelectableContainer::movingStateInt; +} + diff --git a/src/selectable-container.h b/src/selectable-container.h new file mode 100644 index 0000000..a1d7ff3 --- /dev/null +++ b/src/selectable-container.h @@ -0,0 +1,44 @@ +#ifndef SELECTABLE_CONTAINER_H +#define SELECTABLE_CONTAINER_H + +#include + +class BranchContainer; +class Container; + +class SelectableContainer { + friend class BranchContainer; + friend class BranchContainerBase; + friend class ImageContainer; + + public: + /*! States related to moving around */ + enum MovingState { + NotMoving, + Moving, + TemporaryLinked + }; + + SelectableContainer(); + + virtual void select( + Container *container, + const QPen &, + const QBrush &); + void unselect(); + bool isSelected(); + + protected: + MovingState movingStateInt; + BranchContainer *tmpLinkedParentContainer; + BranchContainer *originalParentBranchContainer; + + public: + void setMovingState(const MovingState &, BranchContainer *tpc = nullptr); + MovingState movingState(); + + protected: + Container *selectionContainer; +}; + +#endif diff --git a/src/settings.cpp b/src/settings.cpp index 4e4f3b1..87f6890 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -4,7 +4,8 @@ #include "file.h" #include "settings.h" -#include + +#include ///////////////////////////////////////////////////////////////// // SimpleSettings @@ -27,7 +28,7 @@ bool SimpleSettings::readSettings(const QString &path) return false; } QStringList lines; - lines = s.split(QRegExp("\n")); + lines = s.split(QRegularExpression("\n")); int i; QStringList::Iterator it = lines.begin(); while (it != lines.end()) { @@ -216,7 +217,7 @@ QString Settings::getDataXML(const QString &fpath) s += indent() + valueElement("setting", getCDATA(valuelist.at(i).toString()), - attribut("key", keylist.at(i))); + attribute("key", keylist.at(i))); i++; } return s; diff --git a/src/settings.h b/src/settings.h index 0fa436f..c4b1617 100644 --- a/src/settings.h +++ b/src/settings.h @@ -1,9 +1,8 @@ #ifndef SETTINGS_H #define SETTINGS_H -#include -#include -#include +#include +#include #include "xmlobj.h" diff --git a/src/shortcuts.cpp b/src/shortcuts.cpp index 7858fba..2e0a131 100644 --- a/src/shortcuts.cpp +++ b/src/shortcuts.cpp @@ -2,7 +2,6 @@ #include #include -using namespace std; #include "shortcuts.h" @@ -84,13 +83,13 @@ QString Switchboard::getASCII() return s; } -void Switchboard::printASCII() { cout << qPrintable(getASCII()); } +void Switchboard::printASCII() { std::cout << qPrintable(getASCII()); } void Switchboard::printLaTeX() { QString g; foreach (g, actions.uniqueKeys()) { - cout << "Group: " << qPrintable(g) << "\\\\ \\hline" << endl; + std::cout << "Group: " << qPrintable(g) << "\\\\ \\hline" << std::endl; QList values = actions.values(g); for (int i = 0; i < values.size(); ++i) if (!values.at(i)->shortcut().toString().isEmpty()) { @@ -98,9 +97,9 @@ void Switchboard::printLaTeX() QString sc = values.at(i)->shortcut().toString(); desc = desc.remove('&'); desc = desc.remove("..."); - cout << qPrintable(QString(" %1& %2").arg(sc, 12).arg(desc)) - << endl; + std::cout << qPrintable(QString(" %1& %2").arg(sc, 12).arg(desc)) + << std::endl; } - cout << endl; + std::cout << std::endl; } } diff --git a/src/slidecontrolwidget.cpp b/src/slidecontrolwidget.cpp index cc42329..77a1fd8 100644 --- a/src/slidecontrolwidget.cpp +++ b/src/slidecontrolwidget.cpp @@ -10,6 +10,7 @@ #include "slidecontrolwidget.h" extern Main *mainWindow; +extern QString iconTheme; SlideControlWidget::SlideControlWidget(QWidget *) { @@ -35,7 +36,7 @@ SlideControlWidget::SlideControlWidget(QWidget *) snapshotButton = new QPushButton; // snapshotButton->setIcon (QPixmap ( ":/sliderecord.png" )); // Original: /usr/share/icons/oxygen/32x32/devices/camera-photo.png - snapshotButton->setIcon(QPixmap(":/slide-camera.png")); + snapshotButton->setIcon(QPixmap(QString(":/camera-photo-%1.svg").arg(iconTheme))); connect(snapshotButton, SIGNAL(clicked()), this, SLOT(snapshotPressed())); editButton = new QPushButton; @@ -43,7 +44,7 @@ SlideControlWidget::SlideControlWidget(QWidget *) connect(editButton, SIGNAL(clicked()), this, SLOT(editPressed())); deleteButton = new QPushButton; - deleteButton->setIcon(QPixmap(":/edittrash.png")); + deleteButton->setIcon(QPixmap(QString(":/edit-delete-%1.svg").arg(iconTheme))); connect(deleteButton, SIGNAL(clicked()), this, SLOT(deletePressed())); row2Layout->addWidget(previousButton); @@ -59,16 +60,16 @@ SlideControlWidget::SlideControlWidget(QWidget *) setLayout(mainLayout); } -void SlideControlWidget::snapshotPressed() { emit(takeSnapshot()); } +void SlideControlWidget::snapshotPressed() { emit takeSnapshot(); } -void SlideControlWidget::editPressed() { emit(editButtonPressed()); } +void SlideControlWidget::editPressed() { emit editButtonPressed(); } -void SlideControlWidget::deletePressed() { emit(deleteButtonPressed()); } +void SlideControlWidget::deletePressed() { emit deleteButtonPressed(); } -void SlideControlWidget::previousPressed() { emit(previousButtonPressed()); } +void SlideControlWidget::previousPressed() { emit previousButtonPressed(); } -void SlideControlWidget::nextPressed() { emit(nextButtonPressed()); } +void SlideControlWidget::nextPressed() { emit nextButtonPressed(); } -void SlideControlWidget::upPressed() { emit(upButtonPressed()); } +void SlideControlWidget::upPressed() { emit upButtonPressed(); } -void SlideControlWidget::downPressed() { emit(downButtonPressed()); } +void SlideControlWidget::downPressed() { emit downButtonPressed(); } diff --git a/src/slidecontrolwidget.h b/src/slidecontrolwidget.h index d667022..79eb9e3 100644 --- a/src/slidecontrolwidget.h +++ b/src/slidecontrolwidget.h @@ -10,7 +10,7 @@ class SlideControlWidget : public QWidget { Q_OBJECT public: - SlideControlWidget(QWidget *parent = NULL); + SlideControlWidget(QWidget *parent = nullptr); public slots: void previousPressed(); diff --git a/src/slideeditor.cpp b/src/slideeditor.cpp index 88f0de8..f6798ce 100644 --- a/src/slideeditor.cpp +++ b/src/slideeditor.cpp @@ -62,6 +62,11 @@ SlideEditor::SlideEditor(VymModel *m) // (expandAll() )); } +void SlideEditor::closeEvent(QCloseEvent *event) +{ + mainWindow->windowSetSlideEditorsVisibility(false); +} + void SlideEditor::previousSlide() { QModelIndex ix = slideModel->getSelectedIndex(); @@ -83,7 +88,7 @@ void SlideEditor::nextSlide() void SlideEditor::addSlide() { vymModel->addSlide(); } -void SlideEditor::editSlide() // FIXME-4 not used yet +void SlideEditor::editSlide() // FIXME-5 not used yet { } @@ -99,5 +104,5 @@ void SlideEditor::moveSlideDown() { vymModel->moveSlideDown(); } void SlideEditor::updateSelection(QItemSelection, QItemSelection) { - // FIXME-3 updateActions missing, e.g. state for moveUp/down + // FIXME-4 updateActions missing, e.g. state for moveUp/down } diff --git a/src/slideeditor.h b/src/slideeditor.h index ab5f7d9..110ce03 100644 --- a/src/slideeditor.h +++ b/src/slideeditor.h @@ -15,6 +15,9 @@ class SlideEditor : public QWidget { public: SlideEditor(VymModel *); + protected: + virtual void closeEvent(QCloseEvent *event); + public slots: void previousSlide(); void nextSlide(); diff --git a/src/slideitem.cpp b/src/slideitem.cpp index 25804ba..ee90779 100644 --- a/src/slideitem.cpp +++ b/src/slideitem.cpp @@ -39,14 +39,6 @@ SlideItem *SlideItem::child(int number) { return childItems.value(number); } int SlideItem::childCount() const { return childItems.count(); } -int SlideItem::childNumber() const -{ - if (parentItem) - return parentItem->childItems.indexOf(const_cast(this)); - - return 0; -} - int SlideItem::columnCount() const { return itemData.count(); } QVariant SlideItem::data(int column) const { return itemData.value(column); } @@ -56,7 +48,7 @@ int SlideItem::row() const if (parentItem) return parentItem->childItems.indexOf(const_cast(this)); - return 0; + return -1; } void SlideItem::insertItem(int pos, SlideItem *si) @@ -184,23 +176,23 @@ QString SlideItem::saveToDir() { QString att_ins, att_outs; if (inScript.isEmpty()) { - att_ins = attribut( + att_ins = attribute( "inScript", QString("select(\"%1\")") .arg(model->getVymModel()->getSelectString(treeItemID))); } else - att_ins = attribut("inScript", inScript); + att_ins = attribute("inScript", inScript); if (!outScript.isEmpty()) - att_outs = attribut("outScript", outScript); + att_outs = attribute("outScript", outScript); return singleElement( - "slide", attribut("name", data(0).toString()) + - attribut("zoom", QString().setNum(zoomFactor)) + - attribut("rotation", QString().setNum(rotationAngle)) + - attribut("duration", QString().setNum(duration)) + - attribut("curve", QString().setNum(easingCurve.type())) + - attribut("mapitem", model->getVymModel()->getSelectString( + "slide", attribute("name", data(0).toString()) + + attribute("zoom", QString().setNum(zoomFactor)) + + attribute("rotation", QString().setNum(rotationAngle)) + + attribute("duration", QString().setNum(duration)) + + attribute("curve", QString().setNum(easingCurve.type())) + + attribute("mapitem", model->getVymModel()->getSelectString( treeItemID)) + att_ins + att_outs); } diff --git a/src/slideitem.h b/src/slideitem.h index 097ecbd..e830da6 100644 --- a/src/slideitem.h +++ b/src/slideitem.h @@ -30,7 +30,6 @@ class SlideItem : public XMLObj { SlideItem *parent(); bool removeChildren(int position, int count); bool removeColumns(int position, int columns); - int childNumber() const; bool setData(int column, const QVariant &value); void setName(const QString &n); QString getName(); diff --git a/src/slidemodel.cpp b/src/slidemodel.cpp index 0f08a99..d79bd55 100644 --- a/src/slidemodel.cpp +++ b/src/slidemodel.cpp @@ -6,11 +6,11 @@ #include #include -SlideModel::SlideModel(VymModel *vm) : QAbstractItemModel(NULL) +SlideModel::SlideModel(VymModel *vm) : QAbstractItemModel(nullptr) { QVector rootData; rootData << "Slide"; - rootItem = new SlideItem(rootData, NULL, this); + rootItem = new SlideItem(rootData, nullptr, this); vymModel = vm; } @@ -45,7 +45,7 @@ QVariant SlideModel::data(const QModelIndex &index, int role) const Qt::ItemFlags SlideModel::flags(const QModelIndex &index) const { if (!index.isValid()) - return 0; + return QFlag(0); return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable; } @@ -118,7 +118,7 @@ QModelIndex SlideModel::parent(const QModelIndex &index) const if (parentItem == rootItem) return QModelIndex(); - return createIndex(parentItem->childNumber(), 0, parentItem); + return createIndex(parentItem->row(), 0, parentItem); } bool SlideModel::removeColumns(int position, int columns, @@ -188,11 +188,11 @@ bool SlideModel::setHeaderData(int section, Qt::Orientation orientation, SlideItem *SlideModel::addSlide(SlideItem *dst, int n) { - SlideItem *si = NULL; + SlideItem *si = nullptr; if (!dst) dst = rootItem; - emit(layoutAboutToBeChanged()); + emit layoutAboutToBeChanged(); QModelIndex parix = index(dst); if (n < 0) @@ -203,7 +203,7 @@ SlideItem *SlideModel::addSlide(SlideItem *dst, int n) si = getItem(ix); } endInsertRows(); - emit(layoutChanged()); + emit layoutChanged(); return si; } @@ -213,7 +213,7 @@ void SlideModel::deleteSlide(SlideItem *si) QModelIndex ix = index(si); if (ix.isValid()) { QModelIndex px = ix.parent(); - int n = si->childNumber(); + int n = si->row(); removeRows(n, 1, px); } } @@ -221,11 +221,11 @@ void SlideModel::deleteSlide(SlideItem *si) bool SlideModel::relinkSlide(SlideItem *si, SlideItem *dst, int pos) { if (si && dst) { - emit(layoutAboutToBeChanged()); + emit layoutAboutToBeChanged(); SlideItem *pi = si->parent(); // Remove at current position - int n = si->childNumber(); + int n = si->row(); beginRemoveRows(index(pi), n, n); pi->removeItem(n); @@ -239,7 +239,7 @@ bool SlideModel::relinkSlide(SlideItem *si, SlideItem *dst, int pos) dst->insertItem(pos, si); endInsertRows(); - emit(layoutChanged()); + emit layoutChanged(); selModel->select(index(si), QItemSelectionModel::ClearAndSelect); @@ -261,7 +261,7 @@ SlideItem *SlideModel::getItem(const QModelIndex &index) const SlideItem *SlideModel::getSlide(int n) { if (n >= count() || n < 0) - return NULL; + return nullptr; return getItem(index(n, 0, QModelIndex())); } @@ -270,7 +270,7 @@ SlideItem *SlideModel::findSlideID(uint n) for (int i = 0; i < rootItem->childCount(); i++) if (rootItem->child(i)->getID() == n) return rootItem->child(i); - return NULL; + return nullptr; } QString SlideModel::saveToDir() @@ -310,5 +310,5 @@ SlideItem *SlideModel::getSelectedItem() QModelIndex ix = getSelectedIndex(); if (ix.isValid()) return getItem(ix); - return NULL; + return nullptr; } diff --git a/src/slidemodel.h b/src/slidemodel.h index 6503ebc..b68edfe 100644 --- a/src/slidemodel.h +++ b/src/slidemodel.h @@ -50,7 +50,7 @@ class SlideModel : public QAbstractItemModel, XMLObj { bool removeRows(int position, int rows, const QModelIndex &parent = QModelIndex()); - SlideItem *addSlide(SlideItem *dst = NULL, int n = -1); + SlideItem *addSlide(SlideItem *dst = nullptr, int n = -1); void deleteSlide(SlideItem *si); bool relinkSlide(SlideItem *si, SlideItem *dst, int pos); diff --git a/src/task.cpp b/src/task.cpp index cca1bcc..18b1caa 100644 --- a/src/task.cpp +++ b/src/task.cpp @@ -11,18 +11,18 @@ Task::Task(TaskModel *tm) // qDebug()<<"Constr. Task"; status = NotStarted; awake = Task::WideAwake; - branch = NULL; + branch = nullptr; prio = 0; prio_delta = 0; model = tm; - date_creation = QDateTime::currentDateTime(); + creationTimeInt = QDateTime::currentDateTime(); } Task::~Task() { - // qDebug()<<"Destr. Task"; + // qDebug()<<"Destr. Task " << this; if (branch) - branch->setTask(NULL); + branch->setTask(nullptr); } void Task::setModel(TaskModel *tm) { model = tm; } @@ -173,35 +173,35 @@ int Task::getPriority() { return prio; } int Task::getAgeCreation() { - return date_creation.daysTo(QDateTime::currentDateTime()); + return creationTimeInt.daysTo(QDateTime::currentDateTime()); } int Task::getAgeModification() { - if (date_modification.isValid()) - return date_modification.daysTo(QDateTime::currentDateTime()); + if (modificationTimeInt.isValid()) + return modificationTimeInt.daysTo(QDateTime::currentDateTime()); else return getAgeCreation(); } void Task::setDateCreation(const QString &s) { - date_creation = QDateTime().fromString(s, Qt::ISODate); + creationTimeInt = QDateTime().fromString(s, Qt::ISODate); } -QDateTime Task::getDateCreation() { return date_creation; } +QDateTime Task::getDateCreation() { return creationTimeInt; } void Task::setDateModification() { - date_modification = QDateTime::currentDateTime(); + modificationTimeInt = QDateTime::currentDateTime(); } void Task::setDateModification(const QString &s) { - date_modification = QDateTime().fromString(s, Qt::ISODate); + modificationTimeInt = QDateTime().fromString(s, Qt::ISODate); } -QDateTime Task::getDateModification() { return date_modification; } +QDateTime Task::getDateModification() { return modificationTimeInt; } bool Task::setDaysSleep(qint64 n) { @@ -228,10 +228,7 @@ bool Task::setDateSleep(const QString &s) return true; else if (setDateSleep(QDateTime().fromString(s, Qt::TextDate))) return true; - else if (setDateSleep( - QDateTime().fromString(s, Qt::DefaultLocaleShortDate))) - return true; - else if (setDateSleep(QDateTime().fromString(s, Qt::DefaultLocaleLongDate))) + else if (setDateSleep(QDateTime().fromString(s))) return true; else return false; @@ -242,7 +239,7 @@ bool Task::setDateSleep(const QDateTime &d) if (!d.isValid()) return false; - date_sleep = d; + alarmInt = d; updateAwake(); return true; } @@ -250,11 +247,11 @@ bool Task::setDateSleep(const QDateTime &d) qint64 Task::getDaysSleep() { qint64 d = 1; - if (date_sleep.isValid()) - d = QDateTime::currentDateTime().daysTo(date_sleep); + if (alarmInt.isValid()) + d = QDateTime::currentDateTime().daysTo(alarmInt); else { - // qWarning() << "Task::getDaysSleep date_sleep is invalid for branch " - // << branch->getHeadingPlain(); + // qWarning() << "Task::getDaysSleep alarmInt is invalid for branch " + // << branch->headingPlain(); return -1; } return d; @@ -263,12 +260,12 @@ qint64 Task::getDaysSleep() qint64 Task::getSecsSleep() { qint64 d = 0; // Meaning: No sleep time set so far - if (date_sleep.isValid()) - d = QDateTime::currentDateTime().secsTo(date_sleep); + if (alarmInt.isValid()) + d = QDateTime::currentDateTime().secsTo(alarmInt); return d; } -QDateTime Task::getSleep() { return date_sleep; } +QDateTime Task::alarmTime() { return alarmInt; } void Task::setPriorityDelta(const int &n) { prio_delta = n; } @@ -285,7 +282,7 @@ BranchItem *Task::getBranch() { return branch; } QString Task::getName() { if (branch) - return branch->getHeadingPlain(); + return branch->headingPlain(); else { qWarning() << "Task::getName no branch!"; return "UNDEFINED"; @@ -297,30 +294,30 @@ QString Task::getMapName() { return mapName; } QString Task::saveToDir() { QString sleepAttr; - if (date_sleep.isValid()) - sleepAttr = attribut("date_sleep", date_sleep.toString(Qt::ISODate)); + if (alarmInt.isValid()) + sleepAttr = attribute("date_sleep", alarmInt.toString(Qt::ISODate)); else - sleepAttr = attribut("date_sleep", "2018-01-01T00:00:00"); + sleepAttr = attribute("date_sleep", "2018-01-01T00:00:00"); // Experimental: Also output priority based on arrow flags for external // sorting QString prioAttr; if (branch) { if (branch->hasActiveFlag("2arrow-up")) - prioAttr = attribut("prio", "2"); + prioAttr = attribute("prio", "2"); if (branch->hasActiveFlag("arrow-up")) - prioAttr = attribut("prio", "1"); + prioAttr = attribute("prio", "1"); } QString prioDeltaAttr; if (prio_delta != 0) - prioDeltaAttr = attribut("prio_delta", QString("%1").arg(prio_delta)); + prioDeltaAttr = attribute("prio_delta", QString("%1").arg(prio_delta)); return singleElement( "task", - attribut("status", getStatusString()) + - attribut("awake", getAwakeString()) + - attribut("date_creation", date_creation.toString(Qt::ISODate)) + - attribut("date_modification", - date_modification.toString(Qt::ISODate)) + + attribute("status", getStatusString()) + + attribute("awake", getAwakeString()) + + attribute("date_creation", creationTimeInt.toString(Qt::ISODate)) + + attribute("date_modification", + modificationTimeInt.toString(Qt::ISODate)) + prioDeltaAttr + sleepAttr + prioAttr); } diff --git a/src/task.h b/src/task.h index acad5ae..49e4184 100644 --- a/src/task.h +++ b/src/task.h @@ -49,7 +49,7 @@ class Task : public XMLObj { bool setDateSleep(const QDateTime &d); qint64 getDaysSleep(); qint64 getSecsSleep(); - QDateTime getSleep(); + QDateTime alarmTime(); QString getName(); void setPriorityDelta(const int &n); int getPriorityDelta(); @@ -66,9 +66,9 @@ class Task : public XMLObj { int prio_delta; BranchItem *branch; QString mapName; - QDateTime date_creation; - QDateTime date_modification; - QDateTime date_sleep; + QDateTime creationTimeInt; + QDateTime modificationTimeInt; + QDateTime alarmInt; }; #endif diff --git a/src/taskeditor.cpp b/src/taskeditor.cpp index e15d4b3..c1070cc 100644 --- a/src/taskeditor.cpp +++ b/src/taskeditor.cpp @@ -2,10 +2,12 @@ #include #include +#include #include #include #include #include +#include #include #include #include @@ -13,6 +15,7 @@ #include "branchitem.h" #include "mainwindow.h" #include "task.h" +#include "taskfiltermodel.h" #include "taskmodel.h" #include "vymmodel.h" @@ -182,6 +185,8 @@ TaskEditor::TaskEditor(QWidget *) SIGNAL(customContextMenuRequested(QPoint)), SLOT(headerContextMenu())); + view->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); + view->setStyleSheet("QTableView:focus {" + editorFocusStyle + "}"); updateColumnLayout(); @@ -339,7 +344,6 @@ void TaskEditor::headerContextMenu() void TaskEditor::updateColumnLayout() { // Update column widths and visibility - QString s = "/taskeditor/column/%1/"; // Priority @@ -417,11 +421,12 @@ void TaskEditor::selectionChanged(const QItemSelection &selected, m->select(bi); if (m != mainWindow->currentModel()) mainWindow->gotoModel(m); - view->setStyleSheet( + /* view->setStyleSheet( // FIXME-5 this resets column widths on Windows... "QTableView {selection-background-color: " + m->getSelectionBrushColor().name() + - "; selection-color:" + bi->getHeadingColor().name() + "}" + + "; selection-color:" + bi->headingColor().name() + "}" + "QTableView:focus {" + editorFocusStyle + "}"); + */ view->scrollTo(selected.indexes().first()); } } diff --git a/src/taskeditor.h b/src/taskeditor.h index 109634d..7458f0e 100644 --- a/src/taskeditor.h +++ b/src/taskeditor.h @@ -1,22 +1,22 @@ #ifndef TASKEDITOR_H #define TASKEDITOR_H -#include #include -#include "taskfiltermodel.h" +class QItemSelection; +class QSortFilterProxyModel; class BranchItem; class QTableView; class Task; +class TaskFilterModel; class TaskModel; -class QSortFilterProxyModel; class TaskEditor : public QWidget { Q_OBJECT public: - TaskEditor(QWidget *parent = NULL); + TaskEditor(QWidget *parent = nullptr); ~TaskEditor(); void setMapName(const QString &); bool isUsedFilterMap(); @@ -30,7 +30,6 @@ class TaskEditor : public QWidget { void setFilterFlags3(); void updateFilters(); bool taskVisible(Task*); - void resetDeltaPrio(); bool select(Task *task); void clearSelection(); void showSelection(); diff --git a/src/taskmodel.cpp b/src/taskmodel.cpp index b76baf3..3e94efe 100644 --- a/src/taskmodel.cpp +++ b/src/taskmodel.cpp @@ -3,7 +3,6 @@ #include #include "branchitem.h" -#include "branchobj.h" #include "task.h" #include "vymmodel.h" @@ -69,7 +68,7 @@ Task *TaskModel::getTask(const QModelIndex &ix) const if (ix.isValid()) return tasks.at(ix.row()); else - return NULL; + return nullptr; } Task *TaskModel::getTask(const int i) const @@ -77,7 +76,7 @@ Task *TaskModel::getTask(const int i) const if (i >= 0 && i < count()) return getTask(createIndex(i, 0)); else - return NULL; + return nullptr; } int TaskModel::rowCount(const QModelIndex &parent) const @@ -130,7 +129,7 @@ QVariant TaskModel::data(const QModelIndex &index, int role) const } else if (index.column() == 8) { BranchItem *bi = tasks.at(index.row())->getBranch(); - return bi->getHeadingPlainWithParents(showParentsLevel); + return bi->headingPlainWithParents(showParentsLevel); } } else if (role == Qt::DecorationRole && index.column() == 2) { @@ -174,22 +173,19 @@ QVariant TaskModel::data(const QModelIndex &index, int role) const } else // role != Qt::DisplayRole { - if (role == Qt::EditRole && index.column() == 1) // DeltaPrio - return t->getPriorityDelta(); + if (role == Qt::EditRole) + { + if (index.column() == 1) // DeltaPrio + return t->getPriorityDelta(); + else if (index.column() == 8) { + BranchItem *bi = tasks.at(index.row())->getBranch(); + return bi->headingPlainWithParents(showParentsLevel); + } + } if (role == Qt::ForegroundRole && bi) - return bi->getHeadingColor(); + return bi->headingColor(); if (role == Qt::BackgroundRole && bi) { - BranchItem *frameBI = bi->getFramedParentBranch(bi); - if (frameBI && index.column() != 5) { - BranchObj *bo = frameBI->getBranchObj(); - if (bo) - // Return frame background - return bo->getFrameBrushColor(); - } - else { - // Return map background - return bi->getModel()->getMapBackgroundColor(); - } + return bi->getBackgroundColor(bi); } } @@ -270,7 +266,7 @@ bool TaskModel::setData(const QModelIndex &index, const QVariant &value, VymModel *m = bi->getModel(); m->setTaskPriorityDelta(value.toInt(), bi); recalcPriorities(); - emit(dataChanged(index, index)); + emit dataChanged(index, index); return true; } if (index.column() == 8) // set Heading @@ -278,7 +274,7 @@ bool TaskModel::setData(const QModelIndex &index, const QVariant &value, BranchItem *bi = t->getBranch(); VymModel *m = bi->getModel(); m->setHeadingPlainText(value.toString(), bi); - emit(dataChanged(index, index)); + emit dataChanged(index, index); return true; } } @@ -295,7 +291,7 @@ void TaskModel::emitDataChanged(Task *t) while (col < columnCount(QModelIndex())) { ix = createIndex(row, col, t); if (ix.isValid()) - emit(dataChanged(ix, ix)); + emit dataChanged(ix, ix); col++; } } @@ -306,8 +302,13 @@ Qt::ItemFlags TaskModel::flags(const QModelIndex &index) const if (!index.isValid()) return Qt::ItemIsEnabled; + // Editable columns should match those in the setData method + if (index.column() == 1 || index.column() == 8) + return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | + Qt::ItemIsDropEnabled | Qt::ItemIsEditable; + return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | - Qt::ItemIsDropEnabled | Qt::ItemIsEditable; + Qt::ItemIsDropEnabled; } int TaskModel::count(VymModel *model) const @@ -327,7 +328,7 @@ Task *TaskModel::createTask(BranchItem *bi) foreach (Task *t, tasks) { if (t->getBranch() == bi) { qWarning() << "TaskModel::createTask Branch exists already!"; - return NULL; + return nullptr; } } Task *task = new Task(this); @@ -340,7 +341,7 @@ Task *TaskModel::createTask(BranchItem *bi) return task; } qWarning() << "TaskEditor::addItem - item exists"; - return NULL; + return nullptr; } void TaskModel::deleteTask(Task *t) @@ -364,7 +365,7 @@ bool TaskModel::updateAwake(bool force) void TaskModel::recalcPriorities() { - emit(layoutAboutToBeChanged()); + emit layoutAboutToBeChanged(); int minPrio = 1000000; foreach (Task *t, tasks) { int p = 0; @@ -395,7 +396,7 @@ void TaskModel::recalcPriorities() } // Color (importance) - QColor c = bi->getHeadingColor(); + QColor c = bi->headingColor(); // light blueish green if (c == QColor("#00aa7f")) @@ -442,7 +443,7 @@ void TaskModel::recalcPriorities() t->setPriority(1 - minPrio + t->getPriority()); } - emit(layoutChanged()); + emit layoutChanged(); } void TaskModel::setShowParentsLevel(uint i) @@ -476,7 +477,7 @@ QMimeData *TaskModel::mimeData(const QModelIndexList &indexes) const Task *task = getTask(indexes.first()); // Field 0: Heading - QString text = task->getBranch()->getHeadingPlain(); + QString text = task->getBranch()->headingPlain(); stream << text; // Field 1: task row @@ -516,8 +517,8 @@ bool TaskModel::dropMimeData(const QMimeData *data, Qt::DropAction action, Task *dst = getTask(parent); Task *src = getTask(newItems[1].toInt()); - // qDebug() << "Dropping: " << src->getBranch()->getHeadingPlain() << " on - // " << dst->getBranch()->getHeadingPlain(); + // qDebug() << "Dropping: " << src->getBranch()->headingPlain() << " on + // " << dst->getBranch()->headingPlain(); int delta_p = dst->getPriority() - src->getPriority(); diff --git a/src/texteditor.cpp b/src/texteditor.cpp index ea06851..38978f2 100644 --- a/src/texteditor.cpp +++ b/src/texteditor.cpp @@ -10,20 +10,20 @@ #include #include #include +#include #include #include #include #include -#include - +#include "file.h" #include "mainwindow.h" #include "settings.h" #include "shortcuts.h" extern Main *mainWindow; -extern int statusbarTime; extern Settings settings; +extern QString iconTheme; extern QAction *actionViewToggleNoteEditor; @@ -37,20 +37,20 @@ extern bool debug; /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// -TextEditor::TextEditor() +TextEditor::TextEditor() // FEATURE #137 insert images with drag & drop + // https://stackoverflow.com/questions/3254652/several-ways-of-placing-an-image-in-a-qtextedit { statusBar()->hide(); // Hide sizeGrip on default, which comes with statusBar - e = new QTextEdit(this); - e->setFocus(); - e->setTabStopDistance(20); // unit is pixel, default would be 80 - e->setAutoFillBackground(true); - e->installEventFilter(this); - connect(e, SIGNAL(textChanged()), this, SLOT(editorChanged())); - setCentralWidget(e); - statusBar()->showMessage(tr("Ready", "Statusbar message"), statusbarTime); + editor = new QTextEdit(this); + editor->setFocus(); + editor->setTabStopDistance(20); // unit is pixel, default would be 80 + editor->setAutoFillBackground(true); + editor->installEventFilter(this); + connect(editor, SIGNAL(textChanged()), this, SLOT(editorChanged())); + setCentralWidget(editor); - connect(e, SIGNAL(currentCharFormatChanged(const QTextCharFormat &)), this, + connect(editor, SIGNAL(currentCharFormatChanged(const QTextCharFormat &)), this, SLOT(formatChanged(const QTextCharFormat &))); // Don't show menubar per default @@ -88,8 +88,9 @@ TextEditor::~TextEditor() settings.setValue(n + "fonts/varFont", varFont.toString()); settings.setValue(n + "fonts/fixedFont", fixedFont.toString()); - settings.setValue(n + "colors/richTextDefaultBackground", colorRichTextDefaultBackground.name()); - settings.setValue(n + "colors/richTextDefaultForeground", colorRichTextDefaultForeground.name()); + settings.setValue(n + "colors/richTextEditorBackground", colorRichTextEditorBackground.name()); + settings.setValue(n + "colors/richTextBackground", colorRichTextBackground.name()); + settings.setValue(n + "colors/richTextForeground", colorRichTextForeground.name()); } void TextEditor::init(const QString &scope) @@ -99,7 +100,7 @@ void TextEditor::init(const QString &scope) restoreState(settings.value(n + "state", 0).toByteArray()); filenameHint = ""; fixedFont.fromString( - settings.value(n + "fonts/fixedFont", "Courier,12,-1,5,48,0,0,0,1,0") + settings.value(n + "fonts/fixedFont", "Courier,12,-1,5,48,0,0,0,1,0")// FIXME-2 Replace all occurences of Courier on Mac .toString()); varFont.fromString( settings @@ -109,25 +110,30 @@ void TextEditor::init(const QString &scope) settings.value(n + "fonts/fonthintDefault", "variable").toString(); if (s == "fixed") { actionSettingsFonthintDefault->setChecked(true); - e->setCurrentFont(fixedFont); + editor->setCurrentFont(fixedFont); } else { actionSettingsFonthintDefault->setChecked(false); - e->setCurrentFont(varFont); + editor->setCurrentFont(varFont); } - // Default colors for RichText //FIXME-2 here? Though we use plainText as default? + // Default colors for RichText QPixmap pix(16, 16); - colorRichTextDefaultBackground.setNamedColor( - settings.value(n + "colors/richTextDefaultBackground", "#ffffff").toString()); - pix.fill(colorRichTextDefaultBackground); - actionFilledEditorColor->setIcon(pix); + colorRichTextEditorBackground.fromString( + settings.value(n + "colors/richTextEditorBackground", "#ffffff").toString()); + pix.fill(colorRichTextEditorBackground); + actionActiveEditorBGColor->setIcon(pix); + + colorRichTextForeground.fromString( + settings.value(n + "colors/richTextForeground", "#000000").toString()); + pix.fill(colorRichTextForeground); + actionRichTextFGColor->setIcon(pix); - colorRichTextDefaultForeground.setNamedColor( - settings.value(n + "colors/richTextDefaultForeground", "#000000").toString()); - pix.fill(colorRichTextDefaultForeground); - actionFontColor->setIcon(pix); + colorRichTextBackground.fromString( + settings.value(n + "colors/richTextBackground", "#000000").toString()); + pix.fill(colorRichTextBackground); + actionRichTextBGColor->setIcon(pix); // Default is PlainText actionFormatRichText->setChecked(false); @@ -136,7 +142,7 @@ void TextEditor::init(const QString &scope) bool TextEditor::isEmpty() { - if (e->toPlainText().length() > 0) + if (editor->toPlainText().length() > 0) return false; else return true; @@ -161,7 +167,7 @@ void TextEditor::setFont(const QFont &font) { blockChangedSignal = true; - QTextCursor tc = e->textCursor(); + QTextCursor tc = editor->textCursor(); QTextCharFormat format = tc.charFormat(); tc.select(QTextCursor::Document); @@ -177,12 +183,12 @@ void TextEditor::setFontHint(const QString &fh) { if (fh == "fixed") { actionFormatUseFixedFont->setChecked(true); - e->setCurrentFont(fixedFont); + editor->setCurrentFont(fixedFont); setFont(fixedFont); } else { actionFormatUseFixedFont->setChecked(false); - e->setCurrentFont(varFont); + editor->setCurrentFont(varFont); setFont(varFont); } } @@ -208,16 +214,14 @@ void TextEditor::setFilename(const QString &fn) if (state == filledEditor) { if (fn.isEmpty()) { filename = ""; - statusBar()->showMessage( - tr("No filename available for this note.", "Statusbar message"), - statusbarTime); + mainWindow->statusMessage( + tr("No filename available for this note.", "Statusbar message")); } else { filename = fn; - statusBar()->showMessage( + mainWindow->statusMessage( tr(QString("Current filename is %1").arg(filename).toUtf8(), - "Statusbar message"), - statusbarTime); + "Statusbar message")); } } } @@ -230,23 +234,37 @@ QString TextEditor::getFilenameHint() { return filenameHint; } QString TextEditor::getText() { - if (e->toPlainText().isEmpty()) + if (editor->toPlainText().isEmpty()) return QString(); if (actionFormatRichText->isChecked()) - return e->toHtml(); + return editor->toHtml(); else - return e->toPlainText(); + return editor->toPlainText(); } VymText TextEditor::getVymText() { VymText vt; - if (actionFormatRichText->isChecked()) - vt.setRichText(e->toHtml()); - else - vt.setPlainText(e->toPlainText()); + if (actionFormatRichText->isChecked()) { + // Remove some QTextEdit specific tags and markers from RichText + QString t = editor->toHtml(); + + // Remove "); + re.setPatternOptions( + QRegularExpression::InvertedGreedinessOption | + QRegularExpression::DotMatchesEverythingOption | + QRegularExpression::MultilineOption); + t.replace(re, ""); + + // Remove heading with characters that might cause problems in undo scripts + re.setPattern(".*head>"); + t.replace(re, ""); + vt.setRichText(t); + } else + vt.setPlainText(editor->toPlainText()); if (actionFormatUseFixedFont->isChecked()) vt.setFontHint(getFontHint()); @@ -257,7 +275,7 @@ VymText TextEditor::getVymText() bool TextEditor::findText(const QString &t, const QTextDocument::FindFlags &flags) { - if (e->find(t, flags)) + if (editor->find(t, flags)) return true; else return false; @@ -267,14 +285,14 @@ bool TextEditor::findText(const QString &t, const QTextDocument::FindFlags &flags, int i) { // Position at beginning - QTextCursor c = e->textCursor(); + QTextCursor c = editor->textCursor(); c.setPosition(0, QTextCursor::MoveAnchor); - e->setTextCursor(c); + editor->setTextCursor(c); // Search for t int j = 0; while (j <= i) { - if (!e->find(t, flags)) + if (!editor->find(t, flags)) return false; j++; } @@ -283,12 +301,12 @@ bool TextEditor::findText(const QString &t, void TextEditor::setTextCursor(const QTextCursor &cursor) { - e->setTextCursor(cursor); + editor->setTextCursor(cursor); } -QTextCursor TextEditor::getTextCursor() { return e->textCursor(); } +QTextCursor TextEditor::getTextCursor() { return editor->textCursor(); } -void TextEditor::setFocus() { e->setFocus(); } +void TextEditor::setFocus() { editor->setFocus(); } void TextEditor::setupFileActions() { @@ -298,8 +316,8 @@ void TextEditor::setupFileActions() QString tag = tr("Texteditor", "Shortcuts"); QAction *a; - a = new QAction(QPixmap(":/fileopen.png"), tr("&Import..."), this); - a->setShortcut(Qt::CTRL + Qt::Key_O); + a = new QAction(QPixmap(QString(":/document-open-%1").arg(iconTheme)), tr("&Import..."), this); + a->setShortcut(Qt::CTRL | Qt::Key_O); a->setShortcutContext(Qt::WidgetWithChildrenShortcut); switchboard.addSwitch("textLoad", shortcutScope, a, tag); connect(a, SIGNAL(triggered()), this, SLOT(textLoad())); @@ -308,41 +326,40 @@ void TextEditor::setupFileActions() actionFileLoad = a; fileMenu->addSeparator(); - a = new QAction(QPixmap(":/filesave.png"), tr("&Export..."), this); - a->setShortcut(Qt::CTRL + Qt::Key_S); + a = new QAction(QPixmap(QString(":/document-export-%1").arg(iconTheme)), tr("&Export..."), this); + a->setShortcut(Qt::CTRL | Qt::Key_S); a->setShortcutContext(Qt::WidgetWithChildrenShortcut); switchboard.addSwitch("textSave", shortcutScope, a, tag); - connect(a, SIGNAL(triggered()), this, SLOT(textSave())); + connect(a, SIGNAL(triggered()), this, SLOT(textExport())); tb->addAction(a); fileMenu->addAction(a); addAction(a); - actionFileSave = a; - - a = new QAction(tr("Export &As... (HTML)"), this); - connect(a, SIGNAL(triggered()), this, SLOT(textSaveAs())); - fileMenu->addAction(a); - actionFileSaveAs = a; + filledEditorActions << a; + actionFileExport = a; a = new QAction(tr("Export &As...(ASCII)"), this); switchboard.addSwitch("textExportAsASCII", shortcutScope, a, tag); - connect(a, SIGNAL(triggered()), this, SLOT(textExportAsASCII())); + connect(a, SIGNAL(triggered()), this, SLOT(textExportText())); fileMenu->addAction(a); addAction(a); - actionFileSaveAs = a; + filledEditorActions << a; + actionFileExportText = a; fileMenu->addSeparator(); - a = new QAction(QPixmap(":/fileprint.png"), tr("&Print..."), this); - a->setShortcut(Qt::CTRL + Qt::Key_P); + a = new QAction(QPixmap(QString(":/document-print-%1.svg").arg(iconTheme)), tr("&Print..."), this); + a->setShortcut(Qt::CTRL | Qt::Key_P); switchboard.addSwitch("textPrint", shortcutScope, a, tag); connect(a, SIGNAL(triggered()), this, SLOT(textPrint())); tb->addAction(a); fileMenu->addAction(a); + filledEditorActions << a; actionFilePrint = a; - a = new QAction(QPixmap(":/edittrash.png"), tr("&Delete All"), this); + a = new QAction(QPixmap(QString(":/edit-delete-%1.svg").arg(iconTheme)), tr("&Delete All"), this); connect(a, SIGNAL(triggered()), this, SLOT(deleteAll())); fileMenu->addAction(a); tb->addAction(a); + filledEditorActions << a; actionFileDeleteAll = a; } @@ -356,58 +373,73 @@ void TextEditor::setupEditActions() QAction *a; a = new QAction(QPixmap(":/undo.png"), tr("&Undo"), this); - a->setShortcut(Qt::CTRL + Qt::Key_Z); + a->setShortcut(Qt::CTRL | Qt::Key_Z); a->setShortcutContext(Qt::WidgetWithChildrenShortcut); switchboard.addSwitch("textUndo", shortcutScope, a, tag); - connect(a, SIGNAL(triggered()), e, SLOT(undo())); + connect(a, SIGNAL(triggered()), editor, SLOT(undo())); editMenu->addAction(a); editToolBar->addAction(a); + filledEditorActions << a; // QTextEdit does not seem to have a method to check if undo/redo is available currently actionEditUndo = a; a = new QAction(QPixmap(":/redo.png"), tr("&Redo"), this); - a->setShortcut(Qt::CTRL + Qt::Key_Y); + a->setShortcut(Qt::CTRL | Qt::Key_Y); a->setShortcutContext(Qt::WidgetWithChildrenShortcut); switchboard.addSwitch("textRedo", shortcutScope, a, tag); - connect(a, SIGNAL(triggered()), e, SLOT(redo())); + connect(a, SIGNAL(triggered()), editor, SLOT(redo())); editMenu->addAction(a); editToolBar->addAction(a); + filledEditorActions << a; actionEditRedo = a; editMenu->addSeparator(); a = new QAction(QPixmap(), tr("Select and copy &all"), this); a->setShortcutContext(Qt::WidgetShortcut); - a->setShortcut(Qt::CTRL + Qt::Key_A); + a->setShortcut(Qt::CTRL | Qt::Key_A); switchboard.addSwitch("textCopyAll", shortcutScope, a, tag); connect(a, SIGNAL(triggered()), this, SLOT(editCopyAll())); editMenu->addAction(a); + filledEditorActions << a; + actionSelectAll = a; editMenu->addSeparator(); - a = new QAction(QPixmap(":/editcopy.png"), tr("&Copy"), this); - a->setShortcut(Qt::CTRL + Qt::Key_C); + a = new QAction(QPixmap(QString(":/edit-copy-%1.svg").arg(iconTheme)), tr("&Copy", "Edit menu"), this); + a->setShortcut(Qt::CTRL | Qt::Key_C); a->setShortcutContext(Qt::WidgetWithChildrenShortcut); switchboard.addSwitch("textCopy", shortcutScope, a, tag); - connect(a, SIGNAL(triggered()), e, SLOT(copy())); + connect(a, SIGNAL(triggered()), editor, SLOT(copy())); editMenu->addAction(a); editToolBar->addAction(a); + filledEditorActions << a; actionEditCopy = a; - a = new QAction(QPixmap(":/editcut.png"), tr("Cu&t"), this); - a->setShortcut(Qt::CTRL + Qt::Key_X); + a = new QAction(QPixmap(QString(":/edit-cut-%1.svg").arg(iconTheme)), tr("Cu&t", "Edit menu"), this); + a->setShortcut(Qt::CTRL | Qt::Key_X); a->setShortcutContext(Qt::WidgetWithChildrenShortcut); switchboard.addSwitch("textCut", shortcutScope, a, tag); - connect(a, SIGNAL(triggered()), e, SLOT(cut())); + connect(a, SIGNAL(triggered()), editor, SLOT(cut())); editMenu->addAction(a); editToolBar->addAction(a); + filledEditorActions << a; actionEditCut = a; - a = new QAction(QPixmap(":/editpaste.png"), tr("&Paste"), this); - a->setShortcut(Qt::CTRL + Qt::Key_V); + a = new QAction(QPixmap(QString(":/edit-paste-%1.svg").arg(iconTheme)), tr("&Paste", "Edit menu"), this); + a->setShortcut(Qt::CTRL | Qt::Key_V); a->setShortcutContext(Qt::WidgetWithChildrenShortcut); switchboard.addSwitch("textPaste", shortcutScope, a, tag); - connect(a, SIGNAL(triggered()), e, SLOT(paste())); + connect(a, SIGNAL(triggered()), editor, SLOT(paste())); editMenu->addAction(a); editToolBar->addAction(a); + filledEditorActions << a; actionEditPaste = a; + + a = new QAction(QPixmap(QString(":/insert-image-%1.svg").arg(iconTheme)), tr("Insert image", "TextEditor") + "...", this); + editMenu->addAction(a); + connect(a, SIGNAL(triggered()), this, SLOT(insertImage())); + editMenu->addAction(a); + editToolBar->addAction(a); + filledEditorActions << a; + actionInsertImage = a; } void TextEditor::setupFormatActions() @@ -421,7 +453,7 @@ void TextEditor::setupFormatActions() QAction *a; a = new QAction(QPixmap(":/formatfixedfont.png"), tr("&Font hint"), this); - a->setShortcut(Qt::CTRL + Qt::Key_H); + a->setShortcut(Qt::CTRL | Qt::Key_H); a->setCheckable(true); a->setChecked( settings.value("/noteeditor/fonts/useFixedByDefault", false).toBool()); @@ -429,17 +461,19 @@ void TextEditor::setupFormatActions() connect(a, SIGNAL(triggered()), this, SLOT(toggleFonthint())); formatMenu->addAction(a); fontHintsToolBar->addAction(a); + filledEditorActions << a; actionFormatUseFixedFont = a; // Original icon: ./share/icons/oxygen/22x22/actions/format-text-color.png - a = new QAction(QPixmap(":/formatrichtext.png"), tr("&Richtext"), this); - a->setShortcut(Qt::CTRL + Qt::Key_R); - // a->setShortcutContext (Qt::WidgetShortcut); + a = new QAction(QPixmap(":/formatrichtext.svg"), tr("&Richtext"), this); + // a->setShortcut(Qt::CTRL | Qt::Key_R); + // a->setShortcutContext (Qt::WidgetShortcut); a->setCheckable(true); switchboard.addSwitch("textToggleRichText", shortcutScope, a, tag); connect(a, SIGNAL(triggered()), this, SLOT(toggleRichText())); formatMenu->addAction(a); fontHintsToolBar->addAction(a); + filledEditorActions << a; actionFormatRichText = a; fontToolBar = addToolBar(tr("Fonts", "toolbar in texteditor")); @@ -449,7 +483,7 @@ void TextEditor::setupFormatActions() fontToolBar->addWidget(comboFont); QFontDatabase fontDB; comboFont->insertItems(0, fontDB.families()); - connect(comboFont, SIGNAL(activated(const QString &)), this, + connect(comboFont, SIGNAL(currentTextChanged(const QString &)), this, SLOT(textFamily(const QString &))); comboSize = new QComboBox; @@ -462,7 +496,7 @@ void TextEditor::setupFormatActions() ++it; // increment i before using it comboSize->insertItem(i, QString::number(*it)); } - connect(comboSize, SIGNAL(activated(const QString &)), this, + connect(comboSize, SIGNAL(currentTextChanged(const QString &)), this, SLOT(textSize(const QString &))); formatMenu->addSeparator(); @@ -471,40 +505,52 @@ void TextEditor::setupFormatActions() formatToolBar->setObjectName("noteEditorFormatToolBar"); QPixmap pix(16, 16); - pix.fill(e->textColor()); - a = new QAction(pix, tr("&Color..."), this); + pix.fill(editor->textColor()); + a = new QAction(pix, tr("&Text Color..."), this); formatMenu->addAction(a); formatToolBar->addAction(a); - connect(a, SIGNAL(triggered()), this, SLOT(textColor())); - actionTextColor = a; + connect(a, SIGNAL(triggered()), this, SLOT(selectTextFGColor())); + filledEditorRichTextActions << a; + actionTextFGColor = a; - a = new QAction(QPixmap(":/text_bold.png"), tr("&Bold"), this); - a->setShortcut(Qt::CTRL + Qt::Key_B); + pix.fill(editor->textBackgroundColor()); + a = new QAction(pix, tr("&Text highlight color..."), this); + formatMenu->addAction(a); + formatToolBar->addAction(a); + connect(a, SIGNAL(triggered()), this, SLOT(selectTextBGColor())); + filledEditorRichTextActions << a; + actionTextBGColor = a; + + a = new QAction(QPixmap(QString(":/format-text-bold-%1.svg").arg(iconTheme)), tr("&Bold"), this); + a->setShortcut(Qt::CTRL | Qt::Key_B); // a->setShortcutContext(Qt::WidgetWithChildrenShortcut); switchboard.addSwitch("textToggleBold", shortcutScope, a, tag); connect(a, SIGNAL(triggered()), this, SLOT(textBold())); formatToolBar->addAction(a); formatMenu->addAction(a); a->setCheckable(true); + filledEditorRichTextActions << a; actionTextBold = a; - a = new QAction(QPixmap(":/text_italic.png"), tr("&Italic"), this); - a->setShortcut(Qt::CTRL + Qt::Key_I); + a = new QAction(QPixmap(QString(":/format-text-italic-%1.svg").arg(iconTheme)), tr("&Italic"), this); + a->setShortcut(Qt::CTRL | Qt::Key_I); // a->setShortcutContext(Qt::WidgetWithChildrenShortcut); switchboard.addSwitch("textToggleItalic", shortcutScope, a, tag); connect(a, SIGNAL(triggered()), this, SLOT(textItalic())); formatToolBar->addAction(a); formatMenu->addAction(a); a->setCheckable(true); + filledEditorRichTextActions << a; actionTextItalic = a; - a = new QAction(QPixmap(":/text_under.png"), tr("&Underline"), this); - a->setShortcut(Qt::CTRL + Qt::Key_U); + a = new QAction(QPixmap(QString(":/text-format-underline-%1.svg").arg(iconTheme)), tr("&Underline"), this); + a->setShortcut(Qt::CTRL | Qt::Key_U); // a->setShortcutContext(Qt::WidgetWithChildrenShortcut); switchboard.addSwitch("textToggleUnderline", shortcutScope, a, tag); connect(a, SIGNAL(triggered()), this, SLOT(textUnderline())); formatToolBar->addAction(a); formatMenu->addAction(a); + filledEditorRichTextActions << a; a->setCheckable(true); // richTextWidgets.append((QWidget*)a); actionTextUnderline = a; @@ -512,24 +558,26 @@ void TextEditor::setupFormatActions() QActionGroup *actGrp2 = new QActionGroup(this); actGrp2->setExclusive(true); - a = new QAction(QPixmap(":/text_sub.png"), tr("Subs&cript"), actGrp2); - a->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_B); + a = new QAction(QPixmap(QString(":/text-format-subscript-%1.svg").arg(iconTheme)), tr("Subs&cript"), actGrp2); + a->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_B); // a->setShortcutContext(Qt::WidgetWithChildrenShortcut); a->setCheckable(true); formatToolBar->addAction(a); formatMenu->addAction(a); switchboard.addSwitch("textToggleSub", shortcutScope, a, tag); connect(a, SIGNAL(triggered()), this, SLOT(textVAlign())); + filledEditorRichTextActions << a; actionAlignSubScript = a; - a = new QAction(QPixmap(":/text_super.png"), tr("Su&perscript"), actGrp2); - a->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_P); + a = new QAction(QPixmap(QString(":/text-format-superscript-%1.svg").arg(iconTheme)), tr("Su&perscript"), actGrp2); + a->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_P); // a->setShortcutContext(Qt::WidgetWithChildrenShortcut); a->setCheckable(true); formatToolBar->addAction(a); formatMenu->addAction(a); switchboard.addSwitch("textToggleSuper", shortcutScope, a, tag); connect(a, SIGNAL(triggered()), this, SLOT(textVAlign())); + filledEditorRichTextActions << a; actionAlignSuperScript = a; QActionGroup *grp = new QActionGroup(this); connect(grp, SIGNAL(triggered(QAction *)), this, @@ -537,29 +585,33 @@ void TextEditor::setupFormatActions() formatMenu->addSeparator(); - a = new QAction(QPixmap(":/text_left.png"), tr("&Left"), grp); + a = new QAction(QPixmap(QString(":/format-justify-left-%1.svg").arg(iconTheme)), tr("&Left"), grp); // a->setShortcut( Qt::CTRL+Qt::Key_L ); a->setCheckable(true); formatToolBar->addAction(a); formatMenu->addAction(a); + filledEditorRichTextActions << a; actionAlignLeft = a; - a = new QAction(QPixmap(":/text_center.png"), tr("C&enter"), grp); - // a->setShortcut( Qt::CTRL + Qt::Key_E); + a = new QAction(QPixmap(QString(":/format-justify-center-%1.svg").arg(iconTheme)), tr("C&enter"), grp); + // a->setShortcut( Qt::CTRL | Qt::Key_E); a->setCheckable(true); formatToolBar->addAction(a); formatMenu->addAction(a); + filledEditorRichTextActions << a; actionAlignCenter = a; - a = new QAction(QPixmap(":/text_right.png"), tr("&Right"), grp); - // a->setShortcut(Qt::CTRL + Qt::Key_R ); + a = new QAction(QPixmap(QString(":/format-justify-right-%1.svg").arg(iconTheme)), tr("&Right"), grp); + // a->setShortcut(Qt::CTRL | Qt::Key_R ); a->setCheckable(true); formatToolBar->addAction(a); formatMenu->addAction(a); + filledEditorRichTextActions << a; actionAlignRight = a; - a = new QAction(QPixmap(":/text_block.png"), tr("&Justify"), grp); - // a->setShortcut(Qt::CTRL + Qt::Key_J ); + a = new QAction(QPixmap(QString(":/format-justify-fill-%1.svg").arg(iconTheme)), tr("&Justify"), grp); + // a->setShortcut(Qt::CTRL | Qt::Key_J ); a->setCheckable(true); formatToolBar->addAction(a); formatMenu->addAction(a); + filledEditorRichTextActions << a; actionAlignJustify = a; } @@ -587,32 +639,34 @@ void TextEditor::setupSettingsActions() settingsMenu->addSeparator(); a = new QAction( - tr("Set RichText default background color", "TextEditor") + "...", this); + tr("Set RichText mode editor background color", "TextEditor") + "...", this); settingsMenu->addAction(a); - connect(a, SIGNAL(triggered()), this, SLOT(selectColorRichTextDefaultBackground())); - actionFilledEditorColor = a; + connect(a, SIGNAL(triggered()), this, SLOT(selectRichTextEditorBackgroundColor())); + actionActiveEditorBGColor = a; - a = new QAction(tr("Set RichText default font color", "TextEditor") + "...", this); + a = new QAction(tr("Set RichText mode default text color", "TextEditor") + "...", this); settingsMenu->addAction(a); - connect(a, SIGNAL(triggered()), this, SLOT(selectColorRichTextDefaultForeground())); - actionFontColor = a; + connect(a, SIGNAL(triggered()), this, SLOT(selectRichTextForegroundColor())); + actionRichTextFGColor = a; + + a = new QAction(tr("Set RichText mode default text background color", "TextEditor") + "...", this); + settingsMenu->addAction(a); + connect(a, SIGNAL(triggered()), this, SLOT(selectRichTextBackgroundColor())); + actionRichTextBGColor = a; } void TextEditor::textLoad() { if (state != inactiveEditor) { if (!isEmpty()) { - QMessageBox mb(vymName + " - " + tr("Note Editor"), - "Loading will overwrite the existing note", - QMessageBox::Warning, - QMessageBox::Yes | QMessageBox::Default, - QMessageBox::Cancel, 0); - mb.setButtonText(QMessageBox::Yes, "Load note"); - switch (mb.exec()) { - case QMessageBox::Cancel: - return; - break; - } + QMessageBox mb( + QMessageBox::Warning, + vymName + " - " + tr("Note Editor"), + "Loading will overwrite the existing note"); + QPushButton *overwriteButton = mb.addButton(tr("Overwrite"), QMessageBox::AcceptRole); + mb.addButton(tr("Cancel"), QMessageBox::RejectRole); + mb.exec(); + if (mb.clickedButton() != overwriteButton) return; } // Load note QFileDialog *fd = new QFileDialog(this); @@ -644,13 +698,13 @@ void TextEditor::closeEvent(QCloseEvent *ce) { ce->accept(); // TextEditor can be reopened with show() hide(); - emit(windowClosed()); + emit windowClosed(); return; } bool TextEditor::eventFilter(QObject *obj, QEvent *ev) { - if (obj == e) { + if (obj == editor) { if (ev->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast(ev); if (keyEvent == QKeySequence::Paste) { @@ -678,7 +732,7 @@ void TextEditor::editorChanged() if (!blockChangedSignal) { blockTextUpdate = true; - emit(textHasChanged(getVymText())); + emit textHasChanged(getVymText()); blockTextUpdate = false; } @@ -691,9 +745,10 @@ void TextEditor::editorChanged() void TextEditor::setRichText(const QString &t) { blockChangedSignal = true; - e->setReadOnly(false); - e->setHtml(t); + editor->setReadOnly(false); + editor->setHtml(t); actionFormatRichText->setChecked(true); + actionInsertImage->setEnabled(true); // Update state including colors updateState(); @@ -705,16 +760,17 @@ void TextEditor::setRichText(const QString &t) void TextEditor::setPlainText(const QString &t) { blockChangedSignal = true; - e->setReadOnly(false); + editor->setReadOnly(false); - e->setPlainText(t); + editor->setPlainText(t); actionFormatRichText->setChecked(false); + actionInsertImage->setEnabled(false); // Reset also text format QTextCharFormat textformat; textformat.setForeground(qApp->palette().color(QPalette::WindowText)); textformat.setFont(varFont); - e->setCurrentCharFormat(textformat); + editor->setCurrentCharFormat(textformat); // Update state including colors updateState(); @@ -753,8 +809,8 @@ void TextEditor::setInactive() void TextEditor::editCopyAll() { - e->selectAll(); - e->copy(); + editor->selectAll(); + editor->copy(); } void TextEditor::clear() @@ -763,7 +819,7 @@ void TextEditor::clear() bool blockChangedOrg = blockChangedSignal; blockChangedSignal = true; - e->clear(); + editor->clear(); setState(emptyEditor); blockChangedSignal = blockChangedOrg; @@ -771,11 +827,13 @@ void TextEditor::clear() void TextEditor::deleteAll() { - e->clear(); + editor->clear(); } -void TextEditor::textSaveAs() +void TextEditor::textExportAs() { + QTextCharFormat f = editor->currentCharFormat(); + QString caption = tr("Export Note to single file"); QString fn = QFileDialog::getSaveFileName( this, caption, QString(), "VYM Note (HTML) (*.html);;All files (*)", @@ -785,63 +843,59 @@ void TextEditor::textSaveAs() QFile file(fn); if (file.exists()) { QMessageBox mb( + QMessageBox::Warning, vymName, tr("The file %1\nexists already.\nDo you want to overwrite it?", - "dialog 'save note as'") - .arg(fn), - QMessageBox::Warning, QMessageBox::Yes | QMessageBox::Default, - QMessageBox::Cancel | QMessageBox::Escape, Qt::NoButton); - mb.setButtonText(QMessageBox::Yes, tr("Overwrite")); - mb.setButtonText(QMessageBox::No, tr("Cancel")); - switch (mb.exec()) { - case QMessageBox::Yes: - // save - filename = fn; - textSave(); - return; - case QMessageBox::Cancel: - // do nothing - break; - } + "dialog 'save note as'").arg(fn)); + QPushButton *overwriteButton = mb.addButton(tr("Overwrite"), QMessageBox::AcceptRole); + mb.addButton(tr("Cancel"), QMessageBox::RejectRole); + mb.exec(); + if (mb.clickedButton() != overwriteButton) return; + + // save + filename = fn; + textExport(); + return; } else { filename = fn; - textSave(); + textExport(); return; } } - statusBar()->showMessage( - tr("Couldn't export note ", "dialog 'save note as'") + fn, - statusbarTime); + mainWindow->statusMessage( + tr("Couldn't export note ", "dialog 'save note as'") + fn); } -void TextEditor::textSave() +void TextEditor::textExport() { if (filename.isEmpty()) { - textSaveAs(); + textExportAs(); return; } - QString text = e->toHtml(); // FIXME-4 or plaintext? check... + QString text; + if (actionFormatRichText->isChecked()) + text = editor->toHtml(); + else + text = editor->toPlainText(); + QFile f(filename); if (!f.open(QIODevice::WriteOnly)) { - statusBar()->showMessage(QString("Could not write to %1").arg(filename), - statusbarTime); + mainWindow->statusMessage(QString("Could not write to %1").arg(filename)); return; } QTextStream t(&f); - t.setCodec("UTF-8"); t << text; f.close(); - e->document()->setModified(false); + editor->document()->setModified(false); - statusBar()->showMessage(QString("Note exported as %1").arg(filename), - statusbarTime); + mainWindow->statusMessage(QString("Note exported as %1").arg(filename)); } -void TextEditor::textExportAsASCII() +void TextEditor::textExportText() { QString fn, s; if (!filenameHint.isEmpty()) { @@ -855,43 +909,28 @@ void TextEditor::textExportAsASCII() QString caption = tr("Export Note to single file (ASCII)"); fn = QFileDialog::getSaveFileName( this, caption, s, "VYM Note (ASCII) (*.txt);;All files (*)"); - int ret = -1; if (!fn.isEmpty()) { QFile file(fn); - if (file.exists()) { - QMessageBox mb( - vymName, - tr("The file %1\nexists already.\nDo you want to overwrite it?", - "dialog 'save note as'") - .arg(fn), - QMessageBox::Warning, QMessageBox::Yes | QMessageBox::Default, - QMessageBox::Cancel | QMessageBox::Escape, Qt::NoButton); - mb.setButtonText(QMessageBox::Yes, tr("Overwrite")); - mb.setButtonText(QMessageBox::No, tr("Cancel")); - ret = mb.exec(); - } - if (ret == QMessageBox::Cancel) - return; - // save + // Already tested in QFileDialog, if we may overwrite in case file exists already + if (!file.open(QIODevice::WriteOnly)) - statusBar()->showMessage( - QString("Could not write to %1").arg(filename), statusbarTime); + mainWindow->statusMessage( + QString("Could not write to %1").arg(filename)); else { QTextStream t(&file); t << getVymText().getTextASCII(); file.close(); - statusBar()->showMessage(QString("Note exported as %1").arg(fn), - statusbarTime); + mainWindow->statusMessage(QString("Note exported as %1").arg(fn)); } } } void TextEditor::textPrint() { - QTextDocument *document = e->document(); + QTextDocument *document = editor->document(); if (!printer) mainWindow->setupPrinter(); @@ -909,14 +948,14 @@ void TextEditor::textEditUndo() {} void TextEditor::toggleFonthint() { if (!actionFormatUseFixedFont->isChecked()) { - e->setCurrentFont(varFont); + editor->setCurrentFont(varFont); setFont(varFont); } else { - e->setCurrentFont(fixedFont); + editor->setCurrentFont(fixedFont); setFont(fixedFont); } - emit(textHasChanged(getVymText())); + emit textHasChanged(getVymText()); } void TextEditor::setRichTextMode(bool b) @@ -924,18 +963,19 @@ void TextEditor::setRichTextMode(bool b) //qDebug() << "TE::setRichTextMode b=" << b; actionFormatUseFixedFont->setEnabled(false); if (b) { - setRichText(e->toHtml()); + setRichText(editor->toHtml()); // Use default foreground color for all text when switching to RichText - QTextCursor cursor = e->textCursor(); - e->selectAll(); - e->setTextColor(colorRichTextDefaultForeground); - e->setTextCursor(cursor); + QTextCursor cursor = editor->textCursor(); + editor->selectAll(); + editor->setTextColor(colorRichTextForeground); + editor->setTextBackgroundColor(colorRichTextBackground); + editor->setTextCursor(cursor); } else { - setPlainText(e->toPlainText()); + setPlainText(editor->toPlainText()); } - emit(textHasChanged(getVymText())); + emit textHasChanged(getVymText()); } void TextEditor::toggleRichText() @@ -965,31 +1005,44 @@ void TextEditor::setVarFont() void TextEditor::textBold() { if (actionTextBold->isChecked()) - e->setFontWeight(QFont::Bold); + editor->setFontWeight(QFont::Bold); else - e->setFontWeight(QFont::Normal); + editor->setFontWeight(QFont::Normal); } void TextEditor::textUnderline() { - e->setFontUnderline(actionTextUnderline->isChecked()); + editor->setFontUnderline(actionTextUnderline->isChecked()); } void TextEditor::textItalic() { - e->setFontItalic(actionTextItalic->isChecked()); + editor->setFontItalic(actionTextItalic->isChecked()); } -void TextEditor::textFamily(const QString &f) { e->setFontFamily(f); } +void TextEditor::textFamily(const QString &f) { editor->setFontFamily(f); } -void TextEditor::textSize(const QString &p) { e->setFontPointSize(p.toInt()); } +void TextEditor::textSize(const QString &p) { editor->setFontPointSize(p.toInt()); } + +void TextEditor::selectTextFGColor() +{ + QColor col = QColorDialog::getColor(editor->textColor(), this); + if (!col.isValid()) + return; + editor->setTextColor(col); + /* + QPixmap pix( 16, 16 ); + pix.fill( col ); + actionTextColor->setIcon( pix ); + */ +} -void TextEditor::textColor() +void TextEditor::selectTextBGColor() { - QColor col = QColorDialog::getColor(e->textColor(), this); + QColor col = QColorDialog::getColor(editor->textBackgroundColor(), this); if (!col.isValid()) return; - e->setTextColor(col); + editor->setTextBackgroundColor(col); /* QPixmap pix( 16, 16 ); pix.fill( col ); @@ -999,16 +1052,16 @@ void TextEditor::textColor() void TextEditor::textAlign(QAction *a) { - QTextCursor c = e->textCursor(); + QTextCursor c = editor->textCursor(); if (a == actionAlignLeft) - e->setAlignment(Qt::AlignLeft); + editor->setAlignment(Qt::AlignLeft); else if (a == actionAlignCenter) - e->setAlignment(Qt::AlignHCenter); + editor->setAlignment(Qt::AlignHCenter); else if (a == actionAlignRight) - e->setAlignment(Qt::AlignRight); + editor->setAlignment(Qt::AlignRight); else if (a == actionAlignJustify) - e->setAlignment(Qt::AlignJustify); + editor->setAlignment(Qt::AlignJustify); } void TextEditor::textVAlign() @@ -1026,7 +1079,7 @@ void TextEditor::textVAlign() else { format.setVerticalAlignment(QTextCharFormat::AlignNormal); } - e->mergeCurrentCharFormat(format); + editor->mergeCurrentCharFormat(format); } void TextEditor::fontChanged(const QFont &f) @@ -1042,20 +1095,39 @@ void TextEditor::fontChanged(const QFont &f) actionTextUnderline->setChecked(f.underline()); } -void TextEditor::colorChanged(const QColor &c) +void TextEditor::colorFGChanged(const QColor &c) { - QPixmap pix(16, 16); - pix.fill(c); - actionTextColor->setIcon(pix); + QImage image(":color-text.svg"); + QPainter painter; + painter.begin(&image); + painter.setBrush(c); + painter.drawRect(0,110,128,128); + painter.end(); + + actionTextFGColor->setIcon(QPixmap::fromImage(image)); +} + +void TextEditor::colorBGChanged(const QColor &c) +{ + QImage image(":draw-brush.svg"); + QPainter painter; + painter.begin(&image); + painter.setBrush(c); + painter.drawRect(0,110,128,128); + painter.end(); + + actionTextBGColor->setIcon(QPixmap::fromImage(image)); } void TextEditor::formatChanged(const QTextCharFormat &f) { + //qDebug() << "TE::formatChanged fg=" << f.foreground().color() << " bg=" << f.background().color() << " valid=" << f.isValid(); if (!actionFormatRichText->isChecked()) return; fontChanged(f.font()); - colorChanged(f.foreground().color()); - alignmentChanged(e->alignment()); + colorFGChanged(f.foreground().color()); + colorBGChanged(f.background().color()); + alignmentChanged(editor->alignment()); verticalAlignmentChanged(f.verticalAlignment()); } @@ -1088,90 +1160,63 @@ void TextEditor::verticalAlignmentChanged(QTextCharFormat::VerticalAlignment a) void TextEditor::updateActions() { - bool b; - b = (state == inactiveEditor) ? false : true; - - actionFileLoad->setEnabled(b); - actionFileSave->setEnabled(b); - actionFileSaveAs->setEnabled(b); - actionFilePrint->setEnabled(b); - actionFileDeleteAll->setEnabled(b); - actionEditUndo->setEnabled(b); - actionEditRedo->setEnabled(b); - actionEditCopy->setEnabled(b); - actionEditCut->setEnabled(b); - actionEditPaste->setEnabled(b); - actionFormatUseFixedFont->setEnabled(b); - actionFormatRichText->setEnabled(b); - - if (!actionFormatRichText->isChecked() || !b) { - comboFont->setEnabled(false); - comboSize->setEnabled(false); - fontToolBar->hide(); - formatToolBar->hide(); - actionTextColor->setEnabled(false); - actionTextBold->setEnabled(false); - actionTextUnderline->setEnabled(false); - actionTextItalic->setEnabled(false); - actionTextColor->setEnabled(false); - actionAlignSubScript->setEnabled(false); - actionAlignSuperScript->setEnabled(false); - actionAlignLeft->setEnabled(false); - actionAlignCenter->setEnabled(false); - actionAlignRight->setEnabled(false); - actionAlignJustify->setEnabled(false); - } - else { - comboFont->setEnabled(true); - comboSize->setEnabled(true); - fontToolBar->show(); - formatToolBar->show(); - actionTextColor->setEnabled(true); - actionTextBold->setEnabled(true); - actionTextUnderline->setEnabled(true); - actionTextItalic->setEnabled(true); - actionTextColor->setEnabled(true); - actionAlignSubScript->setEnabled(true); - actionAlignSuperScript->setEnabled(true); - actionAlignLeft->setEnabled(true); - actionAlignCenter->setEnabled(true); - actionAlignRight->setEnabled(true); - actionAlignJustify->setEnabled(true); - actionFormatUseFixedFont->setEnabled(false); + if (state == inactiveEditor) { + actionFileLoad->setEnabled(false); + foreach (QAction* a, filledEditorActions) + a->setEnabled(false); + foreach (QAction* a, filledEditorActions) + a->setEnabled(false); + foreach (QAction* a, filledEditorRichTextActions) + a->setEnabled(false); + return; } + + actionFileLoad->setEnabled(true); + + // editorState is filledEditor or emptyEditor + foreach (QAction* a, emptyEditorActions) + a->setEnabled(true); + + bool b = (state == filledEditor) ? true : false; + foreach (QAction* a, filledEditorActions) + a->setEnabled(b); + + b = (state == filledEditor && actionFormatRichText->isChecked()) ? true : false; + foreach (QAction* a, filledEditorRichTextActions) + a->setEnabled(b); } -void TextEditor::setState(EditorState s) // FIXME-2 called 12x when reselecting once in ME - // 5 alone for HeadingEditor +void TextEditor::setState(EditorState s) { - //qDebug() << "TE::setState" << s << editorName; + // qDebug() << "TE::setState" << s << editorName; QPalette p = qApp->palette(); QColor baseColor; state = s; switch (state) { case emptyEditor: - if (actionFormatRichText->isChecked()) - e->setTextColor(colorRichTextDefaultForeground); - else - e->setTextColor(p.color(QPalette::Text)); + if (actionFormatRichText->isChecked()) { + editor->setTextColor(colorRichTextForeground); + editor->setTextBackgroundColor(colorRichTextBackground); + } else + editor->setTextColor(p.color(QPalette::Text)); case filledEditor: if (actionFormatRichText->isChecked()) { if (useColorMapBackground) baseColor = colorMapBackground; else - baseColor = colorRichTextDefaultBackground; + baseColor = colorRichTextEditorBackground; } else { baseColor = p.color(QPalette::Base); } - e->setReadOnly(false); + editor->setReadOnly(false); break; case inactiveEditor: baseColor = Qt::black; - e->setReadOnly(true); + editor->setReadOnly(true); } p.setColor(QPalette::Base, baseColor); - e->setPalette(p); + editor->setPalette(p); updateActions(); } @@ -1185,41 +1230,80 @@ void TextEditor::updateState() setState(filledEditor); } -void TextEditor::selectColorRichTextDefaultBackground() +void TextEditor::selectRichTextEditorBackgroundColor() { - QColor col = QColorDialog::getColor(colorRichTextDefaultBackground, nullptr); + QColor col = QColorDialog::getColor(colorRichTextEditorBackground, nullptr); if (!col.isValid()) return; - colorRichTextDefaultBackground = col; + colorRichTextEditorBackground = col; QPixmap pix(16, 16); - pix.fill(colorRichTextDefaultBackground); - actionFilledEditorColor->setIcon(pix); + pix.fill(colorRichTextEditorBackground); + actionActiveEditorBGColor->setIcon(pix); } -void TextEditor::selectColorRichTextDefaultForeground() +void TextEditor::selectRichTextForegroundColor() { - QColor col = QColorDialog::getColor(colorRichTextDefaultForeground, nullptr); - if (!col.isValid()) - return; - setColorRichTextDefaultForeground(col); + QColor col = QColorDialog::getColor(colorRichTextForeground, nullptr); + setRichTextForegroundColor(col); +} + +void TextEditor::selectRichTextBackgroundColor() +{ + QColor col = QColorDialog::getColor(colorRichTextBackground, nullptr); + setRichTextBackgroundColor(col); +} + +void TextEditor::insertImage() +{ + QStringList imagePaths = openImageDialog(tr("Load image", "TextEditor")); + + foreach (QString path, imagePaths) { + QUrl Uri ( QString ( "file://%1" ).arg (path)); + QImage image = QImageReader (path).read(); + + QBuffer buffer; + buffer.open(QIODevice::WriteOnly); + image.save(&buffer, "PNG"); + QString encodedImage = buffer.data().toBase64(); + + QTextDocument * textDocument = editor->document(); + textDocument->addResource( QTextDocument::ImageResource, Uri, QVariant (image)); + QTextCursor cursor = editor->textCursor(); + QTextImageFormat imageFormat; + imageFormat.setWidth(image.width()); + imageFormat.setHeight(image.height()); + imageFormat.setName(Uri.toString()); + //cursor.insertImage(imageFormat); + cursor.insertHtml(""); + } } -void TextEditor::setColorRichTextDefaultForeground(const QColor &col) +void TextEditor::setRichTextForegroundColor(const QColor &col) { if (!col.isValid()) return; - colorRichTextDefaultForeground = col; + colorRichTextForeground = col; QPixmap pix(16, 16); - pix.fill(colorRichTextDefaultForeground); - actionFontColor->setIcon(pix); + pix.fill(colorRichTextForeground); + actionRichTextFGColor->setIcon(pix); } -void TextEditor::setColorMapBackground(const QColor &col) +void TextEditor::setRichTextBackgroundColor(const QColor &col) +{ + if (!col.isValid()) return; + + colorRichTextBackground = col; + QPixmap pix(16, 16); + pix.fill(colorRichTextBackground); + actionRichTextBGColor->setIcon(pix); +} + +void TextEditor::setMapBackgroundColor(const QColor &col) { colorMapBackground = col; } -void TextEditor::setUseColorMapBackground(bool b) +void TextEditor::setUseMapBackgroundColor(bool b) { useColorMapBackground = b; -} \ No newline at end of file +} diff --git a/src/texteditor.h b/src/texteditor.h index f159d1f..00a4664 100644 --- a/src/texteditor.h +++ b/src/texteditor.h @@ -68,9 +68,9 @@ class TextEditor : public QMainWindow { private slots: void textLoad(); - void textSaveAs(); - void textSave(); - void textExportAsASCII(); + void textExportAs(); + void textExport(); + void textExportText(); void textPrint(); void textEditUndo(); void toggleFonthint(); @@ -83,29 +83,34 @@ class TextEditor : public QMainWindow { void textItalic(); void textFamily(const QString &f); void textSize(const QString &p); - void textColor(); + void selectTextFGColor(); + void selectTextBGColor(); void textAlign(QAction *); void textVAlign(); void fontChanged(const QFont &f); - void colorChanged(const QColor &c); + void colorFGChanged(const QColor &c); + void colorBGChanged(const QColor &c); void formatChanged(const QTextCharFormat &f); void alignmentChanged(int a); void verticalAlignmentChanged(QTextCharFormat::VerticalAlignment); void updateActions(); void setState(EditorState); void updateState(); - void selectColorRichTextDefaultBackground(); - void selectColorRichTextDefaultForeground(); + void selectRichTextEditorBackgroundColor(); + void selectRichTextForegroundColor(); + void selectRichTextBackgroundColor(); + void insertImage(); public: - void setColorRichTextDefaultForeground(const QColor &); - void setColorRichTextDefaultBackground(const QColor &); - void setColorMapBackground(const QColor&); - void setUseColorMapBackground(bool); + void setRichTextEditorBackgroundColor(const QColor &); + void setRichTextForegroundColor(const QColor &); + void setRichTextBackgroundColor(const QColor &); + void setMapBackgroundColor(const QColor&); + void setUseMapBackgroundColor(bool); protected: QString shortcutScope; // used for settings and shortcut scopes - QTextEdit *e; + QTextEdit *editor; QPoint lastPos; // save last position of window QString editorName; // Name of editor, e.g. note editor, heading editor, ... QString editorTitle; // window title: Editor name + selected branch @@ -116,8 +121,9 @@ class TextEditor : public QMainWindow { bool blockChangedSignal; bool blockTextUpdate; // Set *while* textHasChanged is still being emitted - QColor colorRichTextDefaultBackground; - QColor colorRichTextDefaultForeground; + QColor colorRichTextEditorBackground; + QColor colorRichTextBackground; + QColor colorRichTextForeground; QColor colorMapBackground; bool useColorMapBackground; @@ -130,16 +136,33 @@ class TextEditor : public QMainWindow { QToolBar *fontHintsToolBar; QToolBar *formatToolBar; - QAction *actionFileLoad, *actionFileSave, *actionFileSaveAs, + // Filled editor only actions + QList filledEditorActions; + + // Filled editor RichText actions + QList filledEditorRichTextActions; + + // Empty editor actions + QList emptyEditorActions; + + QAction *actionFileLoad, + *actionFileExport, *actionFileExportHtml, *actionFileExportText, *actionFilePrint, *actionFileDeleteAll, *actionEditUndo, *actionEditRedo, *actionEditCopy, *actionEditCut, *actionEditPaste, + *actionSelectAll, + *actionInsertImage, *actionFormatUseFixedFont, *actionFormatRichText, *actionSettingsVarFont, *actionSettingsFixedFont, - *actionSettingsFonthintDefault, *actionEmptyEditorColor, - *actionFilledEditorColor, *actionInactiveEditorColor, *actionFontColor; - - QAction *actionTextBold, *actionTextUnderline, *actionTextItalic, - *actionTextColor, *actionAlignSubScript, *actionAlignSuperScript, + *actionSettingsFonthintDefault, *actionEmptyEditorBGColor, + *actionActiveEditorBGColor, *actionInactiveEditorBGColor, + *actionRichTextFGColor, + *actionRichTextBGColor; + + QAction + *actionTextFGColor, + *actionTextBGColor, + *actionTextBold, *actionTextUnderline, *actionTextItalic, + *actionAlignSubScript, *actionAlignSuperScript, *actionAlignLeft, *actionAlignCenter, *actionAlignRight, *actionAlignJustify; }; diff --git a/src/tmp-parent-container.cpp b/src/tmp-parent-container.cpp new file mode 100644 index 0000000..62476ce --- /dev/null +++ b/src/tmp-parent-container.cpp @@ -0,0 +1,104 @@ +#include + +#include "heading-container.h" +#include "tmp-parent-container.h" + +#include "branch-container.h" + +#define qdbg() qDebug().nospace().noquote() + +TmpParentContainer::TmpParentContainer() +{ + // qDebug() << "* Const TmpParentContainer begin this = " << this; + init(); +} + +void TmpParentContainer::init() +{ + // General defaults, also used by BranchContainer + orientation = UndefinedOrientation; + + tmpLinkedParentContainer = nullptr; + originalParentBranchContainer = nullptr; + + // setPen(QPen(Qt::green)); // Uncomment for testing + + // TmpParentContainer defaults, should be overridden from MapDesign later + containerType = Container::TmpParent; + + setLayout(Container::FloatingReservedSpace); + + branchesContainer = new Container (); + branchesContainer->setContainerType(Container::BranchesContainer); + branchesContainer->setParentItem(this); // Different for BranchItem! +} + +void TmpParentContainer::addToBranchesContainer(BranchContainer *bc) +{ + QPointF sp = bc->getHeadingContainer()->mapToScene(QPoint(0,0)); + branchesContainer->addContainer(bc); + + // keep position + bc->setPos(branchesContainer->sceneTransform().inverted().map(sp)); +} + +void TmpParentContainer::createImagesContainer() +{ + imagesContainer = new Container (); + imagesContainer->setContainerType(ImagesContainer); + imagesContainer->setLayout(Container::FloatingFree); +} + +void TmpParentContainer::addToImagesContainer(Container *c) +{ + if (!imagesContainer) { + createImagesContainer(); + + imagesContainer->setParentItem(this); // Different for BranchItem! + } + + QPointF sp = c->scenePos(); + imagesContainer->addContainer(c, Z_IMAGE); + + // For TmpParentContainer keep position + c->setPos(imagesContainer->sceneTransform().inverted().map(sp)); +} + +void TmpParentContainer::reposition() +{ + //qdbg() << ind() << "TPC::reposition tpc=" << info() << " orient=" << orientation; + /* + if (pbc) + qdbg() << ind() << " pbc=" << pbc->info(); + else + qdbg() << ind() << " pbc=0"; + qdbg() << ind() << " pbc->orientation=" << pbc->orientation; + */ + + switch (orientation) { + case LeftOfParent: + setHorizontalDirection(RightToLeft); + branchesContainer->setHorizontalAlignment(HorAlignedRight); + break; + case RightOfParent: + setHorizontalDirection(LeftToRight); + branchesContainer->setHorizontalAlignment(HorAlignedLeft); + break; + case UndefinedOrientation: + qWarning() << "TPC::reposition tPC - UndefinedOrientation in " << info(); + break; + default: + qWarning() << "TPC::reposition tPC - Unknown orientation " << orientation << " in " << info(); + break; + } + + Container::reposition(); + + // Update links of children + if (branchesContainer && branchCount() > 0) { + foreach (Container *c, branchesContainer->childContainers()) { + BranchContainer *bc = (BranchContainer*) c; + bc->updateUpLink(); + } + } +} diff --git a/src/tmp-parent-container.h b/src/tmp-parent-container.h new file mode 100644 index 0000000..e1e8362 --- /dev/null +++ b/src/tmp-parent-container.h @@ -0,0 +1,21 @@ +#ifndef TMP_PARENT_CONTAINER_H +#define TMP_PARENT_CONTAINER_H + +#include "branch-container-base.h" + +class TmpParentContainer : public BranchContainerBase { + public: + TmpParentContainer (); + virtual void init(); + + virtual void addToBranchesContainer(BranchContainer *bc); + + virtual void createImagesContainer(); + virtual void addToImagesContainer(Container *c); + + public: + virtual void reposition(); + +}; + +#endif diff --git a/src/treeeditor.cpp b/src/treeeditor.cpp index 155848e..d8bc48d 100644 --- a/src/treeeditor.cpp +++ b/src/treeeditor.cpp @@ -1,8 +1,10 @@ #include "treeeditor.h" #include +#include +#include #include -#include +#include #include "mainwindow.h" #include "vymmodel.h" @@ -61,7 +63,7 @@ void TreeEditor::init() addAction(a); connect(a, SIGNAL(triggered()), this, SLOT(startEdit())); - // Clone actions defined in MainWindow + // Clone actions defined in MainWindow // FIXME-3 PageUp/Down not working in TreeEditor foreach (QAction *qa, mainWindow->mapEditorActions) { a = new QAction(this); a->setShortcut(qa->shortcut()); @@ -100,6 +102,11 @@ void TreeEditor::contextMenuEvent(QContextMenuEvent *e) { e->accept(); } +void TreeEditor::closeEvent(QCloseEvent *event) +{ + mainWindow->windowSetTreeEditorsVisibility(false); +} + void TreeEditor::cursorUp() { QModelIndex ix = getSelectedIndex(); diff --git a/src/treeeditor.h b/src/treeeditor.h index 3f2e97e..73b4c7e 100644 --- a/src/treeeditor.h +++ b/src/treeeditor.h @@ -12,13 +12,14 @@ class TreeEditor : public QTreeView { Q_OBJECT public: - TreeEditor(VymModel *m = NULL); + TreeEditor(VymModel *m = nullptr); ~TreeEditor(); void init(); QModelIndex getSelectedIndex(); protected: virtual void contextMenuEvent(QContextMenuEvent *e); + virtual void closeEvent(QCloseEvent *event); private slots: void cursorUp(); diff --git a/src/treeitem.cpp b/src/treeitem.cpp index 1beb13c..e885a6d 100644 --- a/src/treeitem.cpp +++ b/src/treeitem.cpp @@ -3,14 +3,11 @@ #include "attributeitem.h" #include "branchitem.h" -#include "branchobj.h" #include "misc.h" #include "treeitem.h" #include "vymmodel.h" +#include "xlink.h" #include "xlinkitem.h" -#include "xlinkobj.h" - -using namespace std; extern ulong itemLastID; extern FlagRowMaster *standardFlagsMaster; @@ -32,49 +29,50 @@ TreeItem::TreeItem(TreeItem *parent) TreeItem::~TreeItem() { - // qDebug()<<"Destr TreeItem this="<