diff --git a/libs/global/CMakeLists.txt b/libs/global/CMakeLists.txt
index 873eb80db6..9dbbc2a819 100644
--- a/libs/global/CMakeLists.txt
+++ b/libs/global/CMakeLists.txt
@@ -1,55 +1,56 @@
add_subdirectory( tests )
include(CheckFunctionExists)
check_function_exists(backtrace HAVE_BACKTRACE)
configure_file(config-debug.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-debug.h)
option(HAVE_MEMORY_LEAK_TRACKER "Enable memory leak tracker (always disabled in release build)" OFF)
option(HAVE_BACKTRACE_SUPPORT "Enable recording of backtrace in memory leak tracker" OFF)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config-memory-leak-tracker.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-memory-leak-tracker.h) ### WRONG PLACE???
set(kritaglobal_LIB_SRCS
kis_assert.cpp
kis_debug.cpp
kis_algebra_2d.cpp
kis_memory_leak_tracker.cpp
kis_shared.cpp
kis_dom_utils.cpp
kis_painting_tweaks.cpp
KisHandlePainterHelper.cpp
KisHandleStyle.cpp
kis_relaxed_timer.cpp
kis_signal_compressor.cpp
kis_signal_compressor_with_param.cpp
kis_thread_safe_signal_compressor.cpp
kis_acyclic_signal_connector.cpp
kis_latency_tracker.cpp
KisQPainterStateSaver.cpp
KisSharedThreadPoolAdapter.cpp
KisSharedRunnable.cpp
KisRollingMeanAccumulatorWrapper.cpp
kis_config_notifier.cpp
KisDeleteLaterWrapper.cpp
KisUsageLogger.cpp
+ KisFileUtils.cpp
)
add_library(kritaglobal SHARED ${kritaglobal_LIB_SRCS} )
generate_export_header(kritaglobal BASE_NAME kritaglobal)
target_link_libraries(kritaglobal
PUBLIC
kritaversion
Qt5::Concurrent
Qt5::Core
Qt5::Gui
Qt5::Widgets
Qt5::Xml
KF5::I18n
)
set_target_properties(kritaglobal PROPERTIES
VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION}
)
install(TARGETS kritaglobal ${INSTALL_TARGETS_DEFAULT_ARGS})
diff --git a/libs/global/KisFileUtils.cpp b/libs/global/KisFileUtils.cpp
new file mode 100644
index 0000000000..f21d04df6c
--- /dev/null
+++ b/libs/global/KisFileUtils.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019 Dmitry Kazakov
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "KisFileUtils.h"
+
+#include
+#include
+#include
+
+namespace KritaUtils {
+
+QString resolveAbsoluteFilePath(const QString &baseDir, const QString &fileName)
+{
+ if (QFileInfo(fileName).isAbsolute()) {
+ return fileName;
+ }
+
+ QFileInfo fallbackBaseDirInfo(baseDir);
+
+ return QFileInfo(QDir(fallbackBaseDirInfo.isDir() ?
+ fallbackBaseDirInfo.absoluteFilePath() :
+ fallbackBaseDirInfo.absolutePath()),
+ fileName).absoluteFilePath();
+}
+
+}
diff --git a/libs/global/KisFileUtils.h b/libs/global/KisFileUtils.h
new file mode 100644
index 0000000000..9d822e14b4
--- /dev/null
+++ b/libs/global/KisFileUtils.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019 Dmitry Kazakov
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KISFILEUTILS_H
+#define KISFILEUTILS_H
+
+#include "kritaglobal_export.h"
+
+
+class QString;
+
+namespace KritaUtils {
+
+/**
+ * @brief Resolve absolute file path from a file path and base dir
+ *
+ * If the @p filePath is absolute, just return this path, otherwise
+ * try to merge @p baseDir and @p filePath to form an absolute file
+ * path
+ */
+QString KRITAGLOBAL_EXPORT resolveAbsoluteFilePath(const QString &baseDir, const QString &filePath);
+
+
+}
+
+#endif // KISFILEUTILS_H
diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt
index bb8db4638a..3daf4642f2 100644
--- a/libs/ui/CMakeLists.txt
+++ b/libs/ui/CMakeLists.txt
@@ -1,599 +1,593 @@
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/qtlockedfile
)
include_directories(SYSTEM
${EIGEN3_INCLUDE_DIR}
${OCIO_INCLUDE_DIR}
)
add_subdirectory( tests )
if (APPLE)
find_library(FOUNDATION_LIBRARY Foundation)
find_library(APPKIT_LIBRARY AppKit)
endif ()
set(kritaui_LIB_SRCS
canvas/kis_canvas_widget_base.cpp
canvas/kis_canvas2.cpp
canvas/kis_canvas_updates_compressor.cpp
canvas/kis_canvas_controller.cpp
canvas/kis_paintop_transformation_connector.cpp
canvas/kis_display_color_converter.cpp
canvas/kis_display_filter.cpp
canvas/kis_exposure_gamma_correction_interface.cpp
canvas/kis_tool_proxy.cpp
canvas/kis_canvas_decoration.cc
canvas/kis_coordinates_converter.cpp
canvas/kis_grid_manager.cpp
canvas/kis_grid_decoration.cpp
canvas/kis_grid_config.cpp
canvas/kis_prescaled_projection.cpp
canvas/kis_qpainter_canvas.cpp
canvas/kis_projection_backend.cpp
canvas/kis_update_info.cpp
canvas/kis_image_patch.cpp
canvas/kis_image_pyramid.cpp
canvas/kis_infinity_manager.cpp
canvas/kis_change_guides_command.cpp
canvas/kis_guides_decoration.cpp
canvas/kis_guides_manager.cpp
canvas/kis_guides_config.cpp
canvas/kis_snap_config.cpp
canvas/kis_snap_line_strategy.cpp
canvas/KisSnapPointStrategy.cpp
canvas/KisMirrorAxisConfig.cpp
dialogs/kis_about_application.cpp
dialogs/kis_dlg_adj_layer_props.cc
dialogs/kis_dlg_adjustment_layer.cc
dialogs/kis_dlg_filter.cpp
dialogs/kis_dlg_generator_layer.cpp
dialogs/kis_dlg_file_layer.cpp
dialogs/kis_dlg_filter.cpp
dialogs/kis_dlg_stroke_selection_properties.cpp
dialogs/kis_dlg_image_properties.cc
dialogs/kis_dlg_layer_properties.cc
dialogs/kis_dlg_preferences.cc
dialogs/slider_and_spin_box_sync.cpp
dialogs/kis_dlg_blacklist_cleanup.cpp
dialogs/kis_dlg_layer_style.cpp
dialogs/kis_dlg_png_import.cpp
dialogs/kis_dlg_import_image_sequence.cpp
dialogs/kis_delayed_save_dialog.cpp
dialogs/KisSessionManagerDialog.cpp
dialogs/KisNewWindowLayoutDialog.cpp
flake/kis_node_dummies_graph.cpp
flake/kis_dummies_facade_base.cpp
flake/kis_dummies_facade.cpp
flake/kis_node_shapes_graph.cpp
flake/kis_node_shape.cpp
flake/kis_shape_controller.cpp
flake/kis_shape_layer.cc
flake/kis_shape_layer_canvas.cpp
flake/kis_shape_selection.cpp
flake/kis_shape_selection_canvas.cpp
flake/kis_shape_selection_model.cpp
flake/kis_take_all_shapes_command.cpp
brushhud/kis_uniform_paintop_property_widget.cpp
brushhud/kis_brush_hud.cpp
brushhud/kis_round_hud_button.cpp
brushhud/kis_dlg_brush_hud_config.cpp
brushhud/kis_brush_hud_properties_list.cpp
brushhud/kis_brush_hud_properties_config.cpp
kis_aspect_ratio_locker.cpp
kis_autogradient.cc
kis_bookmarked_configurations_editor.cc
kis_bookmarked_configurations_model.cc
kis_bookmarked_filter_configurations_model.cc
KisPaintopPropertiesBase.cpp
kis_canvas_resource_provider.cpp
kis_derived_resources.cpp
kis_categories_mapper.cpp
kis_categorized_list_model.cpp
kis_categorized_item_delegate.cpp
kis_clipboard.cc
kis_config.cc
KisOcioConfiguration.cpp
kis_control_frame.cpp
kis_composite_ops_model.cc
kis_paint_ops_model.cpp
kis_cursor.cc
kis_cursor_cache.cpp
kis_custom_pattern.cc
kis_file_layer.cpp
kis_change_file_layer_command.h
kis_safe_document_loader.cpp
kis_splash_screen.cpp
kis_filter_manager.cc
kis_filters_model.cc
kis_histogram_view.cc
KisImageBarrierLockerWithFeedback.cpp
kis_image_manager.cc
kis_image_view_converter.cpp
kis_import_catcher.cc
kis_layer_manager.cc
kis_mask_manager.cc
kis_mimedata.cpp
kis_node_commands_adapter.cpp
kis_node_manager.cpp
kis_node_juggler_compressed.cpp
kis_node_selection_adapter.cpp
kis_node_insertion_adapter.cpp
KisNodeDisplayModeAdapter.cpp
kis_node_model.cpp
kis_node_filter_proxy_model.cpp
kis_model_index_converter_base.cpp
kis_model_index_converter.cpp
kis_model_index_converter_show_all.cpp
kis_painting_assistant.cc
kis_painting_assistants_decoration.cpp
KisDecorationsManager.cpp
kis_paintop_box.cc
kis_paintop_option.cpp
kis_paintop_options_model.cpp
kis_paintop_settings_widget.cpp
kis_popup_palette.cpp
kis_png_converter.cpp
kis_preference_set_registry.cpp
KisResourceServerProvider.cpp
KisResourceBundleServerProvider.cpp
KisSelectedShapesProxy.cpp
kis_selection_decoration.cc
kis_selection_manager.cc
KisSelectionActionsAdapter.cpp
kis_statusbar.cc
kis_zoom_manager.cc
kis_favorite_resource_manager.cpp
kis_workspace_resource.cpp
kis_action.cpp
kis_action_manager.cpp
KisActionPlugin.cpp
kis_canvas_controls_manager.cpp
kis_tooltip_manager.cpp
kis_multinode_property.cpp
kis_stopgradient_editor.cpp
KisWelcomePageWidget.cpp
kisexiv2/kis_exif_io.cpp
kisexiv2/kis_exiv2.cpp
kisexiv2/kis_iptc_io.cpp
kisexiv2/kis_xmp_io.cpp
opengl/kis_opengl.cpp
opengl/kis_opengl_canvas2.cpp
opengl/kis_opengl_canvas_debugger.cpp
opengl/kis_opengl_image_textures.cpp
opengl/kis_texture_tile.cpp
opengl/kis_opengl_shader_loader.cpp
opengl/kis_texture_tile_info_pool.cpp
opengl/KisOpenGLUpdateInfoBuilder.cpp
opengl/KisOpenGLModeProber.cpp
opengl/KisScreenInformationAdapter.cpp
kis_fps_decoration.cpp
tool/KisToolChangesTracker.cpp
tool/KisToolChangesTrackerData.cpp
tool/kis_selection_tool_helper.cpp
tool/kis_selection_tool_config_widget_helper.cpp
tool/kis_rectangle_constraint_widget.cpp
tool/kis_shape_tool_helper.cpp
tool/kis_tool.cc
tool/kis_delegated_tool_policies.cpp
tool/kis_tool_freehand.cc
tool/kis_speed_smoother.cpp
tool/kis_painting_information_builder.cpp
tool/kis_stabilized_events_sampler.cpp
tool/kis_tool_freehand_helper.cpp
tool/kis_tool_multihand_helper.cpp
tool/kis_figure_painting_tool_helper.cpp
tool/kis_tool_paint.cc
tool/kis_tool_shape.cc
tool/kis_tool_ellipse_base.cpp
tool/kis_tool_rectangle_base.cpp
tool/kis_tool_polyline_base.cpp
tool/kis_tool_utils.cpp
tool/kis_resources_snapshot.cpp
tool/kis_smoothing_options.cpp
tool/KisStabilizerDelayedPaintHelper.cpp
tool/KisStrokeSpeedMonitor.cpp
tool/strokes/freehand_stroke.cpp
tool/strokes/KisStrokeEfficiencyMeasurer.cpp
tool/strokes/kis_painter_based_stroke_strategy.cpp
tool/strokes/kis_filter_stroke_strategy.cpp
tool/strokes/kis_color_picker_stroke_strategy.cpp
tool/strokes/KisFreehandStrokeInfo.cpp
tool/strokes/KisMaskedFreehandStrokePainter.cpp
tool/strokes/KisMaskingBrushRenderer.cpp
tool/strokes/KisMaskingBrushCompositeOpFactory.cpp
tool/strokes/move_stroke_strategy.cpp
tool/KisSelectionToolFactoryBase.cpp
tool/KisToolPaintFactoryBase.cpp
widgets/kis_cmb_composite.cc
widgets/kis_cmb_contour.cpp
widgets/kis_cmb_gradient.cpp
widgets/kis_paintop_list_widget.cpp
widgets/kis_cmb_idlist.cc
widgets/kis_color_space_selector.cc
widgets/kis_advanced_color_space_selector.cc
widgets/kis_cie_tongue_widget.cpp
widgets/kis_tone_curve_widget.cpp
widgets/kis_curve_widget.cpp
widgets/kis_custom_image_widget.cc
widgets/kis_image_from_clipboard_widget.cpp
widgets/kis_double_widget.cc
widgets/kis_filter_selector_widget.cc
widgets/kis_gradient_chooser.cc
widgets/kis_iconwidget.cc
widgets/kis_mask_widgets.cpp
widgets/kis_meta_data_merge_strategy_chooser_widget.cc
widgets/kis_multi_bool_filter_widget.cc
widgets/kis_multi_double_filter_widget.cc
widgets/kis_multi_integer_filter_widget.cc
widgets/kis_multipliers_double_slider_spinbox.cpp
widgets/kis_paintop_presets_popup.cpp
widgets/kis_tool_options_popup.cpp
widgets/kis_paintop_presets_chooser_popup.cpp
widgets/kis_paintop_presets_save.cpp
widgets/kis_paintop_preset_icon_library.cpp
widgets/kis_pattern_chooser.cc
widgets/kis_preset_chooser.cpp
widgets/kis_progress_widget.cpp
widgets/kis_selection_options.cc
widgets/kis_scratch_pad.cpp
widgets/kis_scratch_pad_event_filter.cpp
widgets/kis_preset_selector_strip.cpp
widgets/kis_slider_spin_box.cpp
widgets/KisSelectionPropertySlider.cpp
widgets/kis_size_group.cpp
widgets/kis_size_group_p.cpp
widgets/kis_wdg_generator.cpp
widgets/kis_workspace_chooser.cpp
widgets/kis_categorized_list_view.cpp
widgets/kis_widget_chooser.cpp
widgets/kis_tool_button.cpp
widgets/kis_floating_message.cpp
widgets/kis_lod_availability_widget.cpp
widgets/kis_color_label_selector_widget.cpp
widgets/kis_color_filter_combo.cpp
widgets/kis_elided_label.cpp
widgets/kis_stopgradient_slider_widget.cpp
widgets/kis_preset_live_preview_view.cpp
widgets/KisScreenColorPicker.cpp
widgets/KoDualColorButton.cpp
widgets/KoStrokeConfigWidget.cpp
widgets/KoFillConfigWidget.cpp
widgets/KisLayerStyleAngleSelector.cpp
widgets/KisMemoryReportButton.cpp
KisPaletteEditor.cpp
dialogs/KisDlgPaletteEditor.cpp
widgets/KisNewsWidget.cpp
widgets/KisGamutMaskToolbar.cpp
utils/kis_document_aware_spin_box_unit_manager.cpp
input/kis_input_manager.cpp
input/kis_input_manager_p.cpp
input/kis_extended_modifiers_mapper.cpp
input/kis_abstract_input_action.cpp
input/kis_tool_invocation_action.cpp
input/kis_pan_action.cpp
input/kis_alternate_invocation_action.cpp
input/kis_rotate_canvas_action.cpp
input/kis_zoom_action.cpp
input/kis_change_frame_action.cpp
input/kis_gamma_exposure_action.cpp
input/kis_show_palette_action.cpp
input/kis_change_primary_setting_action.cpp
input/kis_abstract_shortcut.cpp
input/kis_native_gesture_shortcut.cpp
input/kis_single_action_shortcut.cpp
input/kis_stroke_shortcut.cpp
input/kis_shortcut_matcher.cpp
input/kis_select_layer_action.cpp
input/KisQtWidgetsTweaker.cpp
input/KisInputActionGroup.cpp
operations/kis_operation.cpp
operations/kis_operation_configuration.cpp
operations/kis_operation_registry.cpp
operations/kis_operation_ui_factory.cpp
operations/kis_operation_ui_widget.cpp
operations/kis_filter_selection_operation.cpp
actions/kis_selection_action_factories.cpp
actions/KisPasteActionFactory.cpp
actions/KisTransformToolActivationCommand.cpp
input/kis_touch_shortcut.cpp
kis_document_undo_store.cpp
kis_gui_context_command.cpp
kis_gui_context_command_p.cpp
input/kis_tablet_debugger.cpp
input/kis_input_profile_manager.cpp
input/kis_input_profile.cpp
input/kis_shortcut_configuration.cpp
input/config/kis_input_configuration_page.cpp
input/config/kis_edit_profiles_dialog.cpp
input/config/kis_input_profile_model.cpp
input/config/kis_input_configuration_page_item.cpp
input/config/kis_action_shortcuts_model.cpp
input/config/kis_input_type_delegate.cpp
input/config/kis_input_mode_delegate.cpp
input/config/kis_input_button.cpp
input/config/kis_input_editor_delegate.cpp
input/config/kis_mouse_input_editor.cpp
input/config/kis_wheel_input_editor.cpp
input/config/kis_key_input_editor.cpp
processing/fill_processing_visitor.cpp
kis_asl_layer_style_serializer.cpp
kis_psd_layer_style_resource.cpp
canvas/kis_mirror_axis.cpp
kis_abstract_perspective_grid.cpp
KisApplication.cpp
KisAutoSaveRecoveryDialog.cpp
KisDetailsPane.cpp
KisDocument.cpp
KisCloneDocumentStroke.cpp
- KisNodeDelegate.cpp
- kis_node_view_visibility_delegate.cpp
- KisNodeToolTip.cpp
- KisNodeView.cpp
kis_node_view_color_scheme.cpp
KisImportExportFilter.cpp
KisFilterEntry.cpp
KisImportExportManager.cpp
KisImportExportUtils.cpp
kis_async_action_feedback.cpp
KisMainWindow.cpp
KisOpenPane.cpp
KisPart.cpp
KisPrintJob.cpp
KisTemplate.cpp
KisTemplateCreateDia.cpp
KisTemplateGroup.cpp
KisTemplates.cpp
KisTemplatesPane.cpp
KisTemplateTree.cpp
KisUndoActionsUpdateManager.cpp
KisView.cpp
thememanager.cpp
kis_mainwindow_observer.cpp
KisViewManager.cpp
kis_mirror_manager.cpp
qtlockedfile/qtlockedfile.cpp
qtsingleapplication/qtlocalpeer.cpp
qtsingleapplication/qtsingleapplication.cpp
KisResourceBundle.cpp
KisResourceBundleManifest.cpp
kis_md5_generator.cpp
KisApplicationArguments.cpp
KisNetworkAccessManager.cpp
KisMultiFeedRSSModel.cpp
KisRemoteFileFetcher.cpp
KisSaveGroupVisitor.cpp
KisWindowLayoutResource.cpp
KisWindowLayoutManager.cpp
KisSessionResource.cpp
KisReferenceImagesDecoration.cpp
KisReferenceImage.cpp
flake/KisReferenceImagesLayer.cpp
flake/KisReferenceImagesLayer.h
)
if(WIN32)
set(kritaui_LIB_SRCS
${kritaui_LIB_SRCS}
input/wintab/kis_tablet_support_win.cpp
input/wintab/kis_screen_size_choice_dialog.cpp
qtlockedfile/qtlockedfile_win.cpp
input/wintab/kis_tablet_support_win8.cpp
)
endif()
set(kritaui_LIB_SRCS
${kritaui_LIB_SRCS}
kis_animation_frame_cache.cpp
kis_animation_cache_populator.cpp
KisAsyncAnimationRendererBase.cpp
KisAsyncAnimationCacheRenderer.cpp
KisAsyncAnimationFramesSavingRenderer.cpp
dialogs/KisAsyncAnimationRenderDialogBase.cpp
dialogs/KisAsyncAnimationCacheRenderDialog.cpp
dialogs/KisAsyncAnimationFramesSaveDialog.cpp
canvas/kis_animation_player.cpp
kis_animation_importer.cpp
KisSyncedAudioPlayback.cpp
KisFrameDataSerializer.cpp
KisFrameCacheStore.cpp
KisFrameCacheSwapper.cpp
KisAbstractFrameCacheSwapper.cpp
KisInMemoryFrameCacheSwapper.cpp
input/wintab/drawpile_tablettester/tablettester.cpp
input/wintab/drawpile_tablettester/tablettest.cpp
)
if (UNIX)
set(kritaui_LIB_SRCS
${kritaui_LIB_SRCS}
qtlockedfile/qtlockedfile_unix.cpp
)
if(NOT USE_QT_XCB)
set(kritaui_LIB_SRCS
${kritaui_LIB_SRCS}
input/wintab/kis_tablet_support.cpp
)
endif()
if(NOT APPLE AND NOT USE_QT_XCB)
set(kritaui_LIB_SRCS
${kritaui_LIB_SRCS}
input/wintab/qxcbconnection_xi2.cpp
input/wintab/qxcbconnection.cpp
input/wintab/kis_xi2_event_filter.cpp
)
endif()
endif()
if(APPLE)
set(kritaui_LIB_SRCS
${kritaui_LIB_SRCS}
osx.mm
)
endif()
ki18n_wrap_ui(kritaui_LIB_SRCS
widgets/KoFillConfigWidget.ui
widgets/KoStrokeConfigWidget.ui
forms/wdgdlgpngimport.ui
forms/wdgfullscreensettings.ui
forms/wdgautogradient.ui
forms/wdggeneralsettings.ui
forms/wdgperformancesettings.ui
forms/wdggenerators.ui
forms/wdgbookmarkedconfigurationseditor.ui
forms/wdgapplyprofile.ui
forms/wdgcustompattern.ui
forms/wdglayerproperties.ui
forms/wdgcolorsettings.ui
forms/wdgtabletsettings.ui
forms/wdgcolorspaceselector.ui
forms/wdgcolorspaceselectoradvanced.ui
forms/wdgdisplaysettings.ui
forms/kis_previewwidgetbase.ui
forms/kis_matrix_widget.ui
forms/wdgselectionoptions.ui
forms/wdggeometryoptions.ui
forms/wdgnewimage.ui
forms/wdgimageproperties.ui
forms/wdgmaskfromselection.ui
forms/wdgmasksource.ui
forms/wdgfilterdialog.ui
forms/wdgmetadatamergestrategychooser.ui
forms/wdgpaintoppresets.ui
forms/wdgpaintopsettings.ui
forms/wdgdlggeneratorlayer.ui
forms/wdgdlgfilelayer.ui
forms/wdgfilterselector.ui
forms/wdgfilternodecreation.ui
forms/wdgmultipliersdoublesliderspinbox.ui
forms/wdgnodequerypatheditor.ui
forms/wdgpresetselectorstrip.ui
forms/wdgsavebrushpreset.ui
forms/wdgpreseticonlibrary.ui
forms/wdgdlgblacklistcleanup.ui
forms/wdgrectangleconstraints.ui
forms/wdgimportimagesequence.ui
forms/wdgstrokeselectionproperties.ui
forms/KisDetailsPaneBase.ui
forms/KisOpenPaneBase.ui
forms/wdgstopgradienteditor.ui
forms/wdgsessionmanager.ui
forms/wdgnewwindowlayout.ui
forms/KisWelcomePage.ui
forms/WdgDlgPaletteEditor.ui
forms/KisNewsPage.ui
forms/wdgGamutMaskToolbar.ui
brushhud/kis_dlg_brush_hud_config.ui
dialogs/kis_delayed_save_dialog.ui
input/config/kis_input_configuration_page.ui
input/config/kis_edit_profiles_dialog.ui
input/config/kis_input_configuration_page_item.ui
input/config/kis_mouse_input_editor.ui
input/config/kis_wheel_input_editor.ui
input/config/kis_key_input_editor.ui
layerstyles/wdgBevelAndEmboss.ui
layerstyles/wdgblendingoptions.ui
layerstyles/WdgColorOverlay.ui
layerstyles/wdgContour.ui
layerstyles/wdgdropshadow.ui
layerstyles/WdgGradientOverlay.ui
layerstyles/wdgInnerGlow.ui
layerstyles/wdglayerstyles.ui
layerstyles/WdgPatternOverlay.ui
layerstyles/WdgSatin.ui
layerstyles/WdgStroke.ui
layerstyles/wdgstylesselector.ui
layerstyles/wdgTexture.ui
layerstyles/wdgKisLayerStyleAngleSelector.ui
wdgsplash.ui
input/wintab/kis_screen_size_choice_dialog.ui
input/wintab/drawpile_tablettester/tablettest.ui
)
-QT5_WRAP_CPP(kritaui_HEADERS_MOC KisNodePropertyAction_p.h)
-
add_library(kritaui SHARED ${kritaui_HEADERS_MOC} ${kritaui_LIB_SRCS} )
generate_export_header(kritaui BASE_NAME kritaui)
target_link_libraries(kritaui KF5::CoreAddons KF5::Completion KF5::I18n KF5::ItemViews Qt5::Network
kritaimpex kritacolor kritaimage kritalibbrush kritawidgets kritawidgetutils kritaresources ${PNG_LIBRARIES} LibExiv2::LibExiv2
)
if (HAVE_QT_MULTIMEDIA)
target_link_libraries(kritaui Qt5::Multimedia)
endif()
if (NOT WIN32 AND NOT APPLE)
target_link_libraries(kritaui ${X11_X11_LIB}
${X11_Xinput_LIB}
${XCB_LIBRARIES})
endif()
if(APPLE)
target_link_libraries(kritaui ${FOUNDATION_LIBRARY})
target_link_libraries(kritaui ${APPKIT_LIBRARY})
endif ()
target_link_libraries(kritaui ${OPENEXR_LIBRARIES})
# Add VSync disable workaround
if(NOT WIN32 AND NOT APPLE)
target_link_libraries(kritaui ${CMAKE_DL_LIBS} Qt5::X11Extras)
endif()
if(X11_FOUND)
target_link_libraries(kritaui Qt5::X11Extras ${X11_LIBRARIES})
endif()
target_include_directories(kritaui
PUBLIC
$
$
$
$
$
$
$
)
set_target_properties(kritaui
PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION}
)
install(TARGETS kritaui ${INSTALL_TARGETS_DEFAULT_ARGS})
if (APPLE)
install(FILES osx.stylesheet DESTINATION ${DATA_INSTALL_DIR}/krita)
endif ()
diff --git a/libs/ui/canvas/KisMirrorAxisConfig.cpp b/libs/ui/canvas/KisMirrorAxisConfig.cpp
index b6d5102426..16ed0b6fc8 100644
--- a/libs/ui/canvas/KisMirrorAxisConfig.cpp
+++ b/libs/ui/canvas/KisMirrorAxisConfig.cpp
@@ -1,246 +1,247 @@
/*
* Copyright (c) 2019 Anna Medonosova
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include
#include
#include "KisMirrorAxisConfig.h"
class Q_DECL_HIDDEN KisMirrorAxisConfig::Private
{
public:
Private()
: mirrorHorizontal(false)
, mirrorVertical(false)
, lockHorizontal(false)
, lockVertical(false)
, hideVerticalDecoration(false)
, hideHorizontalDecoration(false)
, handleSize(32.f)
, horizontalHandlePosition(64.f)
, verticalHandlePosition(64.f)
+ , axisPosition(QPointF(0.f,0.f))
{}
bool operator==(const Private& rhs) {
return mirrorHorizontal == rhs.mirrorHorizontal &&
mirrorVertical == rhs.mirrorVertical &&
lockHorizontal == rhs.lockHorizontal &&
lockVertical == rhs.lockVertical &&
hideHorizontalDecoration == rhs.hideHorizontalDecoration &&
hideVerticalDecoration == rhs.hideVerticalDecoration &&
handleSize == rhs.handleSize &&
horizontalHandlePosition == rhs.horizontalHandlePosition &&
verticalHandlePosition == rhs.verticalHandlePosition &&
axisPosition == rhs.axisPosition;
}
bool mirrorHorizontal;
bool mirrorVertical;
bool lockHorizontal;
bool lockVertical;
bool hideVerticalDecoration;
bool hideHorizontalDecoration;
float handleSize;
float horizontalHandlePosition;
float verticalHandlePosition;
QPointF axisPosition;
};
KisMirrorAxisConfig::KisMirrorAxisConfig()
: QObject()
, d(new Private())
{
}
KisMirrorAxisConfig::~KisMirrorAxisConfig()
{
}
KisMirrorAxisConfig::KisMirrorAxisConfig(const KisMirrorAxisConfig &rhs)
: QObject()
, d(new Private(*rhs.d))
{
}
KisMirrorAxisConfig &KisMirrorAxisConfig::operator=(const KisMirrorAxisConfig &rhs)
{
if (&rhs != this) {
*d = *rhs.d;
}
return *this;
}
bool KisMirrorAxisConfig::operator==(const KisMirrorAxisConfig &rhs) const
{
return *d == *rhs.d;
}
bool KisMirrorAxisConfig::mirrorHorizontal()
{
return d->mirrorHorizontal;
}
void KisMirrorAxisConfig::setMirrorHorizontal(bool state)
{
d->mirrorHorizontal = state;
}
bool KisMirrorAxisConfig::mirrorVertical()
{
return d->mirrorVertical;
}
void KisMirrorAxisConfig::setMirrorVertical(bool state)
{
d->mirrorVertical = state;
}
bool KisMirrorAxisConfig::lockHorizontal()
{
return d->lockHorizontal;
}
void KisMirrorAxisConfig::setLockHorizontal(bool state)
{
d->lockHorizontal = state;
}
bool KisMirrorAxisConfig::lockVertical()
{
return d->lockVertical;
}
void KisMirrorAxisConfig::setLockVertical(bool state)
{
d->lockVertical = state;
}
bool KisMirrorAxisConfig::hideVerticalDecoration()
{
return d->hideVerticalDecoration;
}
void KisMirrorAxisConfig::setHideVerticalDecoration(bool state)
{
d->hideVerticalDecoration = state;
}
bool KisMirrorAxisConfig::hideHorizontalDecoration()
{
return d->hideHorizontalDecoration;
}
void KisMirrorAxisConfig::setHideHorizontalDecoration(bool state)
{
d->hideHorizontalDecoration = state;
}
float KisMirrorAxisConfig::handleSize()
{
return d->handleSize;
}
void KisMirrorAxisConfig::setHandleSize(float size)
{
d->handleSize = size;
}
float KisMirrorAxisConfig::horizontalHandlePosition()
{
return d->horizontalHandlePosition;
}
void KisMirrorAxisConfig::setHorizontalHandlePosition(float position)
{
d->horizontalHandlePosition = position;
}
float KisMirrorAxisConfig::verticalHandlePosition()
{
return d->verticalHandlePosition;
}
void KisMirrorAxisConfig::setVerticalHandlePosition(float position)
{
d->verticalHandlePosition = position;
}
QPointF KisMirrorAxisConfig::axisPosition()
{
return d->axisPosition;
}
void KisMirrorAxisConfig::setAxisPosition(QPointF position)
{
d->axisPosition = position;
}
QDomElement KisMirrorAxisConfig::saveToXml(QDomDocument &doc, const QString &tag) const
{
QDomElement mirrorAxisElement = doc.createElement(tag);
KisDomUtils::saveValue(&mirrorAxisElement, "mirrorHorizontal", d->mirrorHorizontal);
KisDomUtils::saveValue(&mirrorAxisElement, "mirrorVertical", d->mirrorVertical);
KisDomUtils::saveValue(&mirrorAxisElement, "lockHorizontal", d->lockHorizontal);
KisDomUtils::saveValue(&mirrorAxisElement, "lockVertical", d->lockVertical);
KisDomUtils::saveValue(&mirrorAxisElement, "hideHorizontalDecoration", d->hideHorizontalDecoration);
KisDomUtils::saveValue(&mirrorAxisElement, "hideVerticalDecoration", d->hideVerticalDecoration);
KisDomUtils::saveValue(&mirrorAxisElement, "handleSize", d->handleSize);
KisDomUtils::saveValue(&mirrorAxisElement, "horizontalHandlePosition", d->horizontalHandlePosition);
KisDomUtils::saveValue(&mirrorAxisElement, "verticalHandlePosition", d->verticalHandlePosition);
KisDomUtils::saveValue(&mirrorAxisElement, "axisPosition", d->axisPosition);
return mirrorAxisElement;
}
bool KisMirrorAxisConfig::loadFromXml(const QDomElement &parent)
{
bool result = true;
result &= KisDomUtils::loadValue(parent, "mirrorHorizontal", &d->mirrorHorizontal);
result &= KisDomUtils::loadValue(parent, "mirrorVertical", &d->mirrorVertical);
result &= KisDomUtils::loadValue(parent, "lockHorizontal", &d->lockHorizontal);
result &= KisDomUtils::loadValue(parent, "lockVertical", &d->lockVertical);
result &= KisDomUtils::loadValue(parent, "hideHorizontalDecoration", &d->hideHorizontalDecoration);
result &= KisDomUtils::loadValue(parent, "hideVerticalDecoration", &d->hideVerticalDecoration);
result &= KisDomUtils::loadValue(parent, "handleSize", &d->handleSize);
result &= KisDomUtils::loadValue(parent, "horizontalHandlePosition", &d->horizontalHandlePosition);
result &= KisDomUtils::loadValue(parent, "verticalHandlePosition", &d->verticalHandlePosition);
result &= KisDomUtils::loadValue(parent, "axisPosition", &d->axisPosition);
return result;
}
bool KisMirrorAxisConfig::isDefault() const
{
KisMirrorAxisConfig defaultConfig;
return *this == defaultConfig;
}
diff --git a/libs/ui/kis_mirror_manager.cpp b/libs/ui/kis_mirror_manager.cpp
index c278a142e1..0a7dfb1fe3 100644
--- a/libs/ui/kis_mirror_manager.cpp
+++ b/libs/ui/kis_mirror_manager.cpp
@@ -1,128 +1,131 @@
/*
* Copyright (c) 2009 Cyrille Berger
* Copyright (c) 2014 Sven Langkamp
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "kis_mirror_manager.h"
#include "KisViewManager.h"
#include
#include
#include
#include
#include
#include
#include
#include "kis_canvas2.h"
#include "kis_mirror_axis.h"
#include
#include
#include
class KisMirrorManager::Private
{
public:
Private()
: mirrorAxisDecoration(nullptr)
{}
KisMirrorAxis* mirrorAxisDecoration;
-// KisMirrorAxisConfig mirrorAxisConfig() {}
};
KisMirrorManager::KisMirrorManager(KisViewManager* view) : QObject(view)
, d(new Private())
, m_imageView(0)
{
}
KisMirrorManager::~KisMirrorManager()
{
}
void KisMirrorManager::setup(KActionCollection * collection)
{
m_mirrorCanvas = new KToggleAction(i18n("Mirror View"), this);
m_mirrorCanvas->setChecked(false);
m_mirrorCanvas->setIcon(KisIconUtils::loadIcon("mirror-view"));
collection->addAction("mirror_canvas", m_mirrorCanvas);
collection->setDefaultShortcut(m_mirrorCanvas, QKeySequence(Qt::Key_M));
updateAction();
}
void KisMirrorManager::setView(QPointer imageView)
{
if (m_imageView) {
m_mirrorCanvas->disconnect();
m_imageView->document()->disconnect();
}
m_imageView = imageView;
if (m_imageView) {
connect(m_mirrorCanvas, SIGNAL(toggled(bool)), dynamic_cast(m_imageView->canvasController()), SLOT(mirrorCanvas(bool)));
connect(m_imageView->document(), SIGNAL(sigMirrorAxisConfigChanged()), this, SLOT(slotDocumentConfigChanged()), Qt::UniqueConnection);
if (!hasDecoration()) {
d->mirrorAxisDecoration = new KisMirrorAxis(m_imageView->viewManager()->resourceProvider(), m_imageView);
connect(d->mirrorAxisDecoration, SIGNAL(sigConfigChanged()), this, SLOT(slotMirrorAxisConfigChanged()), Qt::UniqueConnection);
m_imageView->canvasBase()->addDecoration(d->mirrorAxisDecoration);
}
- d->mirrorAxisDecoration->setMirrorAxisConfig(mirrorAxisConfig());
+ setDecorationConfig();
}
+
updateAction();
}
void KisMirrorManager::updateAction()
{
if (m_imageView) {
m_mirrorCanvas->setEnabled(true);
m_mirrorCanvas->setChecked(m_imageView->canvasIsMirrored());
}
else {
m_mirrorCanvas->setEnabled(false);
m_mirrorCanvas->setChecked(false);
}
}
void KisMirrorManager::slotDocumentConfigChanged()
{
- d->mirrorAxisDecoration->setMirrorAxisConfig(mirrorAxisConfig());
+ setDecorationConfig();
}
void KisMirrorManager::slotMirrorAxisConfigChanged()
{
- if (m_imageView) {
+ if (m_imageView && m_imageView->document()) {
KisSignalsBlocker blocker(m_imageView->document());
m_imageView->document()->setMirrorAxisConfig(d->mirrorAxisDecoration->mirrorAxisConfig());
}
}
KisMirrorAxis* KisMirrorManager::hasDecoration() {
if (m_imageView && m_imageView->canvasBase() && m_imageView->canvasBase()->decoration("mirror_axis")) {
return dynamic_cast(m_imageView->canvasBase()->decoration("mirror_axis").data());
}
return 0;
}
-const KisMirrorAxisConfig& KisMirrorManager::mirrorAxisConfig() const
+void KisMirrorManager::setDecorationConfig()
{
- return m_imageView->document()->mirrorAxisConfig();
+ if (m_imageView && m_imageView->document()) {
+ KisMirrorAxisConfig config = m_imageView->document()->mirrorAxisConfig();
+ d->mirrorAxisDecoration->setMirrorAxisConfig(config);
+ }
}
diff --git a/libs/ui/kis_mirror_manager.h b/libs/ui/kis_mirror_manager.h
index 080d8cc5db..106a3fcf83 100644
--- a/libs/ui/kis_mirror_manager.h
+++ b/libs/ui/kis_mirror_manager.h
@@ -1,61 +1,61 @@
/*
* Copyright (c) 2009 Cyrille Berger
* Copyright (c) 2014 Sven Langkamp
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef KIS_MIRROR_MANAGER_H
#define KIS_MIRROR_MANAGER_H
#include
#include
#include
#include "KisView.h"
class KisViewManager;
class KActionCollection;
class KisMirrorAxis;
class KisMirrorAxisConfig;
class KisMirrorManager : public QObject
{
Q_OBJECT
public:
KisMirrorManager(KisViewManager* view);
~KisMirrorManager() override;
void setup(KActionCollection* collection);
void setView(QPointer imageView);
private Q_SLOTS:
void updateAction();
void slotDocumentConfigChanged();
void slotMirrorAxisConfigChanged();
private:
class Private;
const QScopedPointer d;
QPointer m_imageView;
QAction *m_mirrorCanvas;
KisMirrorAxis* hasDecoration();
- const KisMirrorAxisConfig &mirrorAxisConfig() const;
+ void setDecorationConfig();
};
#endif // KIS__MANAGER_H
diff --git a/libs/ui/tests/CMakeLists.txt b/libs/ui/tests/CMakeLists.txt
index 8e8e3da1a8..1425391285 100644
--- a/libs/ui/tests/CMakeLists.txt
+++ b/libs/ui/tests/CMakeLists.txt
@@ -1,184 +1,177 @@
set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} )
include_directories(${CMAKE_SOURCE_DIR}/libs/image/metadata
${CMAKE_SOURCE_DIR}/sdk/tests )
include(ECMAddTests)
macro_add_unittest_definitions()
ecm_add_tests(
kis_image_view_converter_test.cpp
kis_shape_selection_test.cpp
kis_doc2_test.cpp
kis_coordinates_converter_test.cpp
kis_grid_config_test.cpp
kis_stabilized_events_sampler_test.cpp
kis_derived_resources_test.cpp
kis_brush_hud_properties_config_test.cpp
kis_shape_commands_test.cpp
kis_shape_layer_test.cpp
kis_stop_gradient_editor_test.cpp
kis_file_layer_test.cpp
kis_multinode_property_test.cpp
KisFrameSerializerTest.cpp
KisFrameCacheStoreTest.cpp
kis_animation_exporter_test.cpp
kis_prescaled_projection_test.cpp
kis_asl_layer_style_serializer_test.cpp
kis_animation_importer_test.cpp
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-"
)
ecm_add_test( kis_selection_decoration_test.cpp ../../../sdk/tests/stroke_testing_utils.cpp
TEST_NAME KisSelectionDecorationTest
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
ecm_add_test( kis_node_dummies_graph_test.cpp ../../../sdk/tests/testutil.cpp
TEST_NAME KisNodeDummiesGraphTest
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
ecm_add_test( kis_node_shapes_graph_test.cpp ../../../sdk/tests/testutil.cpp
TEST_NAME KisNodeShapesGraphTest
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
ecm_add_test( kis_model_index_converter_test.cpp ../../../sdk/tests/testutil.cpp
TEST_NAME KisModelIndexConverterTest
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
ecm_add_test( kis_categorized_list_model_test.cpp modeltest.cpp
TEST_NAME KisCategorizedListModelTest
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
ecm_add_test( kis_node_juggler_compressed_test.cpp ../../../sdk/tests/testutil.cpp
TEST_NAME KisNodeJugglerCompressedTest
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
-set(kis_node_view_test_SRCS kis_node_view_test.cpp ../../../sdk/tests/testutil.cpp)
-qt5_add_resources(kis_node_view_test_SRCS ${krita_QRCS})
-ecm_add_test(${kis_node_view_test_SRCS}
- TEST_NAME kis_node_view_test
- LINK_LIBRARIES kritaui Qt5::Test
- NAME_PREFIX "libs-ui-")
-
ecm_add_test(
kis_input_manager_test.cpp ../../../sdk/tests/testutil.cpp
TEST_NAME KisInputManagerTest
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
ecm_add_test(
kis_node_model_test.cpp modeltest.cpp
TEST_NAME kis_node_model_test
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
##### Tests that currently fail and should be fixed #####
include(KritaAddBrokenUnitTest)
krita_add_broken_unit_test(
kis_shape_controller_test.cpp kis_dummies_facade_base_test.cpp
TEST_NAME kis_shape_controller_test
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
krita_add_broken_unit_test(
kis_exiv2_test.cpp
TEST_NAME KisExiv2Test
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
krita_add_broken_unit_test(
kis_clipboard_test.cpp
TEST_NAME KisClipboardTest
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
krita_add_broken_unit_test(
freehand_stroke_test.cpp ${CMAKE_SOURCE_DIR}/sdk/tests/stroke_testing_utils.cpp
TEST_NAME FreehandStrokeTest
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
krita_add_broken_unit_test(
FreehandStrokeBenchmark.cpp ${CMAKE_SOURCE_DIR}/sdk/tests/stroke_testing_utils.cpp
TEST_NAME FreehandStrokeBenchmark
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
krita_add_broken_unit_test(
KisPaintOnTransparencyMaskTest.cpp ${CMAKE_SOURCE_DIR}/sdk/tests/stroke_testing_utils.cpp
TEST_NAME KisPaintOnTransparencyMaskTest
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
ecm_add_test(
fill_processing_visitor_test.cpp ${CMAKE_SOURCE_DIR}/sdk/tests/stroke_testing_utils.cpp
TEST_NAME
FillProcessingVisitorTest
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
krita_add_broken_unit_test(
filter_stroke_test.cpp ../../../sdk/tests/stroke_testing_utils.cpp
TEST_NAME FilterStrokeTest
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
krita_add_broken_unit_test(
kis_selection_manager_test.cpp
TEST_NAME KisSelectionManagerTest
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
#set_tests_properties(libs-ui-KisSelectionManagerTest PROPERTIES TIMEOUT 300)
krita_add_broken_unit_test(
kis_node_manager_test.cpp
TEST_NAME KisNodeManagerTest
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
krita_add_broken_unit_test(
kis_dummies_facade_test.cpp kis_dummies_facade_base_test.cpp ../../../sdk/tests/testutil.cpp
TEST_NAME KisDummiesFacadeTest
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
krita_add_broken_unit_test(
kis_zoom_and_pan_test.cpp ../../../sdk/tests/testutil.cpp
TEST_NAME KisZoomAndPanTest
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
#set_tests_properties(libs-ui-KisZoomAndPanTest PROPERTIES TIMEOUT 300)
krita_add_broken_unit_test(
kis_action_manager_test.cpp
TEST_NAME KisActionManagerTest
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
krita_add_broken_unit_test(
kis_categories_mapper_test.cpp testing_categories_mapper.cpp
TEST_NAME KisCategoriesMapperTest
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
krita_add_broken_unit_test(
kis_animation_frame_cache_test.cpp
TEST_NAME kis_animation_frame_cache_test
LINK_LIBRARIES kritaui Qt5::Test
NAME_PREFIX "libs-ui-")
diff --git a/libs/widgets/kis_file_name_requester.cpp b/libs/widgets/kis_file_name_requester.cpp
index e54080cbde..daea1c14db 100644
--- a/libs/widgets/kis_file_name_requester.cpp
+++ b/libs/widgets/kis_file_name_requester.cpp
@@ -1,108 +1,110 @@
/*
* Copyright (c) 2015 Dmitry Kazakov
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "kis_file_name_requester.h"
#include "ui_wdg_file_name_requester.h"
#include
#include
#include "KoIcon.h"
+#include
KisFileNameRequester::KisFileNameRequester(QWidget *parent)
: QWidget(parent)
, m_ui(new Ui::WdgFileNameRequester)
, m_mode(KoFileDialog::OpenFile)
, m_name("OpenDocument")
{
m_ui->setupUi(this);
m_ui->btnSelectFile->setIcon(kisIcon("folder"));
connect(m_ui->btnSelectFile, SIGNAL(clicked()), SLOT(slotSelectFile()));
connect(m_ui->txtFileName, SIGNAL(textChanged(QString)), SIGNAL(textChanged(QString)));
}
KisFileNameRequester::~KisFileNameRequester()
{
}
void KisFileNameRequester::setStartDir(const QString &path)
{
m_basePath = path;
}
void KisFileNameRequester::setConfigurationName(const QString &name)
{
m_name = name;
}
void KisFileNameRequester::setFileName(const QString &path)
{
m_ui->txtFileName->setText(path);
- m_basePath = path;
emit fileSelected(path);
}
QString KisFileNameRequester::fileName() const
{
return m_ui->txtFileName->text();
}
void KisFileNameRequester::setMode(KoFileDialog::DialogType mode)
{
m_mode = mode;
}
KoFileDialog::DialogType KisFileNameRequester::mode() const
{
return m_mode;
}
void KisFileNameRequester::setMimeTypeFilters(const QStringList &filterList, QString defaultFilter)
{
m_mime_filter_list = filterList;
m_mime_default_filter = defaultFilter;
}
void KisFileNameRequester::slotSelectFile()
{
KoFileDialog dialog(this, m_mode, m_name);
if (m_mode == KoFileDialog::OpenFile)
{
dialog.setCaption(i18n("Select a file to load..."));
}
else if (m_mode == KoFileDialog::OpenDirectory)
{
dialog.setCaption(i18n("Select a directory to load..."));
}
- if (m_basePath.isEmpty()) {
- dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation));
- }
- else {
- dialog.setDefaultDir(m_basePath);
- }
+ const QString basePath =
+ KritaUtils::resolveAbsoluteFilePath(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation),
+ m_basePath);
+
+ const QString filePath =
+ KritaUtils::resolveAbsoluteFilePath(basePath, m_ui->txtFileName->text());
+
+ dialog.setDefaultDir(filePath, true);
dialog.setMimeTypeFilters(m_mime_filter_list, m_mime_default_filter);
QString newFileName = dialog.filename();
if (!newFileName.isEmpty()) {
setFileName(newFileName);
}
}
diff --git a/plugins/dockers/CMakeLists.txt b/plugins/dockers/CMakeLists.txt
index f759f74c28..6952b67468 100644
--- a/plugins/dockers/CMakeLists.txt
+++ b/plugins/dockers/CMakeLists.txt
@@ -1,35 +1,35 @@
-add_subdirectory(defaultdockers)
+add_subdirectory(layerdocker)
if(HAVE_OPENEXR)
add_subdirectory(smallcolorselector)
endif()
add_subdirectory(specificcolorselector)
add_subdirectory(digitalmixer)
add_subdirectory(advancedcolorselector)
add_subdirectory(presetdocker)
add_subdirectory(historydocker)
add_subdirectory(channeldocker)
add_subdirectory(artisticcolorselector)
add_subdirectory(tasksetdocker)
add_subdirectory(compositiondocker)
add_subdirectory(patterndocker)
add_subdirectory(griddocker)
add_subdirectory(arrangedocker)
if(HAVE_OCIO)
add_subdirectory(lut)
endif()
add_subdirectory(overview)
add_subdirectory(palettedocker)
add_subdirectory(animation)
add_subdirectory(presethistory)
add_subdirectory(svgcollectiondocker)
add_subdirectory(histogram)
add_subdirectory(gamutmask)
if(NOT APPLE AND HAVE_QT_QUICK)
add_subdirectory(touchdocker)
option(ENABLE_CPU_THROTTLE "Build the CPU Throttle Docker" OFF)
if (ENABLE_CPU_THROTTLE)
add_subdirectory(throttle)
endif()
endif()
add_subdirectory(logdocker)
diff --git a/plugins/dockers/defaultdockers/CMakeLists.txt b/plugins/dockers/defaultdockers/CMakeLists.txt
deleted file mode 100644
index 70b6ef4366..0000000000
--- a/plugins/dockers/defaultdockers/CMakeLists.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-add_subdirectory( tests )
-
-set(kritadefaultdockers_SOURCES
- kis_layer_box.cpp
- defaultdockers.cpp
- sync_button_and_action.cpp
-)
-
-set(kritadefaultdockers_PART_HEADERS
- kis_layer_box.h
- defaultdockers.h
-)
-
-ki18n_wrap_ui(kritadefaultdockers_SOURCES
- wdglayerbox.ui
-)
-
-add_library(kritadefaultdockers MODULE ${kritadefaultdockers_SOURCES} ${kritadefaultdockers_PART_HEADERS})
-generate_export_header(kritadefaultdockers BASE_NAME kritadefaultdockers EXPORT_MACRO_NAME KRITADEFAULTDOCKERS_EXPORT)
-target_link_libraries(kritadefaultdockers kritaui)
-install(TARGETS kritadefaultdockers DESTINATION ${KRITA_PLUGIN_INSTALL_DIR})
diff --git a/plugins/dockers/defaultdockers/sync_button_and_action.cpp b/plugins/dockers/defaultdockers/sync_button_and_action.cpp
deleted file mode 100644
index 357335ff9a..0000000000
--- a/plugins/dockers/defaultdockers/sync_button_and_action.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (c) 2015 Dmitry Kazakov
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "sync_button_and_action.h"
-
-// just for the moc's sake...
diff --git a/plugins/dockers/defaultdockers/tests/CMakeLists.txt b/plugins/dockers/defaultdockers/tests/CMakeLists.txt
deleted file mode 100644
index 6a523aa4f2..0000000000
--- a/plugins/dockers/defaultdockers/tests/CMakeLists.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-include_directories( ${CMAKE_SOURCE_DIR}/sdk/tests ${CMAKE_CURRENT_BINARY_DIR}/..)
-
-macro_add_unittest_definitions()
-
diff --git a/plugins/dockers/layerdocker/CMakeLists.txt b/plugins/dockers/layerdocker/CMakeLists.txt
new file mode 100644
index 0000000000..f39fc35aeb
--- /dev/null
+++ b/plugins/dockers/layerdocker/CMakeLists.txt
@@ -0,0 +1,37 @@
+add_subdirectory(tests)
+
+set(kritalayerdocker_SOURCES
+ LayerBox.cpp
+ LayerDocker.cpp
+ NodeDelegate.cpp
+ NodeToolTip.cpp
+ NodeView.cpp
+ NodeViewVisibilityDelegate.cpp
+)
+
+
+set(kritalayerdocker_PART_HEADERS
+ LayerBox.h
+ LayerDocker.h
+ NodeDelegate.h
+ NodeToolTip.h
+ NodeView.h
+ NodeViewVisibilityDelegate.h
+)
+
+ki18n_wrap_ui(kritalayerdocker_SOURCES
+ WdgLayerBox.ui
+)
+
+QT5_WRAP_CPP(kritalayerdocker_HEADERS_MOC
+ NodePropertyAction_p.h
+ SyncButtonAndAction.h
+)
+
+add_library(kritalayerdocker MODULE ${kritalayerdocker_SOURCES}
+ ${kritalayerdocker_PART_HEADERS}
+ ${kritalayerdocker_HEADERS_MOC}
+)
+
+target_link_libraries(kritalayerdocker kritaui)
+install(TARGETS kritalayerdocker DESTINATION ${KRITA_PLUGIN_INSTALL_DIR})
diff --git a/plugins/dockers/defaultdockers/kis_layer_box.cpp b/plugins/dockers/layerdocker/LayerBox.cpp
similarity index 91%
rename from plugins/dockers/defaultdockers/kis_layer_box.cpp
rename to plugins/dockers/layerdocker/LayerBox.cpp
index bedb9c7f2f..e4c0c66c6e 100644
--- a/plugins/dockers/defaultdockers/kis_layer_box.cpp
+++ b/plugins/dockers/layerdocker/LayerBox.cpp
@@ -1,1082 +1,1081 @@
/*
- * kis_layer_box.cc - part of Krita aka Krayon aka KimageShop
+ * LayerBox.cc - part of Krita aka Krayon aka KimageShop
*
* Copyright (c) 2002 Patrick Julien
* Copyright (C) 2006 Gábor Lehel
* Copyright (C) 2007 Thomas Zander
* Copyright (C) 2007 Boudewijn Rempt
* Copyright (c) 2011 José Luis Vergara
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include "kis_layer_box.h"
-
+#include "LayerBox.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
+#include
#include
#include
#include
-#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
-#include "kis_action.h"
+#include
#include "kis_action_manager.h"
#include "widgets/kis_cmb_composite.h"
#include "widgets/kis_slider_spin_box.h"
#include "KisViewManager.h"
#include "kis_node_manager.h"
#include "kis_node_model.h"
#include "canvas/kis_canvas2.h"
#include "kis_dummies_facade_base.h"
#include "kis_shape_controller.h"
#include "kis_selection_mask.h"
#include "kis_config.h"
#include "KisView.h"
#include "krita_utils.h"
-#include "sync_button_and_action.h"
#include "kis_color_label_selector_widget.h"
#include "kis_signals_blocker.h"
#include "kis_color_filter_combo.h"
#include "kis_node_filter_proxy_model.h"
#include "kis_selection.h"
#include "kis_processing_applicator.h"
#include "commands/kis_set_global_selection_command.h"
#include "KisSelectionActionsAdapter.h"
#include "kis_layer_utils.h"
-#include "ui_wdglayerbox.h"
+#include "ui_WdgLayerBox.h"
+#include "NodeView.h"
+#include "SyncButtonAndAction.h"
-#include
-class KisLayerBoxStyle : public QProxyStyle
+class LayerBoxStyle : public QProxyStyle
{
public:
- KisLayerBoxStyle(QStyle *baseStyle = 0) : QProxyStyle(baseStyle) {}
+ LayerBoxStyle(QStyle *baseStyle = 0) : QProxyStyle(baseStyle) {}
void drawPrimitive(PrimitiveElement element, const QStyleOption *option,
QPainter *painter, const QWidget *widget) const
{
if (element == QStyle::PE_IndicatorItemViewItemDrop)
{
QColor color(widget->palette().color(QPalette::Highlight).lighter());
if (option->rect.height() == 0) {
QBrush brush(color);
QRect r(option->rect);
r.setTop(r.top() - 2);
r.setBottom(r.bottom() + 2);
painter->fillRect(r, brush);
} else {
color.setAlpha(200);
QBrush brush(color);
painter->fillRect(option->rect, brush);
}
}
else
{
QProxyStyle::drawPrimitive(element, option, painter, widget);
}
}
};
-inline void KisLayerBox::connectActionToButton(KisViewManager* viewManager, QAbstractButton *button, const QString &id)
+inline void LayerBox::connectActionToButton(KisViewManager* viewManager, QAbstractButton *button, const QString &id)
{
if (!viewManager || !button) return;
KisAction *action = viewManager->actionManager()->actionByName(id);
if (!action) return;
connect(button, SIGNAL(clicked()), action, SLOT(trigger()));
connect(action, SIGNAL(sigEnableSlaves(bool)), button, SLOT(setEnabled(bool)));
connect(viewManager->mainWindow(), SIGNAL(themeChanged()), this, SLOT(slotUpdateIcons()));
}
-inline void KisLayerBox::addActionToMenu(QMenu *menu, const QString &id)
+inline void LayerBox::addActionToMenu(QMenu *menu, const QString &id)
{
if (m_canvas) {
menu->addAction(m_canvas->viewManager()->actionManager()->actionByName(id));
}
}
-KisLayerBox::KisLayerBox()
+LayerBox::LayerBox()
: QDockWidget(i18n("Layers"))
, m_canvas(0)
, m_wdgLayerBox(new Ui_WdgLayerBox)
, m_thumbnailCompressor(500, KisSignalCompressor::FIRST_INACTIVE)
, m_colorLabelCompressor(900, KisSignalCompressor::FIRST_INACTIVE)
, m_thumbnailSizeCompressor(100, KisSignalCompressor::FIRST_INACTIVE)
{
KisConfig cfg(false);
QWidget* mainWidget = new QWidget(this);
setWidget(mainWidget);
m_opacityDelayTimer.setSingleShot(true);
m_wdgLayerBox->setupUi(mainWidget);
- m_wdgLayerBox->listLayers->setStyle(new KisLayerBoxStyle(m_wdgLayerBox->listLayers->style()));
+ m_wdgLayerBox->listLayers->setStyle(new LayerBoxStyle(m_wdgLayerBox->listLayers->style()));
connect(m_wdgLayerBox->listLayers,
SIGNAL(contextMenuRequested(QPoint,QModelIndex)),
this, SLOT(slotContextMenuRequested(QPoint,QModelIndex)));
connect(m_wdgLayerBox->listLayers,
SIGNAL(collapsed(QModelIndex)), SLOT(slotCollapsed(QModelIndex)));
connect(m_wdgLayerBox->listLayers,
SIGNAL(expanded(QModelIndex)), SLOT(slotExpanded(QModelIndex)));
connect(m_wdgLayerBox->listLayers,
SIGNAL(selectionChanged(QModelIndexList)), SLOT(selectionChanged(QModelIndexList)));
slotUpdateIcons();
m_wdgLayerBox->bnDelete->setIconSize(QSize(22, 22));
m_wdgLayerBox->bnRaise->setIconSize(QSize(22, 22));
m_wdgLayerBox->bnLower->setIconSize(QSize(22, 22));
m_wdgLayerBox->bnProperties->setIconSize(QSize(22, 22));
m_wdgLayerBox->bnDuplicate->setIconSize(QSize(22, 22));
m_wdgLayerBox->bnLower->setEnabled(false);
m_wdgLayerBox->bnRaise->setEnabled(false);
if (cfg.sliderLabels()) {
m_wdgLayerBox->opacityLabel->hide();
m_wdgLayerBox->doubleOpacity->setPrefix(QString("%1: ").arg(i18n("Opacity")));
}
m_wdgLayerBox->doubleOpacity->setRange(0, 100, 0);
m_wdgLayerBox->doubleOpacity->setSuffix("%");
connect(m_wdgLayerBox->doubleOpacity, SIGNAL(valueChanged(qreal)), SLOT(slotOpacitySliderMoved(qreal)));
connect(&m_opacityDelayTimer, SIGNAL(timeout()), SLOT(slotOpacityChanged()));
connect(m_wdgLayerBox->cmbComposite, SIGNAL(activated(int)), SLOT(slotCompositeOpChanged(int)));
m_newLayerMenu = new QMenu(this);
m_wdgLayerBox->bnAdd->setMenu(m_newLayerMenu);
m_wdgLayerBox->bnAdd->setPopupMode(QToolButton::MenuButtonPopup);
m_nodeModel = new KisNodeModel(this);
m_filteringModel = new KisNodeFilterProxyModel(this);
m_filteringModel->setNodeModel(m_nodeModel);
/**
* Connect model updateUI() to enable/disable controls.
* Note: nodeActivated() is connected separately in setImage(), because
* it needs particular order of calls: first the connection to the
* node manager should be called, then updateUI()
*/
connect(m_nodeModel, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(updateUI()));
connect(m_nodeModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(updateUI()));
connect(m_nodeModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), SLOT(updateUI()));
connect(m_nodeModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(updateUI()));
connect(m_nodeModel, SIGNAL(modelReset()), SLOT(slotModelReset()));
KisAction *showGlobalSelectionMask = new KisAction(i18n("&Show Global Selection Mask"), this);
showGlobalSelectionMask->setObjectName("show-global-selection-mask");
showGlobalSelectionMask->setActivationFlags(KisAction::ACTIVE_IMAGE);
showGlobalSelectionMask->setToolTip(i18nc("@info:tooltip", "Shows global selection as a usual selection mask in Layers docker"));
showGlobalSelectionMask->setCheckable(true);
connect(showGlobalSelectionMask, SIGNAL(triggered(bool)), SLOT(slotEditGlobalSelection(bool)));
m_actions.append(showGlobalSelectionMask);
showGlobalSelectionMask->setChecked(cfg.showGlobalSelection());
m_colorSelector = new KisColorLabelSelectorWidget(this);
connect(m_colorSelector, SIGNAL(currentIndexChanged(int)), SLOT(slotColorLabelChanged(int)));
m_colorSelectorAction = new QWidgetAction(this);
m_colorSelectorAction->setDefaultWidget(m_colorSelector);
connect(m_nodeModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
&m_colorLabelCompressor, SLOT(start()));
m_wdgLayerBox->listLayers->setModel(m_filteringModel);
// this connection should be done *after* the setModel() call to
// happen later than the internal selection model
connect(m_filteringModel.data(), &KisNodeFilterProxyModel::rowsAboutToBeRemoved,
- this, &KisLayerBox::slotAboutToRemoveRows);
+ this, &LayerBox::slotAboutToRemoveRows);
connect(m_wdgLayerBox->cmbFilter, SIGNAL(selectedColorsChanged()), SLOT(updateLayerFiltering()));
setEnabled(false);
connect(&m_thumbnailCompressor, SIGNAL(timeout()), SLOT(updateThumbnail()));
connect(&m_colorLabelCompressor, SIGNAL(timeout()), SLOT(updateAvailableLabels()));
// set up the configure menu for changing thumbnail size
QMenu* configureMenu = new QMenu(this);
configureMenu->setStyleSheet("margin: 6px");
configureMenu->addSection(i18n("Thumbnail Size"));
m_wdgLayerBox->configureLayerDockerToolbar->setMenu(configureMenu);
m_wdgLayerBox->configureLayerDockerToolbar->setIcon(KisIconUtils::loadIcon("configure"));
m_wdgLayerBox->configureLayerDockerToolbar->setPopupMode(QToolButton::InstantPopup);
// add horizontal slider
thumbnailSizeSlider = new QSlider(this);
thumbnailSizeSlider->setOrientation(Qt::Horizontal);
thumbnailSizeSlider->setRange(20, 80);
thumbnailSizeSlider->setValue(cfg.layerThumbnailSize(false)); // grab this from the kritarc
thumbnailSizeSlider->setMinimumHeight(20);
thumbnailSizeSlider->setMinimumWidth(40);
thumbnailSizeSlider->setTickInterval(5);
QWidgetAction *sliderAction= new QWidgetAction(this);
sliderAction->setDefaultWidget(thumbnailSizeSlider);
configureMenu->addAction(sliderAction);
connect(thumbnailSizeSlider, SIGNAL(sliderMoved(int)), &m_thumbnailSizeCompressor, SLOT(start()));
connect(&m_thumbnailSizeCompressor, SIGNAL(timeout()), SLOT(slotUpdateThumbnailIconSize()));
}
-KisLayerBox::~KisLayerBox()
+LayerBox::~LayerBox()
{
delete m_wdgLayerBox;
}
-void expandNodesRecursively(KisNodeSP root, QPointer filteringModel, KisNodeView *nodeView)
+void expandNodesRecursively(KisNodeSP root, QPointer filteringModel, NodeView *nodeView)
{
if (!root) return;
if (filteringModel.isNull()) return;
if (!nodeView) return;
nodeView->blockSignals(true);
KisNodeSP node = root->firstChild();
while (node) {
QModelIndex idx = filteringModel->indexFromNode(node);
if (idx.isValid()) {
nodeView->setExpanded(idx, !node->collapsed());
}
if (!node->collapsed() && node->childCount() > 0) {
expandNodesRecursively(node, filteringModel, nodeView);
}
node = node->nextSibling();
}
nodeView->blockSignals(false);
}
-void KisLayerBox::slotAddLayerBnClicked()
+void LayerBox::slotAddLayerBnClicked()
{
if (m_canvas) {
KisNodeList nodes = m_nodeManager->selectedNodes();
if (nodes.size() == 1) {
KisAction *action = m_canvas->viewManager()->actionManager()->actionByName("add_new_paint_layer");
action->trigger();
} else {
KisAction *action = m_canvas->viewManager()->actionManager()->actionByName("create_quick_group");
action->trigger();
}
}
}
-void KisLayerBox::setViewManager(KisViewManager* kisview)
+void LayerBox::setViewManager(KisViewManager* kisview)
{
m_nodeManager = kisview->nodeManager();
Q_FOREACH (KisAction *action, m_actions) {
kisview->actionManager()->
addAction(action->objectName(),
action);
}
connect(m_wdgLayerBox->bnAdd, SIGNAL(clicked()), this, SLOT(slotAddLayerBnClicked()));
connectActionToButton(kisview, m_wdgLayerBox->bnDuplicate, "duplicatelayer");
KisActionManager *actionManager = kisview->actionManager();
KisAction *action = actionManager->createAction("RenameCurrentLayer");
Q_ASSERT(action);
connect(action, SIGNAL(triggered()), this, SLOT(slotRenameCurrentNode()));
m_propertiesAction = actionManager->createAction("layer_properties");
Q_ASSERT(m_propertiesAction);
new SyncButtonAndAction(m_propertiesAction, m_wdgLayerBox->bnProperties, this);
connect(m_propertiesAction, SIGNAL(triggered()), this, SLOT(slotPropertiesClicked()));
m_removeAction = actionManager->createAction("remove_layer");
Q_ASSERT(m_removeAction);
new SyncButtonAndAction(m_removeAction, m_wdgLayerBox->bnDelete, this);
connect(m_removeAction, SIGNAL(triggered()), this, SLOT(slotRmClicked()));
action = actionManager->createAction("move_layer_up");
Q_ASSERT(action);
new SyncButtonAndAction(action, m_wdgLayerBox->bnRaise, this);
connect(action, SIGNAL(triggered()), this, SLOT(slotRaiseClicked()));
action = actionManager->createAction("move_layer_down");
Q_ASSERT(action);
new SyncButtonAndAction(action, m_wdgLayerBox->bnLower, this);
connect(action, SIGNAL(triggered()), this, SLOT(slotLowerClicked()));
}
-void KisLayerBox::setCanvas(KoCanvasBase *canvas)
+void LayerBox::setCanvas(KoCanvasBase *canvas)
{
if (m_canvas == canvas)
return;
setEnabled(canvas != 0);
if (m_canvas) {
m_canvas->disconnectCanvasObserver(this);
m_nodeModel->setDummiesFacade(0, 0, 0, 0, 0, 0, 0);
m_selectionActionsAdapter.reset();
if (m_image) {
KisImageAnimationInterface *animation = m_image->animationInterface();
animation->disconnect(this);
}
disconnect(m_image, 0, this, 0);
disconnect(m_nodeManager, 0, this, 0);
disconnect(m_nodeModel, 0, m_nodeManager, 0);
m_nodeManager->slotSetSelectedNodes(KisNodeList());
}
m_canvas = dynamic_cast(canvas);
if (m_canvas) {
m_image = m_canvas->image();
connect(m_image, SIGNAL(sigImageUpdated(QRect)), &m_thumbnailCompressor, SLOT(start()));
KisDocument* doc = static_cast(m_canvas->imageView()->document());
KisShapeController *kritaShapeController =
dynamic_cast(doc->shapeController());
KisDummiesFacadeBase *kritaDummiesFacade =
static_cast(kritaShapeController);
m_selectionActionsAdapter.reset(new KisSelectionActionsAdapter(m_canvas->viewManager()->selectionManager()));
m_nodeModel->setDummiesFacade(kritaDummiesFacade,
m_image,
kritaShapeController,
m_nodeManager->nodeSelectionAdapter(),
m_nodeManager->nodeInsertionAdapter(),
m_selectionActionsAdapter.data(),
m_nodeManager->nodeDisplayModeAdapter());
connect(m_image, SIGNAL(sigAboutToBeDeleted()), SLOT(notifyImageDeleted()));
connect(m_image, SIGNAL(sigNodeCollapsedChanged()), SLOT(slotNodeCollapsedChanged()));
// cold start
if (m_nodeManager) {
setCurrentNode(m_nodeManager->activeNode());
- // Connection KisNodeManager -> KisLayerBox
+ // Connection KisNodeManager -> LayerBox
connect(m_nodeManager, SIGNAL(sigUiNeedChangeActiveNode(KisNodeSP)),
this, SLOT(setCurrentNode(KisNodeSP)));
connect(m_nodeManager,
SIGNAL(sigUiNeedChangeSelectedNodes(QList)),
SLOT(slotNodeManagerChangedSelection(QList)));
}
else {
setCurrentNode(m_canvas->imageView()->currentNode());
}
- // Connection KisLayerBox -> KisNodeManager (isolate layer)
+ // Connection LayerBox -> KisNodeManager (isolate layer)
connect(m_nodeModel, SIGNAL(toggleIsolateActiveNode()),
m_nodeManager, SLOT(toggleIsolateActiveNode()));
KisImageAnimationInterface *animation = m_image->animationInterface();
- connect(animation, &KisImageAnimationInterface::sigUiTimeChanged, this, &KisLayerBox::slotImageTimeChanged);
+ connect(animation, &KisImageAnimationInterface::sigUiTimeChanged, this, &LayerBox::slotImageTimeChanged);
expandNodesRecursively(m_image->rootLayer(), m_filteringModel, m_wdgLayerBox->listLayers);
m_wdgLayerBox->listLayers->scrollTo(m_wdgLayerBox->listLayers->currentIndex());
updateAvailableLabels();
addActionToMenu(m_newLayerMenu, "add_new_paint_layer");
addActionToMenu(m_newLayerMenu, "add_new_group_layer");
addActionToMenu(m_newLayerMenu, "add_new_clone_layer");
addActionToMenu(m_newLayerMenu, "add_new_shape_layer");
addActionToMenu(m_newLayerMenu, "add_new_adjustment_layer");
addActionToMenu(m_newLayerMenu, "add_new_fill_layer");
addActionToMenu(m_newLayerMenu, "add_new_file_layer");
m_newLayerMenu->addSeparator();
addActionToMenu(m_newLayerMenu, "add_new_transparency_mask");
addActionToMenu(m_newLayerMenu, "add_new_filter_mask");
addActionToMenu(m_newLayerMenu, "add_new_colorize_mask");
addActionToMenu(m_newLayerMenu, "add_new_transform_mask");
addActionToMenu(m_newLayerMenu, "add_new_selection_mask");
}
}
-void KisLayerBox::unsetCanvas()
+void LayerBox::unsetCanvas()
{
setEnabled(false);
if (m_canvas) {
m_newLayerMenu->clear();
}
m_filteringModel->unsetDummiesFacade();
disconnect(m_image, 0, this, 0);
disconnect(m_nodeManager, 0, this, 0);
disconnect(m_nodeModel, 0, m_nodeManager, 0);
m_nodeManager->slotSetSelectedNodes(KisNodeList());
m_canvas = 0;
}
-void KisLayerBox::notifyImageDeleted()
+void LayerBox::notifyImageDeleted()
{
setCanvas(0);
}
-void KisLayerBox::updateUI()
+void LayerBox::updateUI()
{
if (!m_canvas) return;
if (!m_nodeManager) return;
KisNodeSP activeNode = m_nodeManager->activeNode();
if (activeNode != m_activeNode) {
if( !m_activeNode.isNull() )
m_activeNode->disconnect(this);
m_activeNode = activeNode;
if (activeNode) {
KisKeyframeChannel *opacityChannel = activeNode->getKeyframeChannel(KisKeyframeChannel::Opacity.id(), false);
if (opacityChannel) {
watchOpacityChannel(opacityChannel);
} else {
watchOpacityChannel(0);
- connect(activeNode.data(), &KisNode::keyframeChannelAdded, this, &KisLayerBox::slotKeyframeChannelAdded);
+ connect(activeNode.data(), &KisNode::keyframeChannelAdded, this, &LayerBox::slotKeyframeChannelAdded);
}
}
}
m_wdgLayerBox->bnRaise->setEnabled(activeNode && activeNode->isEditable(false) && (activeNode->nextSibling()
|| (activeNode->parent() && activeNode->parent() != m_image->root())));
m_wdgLayerBox->bnLower->setEnabled(activeNode && activeNode->isEditable(false) && (activeNode->prevSibling()
|| (activeNode->parent() && activeNode->parent() != m_image->root())));
m_wdgLayerBox->doubleOpacity->setEnabled(activeNode && activeNode->isEditable(false));
m_wdgLayerBox->cmbComposite->setEnabled(activeNode && activeNode->isEditable(false));
m_wdgLayerBox->cmbComposite->validate(m_image->colorSpace());
if (activeNode) {
if (activeNode->inherits("KisColorizeMask") ||
activeNode->inherits("KisLayer")) {
m_wdgLayerBox->doubleOpacity->setEnabled(true);
slotSetOpacity(activeNode->opacity() * 100.0 / 255);
const KoCompositeOp* compositeOp = activeNode->compositeOp();
if (compositeOp) {
slotSetCompositeOp(compositeOp);
} else {
m_wdgLayerBox->cmbComposite->setEnabled(false);
}
const KisGroupLayer *group = qobject_cast(activeNode.data());
bool compositeSelectionActive = !(group && group->passThroughMode());
m_wdgLayerBox->cmbComposite->setEnabled(compositeSelectionActive);
} else if (activeNode->inherits("KisMask")) {
m_wdgLayerBox->cmbComposite->setEnabled(false);
m_wdgLayerBox->doubleOpacity->setEnabled(false);
}
}
}
/**
* This method is called *only* when non-GUI code requested the
* change of the current node
*/
-void KisLayerBox::setCurrentNode(KisNodeSP node)
+void LayerBox::setCurrentNode(KisNodeSP node)
{
m_filteringModel->setActiveNode(node);
QModelIndex index = node ? m_filteringModel->indexFromNode(node) : QModelIndex();
m_filteringModel->setData(index, true, KisNodeModel::ActiveRole);
updateUI();
}
-void KisLayerBox::slotModelReset()
+void LayerBox::slotModelReset()
{
if(m_nodeModel->hasDummiesFacade()) {
QItemSelection selection;
Q_FOREACH (const KisNodeSP node, m_nodeManager->selectedNodes()) {
const QModelIndex &idx = m_filteringModel->indexFromNode(node);
if(idx.isValid()){
QItemSelectionRange selectionRange(idx);
selection << selectionRange;
}
}
m_wdgLayerBox->listLayers->selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect);
}
updateUI();
}
-void KisLayerBox::slotSetCompositeOp(const KoCompositeOp* compositeOp)
+void LayerBox::slotSetCompositeOp(const KoCompositeOp* compositeOp)
{
KoID opId = KoCompositeOpRegistry::instance().getKoID(compositeOp->id());
m_wdgLayerBox->cmbComposite->blockSignals(true);
m_wdgLayerBox->cmbComposite->selectCompositeOp(opId);
m_wdgLayerBox->cmbComposite->blockSignals(false);
}
// range: 0-100
-void KisLayerBox::slotSetOpacity(double opacity)
+void LayerBox::slotSetOpacity(double opacity)
{
Q_ASSERT(opacity >= 0 && opacity <= 100);
m_wdgLayerBox->doubleOpacity->blockSignals(true);
m_wdgLayerBox->doubleOpacity->setValue(opacity);
m_wdgLayerBox->doubleOpacity->blockSignals(false);
}
-void KisLayerBox::slotContextMenuRequested(const QPoint &pos, const QModelIndex &index)
+void LayerBox::slotContextMenuRequested(const QPoint &pos, const QModelIndex &index)
{
KisNodeList nodes = m_nodeManager->selectedNodes();
KisNodeSP activeNode = m_nodeManager->activeNode();
if (nodes.isEmpty() || !activeNode) return;
if (m_canvas) {
QMenu menu;
const bool singleLayer = nodes.size() == 1;
if (index.isValid()) {
menu.addAction(m_propertiesAction);
if (singleLayer) {
addActionToMenu(&menu, "layer_style");
}
{
KisSignalsBlocker b(m_colorSelector);
m_colorSelector->setCurrentIndex(singleLayer ? activeNode->colorLabelIndex() : -1);
}
menu.addAction(m_colorSelectorAction);
menu.addSeparator();
addActionToMenu(&menu, "cut_layer_clipboard");
addActionToMenu(&menu, "copy_layer_clipboard");
addActionToMenu(&menu, "paste_layer_from_clipboard");
menu.addAction(m_removeAction);
addActionToMenu(&menu, "duplicatelayer");
addActionToMenu(&menu, "merge_layer");
if (singleLayer) {
addActionToMenu(&menu, "flatten_image");
addActionToMenu(&menu, "flatten_layer");
}
menu.addSeparator();
QMenu *selectMenu = menu.addMenu(i18n("&Select"));
addActionToMenu(selectMenu, "select_all_layers");
addActionToMenu(selectMenu, "select_visible_layers");
addActionToMenu(selectMenu, "select_invisible_layers");
addActionToMenu(selectMenu, "select_locked_layers");
addActionToMenu(selectMenu, "select_unlocked_layers");
QMenu *groupMenu = menu.addMenu(i18n("&Group"));
addActionToMenu(groupMenu, "create_quick_group");
addActionToMenu(groupMenu, "create_quick_clipping_group");
addActionToMenu(groupMenu, "quick_ungroup");
QMenu *locksMenu = menu.addMenu(i18n("&Toggle Locks && Visibility"));
addActionToMenu(locksMenu, "toggle_layer_visibility");
addActionToMenu(locksMenu, "toggle_layer_lock");
addActionToMenu(locksMenu, "toggle_layer_inherit_alpha");
addActionToMenu(locksMenu, "toggle_layer_alpha_lock");
if (singleLayer) {
QMenu *addLayerMenu = menu.addMenu(i18n("&Add"));
addActionToMenu(addLayerMenu, "add_new_transparency_mask");
addActionToMenu(addLayerMenu, "add_new_filter_mask");
addActionToMenu(addLayerMenu, "add_new_colorize_mask");
addActionToMenu(addLayerMenu, "add_new_transform_mask");
addActionToMenu(addLayerMenu, "add_new_selection_mask");
QMenu *convertToMenu = menu.addMenu(i18n("&Convert"));
addActionToMenu(convertToMenu, "convert_to_paint_layer");
addActionToMenu(convertToMenu, "convert_to_transparency_mask");
addActionToMenu(convertToMenu, "convert_to_filter_mask");
addActionToMenu(convertToMenu, "convert_to_selection_mask");
addActionToMenu(convertToMenu, "convert_to_file_layer");
QMenu *splitAlphaMenu = menu.addMenu(i18n("S&plit Alpha"));
addActionToMenu(splitAlphaMenu, "split_alpha_into_mask");
addActionToMenu(splitAlphaMenu, "split_alpha_write");
addActionToMenu(splitAlphaMenu, "split_alpha_save_merged");
}
menu.addSeparator();
addActionToMenu(&menu, "show_in_timeline");
if (singleLayer) {
KisNodeSP node = m_filteringModel->nodeFromIndex(index);
if (node && !node->inherits("KisTransformMask")) {
addActionToMenu(&menu, "isolate_layer");
}
addActionToMenu(&menu, "selectopaque");
}
}
menu.exec(pos);
}
}
-void KisLayerBox::slotMinimalView()
+void LayerBox::slotMinimalView()
{
- m_wdgLayerBox->listLayers->setDisplayMode(KisNodeView::MinimalMode);
+ m_wdgLayerBox->listLayers->setDisplayMode(NodeView::MinimalMode);
}
-void KisLayerBox::slotDetailedView()
+void LayerBox::slotDetailedView()
{
- m_wdgLayerBox->listLayers->setDisplayMode(KisNodeView::DetailedMode);
+ m_wdgLayerBox->listLayers->setDisplayMode(NodeView::DetailedMode);
}
-void KisLayerBox::slotThumbnailView()
+void LayerBox::slotThumbnailView()
{
- m_wdgLayerBox->listLayers->setDisplayMode(KisNodeView::ThumbnailMode);
+ m_wdgLayerBox->listLayers->setDisplayMode(NodeView::ThumbnailMode);
}
-void KisLayerBox::slotRmClicked()
+void LayerBox::slotRmClicked()
{
if (!m_canvas) return;
m_nodeManager->removeNode();
}
-void KisLayerBox::slotRaiseClicked()
+void LayerBox::slotRaiseClicked()
{
if (!m_canvas) return;
m_nodeManager->raiseNode();
}
-void KisLayerBox::slotLowerClicked()
+void LayerBox::slotLowerClicked()
{
if (!m_canvas) return;
m_nodeManager->lowerNode();
}
-void KisLayerBox::slotPropertiesClicked()
+void LayerBox::slotPropertiesClicked()
{
if (!m_canvas) return;
if (KisNodeSP active = m_nodeManager->activeNode()) {
m_nodeManager->nodeProperties(active);
}
}
-void KisLayerBox::slotCompositeOpChanged(int index)
+void LayerBox::slotCompositeOpChanged(int index)
{
Q_UNUSED(index);
if (!m_canvas) return;
QString compositeOp = m_wdgLayerBox->cmbComposite->selectedCompositeOp().id();
m_nodeManager->nodeCompositeOpChanged(m_nodeManager->activeColorSpace()->compositeOp(compositeOp));
}
-void KisLayerBox::slotOpacityChanged()
+void LayerBox::slotOpacityChanged()
{
if (!m_canvas) return;
m_blockOpacityUpdate = true;
m_nodeManager->nodeOpacityChanged(m_newOpacity, true);
m_blockOpacityUpdate = false;
}
-void KisLayerBox::slotOpacitySliderMoved(qreal opacity)
+void LayerBox::slotOpacitySliderMoved(qreal opacity)
{
m_newOpacity = opacity;
m_opacityDelayTimer.start(200);
}
-void KisLayerBox::slotCollapsed(const QModelIndex &index)
+void LayerBox::slotCollapsed(const QModelIndex &index)
{
KisNodeSP node = m_filteringModel->nodeFromIndex(index);
if (node) {
node->setCollapsed(true);
}
}
-void KisLayerBox::slotExpanded(const QModelIndex &index)
+void LayerBox::slotExpanded(const QModelIndex &index)
{
KisNodeSP node = m_filteringModel->nodeFromIndex(index);
if (node) {
node->setCollapsed(false);
}
}
-void KisLayerBox::slotSelectOpaque()
+void LayerBox::slotSelectOpaque()
{
if (!m_canvas) return;
QAction *action = m_canvas->viewManager()->actionManager()->actionByName("selectopaque");
if (action) {
action->trigger();
}
}
-void KisLayerBox::slotNodeCollapsedChanged()
+void LayerBox::slotNodeCollapsedChanged()
{
expandNodesRecursively(m_image->rootLayer(), m_filteringModel, m_wdgLayerBox->listLayers);
}
inline bool isSelectionMask(KisNodeSP node)
{
return dynamic_cast(node.data());
}
-KisNodeSP KisLayerBox::findNonHidableNode(KisNodeSP startNode)
+KisNodeSP LayerBox::findNonHidableNode(KisNodeSP startNode)
{
if (KisNodeManager::isNodeHidden(startNode, true) &&
startNode->parent() &&
!startNode->parent()->parent()) {
KisNodeSP node = startNode->prevSibling();
while (node && KisNodeManager::isNodeHidden(node, true)) {
node = node->prevSibling();
}
if (!node) {
node = startNode->nextSibling();
while (node && KisNodeManager::isNodeHidden(node, true)) {
node = node->nextSibling();
}
}
if (!node) {
node = m_image->root()->lastChild();
while (node && KisNodeManager::isNodeHidden(node, true)) {
node = node->prevSibling();
}
}
KIS_ASSERT_RECOVER_NOOP(node && "cannot activate any node!");
startNode = node;
}
return startNode;
}
-void KisLayerBox::slotEditGlobalSelection(bool showSelections)
+void LayerBox::slotEditGlobalSelection(bool showSelections)
{
KisNodeSP lastActiveNode = m_nodeManager->activeNode();
KisNodeSP activateNode = lastActiveNode;
KisSelectionMaskSP globalSelectionMask;
if (!showSelections) {
activateNode = findNonHidableNode(activateNode);
}
m_nodeModel->setShowGlobalSelection(showSelections);
globalSelectionMask = m_image->rootLayer()->selectionMask();
// try to find deactivated, but visible masks
if (!globalSelectionMask) {
KoProperties properties;
properties.setProperty("visible", true);
QList masks = m_image->rootLayer()->childNodes(QStringList("KisSelectionMask"), properties);
if (!masks.isEmpty()) {
globalSelectionMask = dynamic_cast(masks.first().data());
}
}
// try to find at least any selection mask
if (!globalSelectionMask) {
KoProperties properties;
QList masks = m_image->rootLayer()->childNodes(QStringList("KisSelectionMask"), properties);
if (!masks.isEmpty()) {
globalSelectionMask = dynamic_cast(masks.first().data());
}
}
if (globalSelectionMask) {
if (showSelections) {
activateNode = globalSelectionMask;
}
}
if (activateNode != lastActiveNode) {
m_nodeManager->slotNonUiActivatedNode(activateNode);
} else if (lastActiveNode) {
setCurrentNode(lastActiveNode);
}
if (showSelections && !globalSelectionMask) {
KisProcessingApplicator applicator(m_image, 0,
KisProcessingApplicator::NONE,
KisImageSignalVector() << ModifiedSignal,
kundo2_i18n("Quick Selection Mask"));
applicator.applyCommand(
new KisLayerUtils::KeepNodesSelectedCommand(
m_nodeManager->selectedNodes(), KisNodeList(),
lastActiveNode, 0, m_image, false),
KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE);
applicator.applyCommand(new KisSetEmptyGlobalSelectionCommand(m_image),
KisStrokeJobData::SEQUENTIAL,
KisStrokeJobData::EXCLUSIVE);
applicator.applyCommand(new KisLayerUtils::SelectGlobalSelectionMask(m_image),
KisStrokeJobData::SEQUENTIAL,
KisStrokeJobData::EXCLUSIVE);
applicator.end();
} else if (!showSelections &&
globalSelectionMask &&
globalSelectionMask->selection()->selectedRect().isEmpty()) {
KisProcessingApplicator applicator(m_image, 0,
KisProcessingApplicator::NONE,
KisImageSignalVector() << ModifiedSignal,
kundo2_i18n("Cancel Quick Selection Mask"));
applicator.applyCommand(new KisSetGlobalSelectionCommand(m_image, 0), KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE);
applicator.end();
}
}
-void KisLayerBox::selectionChanged(const QModelIndexList selection)
+void LayerBox::selectionChanged(const QModelIndexList selection)
{
if (!m_nodeManager) return;
/**
* When the user clears the extended selection by clicking on the
* empty area of the docker, the selection should be reset on to
* the active layer, which might be even unselected(!).
*/
if (selection.isEmpty() && m_nodeManager->activeNode()) {
QModelIndex selectedIndex =
m_filteringModel->indexFromNode(m_nodeManager->activeNode());
m_wdgLayerBox->listLayers->selectionModel()->
setCurrentIndex(selectedIndex, QItemSelectionModel::ClearAndSelect);
return;
}
QList selectedNodes;
Q_FOREACH (const QModelIndex &idx, selection) {
selectedNodes << m_filteringModel->nodeFromIndex(idx);
}
m_nodeManager->slotSetSelectedNodes(selectedNodes);
updateUI();
}
-void KisLayerBox::slotAboutToRemoveRows(const QModelIndex &parent, int start, int end)
+void LayerBox::slotAboutToRemoveRows(const QModelIndex &parent, int start, int end)
{
/**
* Qt has changed its behavior when deleting an item. Previously
* the selection priority was on the next item in the list, and
* now it has shanged to the previous item. Here we just adjust
* the selected item after the node removal. Please take care that
* this method overrides what was done by the corresponding method
* of QItemSelectionModel, which *has already done* its work. That
* is why we use (start - 1) and (end + 1) in the activation
* condition.
*
* See bug: https://bugs.kde.org/show_bug.cgi?id=345601
*/
QModelIndex currentIndex = m_wdgLayerBox->listLayers->currentIndex();
QAbstractItemModel *model = m_filteringModel;
if (currentIndex.isValid() && parent == currentIndex.parent()
&& currentIndex.row() >= start - 1 && currentIndex.row() <= end + 1) {
QModelIndex old = currentIndex;
if (model && end < model->rowCount(parent) - 1) // there are rows left below the change
currentIndex = model->index(end + 1, old.column(), parent);
else if (start > 0) // there are rows left above the change
currentIndex = model->index(start - 1, old.column(), parent);
else // there are no rows left in the table
currentIndex = QModelIndex();
if (currentIndex.isValid() && currentIndex != old) {
m_wdgLayerBox->listLayers->setCurrentIndex(currentIndex);
}
}
}
-void KisLayerBox::slotNodeManagerChangedSelection(const KisNodeList &nodes)
+void LayerBox::slotNodeManagerChangedSelection(const KisNodeList &nodes)
{
if (!m_nodeManager) return;
QModelIndexList newSelection;
Q_FOREACH(KisNodeSP node, nodes) {
newSelection << m_filteringModel->indexFromNode(node);
}
QItemSelectionModel *model = m_wdgLayerBox->listLayers->selectionModel();
if (KritaUtils::compareListsUnordered(newSelection, model->selectedIndexes())) {
return;
}
QItemSelection selection;
Q_FOREACH(const QModelIndex &idx, newSelection) {
selection.select(idx, idx);
}
model->select(selection, QItemSelectionModel::ClearAndSelect);
}
-void KisLayerBox::updateThumbnail()
+void LayerBox::updateThumbnail()
{
m_wdgLayerBox->listLayers->updateNode(m_wdgLayerBox->listLayers->currentIndex());
}
-void KisLayerBox::slotRenameCurrentNode()
+void LayerBox::slotRenameCurrentNode()
{
m_wdgLayerBox->listLayers->edit(m_wdgLayerBox->listLayers->currentIndex());
}
-void KisLayerBox::slotColorLabelChanged(int label)
+void LayerBox::slotColorLabelChanged(int label)
{
KisNodeList nodes = m_nodeManager->selectedNodes();
Q_FOREACH(KisNodeSP node, nodes) {
auto applyLabelFunc =
[label](KisNodeSP node) {
node->setColorLabelIndex(label);
};
KisLayerUtils::recursiveApplyNodes(node, applyLabelFunc);
}
}
-void KisLayerBox::updateAvailableLabels()
+void LayerBox::updateAvailableLabels()
{
if (!m_image) return;
m_wdgLayerBox->cmbFilter->updateAvailableLabels(m_image->root());
}
-void KisLayerBox::updateLayerFiltering()
+void LayerBox::updateLayerFiltering()
{
m_filteringModel->setAcceptedLabels(m_wdgLayerBox->cmbFilter->selectedColors());
}
-void KisLayerBox::slotKeyframeChannelAdded(KisKeyframeChannel *channel)
+void LayerBox::slotKeyframeChannelAdded(KisKeyframeChannel *channel)
{
if (channel->id() == KisKeyframeChannel::Opacity.id()) {
watchOpacityChannel(channel);
}
}
-void KisLayerBox::watchOpacityChannel(KisKeyframeChannel *channel)
+void LayerBox::watchOpacityChannel(KisKeyframeChannel *channel)
{
if (m_opacityChannel) {
m_opacityChannel->disconnect(this);
}
m_opacityChannel = channel;
if (m_opacityChannel) {
connect(m_opacityChannel, SIGNAL(sigKeyframeAdded(KisKeyframeSP)), this, SLOT(slotOpacityKeyframeChanged(KisKeyframeSP)));
connect(m_opacityChannel, SIGNAL(sigKeyframeRemoved(KisKeyframeSP)), this, SLOT(slotOpacityKeyframeChanged(KisKeyframeSP)));
connect(m_opacityChannel, SIGNAL(sigKeyframeMoved(KisKeyframeSP)), this, SLOT(slotOpacityKeyframeMoved(KisKeyframeSP)));
connect(m_opacityChannel, SIGNAL(sigKeyframeChanged(KisKeyframeSP)), this, SLOT(slotOpacityKeyframeChanged(KisKeyframeSP)));
}
}
-void KisLayerBox::slotOpacityKeyframeChanged(KisKeyframeSP keyframe)
+void LayerBox::slotOpacityKeyframeChanged(KisKeyframeSP keyframe)
{
Q_UNUSED(keyframe);
if (m_blockOpacityUpdate) return;
updateUI();
}
-void KisLayerBox::slotOpacityKeyframeMoved(KisKeyframeSP keyframe, int fromTime)
+void LayerBox::slotOpacityKeyframeMoved(KisKeyframeSP keyframe, int fromTime)
{
Q_UNUSED(fromTime);
slotOpacityKeyframeChanged(keyframe);
}
-void KisLayerBox::slotImageTimeChanged(int time)
+void LayerBox::slotImageTimeChanged(int time)
{
Q_UNUSED(time);
updateUI();
}
-void KisLayerBox::slotUpdateIcons() {
+void LayerBox::slotUpdateIcons() {
m_wdgLayerBox->bnAdd->setIcon(KisIconUtils::loadIcon("addlayer"));
m_wdgLayerBox->bnRaise->setIcon(KisIconUtils::loadIcon("arrowupblr"));
m_wdgLayerBox->bnDelete->setIcon(KisIconUtils::loadIcon("deletelayer"));
m_wdgLayerBox->bnLower->setIcon(KisIconUtils::loadIcon("arrowdown"));
m_wdgLayerBox->bnProperties->setIcon(KisIconUtils::loadIcon("properties"));
m_wdgLayerBox->bnDuplicate->setIcon(KisIconUtils::loadIcon("duplicatelayer"));
// call child function about needing to update icons
m_wdgLayerBox->listLayers->slotUpdateIcons();
}
-void KisLayerBox::slotUpdateThumbnailIconSize()
+void LayerBox::slotUpdateThumbnailIconSize()
{
KisConfig cfg(false);
cfg.setLayerThumbnailSize(thumbnailSizeSlider->value());
// this is a hack to force the layers list to update its display and
// re-layout all the layers with the new thumbnail size
resize(this->width()+1, this->height()+1);
resize(this->width()-1, this->height()-1);
}
-#include "moc_kis_layer_box.cpp"
+#include "moc_LayerBox.cpp"
diff --git a/plugins/dockers/defaultdockers/kis_layer_box.h b/plugins/dockers/layerdocker/LayerBox.h
similarity index 92%
rename from plugins/dockers/defaultdockers/kis_layer_box.h
rename to plugins/dockers/layerdocker/LayerBox.h
index e392cf0933..6908f39c0a 100644
--- a/plugins/dockers/defaultdockers/kis_layer_box.h
+++ b/plugins/dockers/layerdocker/LayerBox.h
@@ -1,200 +1,200 @@
/*
- * kis_layer_box.h - part of Krita aka Krayon aka KimageShop
+ * LayerBox.h - part of Krita aka Krayon aka KimageShop
*
* Copyright (c) 2002 Patrick Julien
* Copyright (C) 2006 Gábor Lehel
* Copyright (C) 2007 Thomas Zander
* Copyright (C) 2007-2009 Boudewijn Rempt
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef KIS_LAYERBOX_H
#define KIS_LAYERBOX_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "kis_action.h"
#include "KisViewManager.h"
#include "kis_mainwindow_observer.h"
#include "kis_signal_compressor.h"
#include
class QModelIndex;
typedef QList QModelIndexList;
class QMenu;
class QAbstractButton;
class KoCompositeOp;
class KisCanvas2;
class KisNodeModel;
class KisNodeFilterProxyModel;
class Ui_WdgLayerBox;
class KisNodeJugglerCompressed;
class KisColorLabelSelectorWidget;
class QWidgetAction;
class KisKeyframeChannel;
class KisSelectionActionsAdapter;
/**
* A widget that shows a visualization of the layer structure.
*
* The center of the layer box is KisNodeModel, which shows the actual layers.
* This widget adds docking functionality and command buttons.
*
*/
-class KisLayerBox : public QDockWidget, public KisMainwindowObserver
+class LayerBox : public QDockWidget, public KisMainwindowObserver
{
Q_OBJECT
public:
- KisLayerBox();
- ~KisLayerBox() override;
- QString observerName() override { return "KisLayerBox"; }
+ LayerBox();
+ ~LayerBox() override;
+ QString observerName() override { return "LayerBox"; }
/// reimplemented from KisMainwindowObserver
void setViewManager(KisViewManager* kisview) override;
void setCanvas(KoCanvasBase *canvas) override;
void unsetCanvas() override;
private Q_SLOTS:
void notifyImageDeleted();
void slotContextMenuRequested(const QPoint &pos, const QModelIndex &index);
void slotMinimalView();
void slotDetailedView();
void slotThumbnailView();
// From the node manager to the layerbox
void slotSetCompositeOp(const KoCompositeOp* compositeOp);
void slotSetOpacity(double opacity);
void updateUI();
void setCurrentNode(KisNodeSP node);
void slotModelReset();
// from the layerbox to the node manager
void slotRmClicked();
void slotRaiseClicked();
void slotLowerClicked();
void slotPropertiesClicked();
void slotCompositeOpChanged(int index);
void slotOpacityChanged();
void slotOpacitySliderMoved(qreal opacity);
void slotCollapsed(const QModelIndex &index);
void slotExpanded(const QModelIndex &index);
void slotSelectOpaque();
void slotNodeCollapsedChanged();
void slotEditGlobalSelection(bool showSelections);
void slotRenameCurrentNode();
void slotAboutToRemoveRows(const QModelIndex &parent, int first, int last);
void selectionChanged(const QModelIndexList selection);
void slotNodeManagerChangedSelection(const QList &nodes);
void slotColorLabelChanged(int index);
void slotUpdateIcons();
void slotAddLayerBnClicked();
void updateThumbnail();
void updateAvailableLabels();
void updateLayerFiltering();
void slotUpdateThumbnailIconSize();
// Opacity keyframing
void slotKeyframeChannelAdded(KisKeyframeChannel *channel);
void slotOpacityKeyframeChanged(KisKeyframeSP keyframe);
void slotOpacityKeyframeMoved(KisKeyframeSP keyframe, int fromTime);
void slotImageTimeChanged(int time);
private:
inline void connectActionToButton(KisViewManager* view, QAbstractButton *button, const QString &id);
inline void addActionToMenu(QMenu *menu, const QString &id);
void watchOpacityChannel(KisKeyframeChannel *channel);
KisNodeSP findNonHidableNode(KisNodeSP startNode);
private:
QPointer m_canvas;
QScopedPointer m_selectionActionsAdapter;
QMenu *m_newLayerMenu;
KisImageWSP m_image;
QPointer m_nodeModel;
QPointer m_filteringModel;
QPointer m_nodeManager;
QPointer m_colorSelector;
QPointer m_colorSelectorAction;
Ui_WdgLayerBox* m_wdgLayerBox;
QTimer m_opacityDelayTimer;
int m_newOpacity;
QVector m_actions;
KisAction* m_removeAction;
KisAction* m_propertiesAction;
KisSignalCompressor m_thumbnailCompressor;
KisSignalCompressor m_colorLabelCompressor;
KisSignalCompressor m_thumbnailSizeCompressor;
QSlider* thumbnailSizeSlider;
KisNodeSP m_activeNode;
QPointer m_opacityChannel;
bool m_blockOpacityUpdate {false};
};
-class KisLayerBoxFactory : public KoDockFactoryBase
+class LayerBoxFactory : public KoDockFactoryBase
{
public:
- KisLayerBoxFactory() { }
+ LayerBoxFactory() { }
QString id() const override {
- return QString("KisLayerBox");
+ return QString("LayerBox");
}
QDockWidget* createDockWidget() override {
- KisLayerBox * dockWidget = new KisLayerBox();
+ LayerBox * dockWidget = new LayerBox();
dockWidget->setObjectName(id());
return dockWidget;
}
DockPosition defaultDockPosition() const override {
return DockRight;
}
};
#endif // KIS_LAYERBOX_H
diff --git a/plugins/dockers/defaultdockers/defaultdockers.cpp b/plugins/dockers/layerdocker/LayerDocker.cpp
similarity index 68%
rename from plugins/dockers/defaultdockers/defaultdockers.cpp
rename to plugins/dockers/layerdocker/LayerDocker.cpp
index 4d55a5eed1..cbef015e08 100644
--- a/plugins/dockers/defaultdockers/defaultdockers.cpp
+++ b/plugins/dockers/layerdocker/LayerDocker.cpp
@@ -1,41 +1,41 @@
/*
* Copyright (c) 2009 Boudewijn Rempt
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include "defaultdockers.h"
+#include "LayerDocker.h"
#include
#include
#include
#include "kis_debug.h"
-#include "kis_layer_box.h"
+#include "LayerBox.h"
-K_PLUGIN_FACTORY_WITH_JSON(KritaDefaultDockersPluginFactory, "kritadefaultdockers.json", registerPlugin();)
+K_PLUGIN_FACTORY_WITH_JSON(KritaLayerDockerPluginFactory, "kritalayerdocker.json", registerPlugin();)
-KritaDefaultDockersPlugin::KritaDefaultDockersPlugin(QObject *parent, const QVariantList &)
+KritaLayerDockerPlugin::KritaLayerDockerPlugin(QObject *parent, const QVariantList &)
: QObject(parent)
{
- KoDockRegistry::instance()->add(new KisLayerBoxFactory());
+ KoDockRegistry::instance()->add(new LayerBoxFactory());
}
-KritaDefaultDockersPlugin::~KritaDefaultDockersPlugin()
+KritaLayerDockerPlugin::~KritaLayerDockerPlugin()
{
}
-#include "defaultdockers.moc"
+#include "LayerDocker.moc"
diff --git a/plugins/dockers/defaultdockers/defaultdockers.h b/plugins/dockers/layerdocker/LayerDocker.h
similarity index 85%
rename from plugins/dockers/defaultdockers/defaultdockers.h
rename to plugins/dockers/layerdocker/LayerDocker.h
index 0949692cce..e7c0729930 100644
--- a/plugins/dockers/defaultdockers/defaultdockers.h
+++ b/plugins/dockers/layerdocker/LayerDocker.h
@@ -1,37 +1,37 @@
/*
* Copyright (c) 2009 Boudewijn Rempt
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _DEFAULT_DOCKERS_H
#define _DEFAULT_DOCKERS_H
#include
#include
/**
* Template of view plugin
*/
-class KritaDefaultDockersPlugin : public QObject
+class KritaLayerDockerPlugin : public QObject
{
Q_OBJECT
public:
- KritaDefaultDockersPlugin(QObject *parent, const QVariantList &);
- ~KritaDefaultDockersPlugin() override;
+ KritaLayerDockerPlugin(QObject *parent, const QVariantList &);
+ ~KritaLayerDockerPlugin() override;
};
#endif
diff --git a/libs/ui/KisNodeDelegate.cpp b/plugins/dockers/layerdocker/NodeDelegate.cpp
similarity index 90%
rename from libs/ui/KisNodeDelegate.cpp
rename to plugins/dockers/layerdocker/NodeDelegate.cpp
index 06796f19a9..e9182a530a 100644
--- a/libs/ui/KisNodeDelegate.cpp
+++ b/plugins/dockers/layerdocker/NodeDelegate.cpp
@@ -1,1015 +1,1015 @@
/*
Copyright (c) 2006 Gábor Lehel
Copyright (c) 2008 Cyrille Berger
Copyright (c) 2011 José Luis Vergara
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kis_config.h"
-#include "KisNodeDelegate.h"
+#include "NodeDelegate.h"
#include "kis_node_model.h"
-#include "KisNodeToolTip.h"
-#include "KisNodeView.h"
+#include "NodeToolTip.h"
+#include "NodeView.h"
#include "KisPart.h"
#include "input/kis_input_manager.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "kis_node_view_color_scheme.h"
#include "kis_icon_utils.h"
#include "kis_layer_properties_icons.h"
#include "krita_utils.h"
#include "kis_config_notifier.h"
typedef KisBaseNode::Property* OptionalProperty;
#include
-class KisNodeDelegate::Private
+class NodeDelegate::Private
{
public:
Private() : view(0), edit(0) { }
- KisNodeView *view;
+ NodeView *view;
QPointer edit;
- KisNodeToolTip tip;
+ NodeToolTip tip;
QColor checkersColor1;
QColor checkersColor2;
QList rightmostProperties(const KisBaseNode::PropertyList &props) const;
int numProperties(const QModelIndex &index) const;
OptionalProperty findProperty(KisBaseNode::PropertyList &props, const OptionalProperty &refProp) const;
OptionalProperty findVisibilityProperty(KisBaseNode::PropertyList &props) const;
void toggleProperty(KisBaseNode::PropertyList &props, OptionalProperty prop, bool controlPressed, const QModelIndex &index);
};
-KisNodeDelegate::KisNodeDelegate(KisNodeView *view, QObject *parent)
+NodeDelegate::NodeDelegate(NodeView *view, QObject *parent)
: QAbstractItemDelegate(parent)
, d(new Private)
{
d->view = view;
QApplication::instance()->installEventFilter(this);
connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged()));
slotConfigChanged();
}
-KisNodeDelegate::~KisNodeDelegate()
+NodeDelegate::~NodeDelegate()
{
delete d;
}
-QSize KisNodeDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
+QSize NodeDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index);
KisNodeViewColorScheme scm;
return QSize(option.rect.width(), scm.rowHeight());
}
-void KisNodeDelegate::paint(QPainter *p, const QStyleOptionViewItem &o, const QModelIndex &index) const
+void NodeDelegate::paint(QPainter *p, const QStyleOptionViewItem &o, const QModelIndex &index) const
{
p->save();
{
QStyleOptionViewItem option = getOptions(o, index);
QStyle *style = option.widget ? option.widget->style() : QApplication::style();
style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, p, option.widget);
bool shouldGrayOut = index.data(KisNodeModel::ShouldGrayOutRole).toBool();
if (shouldGrayOut) {
option.state &= ~QStyle::State_Enabled;
}
p->setFont(option.font);
drawColorLabel(p, option, index);
drawFrame(p, option, index);
drawThumbnail(p, option, index);
drawText(p, option, index); // BUG: Creating group moves things around (RTL-layout alignment)
drawIcons(p, option, index);
drawVisibilityIconHijack(p, option, index); // TODO hide when dragging
drawDecoration(p, option, index);
drawExpandButton(p, option, index);
drawBranch(p, option, index);
drawProgressBar(p, option, index);
}
p->restore();
}
-void KisNodeDelegate::drawBranch(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
+void NodeDelegate::drawBranch(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QModelIndex tmp = index.parent();
// there is no indention if we have no parent group, so don't draw a branch
if (!tmp.isValid()) return;
KisNodeViewColorScheme scm;
int rtlNum = (option.direction == Qt::RightToLeft) ? 1 : -1;
QRect baseRect = scm.relThumbnailRect();
// Move to current index
baseRect.moveTop(option.rect.topLeft().y());
// Move to correct location.
if (option.direction == Qt::RightToLeft) {
baseRect.moveLeft(option.rect.topRight().x());
} else {
baseRect.moveRight(option.rect.topLeft().x());
}
QPoint base = baseRect.adjusted(rtlNum*scm.indentation(), 0,
rtlNum*scm.indentation(), 0).center() + QPoint(0, scm.iconSize()/4);
QPen oldPen = p->pen();
const qreal oldOpacity = p->opacity(); // remember previous opacity
p->setOpacity(1.0);
QColor color = scm.gridColor(option, d->view);
QColor bgColor = option.state & QStyle::State_Selected ?
qApp->palette().color(QPalette::Base) :
qApp->palette().color(QPalette::Text);
color = KritaUtils::blendColors(color, bgColor, 0.9);
// TODO: if we are a mask type, use dotted lines for the branch style
// p->setPen(QPen(p->pen().color(), 2, Qt::DashLine, Qt::RoundCap, Qt::RoundJoin));
p->setPen(QPen(color, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
QPoint p2 = base - QPoint(rtlNum*(scm.iconSize()/2), 0);
QPoint p3 = base - QPoint(0, scm.iconSize()/2);
p->drawLine(base, p2);
p->drawLine(base, p3);
// draw parent lines (keep drawing until x position is less than 0
QPoint parentBase1 = base + QPoint(rtlNum*scm.indentation(), 0);
QPoint parentBase2 = p3 + QPoint(rtlNum*scm.indentation(), 0);
// indent lines needs to be very subtle to avoid making the docker busy looking
color = KritaUtils::blendColors(color, bgColor, 0.9); // makes it a little lighter than L lines
p->setPen(QPen(color, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
if (tmp.isValid()) {
tmp = tmp.parent(); // Ignore the first group as it was already painted
}
while (tmp.isValid()) {
p->drawLine(parentBase1, parentBase2);
parentBase1 += QPoint(rtlNum*scm.indentation(), 0);
parentBase2 += QPoint(rtlNum*scm.indentation(), 0);
tmp = tmp.parent();
}
p->setPen(oldPen);
p->setOpacity(oldOpacity);
}
-void KisNodeDelegate::drawColorLabel(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
+void NodeDelegate::drawColorLabel(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
KisNodeViewColorScheme scm;
const int label = index.data(KisNodeModel::ColorLabelIndexRole).toInt();
QColor color = scm.colorLabel(label);
if (color.alpha() <= 0) return;
QColor bgColor = qApp->palette().color(QPalette::Base);
if ((option.state & QStyle::State_MouseOver) && !(option.state & QStyle::State_Selected)) {
color = KritaUtils::blendColors(color, bgColor, 0.6);
} else {
color = KritaUtils::blendColors(color, bgColor, 0.3);
}
QRect optionRect = option.rect.adjusted(0, 0, scm.indentation(), 0);
if (option.state & QStyle::State_Selected) {
optionRect = iconsRect(option, index);
}
if (option.direction == Qt::RightToLeft) {
optionRect.moveLeft(option.rect.topLeft().x());
} else {
optionRect.moveRight(option.rect.topRight().x());
}
p->fillRect(optionRect, color);
}
-void KisNodeDelegate::drawFrame(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
+void NodeDelegate::drawFrame(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
KisNodeViewColorScheme scm;
QPen oldPen = p->pen();
p->setPen(scm.gridColor(option, d->view));
const QRect visibilityRect = visibilityClickRect(option, index);
const QRect thumbnailRect = thumbnailClickRect(option, index);
const QRect decorationRect = decorationClickRect(option, index);
const QRect iconsRectR = iconsRect(option, index);
const float topY = thumbnailRect.topLeft().y();
const float bottomY = thumbnailRect.bottomLeft().y();
QPoint bottomLeftPoint;
QPoint bottomRightPoint;
if (option.direction == Qt::RightToLeft) {
bottomLeftPoint = iconsRectR.bottomLeft();
bottomRightPoint = visibilityRect.bottomRight();
} else {
bottomLeftPoint = visibilityRect.bottomLeft();
bottomRightPoint = iconsRectR.bottomRight();
}
// bottom running horizontal line
p->drawLine(bottomLeftPoint.x(), bottomY,
bottomRightPoint.x(), bottomY);
// visiblity icon vertical line - left
p->drawLine(visibilityRect.topLeft().x()-1, topY,
visibilityRect.bottomLeft().x()-1, bottomY);
// visiblity icon vertical line - right
p->drawLine(visibilityRect.topRight().x()+1, topY,
visibilityRect.bottomRight().x()+1, bottomY);
// thumbnail vertical line - left
p->drawLine(thumbnailRect.topLeft().x(), topY,
thumbnailRect.bottomLeft().x(), bottomY);
// thumbnail vertical line - right
p->drawLine(thumbnailRect.topRight().x(), topY,
thumbnailRect.bottomRight().x(), bottomY);
// decoration vertical line - left
p->drawLine(decorationRect.topLeft().x(), topY,
decorationRect.bottomLeft().x(), bottomY);
// decoration vertical line - right
p->drawLine(decorationRect.topRight().x(), topY,
decorationRect.bottomRight().x(), bottomY);
// icons' lines are drawn by drawIcons
//// For debugging purposes only
p->setPen(Qt::blue);
//KritaUtils::renderExactRect(p, iconsRectR);
//KritaUtils::renderExactRect(p, textRect(option, index));
//KritaUtils::renderExactRect(p, visibilityRect);
p->setPen(oldPen);
}
-QRect KisNodeDelegate::thumbnailClickRect(const QStyleOptionViewItem &option, const QModelIndex &index) const
+QRect NodeDelegate::thumbnailClickRect(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index);
KisNodeViewColorScheme scm;
QRect rc = scm.relThumbnailRect();
// Move to current index
rc.moveTop(option.rect.topLeft().y());
// Move to correct location.
if (option.direction == Qt::RightToLeft) {
rc.moveLeft(option.rect.topRight().x());
} else {
rc.moveRight(option.rect.topLeft().x());
}
return rc;
}
-void KisNodeDelegate::drawThumbnail(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
+void NodeDelegate::drawThumbnail(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
KisNodeViewColorScheme scm;
const int thumbSize = scm.thumbnailSize();
const qreal oldOpacity = p->opacity(); // remember previous opacity
QImage img = index.data(int(KisNodeModel::BeginThumbnailRole) + thumbSize).value();
if (!(option.state & QStyle::State_Enabled)) {
p->setOpacity(0.35);
}
QRect fitRect = thumbnailClickRect(option, index);
// Shrink to icon rect
fitRect = kisGrowRect(fitRect, -(scm.thumbnailMargin()+scm.border()));
// paint in a checkerboard pattern behind the layer contents to represent transparent
const int step = scm.thumbnailSize() / 6;
QImage checkers(2 * step, 2 * step, QImage::Format_ARGB32);
QPainter gc(&checkers);
gc.fillRect(QRect(0, 0, step, step), d->checkersColor1);
gc.fillRect(QRect(step, 0, step, step), d->checkersColor2);
gc.fillRect(QRect(step, step, step, step), d->checkersColor1);
gc.fillRect(QRect(0, step, step, step), d->checkersColor2);
QBrush brush(checkers);
p->fillRect(fitRect, brush);
p->drawImage(fitRect, img);
p->setOpacity(oldOpacity); // restore old opacity
QRect borderRect = kisGrowRect(fitRect, 1);
KritaUtils::renderExactRect(p, borderRect, scm.gridColor(option, d->view));
}
-QRect KisNodeDelegate::iconsRect(const QStyleOptionViewItem &option, const QModelIndex &index) const
+QRect NodeDelegate::iconsRect(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
KisNodeViewColorScheme scm;
int propCount = d->numProperties(index);
const int iconsWidth =
propCount * (scm.iconSize() + 2 * scm.iconMargin()) +
(propCount + 1) * scm.border();
QRect fitRect = QRect(0, 0,
iconsWidth, scm.rowHeight() - scm.border());
// Move to current index
fitRect.moveTop(option.rect.topLeft().y());
// Move to correct location.
if (option.direction == Qt::RightToLeft) {
fitRect.moveLeft(option.rect.topLeft().x());
} else {
fitRect.moveRight(option.rect.topRight().x());
}
return fitRect;
}
-QRect KisNodeDelegate::textRect(const QStyleOptionViewItem &option, const QModelIndex &index) const
+QRect NodeDelegate::textRect(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
KisNodeViewColorScheme scm;
static QFont f;
static int minbearing = 1337 + 666; //can be 0 or negative, 2003 is less likely
if (minbearing == 2003 || f != option.font) {
f = option.font; //getting your bearings can be expensive, so we cache them
minbearing = option.fontMetrics.minLeftBearing() + option.fontMetrics.minRightBearing();
}
const QRect decoRect = decorationClickRect(option, index);
const QRect iconRect = iconsRect(option, index);
QRect rc = QRect((option.direction == Qt::RightToLeft) ? iconRect.topRight() : decoRect.topRight(),
(option.direction == Qt::RightToLeft) ? decoRect.bottomLeft() : iconRect.bottomLeft());
rc.adjust(-(scm.border()+minbearing), 0,
(scm.border()+minbearing), 0);
return rc;
}
-void KisNodeDelegate::drawText(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
+void NodeDelegate::drawText(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
KisNodeViewColorScheme scm;
const QRect rc = textRect(option, index).adjusted(scm.textMargin(), 0,
-scm.textMargin(), 0);
QPen oldPen = p->pen();
const qreal oldOpacity = p->opacity(); // remember previous opacity
p->setPen(option.palette.color(QPalette::Active,QPalette::Text ));
if (!(option.state & QStyle::State_Enabled)) {
p->setOpacity(0.55);
}
const QString text = index.data(Qt::DisplayRole).toString();
const QString elided = p->fontMetrics().elidedText(text, Qt::ElideRight, rc.width());
p->drawText(rc, Qt::AlignLeft | Qt::AlignVCenter, elided);
p->setPen(oldPen); // restore pen settings
p->setOpacity(oldOpacity);
}
-QList KisNodeDelegate::Private::rightmostProperties(const KisBaseNode::PropertyList &props) const
+QList NodeDelegate::Private::rightmostProperties(const KisBaseNode::PropertyList &props) const
{
QList list;
QList prependList;
list << OptionalProperty(0);
list << OptionalProperty(0);
list << OptionalProperty(0);
KisBaseNode::PropertyList::const_iterator it = props.constBegin();
KisBaseNode::PropertyList::const_iterator end = props.constEnd();
for (; it != end; ++it) {
if (!it->isMutable) continue;
if (it->id == KisLayerPropertiesIcons::visible.id()) {
// noop...
} else if (it->id == KisLayerPropertiesIcons::locked.id()) {
list[0] = OptionalProperty(&(*it));
} else if (it->id == KisLayerPropertiesIcons::inheritAlpha.id()) {
list[1] = OptionalProperty(&(*it));
} else if (it->id == KisLayerPropertiesIcons::alphaLocked.id()) {
list[2] = OptionalProperty(&(*it));
} else {
prependList.prepend(OptionalProperty(&(*it)));
}
}
{
QMutableListIterator i(prependList);
i.toBack();
while (i.hasPrevious()) {
OptionalProperty val = i.previous();
int emptyIndex = list.lastIndexOf(0);
if (emptyIndex < 0) break;
list[emptyIndex] = val;
i.remove();
}
}
return prependList + list;
}
-int KisNodeDelegate::Private::numProperties(const QModelIndex &index) const
+int NodeDelegate::Private::numProperties(const QModelIndex &index) const
{
KisBaseNode::PropertyList props = index.data(KisNodeModel::PropertiesRole).value();
QList realProps = rightmostProperties(props);
return realProps.size();
}
-OptionalProperty KisNodeDelegate::Private::findProperty(KisBaseNode::PropertyList &props, const OptionalProperty &refProp) const
+OptionalProperty NodeDelegate::Private::findProperty(KisBaseNode::PropertyList &props, const OptionalProperty &refProp) const
{
KisBaseNode::PropertyList::iterator it = props.begin();
KisBaseNode::PropertyList::iterator end = props.end();
for (; it != end; ++it) {
if (it->id == refProp->id) {
return &(*it);
}
}
return 0;
}
-OptionalProperty KisNodeDelegate::Private::findVisibilityProperty(KisBaseNode::PropertyList &props) const
+OptionalProperty NodeDelegate::Private::findVisibilityProperty(KisBaseNode::PropertyList &props) const
{
KisBaseNode::PropertyList::iterator it = props.begin();
KisBaseNode::PropertyList::iterator end = props.end();
for (; it != end; ++it) {
if (it->id == KisLayerPropertiesIcons::visible.id()) {
return &(*it);
}
}
return 0;
}
-void KisNodeDelegate::drawIcons(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
+void NodeDelegate::drawIcons(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
KisNodeViewColorScheme scm;
const QRect rc = iconsRect(option, index);
QTransform oldTransform = p->transform();
QPen oldPen = p->pen();
p->setTransform(QTransform::fromTranslate(rc.x(), rc.y()));
p->setPen(scm.gridColor(option, d->view));
int x = 0;
const int y = (scm.rowHeight() - scm.border() - scm.iconSize()) / 2;
KisBaseNode::PropertyList props = index.data(KisNodeModel::PropertiesRole).value();
QList realProps = d->rightmostProperties(props);
if (option.direction == Qt::RightToLeft) {
std::reverse(realProps.begin(), realProps.end());
}
Q_FOREACH (OptionalProperty prop, realProps) {
if (option.direction == Qt::LeftToRight)
p->drawLine(x, 0, x, scm.rowHeight() - scm.border());
x += scm.iconMargin();
if (prop) {
QIcon icon = prop->state.toBool() ? prop->onIcon : prop->offIcon;
bool fullColor = prop->state.toBool() && option.state & QStyle::State_Enabled;
const qreal oldOpacity = p->opacity(); // remember previous opacity
if (fullColor) {
p->setOpacity(1.0);
}
else {
p->setOpacity(0.35);
}
p->drawPixmap(x, y, icon.pixmap(scm.iconSize(), QIcon::Normal));
p->setOpacity(oldOpacity); // restore old opacity
}
x += scm.iconSize() + scm.iconMargin();
if (!(option.direction == Qt::LeftToRight))
p->drawLine(x, 0, x, scm.rowHeight() - scm.border());
x += scm.border();
}
p->setTransform(oldTransform);
p->setPen(oldPen);
}
-QRect KisNodeDelegate::visibilityClickRect(const QStyleOptionViewItem &option, const QModelIndex &index) const
+QRect NodeDelegate::visibilityClickRect(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index);
KisNodeViewColorScheme scm;
QRect rc = scm.relVisibilityRect();
rc.setHeight(scm.rowHeight());
// Move to current index
rc.moveCenter(option.rect.center());
// Move to correct location.
if (option.direction == Qt::RightToLeft) {
// HACK: Without the -5, the right edge is outside the view
rc.moveRight(d->view->width()-5);
} else {
rc.moveLeft(0);
}
return rc;
}
-QRect KisNodeDelegate::decorationClickRect(const QStyleOptionViewItem &option, const QModelIndex &index) const
+QRect NodeDelegate::decorationClickRect(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index);
KisNodeViewColorScheme scm;
QRect rc = scm.relDecorationRect();
// Move to current index
rc.moveTop(option.rect.topLeft().y());
rc.setHeight(scm.rowHeight());
// Move to correct location.
if (option.direction == Qt::RightToLeft) {
rc.moveRight(option.rect.topRight().x());
} else {
rc.moveLeft(option.rect.topLeft().x());
}
return rc;
}
-void KisNodeDelegate::drawVisibilityIconHijack(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
+void NodeDelegate::drawVisibilityIconHijack(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
/**
* Small hack Alert:
*
* Here wepaint over the area that sits basically outside our layer's
* row. Anyway, just update it later...
*/
KisNodeViewColorScheme scm;
KisBaseNode::PropertyList props = index.data(KisNodeModel::PropertiesRole).value();
OptionalProperty prop = d->findVisibilityProperty(props);
if (!prop) return;
QRect fitRect = visibilityClickRect(option, index);
// Shrink to icon rect
fitRect = kisGrowRect(fitRect, -(scm.visibilityMargin()+scm.border()));
QIcon icon = prop->state.toBool() ? prop->onIcon : prop->offIcon;
// if we are not showing the layer, make the icon slightly transparent like other inactive icons
const qreal oldOpacity = p->opacity();
if (!prop->state.toBool()) {
p->setOpacity(0.35);
}
p->drawPixmap(fitRect.x(), fitRect.center().y() - scm.visibilitySize() / 2,
icon.pixmap(scm.visibilitySize(), QIcon::Normal));
p->setOpacity(oldOpacity);
//// For debugging purposes only
// // // p->save();
// // // p->setPen(Qt::blue);
// // // KritaUtils::renderExactRect(p, visibilityClickRect(option, index));
// // // p->restore();
}
-void KisNodeDelegate::drawDecoration(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
+void NodeDelegate::drawDecoration(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
KisNodeViewColorScheme scm;
QIcon icon = index.data(Qt::DecorationRole).value();
if (!icon.isNull()) {
QPixmap pixmap = icon.pixmap(scm.decorationSize(),
(option.state & QStyle::State_Enabled) ?
QIcon::Normal : QIcon::Disabled);
QRect rc = decorationClickRect(option, index);
// Shrink to icon rect
rc = kisGrowRect(rc, -(scm.decorationMargin()+scm.border()));
const qreal oldOpacity = p->opacity(); // remember previous opacity
if (!(option.state & QStyle::State_Enabled)) {
p->setOpacity(0.35);
}
p->drawPixmap(rc.topLeft()-QPoint(0, 1), pixmap);
p->setOpacity(oldOpacity); // restore old opacity
}
}
-void KisNodeDelegate::drawExpandButton(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
+void NodeDelegate::drawExpandButton(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index);
KisNodeViewColorScheme scm;
QRect rc = decorationClickRect(option, index);
// Move to current index
// rc.moveTop(option.rect.topLeft().y());
// Shrink to icon rect
rc = kisGrowRect(rc, -(scm.decorationMargin()+scm.border()));
if (!(option.state & QStyle::State_Children)) return;
QString iconName = option.state & QStyle::State_Open ?
"arrow-down" : ((option.direction == Qt::RightToLeft) ? "arrow-left" : "arrow-right");
QIcon icon = KisIconUtils::loadIcon(iconName);
QPixmap pixmap = icon.pixmap(rc.width(),
(option.state & QStyle::State_Enabled) ?
QIcon::Normal : QIcon::Disabled);
p->drawPixmap(rc.bottomLeft()-QPoint(0, scm.decorationSize()-1), pixmap);
}
-void KisNodeDelegate::Private::toggleProperty(KisBaseNode::PropertyList &props, OptionalProperty clickedProperty, bool controlPressed, const QModelIndex &index)
+void NodeDelegate::Private::toggleProperty(KisBaseNode::PropertyList &props, OptionalProperty clickedProperty, bool controlPressed, const QModelIndex &index)
{
QAbstractItemModel *model = view->model();
// Using Ctrl+click to enter stasis
if (controlPressed && clickedProperty->canHaveStasis) {
// STEP 0: Prepare to Enter or Leave control key stasis
quint16 numberOfLeaves = model->rowCount(index.parent());
QModelIndex eachItem;
// STEP 1: Go.
if (clickedProperty->isInStasis == false) { // Enter
/* Make every leaf of this node go State = False, saving the old property value to stateInStasis */
for (quint16 i = 0; i < numberOfLeaves; ++i) { // Foreach leaf in the node (index.parent())
eachItem = model->index(i, 1, index.parent());
// The entire property list has to be altered because model->setData cannot set individual properties
KisBaseNode::PropertyList eachPropertyList = eachItem.data(KisNodeModel::PropertiesRole).value();
OptionalProperty prop = findProperty(eachPropertyList, clickedProperty);
if (!prop) continue;
prop->stateInStasis = prop->state.toBool();
prop->state = eachItem == index;
prop->isInStasis = true;
model->setData(eachItem, QVariant::fromValue(eachPropertyList), KisNodeModel::PropertiesRole);
}
for (quint16 i = 0; i < numberOfLeaves; ++i) { // Foreach leaf in the node (index.parent())
eachItem = model->index(i, 1, index.parent());
KisBaseNode::PropertyList eachPropertyList = eachItem.data(KisNodeModel::PropertiesRole).value();
OptionalProperty prop = findProperty(eachPropertyList, clickedProperty);
if (!prop) continue;
}
} else { // Leave
/* Make every leaf of this node go State = stateInStasis */
for (quint16 i = 0; i < numberOfLeaves; ++i) {
eachItem = model->index(i, 1, index.parent());
// The entire property list has to be altered because model->setData cannot set individual properties
KisBaseNode::PropertyList eachPropertyList = eachItem.data(KisNodeModel::PropertiesRole).value();
OptionalProperty prop = findProperty(eachPropertyList, clickedProperty);
if (!prop) continue;
prop->state = prop->stateInStasis;
prop->isInStasis = false;
model->setData(eachItem, QVariant::fromValue(eachPropertyList), KisNodeModel::PropertiesRole);
}
}
} else {
clickedProperty->state = !clickedProperty->state.toBool();
model->setData(index, QVariant::fromValue(props), KisNodeModel::PropertiesRole);
}
}
-bool KisNodeDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
+bool NodeDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
KisNodeViewColorScheme scm;
QStyleOptionViewItem newOption = option;
newOption.rect = d->view->originalVisualRect(index);
if ((event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick)
&& (index.flags() & Qt::ItemIsEnabled))
{
QMouseEvent *mouseEvent = static_cast(event);
/**
* Small hack Alert:
*
* Here we handle clicking even when it happened outside
* the rectangle of the current index. The point is, we
* use some virtual scroling offset to move the tree to the
* right of the visibility icon. So the icon itself is placed
* in an empty area that doesn't belong to any index. But we still
* handle it.
*/
const QRect visibilityRect = visibilityClickRect(newOption, index);
const bool visibilityClicked = visibilityRect.isValid() &&
visibilityRect.contains(mouseEvent->pos());
const QRect thumbnailRect = thumbnailClickRect(newOption, index);
const bool thumbnailClicked = thumbnailRect.isValid() &&
thumbnailRect.contains(mouseEvent->pos());
const QRect decorationRect = decorationClickRect(newOption, index);
const bool decorationClicked = decorationRect.isValid() &&
decorationRect.contains(mouseEvent->pos());
const QRect iconsRect = this->iconsRect(newOption, index);
const bool iconsClicked = iconsRect.isValid() &&
iconsRect.contains(mouseEvent->pos());
const bool leftButton = mouseEvent->buttons() & Qt::LeftButton;
if (leftButton && iconsClicked) {
KisBaseNode::PropertyList props = index.data(KisNodeModel::PropertiesRole).value();
QList realProps = d->rightmostProperties(props);
if (newOption.direction == Qt::RightToLeft) {
std::reverse(realProps.begin(), realProps.end());
}
const int numProps = realProps.size();
const int iconWidth = scm.iconSize() + 2 * scm.iconMargin() + scm.border();
const int xPos = mouseEvent->pos().x() - iconsRect.left();
const int clickedIcon = xPos / iconWidth;
const int distToBorder = qMin(xPos % iconWidth, iconWidth - xPos % iconWidth);
if (iconsClicked &&
clickedIcon >= 0 &&
clickedIcon < numProps &&
distToBorder > scm.iconMargin()) {
OptionalProperty clickedProperty = realProps[clickedIcon];
if (!clickedProperty) return false;
d->toggleProperty(props, clickedProperty, mouseEvent->modifiers() == Qt::ControlModifier, index);
return true;
}
} else if (leftButton && visibilityClicked) {
KisBaseNode::PropertyList props = index.data(KisNodeModel::PropertiesRole).value();
OptionalProperty clickedProperty = d->findVisibilityProperty(props);
if (!clickedProperty) return false;
d->toggleProperty(props, clickedProperty, mouseEvent->modifiers() == Qt::ControlModifier, index);
return true;
} else if (leftButton && decorationClicked) {
bool isExpandable = model->hasChildren(index);
if (isExpandable) {
bool isExpanded = d->view->isExpanded(index);
d->view->setExpanded(index, !isExpanded);
}
return true;
} else if (leftButton && thumbnailClicked) {
bool hasCorrectModifier = false;
SelectionAction action = SELECTION_REPLACE;
if (mouseEvent->modifiers() == Qt::ControlModifier) {
action = SELECTION_REPLACE;
hasCorrectModifier = true;
} else if (mouseEvent->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) {
action = SELECTION_ADD;
hasCorrectModifier = true;
} else if (mouseEvent->modifiers() == (Qt::ControlModifier | Qt::AltModifier)) {
action = SELECTION_SUBTRACT;
hasCorrectModifier = true;
} else if (mouseEvent->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier | Qt::AltModifier)) {
action = SELECTION_INTERSECT;
hasCorrectModifier = true;
}
if (hasCorrectModifier) {
model->setData(index, QVariant(int(action)), KisNodeModel::SelectOpaqueRole);
}
return true; //If not here then the item is !expanded when reaching return false;
}
if (mouseEvent->button() == Qt::LeftButton &&
mouseEvent->modifiers() == Qt::AltModifier) {
d->view->setCurrentIndex(index);
model->setData(index, true, KisNodeModel::AlternateActiveRole);
return true;
}
}
else if (event->type() == QEvent::ToolTip) {
if (!KisConfig(true).hidePopups()) {
QHelpEvent *helpEvent = static_cast(event);
d->tip.showTip(d->view, helpEvent->pos(), newOption, index);
}
return true;
} else if (event->type() == QEvent::Leave) {
d->tip.hide();
}
return false;
}
-QWidget *KisNodeDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem&, const QModelIndex&) const
+QWidget *NodeDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem&, const QModelIndex&) const
{
d->edit = new QLineEdit(parent);
d->edit->setFocusPolicy(Qt::StrongFocus);
- d->edit->installEventFilter(const_cast(this)); //hack?
+ d->edit->installEventFilter(const_cast(this)); //hack?
return d->edit;
}
-void KisNodeDelegate::setEditorData(QWidget *widget, const QModelIndex &index) const
+void NodeDelegate::setEditorData(QWidget *widget, const QModelIndex &index) const
{
QLineEdit *edit = qobject_cast(widget);
Q_ASSERT(edit);
edit->setText(index.data(Qt::DisplayRole).toString());
}
-void KisNodeDelegate::setModelData(QWidget *widget, QAbstractItemModel *model, const QModelIndex &index) const
+void NodeDelegate::setModelData(QWidget *widget, QAbstractItemModel *model, const QModelIndex &index) const
{
QLineEdit *edit = qobject_cast(widget);
Q_ASSERT(edit);
model->setData(index, edit->text(), Qt::DisplayRole);
}
-void KisNodeDelegate::updateEditorGeometry(QWidget *widget, const QStyleOptionViewItem &option, const QModelIndex &index) const
+void NodeDelegate::updateEditorGeometry(QWidget *widget, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index);
widget->setGeometry(option.rect);
}
// PROTECTED
-bool KisNodeDelegate::eventFilter(QObject *object, QEvent *event)
+bool NodeDelegate::eventFilter(QObject *object, QEvent *event)
{
switch (event->type()) {
case QEvent::MouseButtonPress: {
if (d->edit) {
QMouseEvent *me = static_cast(event);
if (!QRect(d->edit->mapToGlobal(QPoint()), d->edit->size()).contains(me->globalPos())) {
emit commitData(d->edit);
emit closeEditor(d->edit);
}
}
} break;
case QEvent::KeyPress: {
QLineEdit *edit = qobject_cast(object);
if (edit && edit == d->edit) {
QKeyEvent *ke = static_cast(event);
switch (ke->key()) {
case Qt::Key_Escape:
emit closeEditor(edit);
return true;
case Qt::Key_Tab:
emit commitData(edit);
emit closeEditor(edit, EditNextItem);
return true;
case Qt::Key_Backtab:
emit commitData(edit);
emit closeEditor(edit, EditPreviousItem);
return true;
case Qt::Key_Return:
case Qt::Key_Enter:
emit commitData(edit);
emit closeEditor(edit);
return true;
default: break;
}
}
} break;
case QEvent::ShortcutOverride : {
QLineEdit *edit = qobject_cast(object);
if (edit && edit == d->edit){
auto* key = static_cast(event);
if (key->modifiers() == Qt::NoModifier){
switch (key->key()){
case Qt::Key_Escape:
case Qt::Key_Tab:
case Qt::Key_Backtab:
case Qt::Key_Return:
case Qt::Key_Enter:
event->accept();
return true;
default: break;
}
}
}
} break;
case QEvent::FocusOut : {
QLineEdit *edit = qobject_cast(object);
if (edit && edit == d->edit) {
emit commitData(edit);
emit closeEditor(edit);
}
}
default: break;
}
return QAbstractItemDelegate::eventFilter(object, event);
}
// PRIVATE
-QStyleOptionViewItem KisNodeDelegate::getOptions(const QStyleOptionViewItem &o, const QModelIndex &index)
+QStyleOptionViewItem NodeDelegate::getOptions(const QStyleOptionViewItem &o, const QModelIndex &index)
{
QStyleOptionViewItem option = o;
QVariant v = index.data(Qt::FontRole);
if (v.isValid()) {
option.font = v.value();
option.fontMetrics = QFontMetrics(option.font);
}
v = index.data(Qt::TextAlignmentRole);
if (v.isValid())
option.displayAlignment = QFlag(v.toInt());
v = index.data(Qt::TextColorRole);
if (v.isValid())
option.palette.setColor(QPalette::Text, v.value());
v = index.data(Qt::BackgroundColorRole);
if (v.isValid())
option.palette.setColor(QPalette::Window, v.value());
return option;
}
-void KisNodeDelegate::drawProgressBar(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
+void NodeDelegate::drawProgressBar(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QVariant value = index.data(KisNodeModel::ProgressRole);
if (!value.isNull() && (value.toInt() >= 0 && value.toInt() <= 100)) {
/// The progress bar will display under the layer name area. The bars have accurate data, so we
/// probably don't need to also show the actual number for % complete
KisNodeViewColorScheme scm;
const QRect thumbnailRect = thumbnailClickRect(option, index);
const QRect iconsRectR = iconsRect(option, index);
const int height = 5;
const QRect rc = QRect(
((option.direction == Qt::RightToLeft) ? iconsRectR.bottomRight()
: thumbnailRect.bottomRight()) - QPoint(0, height),
((option.direction == Qt::RightToLeft) ? thumbnailRect.bottomLeft()
: iconsRectR.bottomLeft()));
p->save();
{
p->setClipRect(rc);
QStyle* style = QApplication::style();
QStyleOptionProgressBar opt;
opt.minimum = 0;
opt.maximum = 100;
opt.progress = value.toInt();
opt.textVisible = false;
opt.textAlignment = Qt::AlignHCenter;
opt.text = i18n("%1 %", opt.progress);
opt.orientation = Qt::Horizontal;
opt.state = option.state;
style->drawControl(QStyle::CE_ProgressBar, &opt, p, 0);
}
p->restore();
}
}
-void KisNodeDelegate::slotConfigChanged()
+void NodeDelegate::slotConfigChanged()
{
KisConfig cfg(true);
d->checkersColor1 = cfg.checkersColor1();
d->checkersColor2 = cfg.checkersColor2();
}
-void KisNodeDelegate::slotUpdateIcon()
+void NodeDelegate::slotUpdateIcon()
{
KisLayerPropertiesIcons::instance()->updateIcons();
}
diff --git a/libs/ui/KisNodeDelegate.h b/plugins/dockers/layerdocker/NodeDelegate.h
similarity index 92%
rename from libs/ui/KisNodeDelegate.h
rename to plugins/dockers/layerdocker/NodeDelegate.h
index 048eee631e..a323e16886 100644
--- a/libs/ui/KisNodeDelegate.h
+++ b/plugins/dockers/layerdocker/NodeDelegate.h
@@ -1,89 +1,89 @@
/*
Copyright (c) 2006 Gábor Lehel
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KIS_DOCUMENT_SECTION_DELEGATE_H
#define KIS_DOCUMENT_SECTION_DELEGATE_H
#include
-class KisNodeView;
+class NodeView;
class KisNodeModel;
/**
- * See KisNodeModel and KisNodeView.
+ * See KisNodeModel and NodeView.
*
* A delegate provides the gui machinery, using Qt's model/view terminology.
- * This class is owned by KisNodeView to do the work of generating the
+ * This class is owned by NodeView to do the work of generating the
* graphical representation of each item.
*/
-class KisNodeDelegate: public QAbstractItemDelegate
+class NodeDelegate: public QAbstractItemDelegate
{
Q_OBJECT
public:
- explicit KisNodeDelegate(KisNodeView *view, QObject *parent = 0);
- ~KisNodeDelegate() override;
+ explicit NodeDelegate(NodeView *view, QObject *parent = 0);
+ ~NodeDelegate() override;
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override;
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex& index) const override;
void slotUpdateIcon();
protected:
bool eventFilter(QObject *object, QEvent *event) override;
private:
typedef KisNodeModel Model;
- typedef KisNodeView View;
+ typedef NodeView View;
class Private;
Private* const d;
static QStyleOptionViewItem getOptions(const QStyleOptionViewItem &option, const QModelIndex &index);
void drawProgressBar(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawBranch(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawColorLabel(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawFrame(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
QRect thumbnailClickRect(const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawThumbnail(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
QRect iconsRect(const QStyleOptionViewItem &option, const QModelIndex &index) const;
QRect textRect(const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawText(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawIcons(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
QRect visibilityClickRect(const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawVisibilityIconHijack(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
QRect decorationClickRect(const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawDecoration(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawExpandButton(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
private Q_SLOTS:
void slotConfigChanged();
};
#endif
diff --git a/libs/ui/KisNodePropertyAction_p.h b/plugins/dockers/layerdocker/NodePropertyAction_p.h
similarity index 88%
rename from libs/ui/KisNodePropertyAction_p.h
rename to plugins/dockers/layerdocker/NodePropertyAction_p.h
index 442d0832b4..06460d8686 100644
--- a/libs/ui/KisNodePropertyAction_p.h
+++ b/plugins/dockers/layerdocker/NodePropertyAction_p.h
@@ -1,66 +1,66 @@
/*
Copyright (c) 2006 Gábor Lehel
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
-#ifndef KIS_DOCUMENT_SECTION_PROPERTY_ACTION_P_H
-#define KIS_DOCUMENT_SECTION_PROPERTY_ACTION_P_H
+#ifndef NODE_PROPERTY_ACTION_P_H
+#define NODE_PROPERTY_ACTION_P_H
-#include "kis_node_model.h"
+#include
#include
-#include "KisNodeView.h"
#include
#include
+#include "NodeView.h"
/**
- * Internal class for the KisNodeView widget. Provides a
+ * Internal class for the NodeView widget. Provides a
* toggle action for a particular property associated with a document
* section, such as visible, selected, locked. Property actions have
* associated on/off icons to show their state in the
- * KisNodeView.
+ * NodeView.
*/
-class KisNodeView::PropertyAction: public QAction
+class NodeView::PropertyAction: public QAction
{
typedef QAction super;
Q_OBJECT
KisBaseNode::Property m_property;
int m_num;
QPersistentModelIndex m_index;
Q_SIGNALS:
void toggled( bool on, const QPersistentModelIndex &index, int property );
public:
PropertyAction( int num, const KisBaseNode::Property &p, const QPersistentModelIndex &index, QObject *parent = 0 )
: QAction( parent ), m_property( p ), m_num( num ), m_index( index )
{
connect( this, SIGNAL( triggered( bool ) ), this, SLOT( slotTriggered() ) );
setText( m_property.name );
setIcon( m_property.state.toBool() ? m_property.onIcon : m_property.offIcon );
}
private Q_SLOTS:
void slotTriggered()
{
m_property.state = !m_property.state.toBool();
setIcon( m_property.state.toBool() ? m_property.onIcon : m_property.offIcon );
emit toggled( m_property.state.toBool(), m_index, m_num );
}
};
#endif
diff --git a/libs/ui/KisNodeToolTip.cpp b/plugins/dockers/layerdocker/NodeToolTip.cpp
similarity index 93%
rename from libs/ui/KisNodeToolTip.cpp
rename to plugins/dockers/layerdocker/NodeToolTip.cpp
index 657918da06..9a3e3c58ad 100644
--- a/libs/ui/KisNodeToolTip.cpp
+++ b/plugins/dockers/layerdocker/NodeToolTip.cpp
@@ -1,75 +1,75 @@
/*
Copyright (c) 2006 Gábor Lehel
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
-#include "KisNodeToolTip.h"
+#include "NodeToolTip.h"
#include "kis_node_model.h"
#include
#include
#include
#include
#include
#include
-KisNodeToolTip::KisNodeToolTip()
+NodeToolTip::NodeToolTip()
{
}
-KisNodeToolTip::~KisNodeToolTip()
+NodeToolTip::~NodeToolTip()
{
}
-QTextDocument *KisNodeToolTip::createDocument(const QModelIndex &index)
+QTextDocument *NodeToolTip::createDocument(const QModelIndex &index)
{
QTextDocument *doc = new QTextDocument(this);
QImage thumb = index.data(int(KisNodeModel::BeginThumbnailRole) + 250).value();
doc->addResource(QTextDocument::ImageResource, QUrl("data:thumbnail"), thumb);
QString name = index.data(Qt::DisplayRole).toString();
KisBaseNode::PropertyList properties = index.data(KisNodeModel::PropertiesRole).value();
QString rows;
const QString row = QString("%1: | %2 |
");
QString value;
for(int i = 0, n = properties.count(); i < n; ++i) {
if (properties[i].isMutable)
value = properties[i].state.toBool() ? i18n("Yes") : i18n("No");
else
value = properties[i].state.toString();
rows.append(row.arg(properties[i].name).arg(value));
}
rows = QString("").arg(rows);
const QString image = QString("");
const QString body = QString("%1
").arg(name)
+ QString("
").arg(image).arg(rows);
const QString html = QString("%1").arg(body);
doc->setHtml(html);
const int margin = 16;
doc->setTextWidth(qMin(doc->size().width() + 2 * margin, qreal(500.0)));
doc->setDocumentMargin(margin);
doc->setUseDesignMetrics(true);
return doc;
}
diff --git a/libs/ui/KisNodeToolTip.h b/plugins/dockers/layerdocker/NodeToolTip.h
similarity index 88%
rename from libs/ui/KisNodeToolTip.h
rename to plugins/dockers/layerdocker/NodeToolTip.h
index a6061ed1f5..dd3472df3b 100644
--- a/libs/ui/KisNodeToolTip.h
+++ b/plugins/dockers/layerdocker/NodeToolTip.h
@@ -1,46 +1,46 @@
/*
Copyright (c) 2006 Gábor Lehel
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KIS_DOCUMENT_SECTION_TOOLTIP_H
#define KIS_DOCUMENT_SECTION_TOOLTIP_H
#include "KoItemToolTip.h"
class KisNodeModel;
/**
- * A default tooltip for a KisNodeView that shows a thumbnail
+ * A default tooltip for a NodeView that shows a thumbnail
* image and the list of properties associated with a node.
*/
-class KisNodeToolTip: public KoItemToolTip
+class NodeToolTip: public KoItemToolTip
{
Q_OBJECT
public:
- KisNodeToolTip();
- ~KisNodeToolTip() override;
+ NodeToolTip();
+ ~NodeToolTip() override;
protected:
QTextDocument *createDocument(const QModelIndex &index) override;
private:
typedef KisNodeModel Model;
};
#endif
diff --git a/libs/ui/KisNodeView.cpp b/plugins/dockers/layerdocker/NodeView.cpp
similarity index 85%
rename from libs/ui/KisNodeView.cpp
rename to plugins/dockers/layerdocker/NodeView.cpp
index 26a1ad4aaa..8c18321979 100644
--- a/libs/ui/KisNodeView.cpp
+++ b/plugins/dockers/layerdocker/NodeView.cpp
@@ -1,592 +1,592 @@
/*
Copyright (c) 2006 Gábor Lehel
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
-#include "KisNodeView.h"
-#include "KisNodePropertyAction_p.h"
-#include "KisNodeDelegate.h"
-#include "kis_node_view_visibility_delegate.h"
+#include "NodeView.h"
+#include "NodePropertyAction_p.h"
+#include "NodeDelegate.h"
+#include "NodeViewVisibilityDelegate.h"
#include "kis_node_model.h"
#include "kis_signals_blocker.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "kis_node_view_color_scheme.h"
#ifdef HAVE_X11
#define DRAG_WHILE_DRAG_WORKAROUND
#endif
#ifdef DRAG_WHILE_DRAG_WORKAROUND
#define DRAG_WHILE_DRAG_WORKAROUND_START() d->isDragging = true
#define DRAG_WHILE_DRAG_WORKAROUND_STOP() d->isDragging = false
#else
#define DRAG_WHILE_DRAG_WORKAROUND_START()
#define DRAG_WHILE_DRAG_WORKAROUND_STOP()
#endif
-class Q_DECL_HIDDEN KisNodeView::Private
+class Q_DECL_HIDDEN NodeView::Private
{
public:
- Private(KisNodeView* _q)
+ Private(NodeView* _q)
: delegate(_q, _q)
- , mode(DetailedMode)
+ , mode(DetailedMode)
#ifdef DRAG_WHILE_DRAG_WORKAROUND
, isDragging(false)
#endif
{
KSharedConfigPtr config = KSharedConfig::openConfig();
KConfigGroup group = config->group("NodeView");
mode = (DisplayMode) group.readEntry("NodeViewMode", (int)MinimalMode);
}
- KisNodeDelegate delegate;
+ NodeDelegate delegate;
DisplayMode mode;
QPersistentModelIndex hovered;
QPoint lastPos;
#ifdef DRAG_WHILE_DRAG_WORKAROUND
bool isDragging;
#endif
};
-KisNodeView::KisNodeView(QWidget *parent)
+NodeView::NodeView(QWidget *parent)
: QTreeView(parent)
, m_draggingFlag(false)
, d(new Private(this))
{
setItemDelegateForColumn(0, &d->delegate);
setMouseTracking(true);
setSelectionBehavior(SelectRows);
setDefaultDropAction(Qt::MoveAction);
setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
setSelectionMode(QAbstractItemView::ExtendedSelection);
header()->hide();
setDragEnabled(true);
setDragDropMode(QAbstractItemView::DragDrop);
setAcceptDrops(true);
setDropIndicatorShown(true);
{
QScroller *scroller = KisKineticScroller::createPreconfiguredScroller(this);
if (scroller) {
connect(scroller, SIGNAL(stateChanged(QScroller::State)),
this, SLOT(slotScrollerStateChanged(QScroller::State)));
}
}
}
-KisNodeView::~KisNodeView()
+NodeView::~NodeView()
{
delete d;
}
-void KisNodeView::setDisplayMode(DisplayMode mode)
+void NodeView::setDisplayMode(DisplayMode mode)
{
if (d->mode != mode) {
d->mode = mode;
KSharedConfigPtr config = KSharedConfig::openConfig();
KConfigGroup group = config->group("NodeView");
group.writeEntry("NodeViewMode", (int)mode);
scheduleDelayedItemsLayout();
}
}
-KisNodeView::DisplayMode KisNodeView::displayMode() const
+NodeView::DisplayMode NodeView::displayMode() const
{
return d->mode;
}
-void KisNodeView::addPropertyActions(QMenu *menu, const QModelIndex &index)
+void NodeView::addPropertyActions(QMenu *menu, const QModelIndex &index)
{
KisBaseNode::PropertyList list = index.data(KisNodeModel::PropertiesRole).value();
for (int i = 0, n = list.count(); i < n; ++i) {
if (list.at(i).isMutable) {
PropertyAction *a = new PropertyAction(i, list.at(i), index, menu);
connect(a, SIGNAL(toggled(bool,QPersistentModelIndex,int)),
this, SLOT(slotActionToggled(bool,QPersistentModelIndex,int)));
menu->addAction(a);
}
}
}
-void KisNodeView::updateNode(const QModelIndex &index)
+void NodeView::updateNode(const QModelIndex &index)
{
dataChanged(index, index);
}
-QItemSelectionModel::SelectionFlags KisNodeView::selectionCommand(const QModelIndex &index,
+QItemSelectionModel::SelectionFlags NodeView::selectionCommand(const QModelIndex &index,
const QEvent *event) const
{
/**
* Qt has a bug: when we Ctrl+click on an item, the item's
* selections gets toggled on mouse *press*, whereas usually it is
* done on mouse *release*. Therefore the user cannot do a
* Ctrl+D&D with the default configuration. This code fixes the
* problem by manually returning QItemSelectionModel::NoUpdate
* flag when the user clicks on an item and returning
* QItemSelectionModel::Toggle on release.
*/
if (event &&
(event->type() == QEvent::MouseButtonPress ||
event->type() == QEvent::MouseButtonRelease) &&
index.isValid()) {
const QMouseEvent *mevent = static_cast(event);
if (mevent->button() == Qt::RightButton &&
selectionModel()->selectedIndexes().contains(index)) {
// Allow calling context menu for multiple layers
return QItemSelectionModel::NoUpdate;
}
if (event->type() == QEvent::MouseButtonPress &&
(mevent->modifiers() & Qt::ControlModifier)) {
return QItemSelectionModel::NoUpdate;
}
if (event->type() == QEvent::MouseButtonRelease &&
(mevent->modifiers() & Qt::ControlModifier)) {
return QItemSelectionModel::Toggle;
}
}
/**
* Qt 5.6 has a bug: it reads global modifiers, not the ones
* passed from event. So if you paste an item using Ctrl+V it'll
* select multiple layers for you
*/
Qt::KeyboardModifiers globalModifiers = QApplication::keyboardModifiers();
if (!event && globalModifiers != Qt::NoModifier) {
return QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows;
}
return QAbstractItemView::selectionCommand(index, event);
}
-QRect KisNodeView::visualRect(const QModelIndex &index) const
+QRect NodeView::visualRect(const QModelIndex &index) const
{
QRect rc = QTreeView::visualRect(index);
if (layoutDirection() == Qt::RightToLeft)
rc.setRight(width());
else
rc.setLeft(0);
return rc;
}
-QRect KisNodeView::originalVisualRect(const QModelIndex &index) const
+QRect NodeView::originalVisualRect(const QModelIndex &index) const
{
return QTreeView::visualRect(index);
}
-QModelIndex KisNodeView::indexAt(const QPoint &point) const
+QModelIndex NodeView::indexAt(const QPoint &point) const
{
KisNodeViewColorScheme scm;
QModelIndex index = QTreeView::indexAt(point);
if (!index.isValid()) {
// Middle is a good position for both LTR and RTL layouts
// First reset x, then get the x in the middle
index = QTreeView::indexAt(point - QPoint(point.x(), 0) + QPoint(width() / 2, 0));
}
return index;
}
-bool KisNodeView::viewportEvent(QEvent *e)
+bool NodeView::viewportEvent(QEvent *e)
{
if (model()) {
switch(e->type()) {
case QEvent::MouseButtonPress: {
DRAG_WHILE_DRAG_WORKAROUND_STOP();
const QPoint pos = static_cast(e)->pos();
d->lastPos = pos;
if (!indexAt(pos).isValid()) {
return QTreeView::viewportEvent(e);
}
QModelIndex index = model()->buddy(indexAt(pos));
if (d->delegate.editorEvent(e, model(), optionForIndex(index), index)) {
return true;
}
} break;
case QEvent::Leave: {
QEvent e(QEvent::Leave);
d->delegate.editorEvent(&e, model(), optionForIndex(d->hovered), d->hovered);
d->hovered = QModelIndex();
} break;
case QEvent::MouseMove: {
#ifdef DRAG_WHILE_DRAG_WORKAROUND
if (d->isDragging) {
return false;
}
#endif
const QPoint pos = static_cast(e)->pos();
QModelIndex hovered = indexAt(pos);
if (hovered != d->hovered) {
if (d->hovered.isValid()) {
QEvent e(QEvent::Leave);
d->delegate.editorEvent(&e, model(), optionForIndex(d->hovered), d->hovered);
}
if (hovered.isValid()) {
QEvent e(QEvent::Enter);
d->delegate.editorEvent(&e, model(), optionForIndex(hovered), hovered);
}
d->hovered = hovered;
}
/* This is a workaround for a bug in QTreeView that immediately begins a dragging action
when the mouse lands on the decoration/icon of a different index and moves 1 pixel or more */
Qt::MouseButtons buttons = static_cast(e)->buttons();
if ((Qt::LeftButton | Qt::MidButton) & buttons) {
if ((pos - d->lastPos).manhattanLength() > qApp->startDragDistance()) {
return QTreeView::viewportEvent(e);
}
return true;
}
} break;
case QEvent::ToolTip: {
const QPoint pos = static_cast(e)->pos();
if (!indexAt(pos).isValid()) {
return QTreeView::viewportEvent(e);
}
QModelIndex index = model()->buddy(indexAt(pos));
return d->delegate.editorEvent(e, model(), optionForIndex(index), index);
} break;
case QEvent::Resize: {
scheduleDelayedItemsLayout();
break;
}
default: break;
}
}
return QTreeView::viewportEvent(e);
}
-void KisNodeView::contextMenuEvent(QContextMenuEvent *e)
+void NodeView::contextMenuEvent(QContextMenuEvent *e)
{
QTreeView::contextMenuEvent(e);
QModelIndex i = indexAt(e->pos());
if (model())
i = model()->buddy(i);
showContextMenu(e->globalPos(), i);
}
-void KisNodeView::showContextMenu(const QPoint &globalPos, const QModelIndex &index)
+void NodeView::showContextMenu(const QPoint &globalPos, const QModelIndex &index)
{
emit contextMenuRequested(globalPos, index);
}
-void KisNodeView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
+void NodeView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
{
QTreeView::currentChanged(current, previous);
if (current != previous) {
Q_ASSERT(!current.isValid() || current.model() == model());
model()->setData(current, true, KisNodeModel::ActiveRole);
}
}
-void KisNodeView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &/*roles*/)
+void NodeView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &/*roles*/)
{
QTreeView::dataChanged(topLeft, bottomRight);
for (int x = topLeft.row(); x <= bottomRight.row(); ++x) {
for (int y = topLeft.column(); y <= bottomRight.column(); ++y) {
QModelIndex index = topLeft.sibling(x, y);
if (index.data(KisNodeModel::ActiveRole).toBool()) {
if (currentIndex() != index) {
setCurrentIndex(index);
}
return;
}
}
}
}
-void KisNodeView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
+void NodeView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
QTreeView::selectionChanged(selected, deselected);
emit selectionChanged(selectedIndexes());
}
-void KisNodeView::slotActionToggled(bool on, const QPersistentModelIndex &index, int num)
+void NodeView::slotActionToggled(bool on, const QPersistentModelIndex &index, int num)
{
KisBaseNode::PropertyList list = index.data(KisNodeModel::PropertiesRole).value();
list[num].state = on;
const_cast(index.model())->setData(index, QVariant::fromValue(list), KisNodeModel::PropertiesRole);
}
-QStyleOptionViewItem KisNodeView::optionForIndex(const QModelIndex &index) const
+QStyleOptionViewItem NodeView::optionForIndex(const QModelIndex &index) const
{
QStyleOptionViewItem option = viewOptions();
option.rect = visualRect(index);
if (index == currentIndex())
option.state |= QStyle::State_HasFocus;
return option;
}
-void KisNodeView::startDrag(Qt::DropActions supportedActions)
+void NodeView::startDrag(Qt::DropActions supportedActions)
{
DRAG_WHILE_DRAG_WORKAROUND_START();
- if (displayMode() == KisNodeView::ThumbnailMode) {
+ if (displayMode() == NodeView::ThumbnailMode) {
const QModelIndexList indexes = selectionModel()->selectedIndexes();
if (!indexes.isEmpty()) {
QMimeData *data = model()->mimeData(indexes);
if (!data) {
return;
}
QDrag *drag = new QDrag(this);
drag->setPixmap(createDragPixmap());
drag->setMimeData(data);
//m_dragSource = this;
drag->exec(supportedActions);
}
}
else {
QTreeView::startDrag(supportedActions);
}
}
-QPixmap KisNodeView::createDragPixmap() const
+QPixmap NodeView::createDragPixmap() const
{
const QModelIndexList selectedIndexes = selectionModel()->selectedIndexes();
Q_ASSERT(!selectedIndexes.isEmpty());
const int itemCount = selectedIndexes.count();
// If more than one item is dragged, align the items inside a
// rectangular grid. The maximum grid size is limited to 4 x 4 items.
int xCount = 2;
int size = 96;
if (itemCount > 9) {
xCount = 4;
size = KisIconUtils::SizeLarge;
}
else if (itemCount > 4) {
xCount = 3;
size = KisIconUtils::SizeHuge;
}
else if (itemCount < xCount) {
xCount = itemCount;
}
int yCount = itemCount / xCount;
if (itemCount % xCount != 0) {
++yCount;
}
if (yCount > xCount) {
yCount = xCount;
}
// Draw the selected items into the grid cells
QPixmap dragPixmap(xCount * size + xCount - 1, yCount * size + yCount - 1);
dragPixmap.fill(Qt::transparent);
QPainter painter(&dragPixmap);
int x = 0;
int y = 0;
Q_FOREACH (const QModelIndex &selectedIndex, selectedIndexes) {
const QImage img = selectedIndex.data(int(KisNodeModel::BeginThumbnailRole) + size).value();
painter.drawPixmap(x, y, QPixmap().fromImage(img.scaled(QSize(size, size), Qt::KeepAspectRatio, Qt::SmoothTransformation)));
x += size + 1;
if (x >= dragPixmap.width()) {
x = 0;
y += size + 1;
}
if (y >= dragPixmap.height()) {
break;
}
}
return dragPixmap;
}
-void KisNodeView::resizeEvent(QResizeEvent * event)
+void NodeView::resizeEvent(QResizeEvent * event)
{
KisNodeViewColorScheme scm;
header()->setStretchLastSection(false);
header()->setOffset(-scm.visibilityColumnWidth());
header()->resizeSection(0, event->size().width() - scm.visibilityColumnWidth());
setIndentation(scm.indentation());
QTreeView::resizeEvent(event);
}
-void KisNodeView::paintEvent(QPaintEvent *event)
+void NodeView::paintEvent(QPaintEvent *event)
{
event->accept();
QTreeView::paintEvent(event);
// Paint the line where the slide should go
- if (isDragging() && (displayMode() == KisNodeView::ThumbnailMode)) {
+ if (isDragging() && (displayMode() == NodeView::ThumbnailMode)) {
QSize size(visualRect(model()->index(0, 0, QModelIndex())).width(), visualRect(model()->index(0, 0, QModelIndex())).height());
int numberRow = cursorPageIndex();
int scrollBarValue = verticalScrollBar()->value();
QPoint point1(0, numberRow * size.height() - scrollBarValue);
QPoint point2(size.width(), numberRow * size.height() - scrollBarValue);
QLineF line(point1, point2);
QPainter painter(this->viewport());
QPen pen = QPen(palette().brush(QPalette::Highlight), 8);
pen.setCapStyle(Qt::RoundCap);
painter.setPen(pen);
painter.setOpacity(0.8);
painter.drawLine(line);
}
}
-void KisNodeView::drawBranches(QPainter *painter, const QRect &rect,
+void NodeView::drawBranches(QPainter *painter, const QRect &rect,
const QModelIndex &index) const
{
Q_UNUSED(painter);
Q_UNUSED(rect);
Q_UNUSED(index);
/**
- * Noop... Everything is going to be painted by KisNodeDelegate.
+ * Noop... Everything is going to be painted by NodeDelegate.
* So this override basically disables painting of Qt's branch-lines.
*/
}
-void KisNodeView::dropEvent(QDropEvent *ev)
+void NodeView::dropEvent(QDropEvent *ev)
{
- if (displayMode() == KisNodeView::ThumbnailMode) {
+ if (displayMode() == NodeView::ThumbnailMode) {
setDraggingFlag(false);
ev->accept();
clearSelection();
if (!model()) {
return;
}
int newIndex = cursorPageIndex();
model()->dropMimeData(ev->mimeData(), ev->dropAction(), newIndex, -1, QModelIndex());
return;
}
QTreeView::dropEvent(ev);
DRAG_WHILE_DRAG_WORKAROUND_STOP();
}
-int KisNodeView::cursorPageIndex() const
+int NodeView::cursorPageIndex() const
{
QSize size(visualRect(model()->index(0, 0, QModelIndex())).width(), visualRect(model()->index(0, 0, QModelIndex())).height());
int scrollBarValue = verticalScrollBar()->value();
QPoint cursorPosition = QWidget::mapFromGlobal(QCursor::pos());
int numberRow = (cursorPosition.y() + scrollBarValue) / size.height();
//If cursor is at the half button of the page then the move action is performed after the slide, otherwise it is
//performed before the page
if (abs((cursorPosition.y() + scrollBarValue) - size.height()*numberRow) > (size.height()/2)) {
numberRow++;
}
if (numberRow > model()->rowCount(QModelIndex())) {
numberRow = model()->rowCount(QModelIndex());
}
return numberRow;
}
-void KisNodeView::dragEnterEvent(QDragEnterEvent *ev)
+void NodeView::dragEnterEvent(QDragEnterEvent *ev)
{
DRAG_WHILE_DRAG_WORKAROUND_START();
QVariant data = qVariantFromValue(
static_cast(const_cast(ev->mimeData())));
model()->setData(QModelIndex(), data, KisNodeModel::DropEnabled);
QTreeView::dragEnterEvent(ev);
}
-void KisNodeView::dragMoveEvent(QDragMoveEvent *ev)
+void NodeView::dragMoveEvent(QDragMoveEvent *ev)
{
DRAG_WHILE_DRAG_WORKAROUND_START();
- if (displayMode() == KisNodeView::ThumbnailMode) {
+ if (displayMode() == NodeView::ThumbnailMode) {
ev->accept();
if (!model()) {
return;
}
QTreeView::dragMoveEvent(ev);
setDraggingFlag();
viewport()->update();
return;
}
QTreeView::dragMoveEvent(ev);
}
-void KisNodeView::dragLeaveEvent(QDragLeaveEvent *e)
+void NodeView::dragLeaveEvent(QDragLeaveEvent *e)
{
- if (displayMode() == KisNodeView::ThumbnailMode) {
+ if (displayMode() == NodeView::ThumbnailMode) {
setDraggingFlag(false);
} else {
QTreeView::dragLeaveEvent(e);
}
DRAG_WHILE_DRAG_WORKAROUND_STOP();
}
-bool KisNodeView::isDragging() const
+bool NodeView::isDragging() const
{
return m_draggingFlag;
}
-void KisNodeView::setDraggingFlag(bool flag)
+void NodeView::setDraggingFlag(bool flag)
{
m_draggingFlag = flag;
}
-void KisNodeView::slotUpdateIcons()
+void NodeView::slotUpdateIcons()
{
d->delegate.slotUpdateIcon();
}
-void KisNodeView::slotScrollerStateChanged(QScroller::State state){
+void NodeView::slotScrollerStateChanged(QScroller::State state){
KisKineticScroller::updateCursor(this, state);
}
diff --git a/libs/ui/KisNodeView.h b/plugins/dockers/layerdocker/NodeView.h
similarity index 95%
rename from libs/ui/KisNodeView.h
rename to plugins/dockers/layerdocker/NodeView.h
index 36b3c32794..abcd06d9af 100644
--- a/libs/ui/KisNodeView.h
+++ b/plugins/dockers/layerdocker/NodeView.h
@@ -1,188 +1,187 @@
/*
Copyright (c) 2006 Gábor Lehel
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KIS_DOCUMENT_SECTION_VIEW_H
#define KIS_DOCUMENT_SECTION_VIEW_H
#include
#include
-#include "kritaui_export.h"
class QStyleOptionViewItem;
class KisNodeModel;
/**
* A widget displaying the Krita nodes (layers, masks, local selections, etc.)
*
* The widget can show the document sections as big thumbnails,
* in a listview with two rows of informative text and icons,
* or as single rows of text and property icons.
*
* This class is designed as a Qt model-view widget.
*
* The Qt documentation explains the design and terminology for these classes:
* http://doc.qt.io/qt-5/model-view-programming.html
*
* This widget should work correctly in your Qt designer .ui file.
*/
-class KRITAUI_EXPORT KisNodeView: public QTreeView
+class NodeView: public QTreeView
{
Q_OBJECT
Q_SIGNALS:
/**
* Emitted whenever the user clicks with the secondary mouse
* button on an item. It is up to the application to design the
* contents of the context menu and show it.
*/
void contextMenuRequested(const QPoint &globalPos, const QModelIndex &index);
void selectionChanged(const QModelIndexList &);
public:
/**
- * Create a new KisNodeView.
+ * Create a new NodeView.
*/
- explicit KisNodeView(QWidget *parent = 0);
- ~KisNodeView() override;
+ explicit NodeView(QWidget *parent = 0);
+ ~NodeView() override;
/// how items should be displayed
enum DisplayMode {
/// large fit-to-width thumbnails, with only titles or page numbers
ThumbnailMode,
/// smaller thumbnails, with titles and property icons in two rows
DetailedMode,
/// no thumbnails, with titles and property icons in a single row
MinimalMode
};
void resizeEvent(QResizeEvent * event) override;
void paintEvent (QPaintEvent *event) override;
void drawBranches(QPainter *painter, const QRect &rect,
const QModelIndex &index) const override;
void dropEvent(QDropEvent *ev) override;
void dragEnterEvent(QDragEnterEvent *e) override;
void dragMoveEvent(QDragMoveEvent *ev) override;
void dragLeaveEvent(QDragLeaveEvent *e) override;
/**
* Set the display mode of the view to one of the options.
*
- * @param mode The KisNodeView::DisplayMode mode
+ * @param mode The NodeView::DisplayMode mode
*/
void setDisplayMode(DisplayMode mode);
/**
* @return the currently active display mode
*/
DisplayMode displayMode() const;
/**
* Add toggle actions for all the properties associated with the
* current document section associated with the model index to the
* specified menu.
*
* For instance, if a document section can be locked and visible,
* the menu will be expanded with locked and visible toggle
* actions.
*
* For instance
@code
- KisNodeView * nodeView;
+ NodeView * nodeView;
QModelIndex index = getCurrentNode();
QMenu menu;
if (index.isValid()) {
sectionView->addPropertyActions(&menu, index);
} else {
menu.addAction(...); // Something to create a new document section, for example.
}
@endcode
*
* @param menu A pointer to the menu that will be expanded with
* the toglge actions
* @param index The model index associated with the document
* section that may or may not provide a number of toggle actions.
*/
void addPropertyActions(QMenu *menu, const QModelIndex &index);
void updateNode(const QModelIndex &index);
QRect originalVisualRect(const QModelIndex &index) const;
protected:
QItemSelectionModel::SelectionFlags selectionCommand(const QModelIndex &index,
const QEvent *event) const override;
QRect visualRect(const QModelIndex &index) const override;
QModelIndex indexAt(const QPoint &point) const override;
bool viewportEvent(QEvent *event) override;
void contextMenuEvent(QContextMenuEvent *event) override;
virtual void showContextMenu(const QPoint &globalPos, const QModelIndex &index);
void startDrag (Qt::DropActions supportedActions) override;
QPixmap createDragPixmap() const;
/**
* Calculates the index of the nearest item to the cursor position
*/
int cursorPageIndex() const;
public Q_SLOTS:
/// called with a theme change to refresh icon colors
void slotUpdateIcons();
void slotScrollerStateChanged(QScroller::State state);
protected Q_SLOTS:
void currentChanged(const QModelIndex ¤t, const QModelIndex &previous) override;
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles = QVector()) override;
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) override;
private Q_SLOTS:
void slotActionToggled(bool on, const QPersistentModelIndex &index, int property);
private:
/**
* Permit to know if a slide is dragging
*
* @return boolean
*/
bool isDragging() const;
/**
* Setter for the dragging flag
*
* @param flag boolean
*/
void setDraggingFlag(bool flag = true);
bool m_draggingFlag;
QStyleOptionViewItem optionForIndex(const QModelIndex &index) const;
typedef KisNodeModel Model;
class PropertyAction;
class Private;
Private* const d;
};
#endif
diff --git a/libs/ui/kis_node_view_visibility_delegate.cpp b/plugins/dockers/layerdocker/NodeViewVisibilityDelegate.cpp
similarity index 71%
rename from libs/ui/kis_node_view_visibility_delegate.cpp
rename to plugins/dockers/layerdocker/NodeViewVisibilityDelegate.cpp
index f0e80e97c8..fd6db93b6e 100644
--- a/libs/ui/kis_node_view_visibility_delegate.cpp
+++ b/plugins/dockers/layerdocker/NodeViewVisibilityDelegate.cpp
@@ -1,46 +1,46 @@
/*
* Copyright (c) 2015 Dmitry Kazakov
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include "kis_node_view_visibility_delegate.h"
+#include "NodeViewVisibilityDelegate.h"
#include "kis_node_view_color_scheme.h"
-KisNodeViewVisibilityDelegate::KisNodeViewVisibilityDelegate(QObject *parent)
+NodeViewVisibilityDelegate::NodeViewVisibilityDelegate(QObject *parent)
: QAbstractItemDelegate(parent)
{
}
-KisNodeViewVisibilityDelegate::~KisNodeViewVisibilityDelegate()
+NodeViewVisibilityDelegate::~NodeViewVisibilityDelegate()
{
}
-void KisNodeViewVisibilityDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+void NodeViewVisibilityDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(painter);
Q_UNUSED(option);
Q_UNUSED(index);
}
-QSize KisNodeViewVisibilityDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
+QSize NodeViewVisibilityDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index);
KisNodeViewColorScheme scm;
return QSize(option.rect.width(), scm.rowHeight());
}
diff --git a/libs/ui/kis_node_view_visibility_delegate.h b/plugins/dockers/layerdocker/NodeViewVisibilityDelegate.h
similarity index 77%
rename from libs/ui/kis_node_view_visibility_delegate.h
rename to plugins/dockers/layerdocker/NodeViewVisibilityDelegate.h
index b5d8da9094..baa6cb41f2 100644
--- a/libs/ui/kis_node_view_visibility_delegate.h
+++ b/plugins/dockers/layerdocker/NodeViewVisibilityDelegate.h
@@ -1,35 +1,35 @@
/*
* Copyright (c) 2015 Dmitry Kazakov
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __KIS_NODE_VIEW_VISIBILITY_DELEGATE_H
-#define __KIS_NODE_VIEW_VISIBILITY_DELEGATE_H
+#ifndef __NODE_VIEW_VISIBILITY_DELEGATE_H
+#define __NODE_VIEW_VISIBILITY_DELEGATE_H
#include
-class KisNodeViewVisibilityDelegate : public QAbstractItemDelegate
+class NodeViewVisibilityDelegate : public QAbstractItemDelegate
{
public:
- KisNodeViewVisibilityDelegate(QObject *parent);
- ~KisNodeViewVisibilityDelegate() override;
+ NodeViewVisibilityDelegate(QObject *parent);
+ ~NodeViewVisibilityDelegate() override;
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
};
-#endif /* __KIS_NODE_VIEW_VISIBILITY_DELEGATE_H */
+#endif
diff --git a/plugins/dockers/defaultdockers/sync_button_and_action.h b/plugins/dockers/layerdocker/SyncButtonAndAction.h
similarity index 96%
rename from plugins/dockers/defaultdockers/sync_button_and_action.h
rename to plugins/dockers/layerdocker/SyncButtonAndAction.h
index 8faf48849b..bbcfcd36ac 100644
--- a/plugins/dockers/defaultdockers/sync_button_and_action.h
+++ b/plugins/dockers/layerdocker/SyncButtonAndAction.h
@@ -1,55 +1,55 @@
/*
* Copyright (c) 2015 Dmitry Kazakov
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __SYNC_BUTTON_AND_ACTION_H
-#define __SYNC_BUTTON_AND_ACTION_H
+#ifndef SYNC_BUTTON_AND_ACTION_H
+#define SYNC_BUTTON_AND_ACTION_H
#include
#include
#include "kis_action.h"
class SyncButtonAndAction : public QObject
{
Q_OBJECT
public:
SyncButtonAndAction(KisAction *action, QAbstractButton *button, QObject *parent)
: QObject(parent),
m_action(action),
m_button(button)
{
connect(m_action, SIGNAL(changed()), SLOT(slotActionChanged()));
connect(m_button, SIGNAL(clicked()), m_action, SLOT(trigger()));
m_button->setIcon(m_action->icon());
m_button->setText(m_action->text());
}
private Q_SLOTS:
void slotActionChanged() {
if (m_action && m_button &&
m_action->isEnabled() != m_button->isEnabled()) {
m_button->setEnabled(m_action->isEnabled());
}
}
private:
QPointer m_action;
QPointer m_button;
};
#endif /* __SYNC_BUTTON_AND_ACTION_H */
diff --git a/plugins/dockers/defaultdockers/wdglayerbox.ui b/plugins/dockers/layerdocker/WdgLayerBox.ui
similarity index 98%
rename from plugins/dockers/defaultdockers/wdglayerbox.ui
rename to plugins/dockers/layerdocker/WdgLayerBox.ui
index 30a68514b9..6822e8329c 100644
--- a/plugins/dockers/defaultdockers/wdglayerbox.ui
+++ b/plugins/dockers/layerdocker/WdgLayerBox.ui
@@ -1,349 +1,349 @@
WdgLayerBox
0
0
220
384
1
0
0
0
0
-
0
0
0
0
-
0
0
Blending Mode
Select the blending mode for the layer.
-
22
22
-
0
0
-
Opacity:
-
0
0
Layer Opacity
Adjust the transparency of the layer
-
0
0
...
22
22
-
-
-
+
0
0
-
2
0
-
0
28
16777215
28
...
true
-
28
28
Duplicate layer or mask
...
22
22
true
-
28
28
Move layer or mask down
...
22
22
true
-
28
28
Move layer or mask up
...
22
22
true
-
28
28
View or change the layer properties
...
22
22
true
-
Qt::Horizontal
QSizePolicy::Expanding
0
28
-
28
28
Delete the layer or mask
...
22
22
true
KisCompositeOpComboBox
QComboBox
widgets/kis_cmb_composite.h
KisDoubleSliderSpinBox
QWidget
- KisNodeView
+ NodeView
-
+
KisToolButton
QToolButton
KisColorFilterCombo
QComboBox
cmbComposite
bnDuplicate
bnLower
bnRaise
bnProperties
bnDelete
diff --git a/plugins/dockers/defaultdockers/kritadefaultdockers.json b/plugins/dockers/layerdocker/kritalayerdocker.json
similarity index 60%
rename from plugins/dockers/defaultdockers/kritadefaultdockers.json
rename to plugins/dockers/layerdocker/kritalayerdocker.json
index d2c6027aaa..b31afe6cac 100644
--- a/plugins/dockers/defaultdockers/kritadefaultdockers.json
+++ b/plugins/dockers/layerdocker/kritalayerdocker.json
@@ -1,9 +1,9 @@
{
- "Id": "Default Dockers",
+ "Id": "Layer Docker",
"Type": "Service",
- "X-KDE-Library": "kritadefaultdockers",
+ "X-KDE-Library": "kritalayerdocker",
"X-KDE-ServiceTypes": [
"Krita/Dock"
],
"X-Krita-Version": "28"
}
diff --git a/plugins/dockers/layerdocker/tests/CMakeLists.txt b/plugins/dockers/layerdocker/tests/CMakeLists.txt
new file mode 100644
index 0000000000..6518a882ea
--- /dev/null
+++ b/plugins/dockers/layerdocker/tests/CMakeLists.txt
@@ -0,0 +1,13 @@
+set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} )
+
+include_directories(${CMAKE_SOURCE_DIR}/libs/image/metadata
+ ${CMAKE_SOURCE_DIR}/sdk/tests )
+include(ECMAddTests)
+
+macro_add_unittest_definitions()
+qt5_add_resources(kis_node_view_test_SRCS ${krita_QRCS})
+ecm_add_test(${kis_node_view_test_SRCS}
+ TEST_NAME TestNodeView
+ LINK_LIBRARIES kritaui Qt5::Test
+ NAME_PREFIX "plugins-dockers-layerdocker-")
+
diff --git a/libs/ui/tests/kis_node_view_test.cpp b/plugins/dockers/layerdocker/tests/TestNodeView.cpp
similarity index 91%
rename from libs/ui/tests/kis_node_view_test.cpp
rename to plugins/dockers/layerdocker/tests/TestNodeView.cpp
index 170d28e917..993e7b647f 100644
--- a/libs/ui/tests/kis_node_view_test.cpp
+++ b/plugins/dockers/layerdocker/tests/TestNodeView.cpp
@@ -1,133 +1,133 @@
/*
* Copyright (c) 2015 Dmitry Kazakov
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include "kis_node_view_test.h"
+#include "TestNodeView.h"
#include
#include
#include
#include
#include
-#include
+#include
#include "KisDocument.h"
#include "KisPart.h"
#include "kis_name_server.h"
#include "flake/kis_shape_controller.h"
#include "kis_undo_adapter.h"
#include "kis_node_model.h"
#include "kis_color_filter_combo.h"
#include
//#define ENABLE_GUI_TESTS
-void KisNodeViewTest::init()
+void NodeViewTest::init()
{
m_doc = KisPart::instance()->createDocument();
m_nameServer = new KisNameServer();
m_shapeController = new KisShapeController(m_doc, m_nameServer);
initBase();
}
-void KisNodeViewTest::cleanup()
+void NodeViewTest::cleanup()
{
cleanupBase();
delete m_shapeController;
delete m_nameServer;
delete m_doc;
}
-void KisNodeViewTest::testLayers()
+void NodeViewTest::testLayers()
{
#ifndef ENABLE_GUI_TESTS
return;
#endif
QDialog dlg;
QFont font;
font.setPointSizeF(8);
dlg.setFont(font);
KisNodeModel *model = new KisNodeModel(this);
- KisNodeView *view = new KisNodeView(&dlg);
+ NodeView *view = new NodeView(&dlg);
view->setModel(model);
constructImage();
addSelectionMasks();
m_shapeController->setImage(m_image);
model->setDummiesFacade(m_shapeController, m_image, m_shapeController, 0, 0, 0, 0);
QVBoxLayout *layout = new QVBoxLayout(&dlg);
KisColorFilterCombo *cb = new KisColorFilterCombo(&dlg);
QSet labels;
for (int i = 0; i < 6; i++) {
labels.insert(i);
}
cb->updateAvailableLabels(labels);
QHBoxLayout *hbox = new QHBoxLayout(&dlg);
hbox->addStretch(1);
hbox->addWidget(cb);
layout->addLayout(hbox);
layout->addWidget(view);
dlg.resize(280, 400);
view->expandAll();
dlg.exec();
}
#include "kis_color_label_selector_widget.h"
-void KisNodeViewTest::testColorLabels()
+void NodeViewTest::testColorLabels()
{
#ifndef ENABLE_GUI_TESTS
return;
#endif
QDialog dlg;
QFont font;
font.setPointSizeF(8);
dlg.setFont(font);
KisColorLabelSelectorWidget *widget = new KisColorLabelSelectorWidget(&dlg);
QSizePolicy policy(QSizePolicy::Preferred, QSizePolicy::Preferred);
widget->setSizePolicy(policy);
QVBoxLayout *layout = new QVBoxLayout(&dlg);
layout->addWidget(widget);
layout->addStretch(1);
dlg.resize(280, 400);
dlg.exec();
}
-KISTEST_MAIN(KisNodeViewTest)
+KISTEST_MAIN(NodeViewTest)
diff --git a/libs/ui/tests/kis_node_view_test.h b/plugins/dockers/layerdocker/tests/TestNodeView.h
similarity index 94%
rename from libs/ui/tests/kis_node_view_test.h
rename to plugins/dockers/layerdocker/tests/TestNodeView.h
index 5d89ef0826..141a6ae37c 100644
--- a/libs/ui/tests/kis_node_view_test.h
+++ b/plugins/dockers/layerdocker/tests/TestNodeView.h
@@ -1,46 +1,46 @@
/*
* Copyright (c) 2015 Dmitry Kazakov
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __KIS_NODE_VIEW_TEST_H
#define __KIS_NODE_VIEW_TEST_H
#include
#include "empty_nodes_test.h"
class KisDocument;
class KisNameServer;
class KisShapeController;
-class KisNodeViewTest : public QObject, public TestUtil::EmptyNodesTest
+class NodeViewTest : public QObject, public TestUtil::EmptyNodesTest
{
Q_OBJECT
private Q_SLOTS:
void init();
void cleanup();
void testLayers();
void testColorLabels();
private:
KisDocument *m_doc;
KisNameServer *m_nameServer;
KisShapeController *m_shapeController;
};
#endif /* __KIS_NODE_VIEW_TEST_H */
diff --git a/plugins/extensions/animationrenderer/AnimationRenderer.cpp b/plugins/extensions/animationrenderer/AnimationRenderer.cpp
index a7ddbcc5ac..8bbb553aa6 100644
--- a/plugins/extensions/animationrenderer/AnimationRenderer.cpp
+++ b/plugins/extensions/animationrenderer/AnimationRenderer.cpp
@@ -1,188 +1,206 @@
/*
* Copyright (c) 2016 Boudewijn Rempt
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "AnimationRenderer.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "DlgAnimationRenderer.h"
#include
#include "video_saver.h"
#include "KisAnimationRenderingOptions.h"
K_PLUGIN_FACTORY_WITH_JSON(AnimaterionRendererFactory, "kritaanimationrenderer.json", registerPlugin();)
AnimaterionRenderer::AnimaterionRenderer(QObject *parent, const QVariantList &)
: KisActionPlugin(parent)
{
// Shows the big dialog
KisAction *action = createAction("render_animation");
action->setActivationFlags(KisAction::IMAGE_HAS_ANIMATION);
connect(action, SIGNAL(triggered()), this, SLOT(slotRenderAnimation()));
// Re-renders the image sequence as defined in the last render
action = createAction("render_animation_again");
action->setActivationFlags(KisAction::IMAGE_HAS_ANIMATION);
connect(action, SIGNAL(triggered()), this, SLOT(slotRenderSequenceAgain()));
}
AnimaterionRenderer::~AnimaterionRenderer()
{
}
void AnimaterionRenderer::slotRenderAnimation()
{
KisImageWSP image = viewManager()->image();
if (!image) return;
if (!image->animationInterface()->hasAnimation()) return;
KisDocument *doc = viewManager()->document();
DlgAnimationRenderer dlgAnimationRenderer(doc, viewManager()->mainWindow());
dlgAnimationRenderer.setCaption(i18n("Render Animation"));
if (dlgAnimationRenderer.exec() == QDialog::Accepted) {
KisAnimationRenderingOptions encoderOptions = dlgAnimationRenderer.getEncoderOptions();
renderAnimationImpl(doc, encoderOptions);
}
}
void AnimaterionRenderer::slotRenderSequenceAgain()
{
KisImageWSP image = viewManager()->image();
if (!image) return;
if (!image->animationInterface()->hasAnimation()) return;
KisDocument *doc = viewManager()->document();
KisConfig cfg(true);
KisPropertiesConfigurationSP settings = cfg.exportConfiguration("ANIMATION_EXPORT");
KisAnimationRenderingOptions encoderOptions;
encoderOptions.fromProperties(settings);
renderAnimationImpl(doc, encoderOptions);
}
void AnimaterionRenderer::renderAnimationImpl(KisDocument *doc, KisAnimationRenderingOptions encoderOptions)
{
const QString frameMimeType = encoderOptions.frameMimeType;
const QString framesDirectory = encoderOptions.resolveAbsoluteFramesDirectory();
const QString extension = KisMimeDatabase::suffixesForMimeType(frameMimeType).first();
const QString baseFileName = QString("%1/%2.%3").arg(framesDirectory)
.arg(encoderOptions.basename)
.arg(extension);
/**
- * The dialog should endure that the size of the video is even
+ * The dialog should ensure that the size of the video is even
*/
KIS_SAFE_ASSERT_RECOVER(
!((encoderOptions.width & 0x1 || encoderOptions.height & 0x1)
&& (encoderOptions.videoMimeType == "video/mp4" ||
encoderOptions.videoMimeType == "video/x-matroska"))) {
encoderOptions.width = encoderOptions.width + (encoderOptions.width & 0x1);
encoderOptions.height = encoderOptions.height + (encoderOptions.height & 0x1);
}
+ const QSize scaledSize =
+ doc->image()->bounds().size().scaled(
+ encoderOptions.width, encoderOptions.height,
+ Qt::KeepAspectRatio);
+
+ if ((scaledSize.width() & 0x1 || scaledSize.height() & 0x1)
+ && (encoderOptions.videoMimeType == "video/mp4" ||
+ encoderOptions.videoMimeType == "video/x-matroska")) {
+ QString m = "Mastroska (.mkv)";
+ if (encoderOptions.videoMimeType == "video/mp4") {
+ m = "Mpeg4 (.mp4)";
+ }
+ qWarning() << m <<"requires width and height to be even, resize and try again!";
+ doc->setErrorMessage(i18n("%1 requires width and height to be even numbers. Please resize or crop the image before exporting.", m));
+ QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Could not render animation:\n%1", doc->errorMessage()));
+ return;
+ }
+
const bool batchMode = false; // TODO: fetch correctly!
KisAsyncAnimationFramesSaveDialog exporter(doc->image(),
KisTimeRange::fromTime(encoderOptions.firstFrame,
encoderOptions.lastFrame),
baseFileName,
encoderOptions.sequenceStart,
encoderOptions.frameExportConfig);
exporter.setBatchMode(batchMode);
KisAsyncAnimationFramesSaveDialog::Result result =
exporter.regenerateRange(viewManager()->mainWindow()->viewManager());
// the folder could have been read-only or something else could happen
if (encoderOptions.shouldEncodeVideo &&
result == KisAsyncAnimationFramesSaveDialog::RenderComplete) {
const QString savedFilesMask = exporter.savedFilesMask();
const QString resultFile = encoderOptions.resolveAbsoluteVideoFilePath();
KIS_SAFE_ASSERT_RECOVER_NOOP(QFileInfo(resultFile).isAbsolute())
{
const QFileInfo info(resultFile);
QDir dir(info.absolutePath());
if (!dir.exists()) {
dir.mkpath(info.absolutePath());
}
KIS_SAFE_ASSERT_RECOVER_NOOP(dir.exists());
}
KisImportExportFilter::ConversionStatus res;
QFile fi(resultFile);
if (!fi.open(QIODevice::WriteOnly)) {
qWarning() << "Could not open" << fi.fileName() << "for writing!";
doc->setErrorMessage(i18n("Could not open %1 for writing!", fi.fileName()));
res = KisImportExportFilter::CreationError;
} else {
fi.close();
}
QScopedPointer encoder(new VideoSaver(doc, batchMode));
res = encoder->convert(doc, savedFilesMask, encoderOptions, batchMode);
if (res != KisImportExportFilter::OK) {
QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Could not render animation:\n%1", doc->errorMessage()));
}
if (encoderOptions.shouldDeleteSequence) {
QDir d(framesDirectory);
QStringList sequenceFiles = d.entryList(QStringList() << encoderOptions.basename + "*." + extension, QDir::Files);
Q_FOREACH(const QString &f, sequenceFiles) {
d.remove(f);
}
}
} else if (result == KisAsyncAnimationFramesSaveDialog::RenderFailed) {
viewManager()->mainWindow()->viewManager()->showFloatingMessage(i18n("Failed to render animation frames!"), QIcon());
}
}
#include "AnimationRenderer.moc"
diff --git a/plugins/extensions/animationrenderer/DlgAnimationRenderer.cpp b/plugins/extensions/animationrenderer/DlgAnimationRenderer.cpp
index 1d0b97eacd..1beb1d6e27 100644
--- a/plugins/extensions/animationrenderer/DlgAnimationRenderer.cpp
+++ b/plugins/extensions/animationrenderer/DlgAnimationRenderer.cpp
@@ -1,576 +1,586 @@
/*
* Copyright (c) 2016 Boudewijn Rempt
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "DlgAnimationRenderer.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "kis_slider_spin_box.h"
#include "kis_acyclic_signal_connector.h"
#include "video_saver.h"
#include "KisAnimationRenderingOptions.h"
#include "video_export_options_dialog.h"
DlgAnimationRenderer::DlgAnimationRenderer(KisDocument *doc, QWidget *parent)
: KoDialog(parent)
, m_image(doc->image())
, m_doc(doc)
{
KisConfig cfg(true);
setCaption(i18n("Render Animation"));
setButtons(Ok | Cancel);
setDefaultButton(Ok);
m_page = new WdgAnimationRenderer(this);
m_page->layout()->setMargin(0);
m_page->dirRequester->setMode(KoFileDialog::OpenDirectory);
m_page->intStart->setMinimum(doc->image()->animationInterface()->fullClipRange().start());
m_page->intStart->setMaximum(doc->image()->animationInterface()->fullClipRange().end());
m_page->intStart->setValue(doc->image()->animationInterface()->playbackRange().start());
m_page->intEnd->setMinimum(doc->image()->animationInterface()->fullClipRange().start());
// animators sometimes want to export after end frame
//m_page->intEnd->setMaximum(doc->image()->animationInterface()->fullClipRange().end());
m_page->intEnd->setValue(doc->image()->animationInterface()->playbackRange().end());
m_page->intHeight->setMinimum(1);
m_page->intHeight->setMaximum(10000);
m_page->intHeight->setValue(doc->image()->height());
m_page->intWidth->setMinimum(1);
m_page->intWidth->setMaximum(10000);
m_page->intWidth->setValue(doc->image()->width());
// try to lock the width and height being updated
KisAcyclicSignalConnector *constrainsConnector = new KisAcyclicSignalConnector(this);
constrainsConnector->createCoordinatedConnector()->connectBackwardInt(m_page->intWidth, SIGNAL(valueChanged(int)), this, SLOT(slotLockAspectRatioDimensionsWidth(int)));
constrainsConnector->createCoordinatedConnector()->connectForwardInt(m_page->intHeight, SIGNAL(valueChanged(int)), this, SLOT(slotLockAspectRatioDimensionsHeight(int)));
m_page->intFramesPerSecond->setValue(doc->image()->animationInterface()->framerate());
QFileInfo audioFileInfo(doc->image()->animationInterface()->audioChannelFileName());
const bool hasAudio = audioFileInfo.exists();
m_page->chkIncludeAudio->setEnabled(hasAudio);
m_page->chkIncludeAudio->setChecked(hasAudio && !doc->image()->animationInterface()->isAudioMuted());
QStringList mimes = KisImportExportManager::supportedMimeTypes(KisImportExportManager::Export);
mimes.sort();
Q_FOREACH(const QString &mime, mimes) {
QString description = KisMimeDatabase::descriptionForMimeType(mime);
if (description.isEmpty()) {
description = mime;
}
m_page->cmbMimetype->addItem(description, mime);
if (mime == "image/png") {
m_page->cmbMimetype->setCurrentIndex(m_page->cmbMimetype->count() - 1);
}
}
setMainWidget(m_page);
QVector supportedMimeType;
supportedMimeType << "video/x-matroska";
supportedMimeType << "image/gif";
supportedMimeType << "video/ogg";
supportedMimeType << "video/mp4";
Q_FOREACH (const QString &mime, supportedMimeType) {
QString description = KisMimeDatabase::descriptionForMimeType(mime);
if (description.isEmpty()) {
description = mime;
}
m_page->cmbRenderType->addItem(description, mime);
}
m_page->videoFilename->setMode(KoFileDialog::SaveFile);
- m_page->videoFilename->setStartDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation));
connect(m_page->bnExportOptions, SIGNAL(clicked()), this, SLOT(sequenceMimeTypeSelected()));
connect(m_page->bnRenderOptions, SIGNAL(clicked()), this, SLOT(selectRenderOptions()));
m_page->ffmpegLocation->setMode(KoFileDialog::OpenFile);
m_page->cmbRenderType->setCurrentIndex(cfg.readEntry("AnimationRenderer/render_type", 0));
connect(m_page->shouldExportOnlyImageSequence, SIGNAL(toggled(bool)), this, SLOT(slotExportTypeChanged()));
connect(m_page->shouldExportOnlyVideo, SIGNAL(toggled(bool)), this, SLOT(slotExportTypeChanged()));
connect(m_page->shouldExportAll, SIGNAL(toggled(bool)), this, SLOT(slotExportTypeChanged()));
// connect and cold init
connect(m_page->cmbRenderType, SIGNAL(currentIndexChanged(int)), this, SLOT(selectRenderType(int)));
selectRenderType(m_page->cmbRenderType->currentIndex());
resize(m_page->sizeHint());
connect(this, SIGNAL(accepted()), SLOT(slotDialogAccepted()));
{
KisPropertiesConfigurationSP settings = cfg.exportConfiguration("ANIMATION_EXPORT");
KisAnimationRenderingOptions options;
options.fromProperties(settings);
loadAnimationOptions(options);
/**
* There is already a (modified) frames config in the options themselves,
* but we should better read the one, generated by the config widget, because
* it may have some changes made to the "last use type config".
*/
m_frameExportConfig = cfg.exportConfiguration(options.frameMimeType);
}
}
DlgAnimationRenderer::~DlgAnimationRenderer()
{
delete m_page;
}
void DlgAnimationRenderer::getDefaultVideoEncoderOptions(const QString &mimeType,
KisPropertiesConfigurationSP cfg,
QString *customFFMpegOptionsString,
bool *forceHDRVideo)
{
const VideoExportOptionsDialog::ContainerType containerType =
mimeType == "video/ogg" ?
VideoExportOptionsDialog::OGV :
VideoExportOptionsDialog::DEFAULT;
QScopedPointer encoderConfigWidget(
new VideoExportOptionsDialog(containerType, 0));
// we always enable HDR, letting the user to force it
encoderConfigWidget->setSupportsHDR(true);
encoderConfigWidget->setConfiguration(cfg);
*customFFMpegOptionsString = encoderConfigWidget->customUserOptionsString();
*forceHDRVideo = encoderConfigWidget->forceHDRModeForFrames();
}
void DlgAnimationRenderer::loadAnimationOptions(const KisAnimationRenderingOptions &options)
{
+ const QString documentPath = m_doc->localFilePath();
+
m_page->txtBasename->setText(options.basename);
if (!options.lastDocuemntPath.isEmpty() &&
- options.lastDocuemntPath == m_doc->localFilePath()) {
+ options.lastDocuemntPath == documentPath) {
m_page->intStart->setValue(options.firstFrame);
m_page->intEnd->setValue(options.lastFrame);
m_page->sequenceStart->setValue(options.sequenceStart);
m_page->intWidth->setValue(options.width);
m_page->intHeight->setValue(options.height);
m_page->intFramesPerSecond->setValue(options.frameRate);
+
+ m_page->videoFilename->setStartDir(options.resolveAbsoluteDocumentFilePath(documentPath));
m_page->videoFilename->setFileName(options.videoFileName);
+
+ m_page->dirRequester->setStartDir(options.resolveAbsoluteDocumentFilePath(documentPath));
+ m_page->dirRequester->setFileName(options.directory);
} else {
m_page->intStart->setValue(m_image->animationInterface()->playbackRange().start());
m_page->intEnd->setValue(m_image->animationInterface()->playbackRange().end());
m_page->sequenceStart->setValue(m_image->animationInterface()->playbackRange().start());
m_page->intWidth->setValue(m_image->width());
m_page->intHeight->setValue(m_image->height());
m_page->intFramesPerSecond->setValue(m_image->animationInterface()->framerate());
+
+ m_page->videoFilename->setStartDir(options.resolveAbsoluteDocumentFilePath(documentPath));
m_page->videoFilename->setFileName(defaultVideoFileName(m_doc, options.videoMimeType));
- }
- m_page->dirRequester->setFileName(options.directory);
+ m_page->dirRequester->setStartDir(options.resolveAbsoluteDocumentFilePath(documentPath));
+ m_page->dirRequester->setFileName(options.directory);
+ }
for (int i = 0; i < m_page->cmbMimetype->count(); ++i) {
if (m_page->cmbMimetype->itemData(i).toString() == options.frameMimeType) {
m_page->cmbMimetype->setCurrentIndex(i);
break;
}
}
for (int i = 0; i < m_page->cmbRenderType->count(); ++i) {
if (m_page->cmbRenderType->itemData(i).toString() == options.videoMimeType) {
m_page->cmbRenderType->setCurrentIndex(i);
break;
}
}
m_page->chkIncludeAudio->setChecked(options.includeAudio);
if (options.shouldDeleteSequence) {
KIS_SAFE_ASSERT_RECOVER_NOOP(options.shouldEncodeVideo);
m_page->shouldExportOnlyVideo->setChecked(true);
} else if (!options.shouldEncodeVideo) {
KIS_SAFE_ASSERT_RECOVER_NOOP(!options.shouldDeleteSequence);
m_page->shouldExportOnlyImageSequence->setChecked(true);
} else {
m_page->shouldExportAll->setChecked(true); // export to both
}
{
KisConfig cfg(true);
KisPropertiesConfigurationSP settings = cfg.exportConfiguration("VIDEO_ENCODER");
getDefaultVideoEncoderOptions(options.videoMimeType, settings,
&m_customFFMpegOptionsString,
&m_forceHDRVideo);
}
+ m_page->ffmpegLocation->setStartDir(QFileInfo(m_doc->localFilePath()).path());
m_page->ffmpegLocation->setFileName(findFFMpeg(options.ffmpegPath));
}
QString DlgAnimationRenderer::defaultVideoFileName(KisDocument *doc, const QString &mimeType)
{
const QString docFileName = !doc->localFilePath().isEmpty() ?
doc->localFilePath() : i18n("Untitled");
return
QString("%1.%2")
.arg(QFileInfo(docFileName).completeBaseName())
.arg(KisMimeDatabase::suffixesForMimeType(mimeType).first());
}
void DlgAnimationRenderer::selectRenderType(int index)
{
const QString mimeType = m_page->cmbRenderType->itemData(index).toString();
QString videoFileName = defaultVideoFileName(m_doc, mimeType);
if (!m_page->videoFilename->fileName().isEmpty()) {
const QFileInfo info = QFileInfo(m_page->videoFilename->fileName());
const QString baseName = info.completeBaseName();
const QString path = info.path();
videoFileName =
QString("%1%2%3.%4").arg(path).arg(QDir::separator()).arg(baseName).arg(KisMimeDatabase::suffixesForMimeType(mimeType).first());
}
m_page->videoFilename->setMimeTypeFilters(QStringList() << mimeType, mimeType);
m_page->videoFilename->setFileName(videoFileName);
}
void DlgAnimationRenderer::selectRenderOptions()
{
const int index = m_page->cmbRenderType->currentIndex();
const QString mimetype = m_page->cmbRenderType->itemData(index).toString();
const VideoExportOptionsDialog::ContainerType containerType =
mimetype == "video/ogg" ?
VideoExportOptionsDialog::OGV :
VideoExportOptionsDialog::DEFAULT;
VideoExportOptionsDialog *encoderConfigWidget =
new VideoExportOptionsDialog(containerType, this);
// we always enable HDR, letting the user to force it
encoderConfigWidget->setSupportsHDR(true);
{
KisConfig cfg(true);
KisPropertiesConfigurationSP settings = cfg.exportConfiguration("VIDEO_ENCODER");
encoderConfigWidget->setConfiguration(settings);
}
KoDialog dlg(this);
dlg.setMainWidget(encoderConfigWidget);
dlg.setButtons(KoDialog::Ok | KoDialog::Cancel);
if (dlg.exec() == QDialog::Accepted) {
KisConfig cfg(false);
cfg.setExportConfiguration("VIDEO_ENCODER", encoderConfigWidget->configuration());
m_customFFMpegOptionsString = encoderConfigWidget->customUserOptionsString();
}
dlg.setMainWidget(0);
encoderConfigWidget->deleteLater();
}
void DlgAnimationRenderer::sequenceMimeTypeSelected()
{
int index = m_page->cmbMimetype->currentIndex();
KisConfigWidget *frameExportConfigWidget = 0;
QString mimetype = m_page->cmbMimetype->itemData(index).toString();
QSharedPointer filter(KisImportExportManager::filterForMimeType(mimetype, KisImportExportManager::Export));
if (filter) {
frameExportConfigWidget = filter->createConfigurationWidget(0, KisDocument::nativeFormatMimeType(), mimetype.toLatin1());
if (frameExportConfigWidget) {
KisPropertiesConfigurationSP config = filter->lastSavedConfiguration("", mimetype.toLatin1());
if (config) {
KisImportExportManager::fillStaticExportConfigurationProperties(config, m_image);
}
frameExportConfigWidget->setConfiguration(config);
KoDialog dlg(this);
dlg.setMainWidget(frameExportConfigWidget);
dlg.setButtons(KoDialog::Ok | KoDialog::Cancel);
if (dlg.exec() == QDialog::Accepted) {
m_frameExportConfig = frameExportConfigWidget->configuration();
KisConfig cfg(false);
cfg.setExportConfiguration(mimetype, frameExportConfigWidget->configuration());
}
frameExportConfigWidget->hide();
dlg.setMainWidget(0);
frameExportConfigWidget->setParent(0);
frameExportConfigWidget->deleteLater();
}
}
}
inline int roundByTwo(int value) {
return value + (value & 0x1);
}
KisAnimationRenderingOptions DlgAnimationRenderer::getEncoderOptions() const
{
KisAnimationRenderingOptions options;
options.lastDocuemntPath = m_doc->localFilePath();
options.videoMimeType = m_page->cmbRenderType->currentData().toString();
options.basename = m_page->txtBasename->text();
options.directory = m_page->dirRequester->fileName();
options.firstFrame = m_page->intStart->value();
options.lastFrame = m_page->intEnd->value();
options.sequenceStart = m_page->sequenceStart->value();
options.shouldEncodeVideo = !m_page->shouldExportOnlyImageSequence->isChecked();
options.shouldDeleteSequence = m_page->shouldExportOnlyVideo->isChecked();
options.includeAudio = m_page->chkIncludeAudio->isChecked();
options.ffmpegPath = m_page->ffmpegLocation->fileName();
options.frameRate = m_page->intFramesPerSecond->value();
options.width = roundByTwo(m_page->intWidth->value());
options.height = roundByTwo(m_page->intHeight->value());
options.videoFileName = m_page->videoFilename->fileName();
options.customFFMpegOptions = m_customFFMpegOptionsString;
// we should create **a copy** of the properties
if (m_frameExportConfig) {
KisPropertiesConfigurationSP cfg = new KisPropertiesConfiguration(*m_frameExportConfig);
const bool forceHDR = m_forceHDRVideo && !m_page->shouldExportOnlyImageSequence->isChecked();
if (forceHDR) {
KIS_SAFE_ASSERT_RECOVER_NOOP(m_page->cmbMimetype->currentData().toString() == "image/png");
cfg->setProperty("forceSRGB", false);
cfg->setProperty("saveAsHDR", true);
}
options.frameExportConfig = cfg;
}
return options;
}
void DlgAnimationRenderer::slotButtonClicked(int button)
{
if (button == KoDialog::Ok && !m_page->shouldExportOnlyImageSequence->isChecked()) {
QString ffmpeg = m_page->ffmpegLocation->fileName();
if (m_page->videoFilename->fileName().isEmpty()) {
QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("Please enter a file name to render to."));
return;
}
else if (ffmpeg.isEmpty()) {
QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("The location of FFmpeg is unknown. Please install FFmpeg first: Krita cannot render animations without FFmpeg. (www.ffmpeg.org)"));
return;
}
else {
QFileInfo fi(ffmpeg);
if (!fi.exists()) {
QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("The location of FFmpeg is invalid. Please select the correct location of the FFmpeg executable on your system."));
return;
}
}
}
KoDialog::slotButtonClicked(button);
}
void DlgAnimationRenderer::slotDialogAccepted()
{
KisConfig cfg(false);
KisAnimationRenderingOptions options = getEncoderOptions();
cfg.setExportConfiguration("ANIMATION_EXPORT", options.toProperties());
}
QString DlgAnimationRenderer::findFFMpeg(const QString &customLocation)
{
QString result;
QStringList proposedPaths;
if (!customLocation.isEmpty()) {
proposedPaths << customLocation;
proposedPaths << customLocation + QDir::separator() + "ffmpeg";
}
#ifndef Q_OS_WIN
proposedPaths << QDir::homePath() + "/bin/ffmpeg";
proposedPaths << "/usr/bin/ffmpeg";
proposedPaths << "/usr/local/bin/ffmpeg";
#endif
proposedPaths << KoResourcePaths::getApplicationRoot() +
QDir::separator() + "bin" + QDir::separator() + "ffmpeg";
Q_FOREACH (QString path, proposedPaths) {
if (path.isEmpty()) continue;
#ifdef Q_OS_WIN
path = QDir::toNativeSeparators(QDir::cleanPath(path));
if (path.endsWith(QDir::separator())) {
continue;
}
if (!path.endsWith(".exe")) {
if (!QFile::exists(path)) {
path += ".exe";
if (!QFile::exists(path)) {
continue;
}
}
}
#endif
QProcess testProcess;
testProcess.start(path, QStringList() << "-version");
if (testProcess.waitForStarted(1000)) {
testProcess.waitForFinished(1000);
}
const bool successfulStart =
testProcess.state() == QProcess::NotRunning &&
testProcess.error() == QProcess::UnknownError;
if (successfulStart) {
result = path;
break;
}
}
return result;
}
void DlgAnimationRenderer::slotExportTypeChanged()
{
KisConfig cfg(false);
bool willEncodeVideo =
m_page->shouldExportAll->isChecked() || m_page->shouldExportOnlyVideo->isChecked();
// if a video format needs to be outputted
if (willEncodeVideo) {
// videos always uses PNG for creating video, so disable the ability to change the format
m_page->cmbMimetype->setEnabled(false);
for (int i = 0; i < m_page->cmbMimetype->count(); ++i) {
if (m_page->cmbMimetype->itemData(i).toString() == "image/png") {
m_page->cmbMimetype->setCurrentIndex(i);
break;
}
}
}
m_page->intWidth->setVisible(willEncodeVideo);
m_page->intHeight->setVisible(willEncodeVideo);
m_page->intFramesPerSecond->setVisible(willEncodeVideo);
m_page->fpsLabel->setVisible(willEncodeVideo);
m_page->lblWidth->setVisible(willEncodeVideo);
m_page->lblHeight->setVisible(willEncodeVideo);
// if only exporting video
if (m_page->shouldExportOnlyVideo->isChecked()) {
m_page->cmbMimetype->setEnabled(false); // allow to change image format
m_page->imageSequenceOptionsGroup->setVisible(false);
m_page->videoOptionsGroup->setVisible(false); //shrinks the horizontal space temporarily to help resize() work
m_page->videoOptionsGroup->setVisible(true);
cfg.writeEntry("AnimationRenderer/export_type", "Video");
}
// if only an image sequence needs to be output
if (m_page->shouldExportOnlyImageSequence->isChecked()) {
m_page->cmbMimetype->setEnabled(true); // allow to change image format
m_page->videoOptionsGroup->setVisible(false);
m_page->imageSequenceOptionsGroup->setVisible(false);
m_page->imageSequenceOptionsGroup->setVisible(true);
cfg.writeEntry("AnimationRenderer/export_type", "ImageSequence");
}
// show all options
if (m_page->shouldExportAll->isChecked() ) {
m_page->imageSequenceOptionsGroup->setVisible(true);
m_page->videoOptionsGroup->setVisible(true);
cfg.writeEntry("AnimationRenderer/export_type", "VideoAndImageSequence");
}
// for the resize to work as expected, try to hide elements first before displaying other ones.
// if the widget gets bigger at any point, the resize will use that, even if elements are hidden later to make it smaller
resize(m_page->sizeHint());
}
void DlgAnimationRenderer::slotLockAspectRatioDimensionsWidth(int width)
{
Q_UNUSED(width);
float aspectRatio = (float)m_image->width() / (float)m_image->height();
// update height here
float newHeight = m_page->intWidth->value() / aspectRatio ;
m_page->intHeight->setValue(newHeight);
}
void DlgAnimationRenderer::slotLockAspectRatioDimensionsHeight(int height)
{
Q_UNUSED(height);
float aspectRatio = (float)m_image->width() / (float)m_image->height();
// update width here
float newWidth = aspectRatio * m_page->intHeight->value();
m_page->intWidth->setValue(newWidth);
}
diff --git a/plugins/extensions/animationrenderer/KisAnimationRenderingOptions.cpp b/plugins/extensions/animationrenderer/KisAnimationRenderingOptions.cpp
index ab45eff192..990676e685 100644
--- a/plugins/extensions/animationrenderer/KisAnimationRenderingOptions.cpp
+++ b/plugins/extensions/animationrenderer/KisAnimationRenderingOptions.cpp
@@ -1,125 +1,136 @@
/*
* Copyright (c) 2019 Dmitry Kazakov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "KisAnimationRenderingOptions.h"
#include
#include
-#include
+
+#include
KisAnimationRenderingOptions::KisAnimationRenderingOptions()
: videoMimeType("video/mp4"),
frameMimeType("image/png"),
basename("frame"),
directory("")
{
}
-inline QString composePath(const QString &pathChunk, const QString &fileNameChunk)
+QString KisAnimationRenderingOptions::resolveAbsoluteDocumentFilePath(const QString &documentPath) const
{
- if (QFileInfo(fileNameChunk).isAbsolute()) {
- return fileNameChunk;
- }
-
- return QFileInfo(QDir(QFileInfo(pathChunk).absolutePath()),
- fileNameChunk).absoluteFilePath();
+ return
+ !documentPath.isEmpty() ?
+ documentPath :
+ QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
}
-QString KisAnimationRenderingOptions::resolveAbsoluteVideoFilePath() const
+QString KisAnimationRenderingOptions::resolveAbsoluteVideoFilePath(const QString &documentPath) const
{
- return composePath(lastDocuemntPath, videoFileName);
+ const QString basePath = resolveAbsoluteDocumentFilePath(documentPath);
+ return KritaUtils::resolveAbsoluteFilePath(basePath, videoFileName);
}
-QString KisAnimationRenderingOptions::resolveAbsoluteFramesDirectory() const
+QString KisAnimationRenderingOptions::resolveAbsoluteFramesDirectory(const QString &documentPath) const
{
if (renderMode() == RENDER_VIDEO_ONLY) {
return QFileInfo(resolveAbsoluteVideoFilePath()).absolutePath();
}
- return composePath(lastDocuemntPath, directory);
+ const QString basePath = resolveAbsoluteDocumentFilePath(documentPath);
+ return KritaUtils::resolveAbsoluteFilePath(basePath, directory);
+}
+
+QString KisAnimationRenderingOptions::resolveAbsoluteVideoFilePath() const
+{
+ return resolveAbsoluteVideoFilePath(lastDocuemntPath);
+}
+
+QString KisAnimationRenderingOptions::resolveAbsoluteFramesDirectory() const
+{
+ return resolveAbsoluteFramesDirectory(lastDocuemntPath);
}
KisAnimationRenderingOptions::RenderMode KisAnimationRenderingOptions::renderMode() const
{
if (shouldDeleteSequence) {
KIS_SAFE_ASSERT_RECOVER_NOOP(shouldEncodeVideo);
return RENDER_VIDEO_ONLY;
} else if (!shouldEncodeVideo) {
KIS_SAFE_ASSERT_RECOVER_NOOP(!shouldDeleteSequence);
return RENDER_FRAMES_ONLY;
} else {
return RENDER_FRAMES_AND_VIDEO;
}
}
KisPropertiesConfigurationSP KisAnimationRenderingOptions::toProperties() const
{
KisPropertiesConfigurationSP config = new KisPropertiesConfiguration();
config->setProperty("basename", basename);
config->setProperty("last_document_path", lastDocuemntPath);
config->setProperty("directory", directory);
config->setProperty("first_frame", firstFrame);
config->setProperty("last_frame", lastFrame);
config->setProperty("sequence_start", sequenceStart);
config->setProperty("video_mimetype", videoMimeType);
config->setProperty("frame_mimetype", frameMimeType);
config->setProperty("encode_video", shouldEncodeVideo);
config->setProperty("delete_sequence", shouldDeleteSequence);
config->setProperty("ffmpeg_path", ffmpegPath);
config->setProperty("framerate", frameRate);
config->setProperty("height", height);
config->setProperty("width", width);
config->setProperty("include_audio", includeAudio);
config->setProperty("filename", videoFileName);
config->setProperty("custom_ffmpeg_options", customFFMpegOptions);
config->setPrefixedProperties("frame_export/", frameExportConfig);
return config;
}
void KisAnimationRenderingOptions::fromProperties(KisPropertiesConfigurationSP config)
{
basename = config->getPropertyLazy("basename", basename);
lastDocuemntPath = config->getPropertyLazy("last_document_path", "");
directory = config->getPropertyLazy("directory", directory);
firstFrame = config->getPropertyLazy("first_frame", 0);
lastFrame = config->getPropertyLazy("last_frame", 0);
sequenceStart = config->getPropertyLazy("sequence_start", 0);
videoMimeType = config->getPropertyLazy("video_mimetype", videoMimeType);
frameMimeType = config->getPropertyLazy("frame_mimetype", frameMimeType);
shouldEncodeVideo = config->getPropertyLazy("encode_video", false);
shouldDeleteSequence = config->getPropertyLazy("delete_sequence", false);
ffmpegPath = config->getPropertyLazy("ffmpeg_path", "");
frameRate = config->getPropertyLazy("framerate", 25);
height = config->getPropertyLazy("height", 0);
width = config->getPropertyLazy("width", 0);
includeAudio = config->getPropertyLazy("include_audio", true);
videoFileName = config->getPropertyLazy("filename", "");
customFFMpegOptions = config->getPropertyLazy("custom_ffmpeg_options", "");
frameExportConfig = new KisPropertiesConfiguration();
frameExportConfig->setPrefixedProperties("frame_export/", frameExportConfig);
}
diff --git a/plugins/extensions/animationrenderer/KisAnimationRenderingOptions.h b/plugins/extensions/animationrenderer/KisAnimationRenderingOptions.h
index eb787a045b..ffeff923e4 100644
--- a/plugins/extensions/animationrenderer/KisAnimationRenderingOptions.h
+++ b/plugins/extensions/animationrenderer/KisAnimationRenderingOptions.h
@@ -1,70 +1,75 @@
/*
* Copyright (c) 2019 Dmitry Kazakov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef KISANIMATIONRENDERINGOPTIONS_H
#define KISANIMATIONRENDERINGOPTIONS_H
#include
#include "kis_properties_configuration.h"
struct KisAnimationRenderingOptions
{
KisAnimationRenderingOptions();
QString lastDocuemntPath;
QString videoMimeType;
QString frameMimeType;
QString basename;
QString directory;
int firstFrame = 0;
int lastFrame = 0;
int sequenceStart = 0;
bool shouldEncodeVideo = false;
bool shouldDeleteSequence = false;
bool includeAudio = false;
QString ffmpegPath;
int frameRate = 25;
int width = 0;
int height = 0;
QString videoFileName;
QString customFFMpegOptions;
KisPropertiesConfigurationSP frameExportConfig;
+ QString resolveAbsoluteDocumentFilePath(const QString &documentPath) const;
+ QString resolveAbsoluteVideoFilePath(const QString &documentPath) const;
+ QString resolveAbsoluteFramesDirectory(const QString &documentPath) const;
+
QString resolveAbsoluteVideoFilePath() const;
QString resolveAbsoluteFramesDirectory() const;
+
enum RenderMode {
RENDER_FRAMES_ONLY,
RENDER_VIDEO_ONLY,
RENDER_FRAMES_AND_VIDEO
};
RenderMode renderMode() const;
KisPropertiesConfigurationSP toProperties() const;
void fromProperties(KisPropertiesConfigurationSP config);
};
#endif // KISANIMATIONRENDERINGOPTIONS_H