diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt index 17bf3ca3f3..659ed48a7f 100644 --- a/libs/ui/CMakeLists.txt +++ b/libs/ui/CMakeLists.txt @@ -1,527 +1,532 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/qtlockedfile ${EXIV2_INCLUDE_DIR} ) include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR} ${OCIO_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} ) add_subdirectory( tests ) if (APPLE) find_library(FOUNDATION_LIBRARY Foundation) 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 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/kis_dlg_internal_color_selector.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 kis_base_option.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 kis_config_notifier.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_safe_document_loader.cpp kis_splash_screen.cpp kis_filter_manager.cc kis_filters_model.cc kis_histogram_view.cc 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 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 kis_painting_assistants_manager.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 kis_resource_server_provider.cpp kis_selection_decoration.cc kis_selection_manager.cc kis_statusbar.cc kis_zoom_manager.cc kis_favorite_resource_manager.cpp kis_workspace_resource.cpp kis_action.cpp kis_action_manager.cpp kis_view_plugin.cpp kis_canvas_controls_manager.cpp kis_tooltip_manager.cpp kis_multinode_property.cpp kis_stopgradient_editor.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 kis_fps_decoration.cpp recorder/kis_node_query_path_editor.cc recorder/kis_recorded_action_creator.cc recorder/kis_recorded_action_creator_factory.cc recorder/kis_recorded_action_creator_factory_registry.cc recorder/kis_recorded_action_editor_factory.cc recorder/kis_recorded_action_editor_factory_registry.cc recorder/kis_recorded_filter_action_editor.cc recorder/kis_recorded_filter_action_creator.cpp recorder/kis_recorded_paint_action_editor.cc 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_recording_adapter.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/strokes/freehand_stroke.cpp tool/strokes/kis_painter_based_stroke_strategy.cpp tool/strokes/kis_filter_stroke_strategy.cpp tool/strokes/kis_color_picker_stroke_strategy.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_gradient_slider_widget.cc widgets/kis_gradient_slider.cpp 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_pattern_chooser.cc widgets/kis_popup_button.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/kis_size_group.cpp widgets/kis_size_group_p.cpp widgets/kis_wdg_generator.cpp widgets/kis_workspace_chooser.cpp widgets/squeezedcombobox.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_spinbox_color_selector.cpp widgets/kis_screen_color_picker.cpp - widgets/kis_visual_color_selector.cpp widgets/KoDualColorButton.cpp widgets/kis_color_input.cpp widgets/kis_color_button.cpp + widgets/KisVisualColorSelector.cpp + widgets/KisVisualColorSelectorShape.cpp + widgets/KisVisualEllipticalSelectorShape.cpp + widgets/KisVisualRectangleSelectorShape.cpp + widgets/KisVisualTriangleSelectorShape.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_single_action_shortcut.cpp input/kis_stroke_shortcut.cpp input/kis_shortcut_matcher.cpp input/kis_select_layer_action.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 input/kis_touch_shortcut.cpp kis_document_undo_store.cpp kis_transaction_based_command.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 KisNodeDelegate.cpp kis_node_view_visibility_delegate.cpp KisNodeToolTip.cpp KisNodeView.cpp kis_node_view_color_scheme.cpp KisImportExportFilter.cpp KisFilterEntry.cpp KisImportExportManager.cpp KisMainWindow.cpp KisOpenPane.cpp KisPart.cpp KisPrintJob.cpp KisTemplate.cpp KisTemplateCreateDia.cpp KisTemplateGroup.cpp KisTemplates.cpp KisTemplatesPane.cpp KisTemplateTree.cpp KisUndoStackAction.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 KisPaletteModel.cpp kis_palette_delegate.cpp kis_palette_view.cpp KisColorsetChooser.cpp KisSaveGroupVisitor.cpp ) if(WIN32) if (NOT Qt5Gui_PRIVATE_INCLUDE_DIRS) message(FATAL_ERROR "Qt5Gui Private header are missing!") endif() set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/kis_tablet_event.cpp input/wintab/kis_tablet_support_win.cpp input/wintab/kis_screen_size_choice_dialog.cpp qtlockedfile/qtlockedfile_win.cpp ) include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS}) endif() set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} kis_animation_frame_cache.cpp kis_animation_cache_populator.cpp canvas/kis_animation_player.cpp kis_animation_exporter.cpp kis_animation_importer.cpp ) if(UNIX) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/kis_tablet_event.cpp input/wintab/kis_tablet_support.cpp qtlockedfile/qtlockedfile_unix.cpp ) if(NOT APPLE) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/wintab/kis_tablet_support_x11.cpp input/wintab/qxcbconnection_xi2.cpp input/wintab/qxcbconnection.cpp input/wintab/kis_xi2_event_filter.cpp ) endif() endif() ki18n_wrap_ui(kritaui_LIB_SRCS 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/wdgpaintactioneditor.ui forms/wdgmultipliersdoublesliderspinbox.ui forms/wdgnodequerypatheditor.ui forms/wdgpresetselectorstrip.ui forms/wdgdlgblacklistcleanup.ui forms/wdgrectangleconstraints.ui forms/wdgimportimagesequence.ui forms/wdgstrokeselectionproperties.ui forms/KisDetailsPaneBase.ui forms/KisOpenPaneBase.ui forms/wdgstopgradienteditor.ui brushhud/kis_dlg_brush_hud_config.ui forms/wdgdlginternalcolorselector.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 wdgsplash.ui input/wintab/kis_screen_size_choice_dialog.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 ${PNG_LIBRARIES} ${EXIV2_LIBRARIES} ) if (HAVE_KIO) target_link_libraries(kritaui KF5::KIOCore) 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}) 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/dialogs/kis_dlg_internal_color_selector.cpp b/libs/ui/dialogs/kis_dlg_internal_color_selector.cpp index 870cff6be0..3654da4e8a 100644 --- a/libs/ui/dialogs/kis_dlg_internal_color_selector.cpp +++ b/libs/ui/dialogs/kis_dlg_internal_color_selector.cpp @@ -1,280 +1,280 @@ /* * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 * * 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 #include #include #include #include #include "KoColorSpaceRegistry.h" #include #include #include #include "kis_signal_compressor.h" #include "KisViewManager.h" #include "KoColorDisplayRendererInterface.h" #include "kis_spinbox_color_selector.h" #include "kis_dlg_internal_color_selector.h" #include "ui_wdgdlginternalcolorselector.h" #include "kis_config.h" #include "kis_config_notifier.h" #include "kis_color_input.h" struct KisDlgInternalColorSelector::Private { bool allowUpdates = true; KoColor currentColor; KoColor previousColor; KoColor sRGB = KoColor(KoColorSpaceRegistry::instance()->rgb8()); const KoColorSpace *currentColorSpace; bool lockUsedCS = false; bool chooseAlpha = false; KisSignalCompressor *compressColorChanges; const KoColorDisplayRendererInterface *displayRenderer; KisHexColorInput *hexColorInput; }; KisDlgInternalColorSelector::KisDlgInternalColorSelector(QWidget *parent, KoColor color, Config config, const QString &caption, const KoColorDisplayRendererInterface *displayRenderer) : QDialog(parent) ,m_d(new Private) { setModal(config.modal); this->setFocusPolicy(Qt::ClickFocus); m_ui = new Ui_WdgDlgInternalColorSelector(); m_ui->setupUi(this); setWindowTitle(caption); m_d->currentColor = color; m_d->currentColorSpace = m_d->currentColor.colorSpace(); m_d->displayRenderer = displayRenderer; m_ui->spinboxselector->slotSetColor(color); connect(m_ui->spinboxselector, SIGNAL(sigNewColor(KoColor)), this, SLOT(slotColorUpdated(KoColor))); m_ui->visualSelector->slotSetColor(color); m_ui->visualSelector->setDisplayRenderer(displayRenderer); m_ui->visualSelector->setConfig(false, config.modal); if (config.visualColorSelector) { connect(m_ui->visualSelector, SIGNAL(sigNewColor(KoColor)), this, SLOT(slotColorUpdated(KoColor))); - connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), m_ui->visualSelector, SLOT(ConfigurationChanged())); + connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), m_ui->visualSelector, SLOT(configurationChanged())); } else { m_ui->visualSelector->hide(); } if (config.screenColorPicker) { connect(m_ui->screenColorPicker, SIGNAL(sigNewColorPicked(KoColor)),this, SLOT(slotColorUpdated(KoColor))); } else { m_ui->screenColorPicker->hide(); } //TODO: Add disable signal as well. Might be not necessary...? KisConfig cfg; QString paletteName = cfg.readEntry("internal_selector_active_color_set", QString()); KoResourceServer* rServer = KoResourceServerProvider::instance()->paletteServer(false); KoColorSet *savedPal = rServer->resourceByName(paletteName); if (savedPal) { m_ui->paletteBox->setColorSet(savedPal); } else { Q_ASSERT(rServer->resources().count()); if (rServer->resources().count()) { savedPal = rServer->resources().first(); if (savedPal) { m_ui->paletteBox->setColorSet(savedPal); } } } if (config.paletteBox) { connect(m_ui->paletteBox, SIGNAL(colorChanged(KoColor,bool)), this, SLOT(slotColorUpdated(KoColor))); m_ui->paletteBox->setDisplayRenderer(displayRenderer); } else { m_ui->paletteBox->hide(); } if (config.prevNextButtons) { m_ui->currentColor->setColor(m_d->currentColor); m_ui->currentColor->setDisplayRenderer(displayRenderer); m_ui->previousColor->setColor(m_d->currentColor); m_ui->previousColor->setDisplayRenderer(displayRenderer); connect(m_ui->previousColor, SIGNAL(triggered(KoColorPatch*)), SLOT(slotSetColorFromPatch(KoColorPatch*))); } else { m_ui->currentColor->hide(); m_ui->previousColor->hide(); } if (config.hexInput) { m_d->sRGB.fromKoColor(m_d->currentColor); m_d->hexColorInput = new KisHexColorInput(this, &m_d->sRGB); m_d->hexColorInput->update(); connect(m_d->hexColorInput, SIGNAL(updated()), SLOT(slotSetColorFromHex())); m_ui->rightPane->addWidget(m_d->hexColorInput); m_d->hexColorInput->setToolTip(i18n("This is a hexcode input, for webcolors. It can only get colors in the sRGB space.")); } connect(this, SIGNAL(signalForegroundColorChosen(KoColor)), this, SLOT(slotLockSelector())); m_d->compressColorChanges = new KisSignalCompressor(100 /* ms */, KisSignalCompressor::POSTPONE, this); connect(m_d->compressColorChanges, SIGNAL(timeout()), this, SLOT(endUpdateWithNewColor())); connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); connect(this, SIGNAL(finished(int)), SLOT(slotFinishUp())); } KisDlgInternalColorSelector::~KisDlgInternalColorSelector() { delete m_ui; } void KisDlgInternalColorSelector::slotColorUpdated(KoColor newColor) { //if the update did not come from this selector... if (m_d->allowUpdates || QObject::sender() == this->parent()) { if (m_d->lockUsedCS){ newColor.convertTo(m_d->currentColorSpace); m_d->currentColor = newColor; } else { m_d->currentColor = newColor; } updateAllElements(QObject::sender()); } } void KisDlgInternalColorSelector::colorSpaceChanged(const KoColorSpace *cs) { if (cs == m_d->currentColorSpace) { return; } m_d->currentColorSpace = KoColorSpaceRegistry::instance()->colorSpace(cs->colorModelId().id(), cs->colorDepthId().id(), cs->profile()); m_ui->spinboxselector->slotSetColorSpace(m_d->currentColorSpace); m_ui->visualSelector->slotsetColorSpace(m_d->currentColorSpace); } void KisDlgInternalColorSelector::lockUsedColorSpace(const KoColorSpace *cs) { colorSpaceChanged(cs); m_d->lockUsedCS = true; } void KisDlgInternalColorSelector::setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer) { if (displayRenderer) { m_d->displayRenderer = displayRenderer; m_ui->visualSelector->setDisplayRenderer(displayRenderer); m_ui->currentColor->setDisplayRenderer(displayRenderer); m_ui->previousColor->setDisplayRenderer(displayRenderer); m_ui->paletteBox->setDisplayRenderer(displayRenderer); } else { m_d->displayRenderer = KoDumbColorDisplayRenderer::instance(); } } KoColor KisDlgInternalColorSelector::getModalColorDialog(const KoColor color, QWidget* parent, QString caption) { Config config = Config(); KisDlgInternalColorSelector dialog(parent, color, config, caption); dialog.setPreviousColor(color); dialog.exec(); return dialog.getCurrentColor(); } KoColor KisDlgInternalColorSelector::getCurrentColor() { return m_d->currentColor; } void KisDlgInternalColorSelector::chooseAlpha(bool chooseAlpha) { m_d->chooseAlpha = chooseAlpha; } void KisDlgInternalColorSelector::slotConfigurationChanged() { //m_d->canvas->displayColorConverter()-> //slotColorSpaceChanged(m_d->canvas->image()->colorSpace()); } void KisDlgInternalColorSelector::slotLockSelector() { m_d->allowUpdates = false; } void KisDlgInternalColorSelector::setPreviousColor(KoColor c) { m_d->previousColor = c; } void KisDlgInternalColorSelector::updateAllElements(QObject *source) { //update everything!!! if (source != m_ui->spinboxselector) { m_ui->spinboxselector->slotSetColor(m_d->currentColor); } if (source != m_ui->visualSelector) { m_ui->visualSelector->slotSetColor(m_d->currentColor); } if (source != m_d->hexColorInput) { m_d->sRGB.fromKoColor(m_d->currentColor); m_d->hexColorInput->update(); } m_ui->previousColor->setColor(m_d->previousColor); m_ui->currentColor->setColor(m_d->currentColor); if (source != this->parent()) { emit(signalForegroundColorChosen(m_d->currentColor)); m_d->compressColorChanges->start(); } } void KisDlgInternalColorSelector::endUpdateWithNewColor() { m_d->allowUpdates = true; } void KisDlgInternalColorSelector::focusInEvent(QFocusEvent *) { //setPreviousColor(); } void KisDlgInternalColorSelector::slotFinishUp() { setPreviousColor(m_d->currentColor); KisConfig cfg; if (m_ui->paletteBox->colorSet()) { cfg.writeEntry("internal_selector_active_color_set", m_ui->paletteBox->colorSet()->name()); } } void KisDlgInternalColorSelector::slotSetColorFromPatch(KoColorPatch* patch) { slotColorUpdated(patch->color()); } void KisDlgInternalColorSelector::slotSetColorFromHex() { slotColorUpdated(m_d->sRGB); } diff --git a/libs/ui/forms/wdgdlginternalcolorselector.ui b/libs/ui/forms/wdgdlginternalcolorselector.ui index 4ad1fb8e03..741058e3d5 100644 --- a/libs/ui/forms/wdgdlginternalcolorselector.ui +++ b/libs/ui/forms/wdgdlginternalcolorselector.ui @@ -1,237 +1,237 @@ WdgDlgInternalColorSelector 0 0 505 483 Dialog 0 0 90 90 0 0 0 50 QFrame::StyledPanel QFrame::Sunken 2 2 0 0 0 0 0 0 0 50 70 0 0 25 25 0 0 225 50 0 0 50 50 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok KisSpinboxColorSelector QWidget
kis_spinbox_color_selector.h
1
KisScreenColorPicker QWidget
kis_screen_color_picker.h
1
KisVisualColorSelector QWidget -
kis_visual_color_selector.h
+
KisVisualColorSelector.h
1
KoColorPatch QWidget
KoColorPatch.h
1
KoColorSetWidget QFrame
KoColorSetWidget.h
1
buttonBox accepted() WdgDlgInternalColorSelector accept() 248 254 157 274 buttonBox rejected() WdgDlgInternalColorSelector reject() 316 260 286 274
diff --git a/libs/ui/kis_popup_palette.cpp b/libs/ui/kis_popup_palette.cpp index ca67a329f4..887c81a6ba 100644 --- a/libs/ui/kis_popup_palette.cpp +++ b/libs/ui/kis_popup_palette.cpp @@ -1,858 +1,858 @@ /* This file is part of the KDE project Copyright 2009 Vera Lukman Copyright 2011 Sven Langkamp Copyright 2016 Scott Petrovic This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. 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 "kis_popup_palette.h" #include "kis_paintop_box.h" #include "kis_favorite_resource_manager.h" #include "kis_icon_utils.h" #include #include "kis_resource_server_provider.h" #include #include -#include +#include #include #include "KoColorSpaceRegistry.h" #include #include #include #include #include #include #include #include #include #include #include #include "kis_signal_compressor.h" #include #include "brushhud/kis_brush_hud.h" #include "brushhud/kis_round_hud_button.h" #include KisPopupPalette::KisPopupPalette(KisViewManager* viewManager, KisCoordinatesConverter* coordinatesConverter ,KisFavoriteResourceManager* manager, const KoColorDisplayRendererInterface *displayRenderer, KisCanvasResourceProvider *provider, QWidget *parent) : QWidget(parent, Qt::FramelessWindowHint) , m_hoveredPreset(0) , m_hoveredColor(0) , m_selectedColor(0) , m_coordinatesConverter(coordinatesConverter) , m_actionManager(viewManager->actionManager()) , m_resourceManager(manager) , m_triangleColorSelector(0) , m_displayRenderer(displayRenderer) , m_colorChangeCompressor(new KisSignalCompressor(50, KisSignalCompressor::POSTPONE)) , m_actionCollection(viewManager->actionCollection()) , m_brushHud(0) , m_popupPaletteSize(385.0) , m_colorHistoryInnerRadius(72.0) , m_colorHistoryOuterRadius(92.0) , m_isOverCanvasRotationIndicator(false) , m_isRotatingCanvasIndicator(false) { // some UI controls are defined and created based off these variables const int borderWidth = 3; m_triangleColorSelector = new KisVisualColorSelector(this); m_triangleColorSelector->setDisplayRenderer(displayRenderer); m_triangleColorSelector->setConfig(true,false); m_triangleColorSelector->move(m_popupPaletteSize/2-m_colorHistoryInnerRadius+borderWidth, m_popupPaletteSize/2-m_colorHistoryInnerRadius+borderWidth); m_triangleColorSelector->resize(m_colorHistoryInnerRadius*2-borderWidth*2, m_colorHistoryInnerRadius*2-borderWidth*2); m_triangleColorSelector->setVisible(true); KoColor fgcolor(Qt::black, KoColorSpaceRegistry::instance()->rgb8()); if (m_resourceManager) { fgcolor = provider->fgColor(); } m_triangleColorSelector->slotSetColor(fgcolor); QRegion maskedRegion(0, 0, m_triangleColorSelector->width(), m_triangleColorSelector->height(), QRegion::Ellipse ); m_triangleColorSelector->setMask(maskedRegion); //setAttribute(Qt::WA_TranslucentBackground, true); connect(m_triangleColorSelector, SIGNAL(sigNewColor(KoColor)), m_colorChangeCompressor.data(), SLOT(start())); connect(m_colorChangeCompressor.data(), SIGNAL(timeout()), SLOT(slotEmitColorChanged())); - connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), m_triangleColorSelector, SLOT(ConfigurationChanged())); + connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), m_triangleColorSelector, SLOT(configurationChanged())); connect(m_resourceManager, SIGNAL(sigChangeFGColorSelector(KoColor)), SLOT(slotExternalFgColorChanged(KoColor))); connect(this, SIGNAL(sigChangefGColor(KoColor)), m_resourceManager, SIGNAL(sigSetFGColor(KoColor))); connect(this, SIGNAL(sigChangeActivePaintop(int)), m_resourceManager, SLOT(slotChangeActivePaintop(int))); connect(this, SIGNAL(sigUpdateRecentColor(int)), m_resourceManager, SLOT(slotUpdateRecentColor(int))); connect(m_resourceManager, SIGNAL(setSelectedColor(int)), SLOT(slotSetSelectedColor(int))); connect(m_resourceManager, SIGNAL(updatePalettes()), SLOT(slotUpdate())); connect(m_resourceManager, SIGNAL(hidePalettes()), SLOT(slotHide())); // This is used to handle a bug: // If pop up palette is visible and a new colour is selected, the new colour // will be added when the user clicks on the canvas to hide the palette // In general, we want to be able to store recent color if the pop up palette // is not visible m_timer.setSingleShot(true); connect(this, SIGNAL(sigTriggerTimer()), this, SLOT(slotTriggerTimer())); connect(&m_timer, SIGNAL(timeout()), this, SLOT(slotEnableChangeFGColor())); connect(this, SIGNAL(sigEnableChangeFGColor(bool)), m_resourceManager, SIGNAL(sigEnableChangeColor(bool))); setCursor(Qt::ArrowCursor); setMouseTracking(true); setHoveredPreset(-1); setHoveredColor(-1); setSelectedColor(-1); m_brushHud = new KisBrushHud(provider, parent); m_brushHud->setMaximumHeight(m_popupPaletteSize); m_brushHud->setVisible(false); const int auxButtonSize = 35; m_settingsButton = new KisRoundHudButton(this); m_settingsButton->setIcon(KisIconUtils::loadIcon("configure")); m_settingsButton->setGeometry(m_popupPaletteSize - 2.2 * auxButtonSize, m_popupPaletteSize - auxButtonSize, auxButtonSize, auxButtonSize); connect(m_settingsButton, SIGNAL(clicked()), SLOT(slotShowTagsPopup())); KisConfig cfg; m_brushHudButton = new KisRoundHudButton(this); m_brushHudButton->setCheckable(true); m_brushHudButton->setOnOffIcons(KisIconUtils::loadIcon("arrow-left"), KisIconUtils::loadIcon("arrow-right")); m_brushHudButton->setGeometry(m_popupPaletteSize - 1.0 * auxButtonSize, m_popupPaletteSize - auxButtonSize, auxButtonSize, auxButtonSize); connect(m_brushHudButton, SIGNAL(toggled(bool)), SLOT(showHudWidget(bool))); m_brushHudButton->setChecked(cfg.showBrushHud()); // add some stuff below the pop-up palette that will make it easier to use for tablet people QVBoxLayout* vLayout = new QVBoxLayout(this); // main layout QSpacerItem* verticalSpacer = new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding); vLayout->addSpacerItem(verticalSpacer); // this should push the box to the bottom QHBoxLayout* hLayout = new QHBoxLayout(); vLayout->addLayout(hLayout); mirrorMode = new KisHighlightedToolButton(this); mirrorMode->setCheckable(true); mirrorMode->setFixedSize(35, 35); mirrorMode->setIcon(KisIconUtils::loadIcon("symmetry-horizontal")); mirrorMode->setToolTip(i18n("Mirror Canvas")); connect(mirrorMode, SIGNAL(clicked(bool)), this, SLOT(slotmirroModeClicked())); canvasOnlyButton = new KisHighlightedToolButton(this); canvasOnlyButton->setCheckable(true); canvasOnlyButton->setFixedSize(35, 35); canvasOnlyButton->setIcon(KisIconUtils::loadIcon("document-new")); canvasOnlyButton->setToolTip(i18n("Canvas Only")); connect(canvasOnlyButton, SIGNAL(clicked(bool)), this, SLOT(slotCanvasonlyModeClicked())); zoomToOneHundredPercentButton = new QPushButton(this); zoomToOneHundredPercentButton->setText(i18n("100%")); zoomToOneHundredPercentButton->setFixedHeight(35); zoomToOneHundredPercentButton->setIcon(KisIconUtils::loadIcon("zoom-original")); zoomToOneHundredPercentButton->setToolTip(i18n("Zoom to 100%")); connect(zoomToOneHundredPercentButton, SIGNAL(clicked(bool)), this, SLOT(slotZoomToOneHundredPercentClicked())); zoomCanvasSlider = new QSlider(Qt::Horizontal, this); zoomCanvasSlider->setRange(10, 200); // 10% to 200 % zoomCanvasSlider->setFixedHeight(35); zoomCanvasSlider->setValue(m_coordinatesConverter->zoomInPercent()); zoomCanvasSlider->setSingleStep(1); zoomCanvasSlider->setPageStep(1); connect(zoomCanvasSlider, SIGNAL(valueChanged(int)), this, SLOT(slotZoomSliderChanged(int))); hLayout->addWidget(mirrorMode); hLayout->addWidget(canvasOnlyButton); hLayout->addWidget(zoomToOneHundredPercentButton); hLayout->addWidget(zoomCanvasSlider); setVisible(true); setVisible(false); } void KisPopupPalette::slotExternalFgColorChanged(const KoColor &color) { //m_triangleColorSelector->setRealColor(color); //hack to get around cmyk for now. if (color.colorSpace()->colorChannelCount()>3) { KoColor c(KoColorSpaceRegistry::instance()->rgb8()); c.fromKoColor(color); m_triangleColorSelector->slotSetColor(c); } else { m_triangleColorSelector->slotSetColor(color); } } void KisPopupPalette::slotEmitColorChanged() { if (isVisible()) { update(); emit sigChangefGColor(m_triangleColorSelector->getCurrentColor()); } } //setting KisPopupPalette properties int KisPopupPalette::hoveredPreset() const { return m_hoveredPreset; } void KisPopupPalette::setHoveredPreset(int x) { m_hoveredPreset = x; } int KisPopupPalette::hoveredColor() const { return m_hoveredColor; } void KisPopupPalette::setHoveredColor(int x) { m_hoveredColor = x; } int KisPopupPalette::selectedColor() const { return m_selectedColor; } void KisPopupPalette::setSelectedColor(int x) { m_selectedColor = x; } void KisPopupPalette::slotTriggerTimer() { m_timer.start(750); } void KisPopupPalette::slotEnableChangeFGColor() { emit sigEnableChangeFGColor(true); } void KisPopupPalette::slotZoomSliderChanged(int zoom) { emit zoomLevelChanged(zoom); } void KisPopupPalette::adjustLayout(const QPoint &p) { KIS_ASSERT_RECOVER_RETURN(m_brushHud); if (isVisible() && parentWidget()) { float hudMargin = 30.0; const QRect fitRect = kisGrowRect(parentWidget()->rect(), -20.0); // -20 is widget margin const QPoint paletteCenterOffset(m_popupPaletteSize / 2, m_popupPaletteSize / 2); QRect paletteRect = rect(); paletteRect.moveTo(p - paletteCenterOffset); if (m_brushHudButton->isChecked()) { m_brushHud->updateGeometry(); paletteRect.adjust(0, 0, m_brushHud->width() + hudMargin, 0); } paletteRect = kisEnsureInRect(paletteRect, fitRect); move(paletteRect.topLeft()); m_brushHud->move(paletteRect.topLeft() + QPoint(m_popupPaletteSize + hudMargin, 0)); m_lastCenterPoint = p; } } void KisPopupPalette::showHudWidget(bool visible) { KIS_ASSERT_RECOVER_RETURN(m_brushHud); const bool reallyVisible = visible && m_brushHudButton->isChecked(); if (reallyVisible) { m_brushHud->updateProperties(); } m_brushHud->setVisible(reallyVisible); adjustLayout(m_lastCenterPoint); KisConfig cfg; cfg.setShowBrushHud(visible); } void KisPopupPalette::showPopupPalette(const QPoint &p) { showPopupPalette(!isVisible()); adjustLayout(p); } void KisPopupPalette::showPopupPalette(bool show) { if (show) { zoomCanvasSlider->setValue(m_coordinatesConverter->zoomInPercent()); // sync the zoom slider emit sigEnableChangeFGColor(!show); } else { emit sigTriggerTimer(); } setVisible(show); m_brushHud->setVisible(show && m_brushHudButton->isChecked()); } //redefinition of setVariable function to change the scope to private void KisPopupPalette::setVisible(bool b) { QWidget::setVisible(b); } void KisPopupPalette::setParent(QWidget *parent) { m_brushHud->setParent(parent); QWidget::setParent(parent); } QSize KisPopupPalette::sizeHint() const { return QSize(m_popupPaletteSize, m_popupPaletteSize + 50); // last number is the space for the toolbar below } void KisPopupPalette::resizeEvent(QResizeEvent*) { } void KisPopupPalette::paintEvent(QPaintEvent* e) { Q_UNUSED(e); QPainter painter(this); QPen pen(palette().color(QPalette::Text)); pen.setWidth(3); painter.setPen(pen); painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::SmoothPixmapTransform); //painting background color indicator QPainterPath bgColor; bgColor.addEllipse(QPoint( 50, 80), 30, 30); painter.fillPath(bgColor, m_displayRenderer->toQColor(m_resourceManager->bgColor())); painter.drawPath(bgColor); //painting foreground color indicator QPainterPath fgColor; fgColor.addEllipse(QPoint( 60, 50), 30, 30); painter.fillPath(fgColor, m_displayRenderer->toQColor(m_triangleColorSelector->getCurrentColor())); painter.drawPath(fgColor); // create a circle background that everything else will go into QPainterPath backgroundContainer; float shrinkCircleAmount = 3;// helps the circle when the stroke is put around it QRectF circleRect(shrinkCircleAmount, shrinkCircleAmount, m_popupPaletteSize - shrinkCircleAmount*2,m_popupPaletteSize - shrinkCircleAmount*2); backgroundContainer.addEllipse( circleRect ); painter.fillPath(backgroundContainer,palette().brush(QPalette::Background)); painter.drawPath(backgroundContainer); // create a path slightly inside the container circle. this will create a 'track' to indicate that we can rotate the canvas // with the indicator QPainterPath rotationTrackPath; shrinkCircleAmount = 18; QRectF circleRect2(shrinkCircleAmount, shrinkCircleAmount, m_popupPaletteSize - shrinkCircleAmount*2,m_popupPaletteSize - shrinkCircleAmount*2); rotationTrackPath.addEllipse( circleRect2 ); pen.setWidth(1); painter.setPen(pen); painter.drawPath(rotationTrackPath); // this thing will help indicate where the starting brush preset is at. // also what direction they go to give sor order to the presets populated /* pen.setWidth(6); pen.setCapStyle(Qt::RoundCap); painter.setPen(pen); painter.drawArc(circleRect, (16*90), (16*-30)); // span angle (last parameter) is in 16th of degrees QPainterPath brushDir; brushDir.arcMoveTo(circleRect, 60); brushDir.lineTo(brushDir.currentPosition().x()-5, brushDir.currentPosition().y() - 14); painter.drawPath(brushDir); brushDir.lineTo(brushDir.currentPosition().x()-2, brushDir.currentPosition().y() + 6); painter.drawPath(brushDir); */ // the following things needs to be based off the center, so let's translate the painter painter.translate(m_popupPaletteSize / 2, m_popupPaletteSize / 2); // create the canvas rotation handle QPainterPath rotationIndicator = drawRotationIndicator(m_coordinatesConverter->rotationAngle(), true); painter.fillPath(rotationIndicator,palette().brush(QPalette::Text)); // hover indicator for the canvas rotation if (m_isOverCanvasRotationIndicator == true) { painter.save(); QPen pen(palette().color(QPalette::Highlight)); pen.setWidth(2); painter.setPen(pen); painter.drawPath(rotationIndicator); painter.restore(); } // create a reset canvas rotation indicator to bring the canvas back to 0 degrees QPainterPath resetRotationIndicator = drawRotationIndicator(0, false); QPen resetPen(palette().color(QPalette::Text)); resetPen.setWidth(1); painter.save(); painter.setPen(resetPen); painter.drawPath(resetRotationIndicator); painter.restore(); //painting favorite brushes QList images(m_resourceManager->favoritePresetImages()); //painting favorite brushes pixmap/icon QPainterPath presetPath; for (int pos = 0; pos < numSlots(); pos++) { painter.save(); presetPath = createPathFromPresetIndex(pos); if (pos < images.size()) { painter.setClipPath(presetPath); QRect bounds = presetPath.boundingRect().toAlignedRect(); painter.drawImage(bounds.topLeft() , images.at(pos).scaled(bounds.size() , Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation)); } else { painter.fillPath(presetPath, palette().brush(QPalette::Window)); // brush slot that has no brush in it } QPen pen = painter.pen(); pen.setWidth(1); painter.setPen(pen); painter.drawPath(presetPath); painter.restore(); } if (hoveredPreset() > -1) { presetPath = createPathFromPresetIndex(hoveredPreset()); QPen pen(palette().color(QPalette::Highlight)); pen.setWidth(3); painter.setPen(pen); painter.drawPath(presetPath); } // paint recent colors area. painter.setPen(Qt::NoPen); float rotationAngle = -360.0 / m_resourceManager->recentColorsTotal(); // there might be no recent colors at the start, so paint a placeholder if (m_resourceManager->recentColorsTotal() == 0) { painter.setBrush(Qt::transparent); QPainterPath emptyRecentColorsPath(drawDonutPathFull(0, 0, m_colorHistoryInnerRadius, m_colorHistoryOuterRadius)); painter.setPen(QPen(palette().color(QPalette::Background).lighter(150), 2, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin)); painter.drawPath(emptyRecentColorsPath); } else { for (int pos = 0; pos < m_resourceManager->recentColorsTotal(); pos++) { QPainterPath recentColorsPath(drawDonutPathAngle(m_colorHistoryInnerRadius, m_colorHistoryOuterRadius, m_resourceManager->recentColorsTotal())); //accessing recent color of index pos painter.fillPath(recentColorsPath, m_displayRenderer->toQColor( m_resourceManager->recentColorAt(pos) )); painter.drawPath(recentColorsPath); painter.rotate(rotationAngle); } } //painting hovered color if (hoveredColor() > -1) { painter.setPen(QPen(palette().color(QPalette::Highlight), 2, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin)); if (m_resourceManager->recentColorsTotal() == 1) { QPainterPath path_ColorDonut(drawDonutPathFull(0, 0, m_colorHistoryInnerRadius, m_colorHistoryOuterRadius)); painter.drawPath(path_ColorDonut); } else { painter.rotate((m_resourceManager->recentColorsTotal() + hoveredColor()) *rotationAngle); QPainterPath path(drawDonutPathAngle(m_colorHistoryInnerRadius, m_colorHistoryOuterRadius, m_resourceManager->recentColorsTotal())); painter.drawPath(path); painter.rotate(hoveredColor() * -1 * rotationAngle); } } //painting selected color if (selectedColor() > -1) { painter.setPen(QPen(palette().color(QPalette::Highlight).darker(130), 2, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin)); if (m_resourceManager->recentColorsTotal() == 1) { QPainterPath path_ColorDonut(drawDonutPathFull(0, 0, m_colorHistoryInnerRadius, m_colorHistoryOuterRadius)); painter.drawPath(path_ColorDonut); } else { painter.rotate((m_resourceManager->recentColorsTotal() + selectedColor()) *rotationAngle); QPainterPath path(drawDonutPathAngle(m_colorHistoryInnerRadius, m_colorHistoryOuterRadius, m_resourceManager->recentColorsTotal())); painter.drawPath(path); painter.rotate(selectedColor() * -1 * rotationAngle); } } } QPainterPath KisPopupPalette::drawDonutPathFull(int x, int y, int inner_radius, int outer_radius) { QPainterPath path; path.addEllipse(QPointF(x, y), outer_radius, outer_radius); path.addEllipse(QPointF(x, y), inner_radius, inner_radius); path.setFillRule(Qt::OddEvenFill); return path; } QPainterPath KisPopupPalette::drawDonutPathAngle(int inner_radius, int outer_radius, int limit) { QPainterPath path; path.moveTo(-0.999 * outer_radius * sin(M_PI / limit), 0.999 * outer_radius * cos(M_PI / limit)); path.arcTo(-1 * outer_radius, -1 * outer_radius, 2 * outer_radius, 2 * outer_radius, -90.0 - 180.0 / limit, 360.0 / limit); path.arcTo(-1 * inner_radius, -1 * inner_radius, 2 * inner_radius, 2 * inner_radius, -90.0 + 180.0 / limit, - 360.0 / limit); path.closeSubpath(); return path; } QPainterPath KisPopupPalette::drawRotationIndicator(qreal rotationAngle, bool canDrag) { // used for canvas rotation. This function gets called twice. Once by the canvas rotation indicator, // and another time by the reset canvas position float canvasRotationRadians = qDegreesToRadians(rotationAngle - 90); // -90 will make 0 degrees be at the top float rotationDialXPosition = qCos(canvasRotationRadians) * (m_popupPaletteSize/2 - 10); // m_popupPaletteSize/2 = radius float rotationDialYPosition = qSin(canvasRotationRadians) * (m_popupPaletteSize/2 - 10); QPainterPath canvasRotationIndicator; int canvasIndicatorSize = 15; float canvasIndicatorMiddle = canvasIndicatorSize/2; QRect indicatorRectangle = QRect( rotationDialXPosition - canvasIndicatorMiddle, rotationDialYPosition - canvasIndicatorMiddle, canvasIndicatorSize, canvasIndicatorSize ); if (canDrag) { m_canvasRotationIndicatorRect = indicatorRectangle; } else { m_resetCanvasRotationIndicatorRect = indicatorRectangle; } canvasRotationIndicator.addEllipse(indicatorRectangle.x(), indicatorRectangle.y(), indicatorRectangle.width(), indicatorRectangle.height() ); return canvasRotationIndicator; } void KisPopupPalette::mouseMoveEvent(QMouseEvent* event) { QPointF point = event->posF(); event->accept(); setToolTip(QString()); setHoveredPreset(-1); setHoveredColor(-1); // calculate if we are over the canvas rotation knob // before we started painting, we moved the painter to the center of the widget, so the X/Y positions are offset. we need to // correct them first before looking for a click event intersection float rotationCorrectedXPos = m_canvasRotationIndicatorRect.x() + (m_popupPaletteSize / 2); float rotationCorrectedYPos = m_canvasRotationIndicatorRect.y() + (m_popupPaletteSize / 2); QRect correctedCanvasRotationIndicator = QRect(rotationCorrectedXPos, rotationCorrectedYPos, m_canvasRotationIndicatorRect.width(), m_canvasRotationIndicatorRect.height()); if (correctedCanvasRotationIndicator.contains(point.x(), point.y())) { m_isOverCanvasRotationIndicator = true; } else { m_isOverCanvasRotationIndicator = false; } if (m_isRotatingCanvasIndicator) { // we are rotating the canvas, so calculate the rotation angle based off the center // calculate the angle we are at first QPoint widgetCenterPoint = QPoint(m_popupPaletteSize/2, m_popupPaletteSize/2); float dX = point.x() - widgetCenterPoint.x(); float dY = point.y() - widgetCenterPoint.y(); float finalAngle = qAtan2(dY,dX) * 180 / M_PI; // what we need if we have two points, but don't know the angle finalAngle = finalAngle + 90; // add 90 degrees so 0 degree position points up float angleDifference = finalAngle - m_coordinatesConverter->rotationAngle(); // the rotation function accepts diffs, so find it out m_coordinatesConverter->rotate(m_coordinatesConverter->widgetCenterPoint(), angleDifference); emit sigUpdateCanvas(); } // don't highlight the presets if we are in the middle of rotating the canvas if (m_isRotatingCanvasIndicator == false) { QPainterPath pathColor(drawDonutPathFull(m_popupPaletteSize / 2, m_popupPaletteSize / 2, m_colorHistoryInnerRadius, m_colorHistoryOuterRadius)); { int pos = calculatePresetIndex(point, m_resourceManager->numFavoritePresets()); if (pos >= 0 && pos < m_resourceManager->numFavoritePresets()) { setToolTip(m_resourceManager->favoritePresetList().at(pos).data()->name()); setHoveredPreset(pos); } } if (pathColor.contains(point)) { int pos = calculateIndex(point, m_resourceManager->recentColorsTotal()); if (pos >= 0 && pos < m_resourceManager->recentColorsTotal()) { setHoveredColor(pos); } } } update(); } void KisPopupPalette::mousePressEvent(QMouseEvent* event) { QPointF point = event->posF(); event->accept(); if (event->button() == Qt::LeftButton) { //in favorite brushes area int pos = calculateIndex(point, m_resourceManager->numFavoritePresets()); if (pos >= 0 && pos < m_resourceManager->numFavoritePresets() && isPointInPixmap(point, pos)) { //setSelectedBrush(pos); update(); } if (m_isOverCanvasRotationIndicator) { m_isRotatingCanvasIndicator = true; } // reset the canvas if we are over the reset canvas rotation indicator float rotationCorrectedXPos = m_resetCanvasRotationIndicatorRect.x() + (m_popupPaletteSize / 2); float rotationCorrectedYPos = m_resetCanvasRotationIndicatorRect.y() + (m_popupPaletteSize / 2); QRect correctedResetCanvasRotationIndicator = QRect(rotationCorrectedXPos, rotationCorrectedYPos, m_resetCanvasRotationIndicatorRect.width(), m_resetCanvasRotationIndicatorRect.height()); if (correctedResetCanvasRotationIndicator.contains(point.x(), point.y())) { float angleDifference = -m_coordinatesConverter->rotationAngle(); // the rotation function accepts diffs, so find it ou m_coordinatesConverter->rotate(m_coordinatesConverter->widgetCenterPoint(), angleDifference); emit sigUpdateCanvas(); } } } void KisPopupPalette::slotShowTagsPopup() { KisPaintOpPresetResourceServer* rServer = KisResourceServerProvider::instance()->paintOpPresetServer(); QStringList tags = rServer->tagNamesList(); qSort(tags); if (!tags.isEmpty()) { QMenu menu; Q_FOREACH (const QString& tag, tags) { menu.addAction(tag); } QAction* action = menu.exec(QCursor::pos()); if (action) { m_resourceManager->setCurrentTag(action->text()); } } else { QWhatsThis::showText(QCursor::pos(), i18n("There are no tags available to show in this popup. To add presets, you need to tag them and then select the tag here.")); } } void KisPopupPalette::slotmirroModeClicked() { QAction* action = m_actionCollection->action("mirror_canvas"); if (action) { action->trigger(); } } void KisPopupPalette::slotCanvasonlyModeClicked() { QAction* action = m_actionCollection->action("view_show_canvas_only"); if (action) { action->trigger(); } } void KisPopupPalette::slotZoomToOneHundredPercentClicked() { QAction* action = m_actionCollection->action("zoom_to_100pct"); if (action) { action->trigger(); } } void KisPopupPalette::tabletEvent(QTabletEvent* /*event*/) { } void KisPopupPalette::mouseReleaseEvent(QMouseEvent * event) { QPointF point = event->posF(); event->accept(); m_isOverCanvasRotationIndicator = false; m_isRotatingCanvasIndicator = false; if (event->button() == Qt::LeftButton || event->button() == Qt::RightButton) { QPainterPath pathColor(drawDonutPathFull(m_popupPaletteSize / 2, m_popupPaletteSize / 2, m_colorHistoryInnerRadius, m_colorHistoryOuterRadius)); //in favorite brushes area if (hoveredPreset() > -1) { //setSelectedBrush(hoveredBrush()); emit sigChangeActivePaintop(hoveredPreset()); } if (pathColor.contains(point)) { int pos = calculateIndex(point, m_resourceManager->recentColorsTotal()); if (pos >= 0 && pos < m_resourceManager->recentColorsTotal()) { emit sigUpdateRecentColor(pos); } } } } int KisPopupPalette::calculateIndex(QPointF point, int n) { calculatePresetIndex(point, n); //translate to (0,0) point.setX(point.x() - m_popupPaletteSize / 2); point.setY(point.y() - m_popupPaletteSize / 2); //rotate float smallerAngle = M_PI / 2 + M_PI / n - atan2(point.y(), point.x()); float radius = sqrt((float)point.x() * point.x() + point.y() * point.y()); point.setX(radius * cos(smallerAngle)); point.setY(radius * sin(smallerAngle)); //calculate brush index int pos = floor(acos(point.x() / radius) * n / (2 * M_PI)); if (point.y() < 0) pos = n - pos - 1; return pos; } bool KisPopupPalette::isPointInPixmap(QPointF& point, int pos) { if (createPathFromPresetIndex(pos).contains(point + QPointF(-m_popupPaletteSize / 2, -m_popupPaletteSize / 2))) { return true; } return false; } KisPopupPalette::~KisPopupPalette() { } QPainterPath KisPopupPalette::createPathFromPresetIndex(int index) { qreal angleSlice = 360.0 / numSlots() ; // how many degrees each slice will get // the starting angle of the slice we need to draw. the negative sign makes us go clockwise. // adding 90 degrees makes us start at the top. otherwise we would start at the right qreal startingAngle = -(index * angleSlice) + 90; // the radius will get smaller as the amount of presets shown increases. 10 slots == 41 qreal presetRadius = m_colorHistoryOuterRadius * qSin(qDegreesToRadians(angleSlice/2)) / (1-qSin(qDegreesToRadians(angleSlice/2))); QPainterPath path; float pathX = (m_colorHistoryOuterRadius + presetRadius) * qCos(qDegreesToRadians(startingAngle)) - presetRadius; float pathY = -(m_colorHistoryOuterRadius + presetRadius) * qSin(qDegreesToRadians(startingAngle)) - presetRadius; float pathDiameter = 2 * presetRadius; // distance is used to calculate the X/Y in addition to the preset circle size path.addEllipse(pathX, pathY, pathDiameter, pathDiameter); return path; } int KisPopupPalette::calculatePresetIndex(QPointF point, int /*n*/) { for(int i = 0; i < numSlots(); i++) { QPointF adujustedPoint = point - QPointF(m_popupPaletteSize/2, m_popupPaletteSize/2); if(createPathFromPresetIndex(i).contains(adujustedPoint)) { return i; } } return -1; } int KisPopupPalette::numSlots() { KisConfig config; return qMax(config.favoritePresets(), 10); } diff --git a/libs/ui/widgets/KisColorSelectorConfiguration.h b/libs/ui/widgets/KisColorSelectorConfiguration.h new file mode 100644 index 0000000000..3076d381d5 --- /dev/null +++ b/libs/ui/widgets/KisColorSelectorConfiguration.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 + * + * 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_COLOR_SELECTOR_CONFIGURATION_H +#define KIS_COLOR_SELECTOR_CONFIGURATION_H + +#include +#include + +#include "kritaui_export.h" + +class KRITAUI_EXPORT KisColorSelectorConfiguration { + +public: + + enum Type {Ring, Square, Wheel, Triangle, Slider}; + enum Parameters {H, hsvS, V, hslS, L, SL, SV, SV2, hsvSH, hslSH, VH, LH, SI, SY, hsiSH, hsySH, I, Y, IH, YH, hsiS, hsyS}; + + Type mainType; + Type subType; + Parameters mainTypeParameter; + Parameters subTypeParameter; + + KisColorSelectorConfiguration(Type mainT = Triangle, Type subT = Ring, Parameters mainTP = SL, Parameters subTP = H) + : mainType(mainT) + , subType(subT) + , mainTypeParameter(mainTP) + , subTypeParameter(subTP) + { + } + + KisColorSelectorConfiguration(QString string) + { + readString(string); + } + + QString toString() const + { + return QString("%1|%2|%3|%4").arg(mainType).arg(subType).arg(mainTypeParameter).arg(subTypeParameter); + } + void readString(QString string) + { + QStringList strili = string.split('|'); + if(strili.length()!=4) return; + + int imt=strili.at(0).toInt(); + int ist=strili.at(1).toInt(); + int imtp=strili.at(2).toInt(); + int istp=strili.at(3).toInt(); + + if(imt>Slider || ist>Slider || imtp>hsyS || istp>hsyS)//this was LH before + return; + + mainType = Type(imt); + subType = Type(ist); + mainTypeParameter = Parameters(imtp); + subTypeParameter = Parameters(istp); + } + + static KisColorSelectorConfiguration fromString(QString string) + { + KisColorSelectorConfiguration ret; + ret.readString(string); + return ret; + } +}; + +#endif diff --git a/libs/ui/widgets/KisVisualColorSelector.cpp b/libs/ui/widgets/KisVisualColorSelector.cpp new file mode 100644 index 0000000000..90f6478e4d --- /dev/null +++ b/libs/ui/widgets/KisVisualColorSelector.cpp @@ -0,0 +1,442 @@ +/* + * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 + * + * 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 "KisVisualColorSelector.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "KoColorConversions.h" +#include "KoColorDisplayRendererInterface.h" +#include "KoChannelInfo.h" +#include +#include +#include "kis_signal_compressor.h" +#include "kis_debug.h" + +#include "KisVisualColorSelectorShape.h" +#include "KisVisualRectangleSelectorShape.h" +#include "KisVisualTriangleSelectorShape.h" +#include "KisVisualEllipticalSelectorShape.h" + +struct KisVisualColorSelector::Private +{ + KoColor currentcolor; + const KoColorSpace *currentCS {0}; + QList widgetlist; + bool updateSelf {false}; + bool updateLonesome {false}; // for modal dialogs. + bool circular {false}; + const KoColorDisplayRendererInterface *displayRenderer {0}; + KisColorSelectorConfiguration acs_config; + KisSignalCompressor *updateTimer {0}; +}; + +KisVisualColorSelector::KisVisualColorSelector(QWidget *parent) + : QWidget(parent) + , m_d(new Private) +{ + this->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); + QVBoxLayout *layout = new QVBoxLayout; + this->setLayout(layout); + + KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); + m_d->acs_config = KisColorSelectorConfiguration::fromString(cfg.readEntry("colorSelectorConfiguration", KisColorSelectorConfiguration().toString())); + m_d->updateTimer = new KisSignalCompressor(100 /* ms */, KisSignalCompressor::POSTPONE); + connect(m_d->updateTimer, SIGNAL(timeout()), SLOT(slotRebuildSelectors()), Qt::UniqueConnection); +} + +KisVisualColorSelector::~KisVisualColorSelector() +{ + delete m_d->updateTimer; +} + +void KisVisualColorSelector::slotSetColor(KoColor c) +{ + if (m_d->updateSelf == false) { + m_d->currentcolor = c; + if (m_d->currentCS != c.colorSpace()) { + slotsetColorSpace(c.colorSpace()); + } + } + updateSelectorElements(QObject::sender()); +} + +void KisVisualColorSelector::slotsetColorSpace(const KoColorSpace *cs) +{ + if (m_d->currentCS != cs) { + m_d->currentCS = cs; + slotRebuildSelectors(); + } +} + +void KisVisualColorSelector::setConfig(bool forceCircular, bool forceSelfUpdate) +{ + m_d->circular = forceCircular; + m_d->updateLonesome = forceSelfUpdate; +} + +KoColor KisVisualColorSelector::getCurrentColor() +{ + return m_d->currentcolor; +} + +void KisVisualColorSelector::configurationChanged() +{ + if (m_d->updateTimer) { + m_d->updateTimer->start(); + } +} + +void KisVisualColorSelector::slotRebuildSelectors() +{ + KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); + m_d->acs_config = KisColorSelectorConfiguration::fromString(cfg.readEntry("colorSelectorConfiguration", KisColorSelectorConfiguration().toString())); + + qDeleteAll(children()); + m_d->widgetlist.clear(); + QLayout *layout = new QHBoxLayout; + //redraw all the widgets. + int sizeValue = qMin(width(), height()); + int borderWidth = qMax(sizeValue*0.1, 20.0); + + if (m_d->currentCS->colorChannelCount() == 1) { + + KisVisualColorSelectorShape *bar; + + if (m_d->circular==false) { + bar = new KisVisualRectangleSelectorShape(this, KisVisualColorSelectorShape::onedimensional,KisVisualColorSelectorShape::Channel, m_d->currentCS, 0, 0,m_d->displayRenderer, borderWidth); + bar->setMaximumWidth(width()*0.1); + bar->setMaximumHeight(height()); + } + else { + bar = new KisVisualEllipticalSelectorShape(this, KisVisualColorSelectorShape::onedimensional,KisVisualColorSelectorShape::Channel, m_d->currentCS, 0, 0,m_d->displayRenderer, borderWidth, KisVisualEllipticalSelectorShape::borderMirrored); + layout->setMargin(0); + } + + connect (bar, SIGNAL(sigNewColor(KoColor)), this, SLOT(updateFromWidgets(KoColor))); + layout->addWidget(bar); + m_d->widgetlist.append(bar); + } + else if (m_d->currentCS->colorChannelCount() == 3) { + QRect newrect(0,0, this->geometry().width(), this->geometry().height()); + + KisVisualColorSelectorShape::ColorModel modelS = KisVisualColorSelectorShape::HSV; + int channel1 = 0; + int channel2 = 1; + int channel3 = 2; + + switch(m_d->acs_config.subTypeParameter) + { + case KisColorSelectorConfiguration::H: + channel1 = 0; + break; + case KisColorSelectorConfiguration::hsyS: + case KisColorSelectorConfiguration::hsiS: + case KisColorSelectorConfiguration::hslS: + case KisColorSelectorConfiguration::hsvS: + channel1 = 1; + break; + case KisColorSelectorConfiguration::V: + case KisColorSelectorConfiguration::L: + case KisColorSelectorConfiguration::I: + case KisColorSelectorConfiguration::Y: + channel1 = 2; + break; + default: + Q_ASSERT_X(false, "", "Invalid acs_config.subTypeParameter"); + } + + switch(m_d->acs_config.mainTypeParameter) + { + case KisColorSelectorConfiguration::hsySH: + modelS = KisVisualColorSelectorShape::HSY; + channel2 = 0; + channel3 = 1; + break; + case KisColorSelectorConfiguration::hsiSH: + modelS = KisVisualColorSelectorShape::HSI; + channel2 = 0; + channel3 = 1; + break; + case KisColorSelectorConfiguration::hslSH: + modelS = KisVisualColorSelectorShape::HSL; + channel2 = 0; + channel3 = 1; + break; + case KisColorSelectorConfiguration::hsvSH: + modelS = KisVisualColorSelectorShape::HSV; + channel2 = 0; + channel3 = 1; + break; + case KisColorSelectorConfiguration::YH: + modelS = KisVisualColorSelectorShape::HSY; + channel2 = 0; + channel3 = 2; + break; + case KisColorSelectorConfiguration::LH: + modelS = KisVisualColorSelectorShape::HSL; + channel2 = 0; + channel3 = 2; + break; + case KisColorSelectorConfiguration::IH: + modelS = KisVisualColorSelectorShape::HSL; + channel2 = 0; + channel3 = 2; + break; + case KisColorSelectorConfiguration::VH: + modelS = KisVisualColorSelectorShape::HSV; + channel2 = 0; + channel3 = 2; + break; + case KisColorSelectorConfiguration::SY: + modelS = KisVisualColorSelectorShape::HSY; + channel2 = 1; + channel3 = 2; + break; + case KisColorSelectorConfiguration::SI: + modelS = KisVisualColorSelectorShape::HSI; + channel2 = 1; + channel3 = 2; + break; + case KisColorSelectorConfiguration::SL: + modelS = KisVisualColorSelectorShape::HSL; + channel2 = 1; + channel3 = 2; + break; + case KisColorSelectorConfiguration::SV: + case KisColorSelectorConfiguration::SV2: + modelS = KisVisualColorSelectorShape::HSV; + channel2 = 1; + channel3 = 2; + break; + default: + Q_ASSERT_X(false, "", "Invalid acs_config.mainTypeParameter"); + } + if (m_d->acs_config.mainType == KisColorSelectorConfiguration::Triangle) { + modelS = KisVisualColorSelectorShape::HSV; + //Triangle only really works in HSV mode. + } + KisVisualColorSelectorShape *bar; + if (m_d->acs_config.subType == KisColorSelectorConfiguration::Ring) { + bar = new KisVisualEllipticalSelectorShape(this, + KisVisualColorSelectorShape::onedimensional, + modelS, + m_d->currentCS, channel1, channel1, + m_d->displayRenderer, borderWidth,KisVisualEllipticalSelectorShape::border); + bar->resize(sizeValue, sizeValue); + } + else if (m_d->acs_config.subType == KisColorSelectorConfiguration::Slider && m_d->circular == false) { + bar = new KisVisualRectangleSelectorShape(this, + KisVisualColorSelectorShape::onedimensional, + modelS, + m_d->currentCS, channel1, channel1, + m_d->displayRenderer, borderWidth); + bar->setMaximumWidth(borderWidth); + bar->setMinimumWidth(borderWidth); + bar->setMinimumHeight(sizeValue); + } + else if (m_d->acs_config.subType == KisColorSelectorConfiguration::Slider && m_d->circular == true) { + bar = new KisVisualEllipticalSelectorShape(this, + KisVisualColorSelectorShape::onedimensional, + modelS, + m_d->currentCS, channel1, channel1, + m_d->displayRenderer, borderWidth, KisVisualEllipticalSelectorShape::borderMirrored); + bar->resize(sizeValue, sizeValue); + } else { + // Accessing bar below would crash since it's not initialized. + // Hopefully this can never happen. + warnUI << "Invalid subType, cannot initialize KisVisualColorSelectorShape"; + Q_ASSERT_X(false, "", "Invalid subType, cannot initialize KisVisualColorSelectorShape"); + return; + } + + bar->setColor(m_d->currentcolor); + m_d->widgetlist.append(bar); + + KisVisualColorSelectorShape *block; + if (m_d->acs_config.mainType == KisColorSelectorConfiguration::Triangle) { + block = new KisVisualTriangleSelectorShape(this, KisVisualColorSelectorShape::twodimensional, + modelS, + m_d->currentCS, channel2, channel3, + m_d->displayRenderer); + block->setGeometry(bar->getSpaceForTriangle(newrect)); + } + else if (m_d->acs_config.mainType == KisColorSelectorConfiguration::Square) { + block = new KisVisualRectangleSelectorShape(this, KisVisualColorSelectorShape::twodimensional, + modelS, + m_d->currentCS, channel2, channel3, + m_d->displayRenderer); + block->setGeometry(bar->getSpaceForSquare(newrect)); + } + else { + block = new KisVisualEllipticalSelectorShape(this, KisVisualColorSelectorShape::twodimensional, + modelS, + m_d->currentCS, channel2, channel3, + m_d->displayRenderer); + block->setGeometry(bar->getSpaceForCircle(newrect)); + + } + + block->setColor(m_d->currentcolor); + connect (bar, SIGNAL(sigNewColor(KoColor)), block, SLOT(setColorFromSibling(KoColor))); + connect (block, SIGNAL(sigNewColor(KoColor)), SLOT(updateFromWidgets(KoColor))); + connect (bar, SIGNAL(sigHSXchange()), SLOT(HSXwrangler())); + connect (block, SIGNAL(sigHSXchange()), SLOT(HSXwrangler())); + m_d->widgetlist.append(block); + } + else if (m_d->currentCS->colorChannelCount() == 4) { + KisVisualRectangleSelectorShape *block = new KisVisualRectangleSelectorShape(this, KisVisualRectangleSelectorShape::twodimensional,KisVisualColorSelectorShape::Channel, m_d->currentCS, 0, 1); + KisVisualRectangleSelectorShape *block2 = new KisVisualRectangleSelectorShape(this, KisVisualRectangleSelectorShape::twodimensional,KisVisualColorSelectorShape::Channel, m_d->currentCS, 2, 3); + block->setMaximumWidth(width()*0.5); + block->setMaximumHeight(height()); + block2->setMaximumWidth(width()*0.5); + block2->setMaximumHeight(height()); + block->setColor(m_d->currentcolor); + block2->setColor(m_d->currentcolor); + connect (block, SIGNAL(sigNewColor(KoColor)), block2, SLOT(setColorFromSibling(KoColor))); + connect (block2, SIGNAL(sigNewColor(KoColor)), SLOT(updateFromWidgets(KoColor))); + layout->addWidget(block); + layout->addWidget(block2); + m_d->widgetlist.append(block); + m_d->widgetlist.append(block2); + } + + Q_ASSERT(m_d->widgetlist.size() == 2); + this->setLayout(layout); +} + +void KisVisualColorSelector::setDisplayRenderer (const KoColorDisplayRendererInterface *displayRenderer) { + m_d->displayRenderer = displayRenderer; + if (m_d->widgetlist.size()>0) { + Q_FOREACH (KisVisualColorSelectorShape *shape, m_d->widgetlist) { + shape->setDisplayRenderer(displayRenderer); + } + } +} + +void KisVisualColorSelector::updateSelectorElements(QObject *source) +{ + //first lock all elements from sending updates, then update all elements. + Q_FOREACH (KisVisualColorSelectorShape *shape, m_d->widgetlist) { + shape->blockSignals(true); + } + + Q_FOREACH (KisVisualColorSelectorShape *shape, m_d->widgetlist) { + if (shape!=source) { + if (m_d->updateSelf) { + shape->setColorFromSibling(m_d->currentcolor); + } else { + shape->setColor(m_d->currentcolor); + } + } + } + Q_FOREACH (KisVisualColorSelectorShape *shape, m_d->widgetlist) { + shape->blockSignals(false); + } + +} + +void KisVisualColorSelector::updateFromWidgets(KoColor c) +{ + m_d->currentcolor = c; + m_d->updateSelf = true; + if (m_d->updateLonesome) { + slotSetColor(c); + Q_EMIT sigNewColor(c); + + } else { + Q_EMIT sigNewColor(c); + } +} + +void KisVisualColorSelector::leaveEvent(QEvent *) +{ + m_d->updateSelf = false; +} + +void KisVisualColorSelector::resizeEvent(QResizeEvent *) { + int sizeValue = qMin(width(), height()); + int borderWidth = qMax(sizeValue*0.1, 20.0); + QRect newrect(0,0, this->geometry().width(), this->geometry().height()); + if (!m_d->currentCS) { + slotsetColorSpace(m_d->currentcolor.colorSpace()); + } + if (m_d->currentCS->colorChannelCount()==3) { + + if (m_d->acs_config.subType == KisColorSelectorConfiguration::Ring) { + m_d->widgetlist.at(0)->resize(sizeValue,sizeValue); + } + else if (m_d->acs_config.subType == KisColorSelectorConfiguration::Slider && m_d->circular==false) { + m_d->widgetlist.at(0)->setMaximumWidth(borderWidth); + m_d->widgetlist.at(0)->setMinimumWidth(borderWidth); + m_d->widgetlist.at(0)->setMinimumHeight(sizeValue); + m_d->widgetlist.at(0)->setMaximumHeight(sizeValue); + } + else if (m_d->acs_config.subType == KisColorSelectorConfiguration::Slider && m_d->circular==true) { + m_d->widgetlist.at(0)->resize(sizeValue,sizeValue); + } + m_d->widgetlist.at(0)->setBorderWidth(borderWidth); + + if (m_d->acs_config.mainType == KisColorSelectorConfiguration::Triangle) { + m_d->widgetlist.at(1)->setGeometry(m_d->widgetlist.at(0)->getSpaceForTriangle(newrect)); + } + else if (m_d->acs_config.mainType == KisColorSelectorConfiguration::Square) { + m_d->widgetlist.at(1)->setGeometry(m_d->widgetlist.at(0)->getSpaceForSquare(newrect)); + } + else if (m_d->acs_config.mainType == KisColorSelectorConfiguration::Wheel) { + m_d->widgetlist.at(1)->setGeometry(m_d->widgetlist.at(0)->getSpaceForCircle(newrect)); + } + } + Q_FOREACH (KisVisualColorSelectorShape *shape, m_d->widgetlist) { + shape->update(); + } +} + +void KisVisualColorSelector::HSXwrangler() +{ + qDebug() << this << "HSXWrangler"; + + QVector currentCoordinates = QVector(3); + + QVector w1 = m_d->widgetlist.at(0)->getHSX(currentCoordinates, true); + QVector w2 = m_d->widgetlist.at(1)->getHSX(currentCoordinates, true); + QVector ch(3); + + ch[0] = m_d->widgetlist.at(0)->getChannels().at(0); + ch[1] = m_d->widgetlist.at(1)->getChannels().at(0); + ch[2] = m_d->widgetlist.at(1)->getChannels().at(1); + + currentCoordinates[ch[0]] = w1[ch[0]]; + currentCoordinates[ch[1]] = w2[ch[1]]; + currentCoordinates[ch[2]] = w2[ch[2]]; + + m_d->widgetlist.at(0)->setHSX(currentCoordinates, true); + m_d->widgetlist.at(1)->setHSX(currentCoordinates, true); +} diff --git a/libs/ui/widgets/KisVisualColorSelector.h b/libs/ui/widgets/KisVisualColorSelector.h new file mode 100644 index 0000000000..2eabe09d33 --- /dev/null +++ b/libs/ui/widgets/KisVisualColorSelector.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 + * + * 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_VISUAL_COLOR_SELECTOR_H +#define KIS_VISUAL_COLOR_SELECTOR_H + +#include +#include +#include +#include +#include + +#include +#include +#include "KoColorDisplayRendererInterface.h" + +#include "KisColorSelectorConfiguration.h" + +#include "kritaui_export.h" + +/** + * @brief The KisVisualColorSelector class + * + * This gives a color selector box that draws gradients and everything. + * + * Unlike other color selectors, this one draws the full gamut of the given + * colorspace. + */ +class KRITAUI_EXPORT KisVisualColorSelector : public QWidget +{ + Q_OBJECT +public: + + explicit KisVisualColorSelector(QWidget *parent = 0); + ~KisVisualColorSelector(); + + /** + * @brief setConfig + * @param forceCircular + * Force circular is for space where you only have room for a circular selector. + * @param forceSelfUpdate + * force self-update is for making it update itself when using a modal dialog. + */ + void setConfig(bool forceCircular, bool forceSelfUpdate); + KoColor getCurrentColor(); + +Q_SIGNALS: + void sigNewColor(KoColor c); + +public Q_SLOTS: + + void slotSetColor(KoColor c); + void slotsetColorSpace(const KoColorSpace *cs); + void slotRebuildSelectors(); + void configurationChanged(); + void setDisplayRenderer (const KoColorDisplayRendererInterface *displayRenderer); +private Q_SLOTS: + void updateFromWidgets(KoColor c); + void HSXwrangler(); +protected: + void leaveEvent(QEvent *); + void resizeEvent(QResizeEvent *); +private: + struct Private; + const QScopedPointer m_d; + + void updateSelectorElements(QObject *source); + void drawGradients(); + +}; + +#endif diff --git a/libs/ui/widgets/KisVisualColorSelectorShape.cpp b/libs/ui/widgets/KisVisualColorSelectorShape.cpp new file mode 100644 index 0000000000..d4ee76fd5a --- /dev/null +++ b/libs/ui/widgets/KisVisualColorSelectorShape.cpp @@ -0,0 +1,594 @@ +/* + * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 + * + * 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 "KisVisualColorSelectorShape.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "KoColorConversions.h" +#include "KoColorDisplayRendererInterface.h" +#include "KoChannelInfo.h" +#include +#include +#include "kis_signal_compressor.h" +#include "kis_debug.h" + +struct KisVisualColorSelectorShape::Private +{ + QImage gradient; + QImage fullSelector; + bool imagesNeedUpdate {true}; + QPointF currentCoordinates; + Dimensions dimension; + ColorModel model; + const KoColorSpace *cs; + KoColor currentColor; + int channel1; + int channel2; + KisSignalCompressor *updateTimer {0}; + bool mousePressActive = false; + const KoColorDisplayRendererInterface *displayRenderer = 0; + qreal hue = 0.0; + qreal sat = 0.0; + qreal tone = 0.0; + +}; + +KisVisualColorSelectorShape::KisVisualColorSelectorShape(QWidget *parent, + KisVisualColorSelectorShape::Dimensions dimension, + KisVisualColorSelectorShape::ColorModel model, + const KoColorSpace *cs, + int channel1, + int channel2, + const KoColorDisplayRendererInterface *displayRenderer): QWidget(parent), m_d(new Private) +{ + m_d->dimension = dimension; + m_d->model = model; + m_d->cs = cs; + m_d->currentColor = KoColor(); + m_d->currentColor.setOpacity(1.0); + m_d->currentColor.convertTo(cs); + int maxchannel = m_d->cs->colorChannelCount()-1; + m_d->channel1 = qBound(0, channel1, maxchannel); + m_d->channel2 = qBound(0, channel2, maxchannel); + this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + // HACK: the updateTimer isn't connected to anything, we only check whether it's still active + // and running in order to determine whether we will emit a certain signal. + m_d->updateTimer = new KisSignalCompressor(100 /* ms */, KisSignalCompressor::POSTPONE, this); + setDisplayRenderer(displayRenderer); + show(); + +} + +KisVisualColorSelectorShape::~KisVisualColorSelectorShape() +{ +} + +void KisVisualColorSelectorShape::updateCursor() +{ + QPointF point1 = convertKoColorToShapeCoordinate(m_d->currentColor); + if (point1 != m_d->currentCoordinates) { + m_d->currentCoordinates = point1; + } +} + +QPointF KisVisualColorSelectorShape::getCursorPosition() { + return m_d->currentCoordinates; +} + +void KisVisualColorSelectorShape::setColor(KoColor c) +{ + //qDebug() << this << "KisVisualColorSelectorShape::setColor"; + if (c.colorSpace() != m_d->cs) { + c.convertTo(m_d->cs); + } + m_d->currentColor = c; + updateCursor(); + + m_d->imagesNeedUpdate = true; + update(); +} + +void KisVisualColorSelectorShape::setColorFromSibling(KoColor c) +{ + //qDebug() << this << "setColorFromSibling"; + if (c.colorSpace() != m_d->cs) { + c.convertTo(m_d->cs); + } + m_d->currentColor = c; + Q_EMIT sigNewColor(c); + m_d->imagesNeedUpdate = true; + update(); +} + +void KisVisualColorSelectorShape::setDisplayRenderer (const KoColorDisplayRendererInterface *displayRenderer) +{ + if (displayRenderer) { + if (m_d->displayRenderer) { + m_d->displayRenderer->disconnect(this); + } + m_d->displayRenderer = displayRenderer; + } else { + m_d->displayRenderer = KoDumbColorDisplayRenderer::instance(); + } + connect(m_d->displayRenderer, SIGNAL(displayConfigurationChanged()), + SLOT(updateFromChangedDisplayRenderer()), Qt::UniqueConnection); + +} + +void KisVisualColorSelectorShape::updateFromChangedDisplayRenderer() +{ + //qDebug() << this << "updateFromChangedDisplayRenderer();"; + m_d->imagesNeedUpdate = true; + updateCursor(); + //m_d->currentColor = convertShapeCoordinateToKoColor(getCursorPosition()); + update(); +} + +void KisVisualColorSelectorShape::forceImageUpdate() +{ + //qDebug() << this << "forceImageUpdate"; + m_d->imagesNeedUpdate = true; +} + +QColor KisVisualColorSelectorShape::getColorFromConverter(KoColor c){ + QColor col; + KoColor color = c; + if (m_d->displayRenderer) { + color.convertTo(m_d->displayRenderer->getPaintingColorSpace()); + col = m_d->displayRenderer->toQColor(c); + } else { + col = c.toQColor(); + } + return col; +} + +void KisVisualColorSelectorShape::slotSetActiveChannels(int channel1, int channel2) +{ + //qDebug() << this << "slotSetActiveChannels"; + int maxchannel = m_d->cs->colorChannelCount()-1; + m_d->channel1 = qBound(0, channel1, maxchannel); + m_d->channel2 = qBound(0, channel2, maxchannel); + m_d->imagesNeedUpdate = true; + update(); +} + +bool KisVisualColorSelectorShape::imagesNeedUpdate() const { + return m_d->imagesNeedUpdate; +} + +QImage KisVisualColorSelectorShape::getImageMap() +{ + //qDebug() << this << ">>>>>>>>> getImageMap()" << m_d->imagesNeedUpdate; + + if (m_d->imagesNeedUpdate == true) { + m_d->gradient = QImage(width(), height(), QImage::Format_ARGB32); + m_d->gradient.fill(Qt::transparent); + QImage img(width(), height(), QImage::Format_ARGB32); + img.fill(Qt::transparent); + for (int y = 0; y(img.scanLine(y)); + for (int x=0; ximagesNeedUpdate = false; + m_d->gradient = img; + } + return m_d->gradient; +} + +KoColor KisVisualColorSelectorShape::convertShapeCoordinateToKoColor(QPointF coordinates, bool cursor) +{ + ////qDebug() << this << ">>>>>>>>> convertShapeCoordinateToKoColor()" << coordinates; + + KoColor c = m_d->currentColor; + QVector channelValues (c.colorSpace()->channelCount()); + channelValues.fill(1.0); + c.colorSpace()->normalisedChannelsValue(c.data(), channelValues); + QVector channelValuesDisplay = channelValues; + QVector maxvalue(c.colorSpace()->channelCount()); + maxvalue.fill(1.0); + + if (m_d->displayRenderer + && (m_d->cs->colorDepthId() == Float16BitsColorDepthID + || m_d->cs->colorDepthId() == Float32BitsColorDepthID + || m_d->cs->colorDepthId() == Float64BitsColorDepthID) + && m_d->cs->colorModelId() != LABAColorModelID + && m_d->cs->colorModelId() != CMYKAColorModelID) { + + for (int ch = 0; ch < maxvalue.size(); ch++) { + KoChannelInfo *channel = m_d->cs->channels()[ch]; + maxvalue[ch] = m_d->displayRenderer->maxVisibleFloatValue(channel); + channelValues[ch] = channelValues[ch]/(maxvalue[ch]); + channelValuesDisplay[KoChannelInfo::displayPositionToChannelIndex(ch, m_d->cs->channels())] = channelValues[ch]; + } + } + else { + for (int i =0; i < channelValues.size();i++) { + channelValuesDisplay[KoChannelInfo::displayPositionToChannelIndex(i, m_d->cs->channels())] = qBound((float)0.0,channelValues[i], (float)1.0); + } + } + + qreal huedivider = 1.0; + qreal huedivider2 = 1.0; + + if (m_d->channel1 == 0) { + huedivider = 360.0; + } + + if (m_d->channel2 == 0) { + huedivider2 = 360.0; + } + + if (m_d->model != ColorModel::Channel && c.colorSpace()->colorModelId().id() == "RGBA") { + + if (m_d->model == ColorModel::HSV) { + /* + * RGBToHSV has a undefined hue possibility. This means that hue will be -1. + * This can be annoying for dealing with a selector, but I understand it is being + * used for the KoColorSelector... For now implement a qMax here. + */ + QVector inbetween(3); + RGBToHSV(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); + inbetween = convertvectorqrealTofloat(getHSX(convertvectorfloatToqreal(inbetween))); + inbetween[m_d->channel1] = coordinates.x()*huedivider; + if (m_d->dimension == Dimensions::twodimensional) { + inbetween[m_d->channel2] = coordinates.y()*huedivider2; + } + if (cursor) { + setHSX(convertvectorfloatToqreal(inbetween)); + Q_EMIT sigHSXchange(); + } + HSVToRGB(qMax(inbetween[0],(float)0.0), inbetween[1], inbetween[2], &channelValuesDisplay[0], &channelValuesDisplay[1], &channelValuesDisplay[2]); + } + else if (m_d->model == ColorModel::HSL) { + /* + * HSLToRGB can give negative values on the grey. I fixed the fromNormalisedChannel function to clamp, + * but you might want to manually clamp for floating point values. + */ + QVector inbetween(3); + RGBToHSL(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); + inbetween = convertvectorqrealTofloat(getHSX(convertvectorfloatToqreal(inbetween))); + inbetween[m_d->channel1] = fmod(coordinates.x()*huedivider, 360.0); + if (m_d->dimension == Dimensions::twodimensional) { + inbetween[m_d->channel2] = coordinates.y()*huedivider2; + } + if (cursor) { + setHSX(convertvectorfloatToqreal(inbetween)); + Q_EMIT sigHSXchange(); + } + HSLToRGB(qMax(inbetween[0], (float)0.0), inbetween[1], inbetween[2], &channelValuesDisplay[0], &channelValuesDisplay[1], &channelValuesDisplay[2]); + } + else if (m_d->model == ColorModel::HSI) { + /* + * HSI is a modified HSY function. + */ + QVector chan2 = convertvectorfloatToqreal(channelValuesDisplay); + QVector inbetween(3); + RGBToHSI(chan2[0],chan2[1], chan2[2], &inbetween[0], &inbetween[1], &inbetween[2]); + inbetween = getHSX(inbetween); + inbetween[m_d->channel1] = coordinates.x(); + if (m_d->dimension == Dimensions::twodimensional) { + inbetween[m_d->channel2] = coordinates.y(); + } + if (cursor) { + setHSX(inbetween); + Q_EMIT sigHSXchange(); + } + HSIToRGB(inbetween[0], inbetween[1], inbetween[2],&chan2[0],&chan2[1], &chan2[2]); + channelValuesDisplay = convertvectorqrealTofloat(chan2); + } + else /*if (m_d->model == ColorModel::HSY)*/ { + /* + * HSY is pretty slow to render due being a pretty over-the-top function. + * Might be worth investigating whether HCY can be used instead, but I have had + * some weird results with that. + */ + QVector luma= m_d->cs->lumaCoefficients(); + QVector chan2 = convertvectorfloatToqreal(channelValuesDisplay); + QVector inbetween(3); + RGBToHSY(chan2[0],chan2[1], chan2[2], &inbetween[0], &inbetween[1], &inbetween[2], + luma[0], luma[1], luma[2]); + inbetween = getHSX(inbetween); + inbetween[m_d->channel1] = coordinates.x(); + if (m_d->dimension == Dimensions::twodimensional) { + inbetween[m_d->channel2] = coordinates.y(); + } + if (cursor) { + setHSX(inbetween); + Q_EMIT sigHSXchange(); + } + HSYToRGB(inbetween[0], inbetween[1], inbetween[2],&chan2[0],&chan2[1], &chan2[2], + luma[0], luma[1], luma[2]); + channelValuesDisplay = convertvectorqrealTofloat(chan2); + } + + } + else { + channelValuesDisplay[m_d->channel1] = coordinates.x(); + if (m_d->dimension == Dimensions::twodimensional) { + channelValuesDisplay[m_d->channel2] = coordinates.y(); + } + } + + for (int i=0; ics->channels())]*(maxvalue[i]); + } + + c.colorSpace()->fromNormalisedChannelsValue(c.data(), channelValues); + + return c; +} + +QPointF KisVisualColorSelectorShape::convertKoColorToShapeCoordinate(KoColor c) +{ + ////qDebug() << this << ">>>>>>>>> convertKoColorToShapeCoordinate()"; + + if (c.colorSpace() != m_d->cs) { + c.convertTo(m_d->cs); + } + QVector channelValues (m_d->currentColor.colorSpace()->channelCount()); + channelValues.fill(1.0); + m_d->cs->normalisedChannelsValue(c.data(), channelValues); + QVector channelValuesDisplay = channelValues; + QVector maxvalue(c.colorSpace()->channelCount()); + maxvalue.fill(1.0); + if (m_d->displayRenderer + && (m_d->cs->colorDepthId() == Float16BitsColorDepthID + || m_d->cs->colorDepthId() == Float32BitsColorDepthID + || m_d->cs->colorDepthId() == Float64BitsColorDepthID) + && m_d->cs->colorModelId() != LABAColorModelID + && m_d->cs->colorModelId() != CMYKAColorModelID) { + for (int ch = 0; chcs->channels()[ch]; + maxvalue[ch] = m_d->displayRenderer->maxVisibleFloatValue(channel); + channelValues[ch] = channelValues[ch]/(maxvalue[ch]); + channelValuesDisplay[KoChannelInfo::displayPositionToChannelIndex(ch, m_d->cs->channels())] = channelValues[ch]; + } + } else { + for (int i =0; ics->channels())] = qBound((float)0.0,channelValues[i], (float)1.0); + } + } + QPointF coordinates(0.0,0.0); + qreal huedivider = 1.0; + qreal huedivider2 = 1.0; + if (m_d->channel1==0) { + huedivider = 360.0; + } + if (m_d->channel2==0) { + huedivider2 = 360.0; + } + if (m_d->model != ColorModel::Channel && c.colorSpace()->colorModelId().id() == "RGBA") { + if (c.colorSpace()->colorModelId().id() == "RGBA") { + if (m_d->model == ColorModel::HSV){ + QVector inbetween(3); + RGBToHSV(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); + inbetween = convertvectorqrealTofloat(getHSX(convertvectorfloatToqreal(inbetween))); + coordinates.setX(inbetween[m_d->channel1]/huedivider); + if (m_d->dimension == Dimensions::twodimensional) { + coordinates.setY(inbetween[m_d->channel2]/huedivider2); + } + } else if (m_d->model == ColorModel::HSL) { + QVector inbetween(3); + RGBToHSL(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); + inbetween = convertvectorqrealTofloat(getHSX(convertvectorfloatToqreal(inbetween))); + coordinates.setX(inbetween[m_d->channel1]/huedivider); + if (m_d->dimension == Dimensions::twodimensional) { + coordinates.setY(inbetween[m_d->channel2]/huedivider2); + } + } else if (m_d->model == ColorModel::HSI) { + QVector chan2 = convertvectorfloatToqreal(channelValuesDisplay); + QVector inbetween(3); + RGBToHSI(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); + inbetween = getHSX(inbetween); + coordinates.setX(inbetween[m_d->channel1]); + if (m_d->dimension == Dimensions::twodimensional) { + coordinates.setY(inbetween[m_d->channel2]); + } + } else if (m_d->model == ColorModel::HSY) { + QVector luma = m_d->cs->lumaCoefficients(); + QVector chan2 = convertvectorfloatToqreal(channelValuesDisplay); + QVector inbetween(3); + RGBToHSY(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2], luma[0], luma[1], luma[2]); + inbetween = getHSX(inbetween); + coordinates.setX(inbetween[m_d->channel1]); + if (m_d->dimension == Dimensions::twodimensional) { + coordinates.setY(inbetween[m_d->channel2]); + } + } + } + } else { + coordinates.setX(qBound((float)0.0, channelValuesDisplay[m_d->channel1], (float)1.0)); + if (m_d->dimension == Dimensions::twodimensional) { + coordinates.setY(qBound((float)0.0, channelValuesDisplay[m_d->channel2], (float)1.0)); + } + } + return coordinates; +} + +QVector KisVisualColorSelectorShape::convertvectorqrealTofloat(QVector real) +{ + QVector vloat(real.size()); + for (int i=0; i KisVisualColorSelectorShape::convertvectorfloatToqreal(QVector vloat) +{ + QVector real(vloat.size()); + for (int i=0; ibutton()==Qt::LeftButton) { + m_d->mousePressActive = true; + QPointF coordinates = convertWidgetCoordinateToShapeCoordinate(e->pos()); + KoColor col = convertShapeCoordinateToKoColor(coordinates, true); + setColor(col); + Q_EMIT sigNewColor(col); + m_d->updateTimer->start(); + } +} + +void KisVisualColorSelectorShape::mouseMoveEvent(QMouseEvent *e) +{ + if (m_d->mousePressActive==true && this->mask().contains(e->pos())) { + QPointF coordinates = convertWidgetCoordinateToShapeCoordinate(e->pos()); + quint8* oldData = m_d->currentColor.data(); + KoColor col = convertShapeCoordinateToKoColor(coordinates, true); + QRect offsetrect(this->geometry().topLeft()+QPoint(7.0,7.0), this->geometry().bottomRight()-QPoint(7.0,7.0)); + if (offsetrect.contains(e->pos()) || (m_d->cs->difference(col.data(), oldData)>5)) { + setColor(col); + if (!m_d->updateTimer->isActive()) { + Q_EMIT sigNewColor(col); + m_d->updateTimer->start(); + } + } + + } else { + e->ignore(); + } +} + +void KisVisualColorSelectorShape::mouseReleaseEvent(QMouseEvent *) +{ + m_d->mousePressActive = false; +} +void KisVisualColorSelectorShape::paintEvent(QPaintEvent*) +{ + QPainter painter(this); + + //check if old and new colors differ. + + if (m_d->imagesNeedUpdate) { + setMask(getMaskMap()); + } + drawCursor(); + painter.drawImage(0,0,m_d->fullSelector); +} + +KisVisualColorSelectorShape::Dimensions KisVisualColorSelectorShape::getDimensions() +{ + return m_d->dimension; +} + +KisVisualColorSelectorShape::ColorModel KisVisualColorSelectorShape::getColorModel() +{ + return m_d->model; +} + +void KisVisualColorSelectorShape::setFullImage(QImage full) +{ + m_d->fullSelector = full; +} +KoColor KisVisualColorSelectorShape::getCurrentColor() +{ + return m_d->currentColor; +} + +QVector KisVisualColorSelectorShape::getHSX(QVector hsx, bool wrangler) +{ + QVector ihsx = hsx; + if (!wrangler){ + //Ok, so this docker will not update luminosity if there's not at the least 3% more variation. + //This is necessary for 8bit. + if (m_d->cs->colorDepthId()==Integer8BitsColorDepthID){ + if (hsx[2]>m_d->tone-0.03 && hsx[2]tone+0.03) { + ihsx[2] = m_d->tone; + } + } else { + if (hsx[2]>m_d->tone-0.005 && hsx[2]tone+0.005) { + ihsx[2] = m_d->tone; + } + } + if (m_d->model==HSV){ + if (hsx[2]<=0.0) { + ihsx[1] = m_d->sat; + } + } else { + if ((hsx[2]<=0.0 || hsx[2]>=1.0)) { + ihsx[1] = m_d->sat; + } + } + if ((hsx[1]<=0.0 || hsx[0]<0.0)){ + ihsx[0]=m_d->hue; + } + } else { + ihsx[0]=m_d->hue; + ihsx[1]=m_d->sat; + ihsx[2]=m_d->tone; + } + return ihsx; +} + +void KisVisualColorSelectorShape::setHSX(QVector hsx, bool wrangler) +{ + if (wrangler){ + m_d->tone = hsx[2]; + m_d->sat = hsx[1]; + m_d->hue = hsx[0]; + } else { + if (m_d->channel1==2 || m_d->channel2==2){ + m_d->tone=hsx[2]; + } + if (m_d->model==HSV){ + if (hsx[2]>0.0) { + m_d->sat = hsx[1]; + } + } else { + if ((hsx[2]>0.0 || hsx[2]<1.0)) { + m_d->sat = hsx[1]; + } + } + if ((hsx[1]>0.0 && hsx[0]>=0.0)){ + m_d->hue = hsx[0]; + } + } +} + +QVector KisVisualColorSelectorShape::getChannels() +{ + QVector channels(2); + channels[0] = m_d->channel1; + channels[1] = m_d->channel2; + return channels; +} diff --git a/libs/ui/widgets/kis_visual_color_selector.h b/libs/ui/widgets/KisVisualColorSelectorShape.h similarity index 50% rename from libs/ui/widgets/kis_visual_color_selector.h rename to libs/ui/widgets/KisVisualColorSelectorShape.h index fa84c50a3b..9a6609b6d7 100644 --- a/libs/ui/widgets/kis_visual_color_selector.h +++ b/libs/ui/widgets/KisVisualColorSelectorShape.h @@ -1,460 +1,236 @@ /* * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 * * 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 KISVISUALCOLORSELECTOR_H -#define KISVISUALCOLORSELECTOR_H +#ifndef KIS_VISUAL_COLOR_SELECTOR_SHAPE_H +#define KIS_VISUAL_COLOR_SELECTOR_SHAPE_H #include #include #include #include #include #include #include #include "KoColorDisplayRendererInterface.h" +#include "KisVisualColorSelector.h" +#include "KisColorSelectorConfiguration.h" #include "kritaui_export.h" -class KRITAUI_EXPORT KisColorSelectorConfiguration { - -public: - - enum Type {Ring, Square, Wheel, Triangle, Slider}; - enum Parameters {H, hsvS, V, hslS, L, SL, SV, SV2, hsvSH, hslSH, VH, LH, SI, SY, hsiSH, hsySH, I, Y, IH, YH, hsiS, hsyS}; - - Type mainType; - Type subType; - Parameters mainTypeParameter; - Parameters subTypeParameter; - - KisColorSelectorConfiguration(Type mainT = Triangle, Type subT = Ring, Parameters mainTP = SL, Parameters subTP = H) - : mainType(mainT) - , subType(subT) - , mainTypeParameter(mainTP) - , subTypeParameter(subTP) - { - } - - KisColorSelectorConfiguration(QString string) - { - readString(string); - } - - QString toString() const - { - return QString("%1|%2|%3|%4").arg(mainType).arg(subType).arg(mainTypeParameter).arg(subTypeParameter); - } - void readString(QString string) - { - QStringList strili = string.split('|'); - if(strili.length()!=4) return; - - int imt=strili.at(0).toInt(); - int ist=strili.at(1).toInt(); - int imtp=strili.at(2).toInt(); - int istp=strili.at(3).toInt(); - - if(imt>Slider || ist>Slider || imtp>hsyS || istp>hsyS)//this was LH before - return; - - mainType = Type(imt); - subType = Type(ist); - mainTypeParameter = Parameters(imtp); - subTypeParameter = Parameters(istp); - } - - static KisColorSelectorConfiguration fromString(QString string) - { - KisColorSelectorConfiguration ret; - ret.readString(string); - return ret; - } -}; - - -/** - * @brief The KisVisualColorSelector class - * - * This gives a color selector box that draws gradients and everything. - * - * Unlike other color selectors, this one draws the full gamut of the given - * colorspace. - */ -class KRITAUI_EXPORT KisVisualColorSelector : public QWidget -{ - Q_OBJECT -public: - - explicit KisVisualColorSelector(QWidget *parent = 0); - ~KisVisualColorSelector(); - - /** - * @brief setConfig - * @param forceCircular - * Force circular is for space where you only have room for a circular selector. - * @param forceSelfUpdate - * force self-update is for making it update itself when using a modal dialog. - */ - void setConfig(bool forceCircular, bool forceSelfUpdate); - KoColor getCurrentColor(); - -Q_SIGNALS: - void sigNewColor(KoColor c); - -public Q_SLOTS: - - void slotSetColor(KoColor c); - void slotsetColorSpace(const KoColorSpace *cs); - void slotRebuildSelectors(); - void ConfigurationChanged(); - void setDisplayRenderer (const KoColorDisplayRendererInterface *displayRenderer); -private Q_SLOTS: - void updateFromWidgets(KoColor c); - void HSXwrangler(); -protected: - void leaveEvent(QEvent *); - void resizeEvent(QResizeEvent *); -private: - struct Private; - const QScopedPointer m_d; - - void updateSelectorElements(QObject *source); - void drawGradients(); - -}; - -//kis_visual_color_selector_shape - /** * @brief The KisVisualColorSelectorShape class * A 2d widget can represent at maximum 2 coordinates. * So first decide howmany coordinates you need. (onedimensional, or twodimensional) * Then the model, (Channel, HSV, HSL, HSI, YUV). Channel is the raw color channels. * When it finds a non-implemented feature it'll return to Channel. * Then, select the channels you wish to be affected. This uses the model, so for cmyk * the channel is c=0, m=1, y=2, k=3, but for hsv, hue=0, sat=1, and val=2 * These can also be set with 'slotsetactive channels'. * Then finally, connect the displayrenderer, you can also do this with 'setdisplayrenderer' * * Either way, this class is made to be subclassed, with a few virtuals so that the geometry * can be calculated properly. */ class KisVisualColorSelectorShape : public QWidget { Q_OBJECT public: /** * @brief The Dimensions enum * Wether or not the shape is single or two dimensional. **/ enum Dimensions{onedimensional, twodimensional}; enum ColorModel{Channel, HSV, HSL, HSI, HSY, YUV}; explicit KisVisualColorSelectorShape(QWidget *parent, KisVisualColorSelectorShape::Dimensions dimension, KisVisualColorSelectorShape::ColorModel model, const KoColorSpace *cs, int channel1, int channel2, const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance()); ~KisVisualColorSelectorShape(); /** * @brief getCursorPosition * @return current cursor position in shape-coordinates. */ QPointF getCursorPosition(); /** * @brief getDimensions * @return whether this is a single or twodimensional widget. */ Dimensions getDimensions(); /** * @brief getColorModel * @return the model of this widget. */ ColorModel getColorModel(); /** * @brief getPixmap * @return the pixmap of the gradient, for drawing on with a subclass. * the pixmap will not change unless 'm_d->setPixmap=true' which is toggled by * refresh and update functions. */ bool imagesNeedUpdate() const; QImage getImageMap(); /** * @brief setFullImage * Set the full widget image to be painted. * @param full this should be the full image. */ void setFullImage(QImage full); /** * @brief getCurrentColor * @return the current kocolor */ KoColor getCurrentColor(); /** * @brief setDisplayRenderer * disconnect the old display renderer if needed and connect the new one. * @param displayRenderer */ void setDisplayRenderer (const KoColorDisplayRendererInterface *displayRenderer); /** * @brief getColorFromConverter * @param c a koColor. * @return get the qcolor from the given kocolorusing this widget's display renderer. */ QColor getColorFromConverter(KoColor c); /** * @brief getSpaceForSquare * @param geom the full widget rectangle * @return rectangle with enough space for second widget */ virtual QRect getSpaceForSquare(QRect geom) = 0; virtual QRect getSpaceForCircle(QRect geom) = 0; virtual QRect getSpaceForTriangle(QRect geom) = 0; /** * @brief forceImageUpdate * force the image to recache. */ void forceImageUpdate(); /** * @brief setBorderWidth * set the border of the single dimensional selector. * @param width */ virtual void setBorderWidth(int width) = 0; /** * @brief getChannels * get used channels * @return */ QVector getChannels(); /** * @brief setHSX * This is for the cursor not to change when selecting * black, white, and desaturated values. Will not change the non-native values. * @param hsx the hsx value. */ void setHSX(QVector hsx, bool wrangler=false); /** * @brief getHSX sets the sat and hue so they won't * switch around much. * @param hsx the hsx values. * @return returns hsx, corrected. */ QVector getHSX(QVector hsx, bool wrangler= false); Q_SIGNALS: void sigNewColor(KoColor col); void sigHSXchange(); public Q_SLOTS: /** * @brief setColor * Set this widget's current color and change the cursor position. * @param c */ void setColor(KoColor c); /** * @brief setColorFromSibling * set this widget's current color, but don't change the cursor position, * instead sent out a signal of the new color. * @param c */ void setColorFromSibling(KoColor c); /** * @brief slotSetActiveChannels * Change the active channels if necessary. * @param channel1 used by single and twodimensional widgets. * @param channel2 only used by twodimensional widgets. */ void slotSetActiveChannels(int channel1, int channel2); /** * @brief updateFromChangedDisplayRenderer * for updating from the display renderer... not sure why this one is public. */ void updateFromChangedDisplayRenderer(); + protected: + void mousePressEvent(QMouseEvent *e); void mouseMoveEvent(QMouseEvent *e); void mouseReleaseEvent(QMouseEvent *e); void paintEvent(QPaintEvent*); + private: struct Private; const QScopedPointer m_d; /** * @brief convertShapeCoordinateToWidgetCoordinate * @return take the position in the shape and convert it to screen coordinates. */ virtual QPointF convertShapeCoordinateToWidgetCoordinate(QPointF) = 0; /** * @brief convertWidgetCoordinateToShapeCoordinate * Convert a coordinate in the widget's height/width to a shape coordinate. * @param coordinate the position your wish to have the shape coordinates of. */ virtual QPointF convertWidgetCoordinateToShapeCoordinate(QPoint coordinate) = 0; /** * @brief updateCursor * Update the cursor position. */ void updateCursor(); QPointF convertKoColorToShapeCoordinate(KoColor c); KoColor convertShapeCoordinateToKoColor(QPointF coordinates, bool cursor=false); /** * @brief getPixmap * @return the pixmap of this shape. */ virtual QRegion getMaskMap() = 0; virtual void drawCursor() = 0; QVector convertvectorqrealTofloat(QVector real); QVector convertvectorfloatToqreal(QVector vloat); }; -class KisVisualRectangleSelectorShape : public KisVisualColorSelectorShape -{ - Q_OBJECT -public: - enum singelDTypes{vertical, horizontal, border, borderMirrored}; - explicit KisVisualRectangleSelectorShape(QWidget *parent, - Dimensions dimension, - ColorModel model, - const KoColorSpace *cs, - int channel1, int channel2, - const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance(), int width=20, - KisVisualRectangleSelectorShape::singelDTypes d = KisVisualRectangleSelectorShape::vertical - ); - ~KisVisualRectangleSelectorShape(); - - void setBorderWidth(int width); - - /** - * @brief getSpaceForSquare - * @param geom the full widget rectangle - * @return rectangle with enough space for second widget - */ - virtual QRect getSpaceForSquare(QRect geom); - virtual QRect getSpaceForCircle(QRect geom); - virtual QRect getSpaceForTriangle(QRect geom); -protected: - void resizeEvent(QResizeEvent *); -private: - virtual QPointF convertShapeCoordinateToWidgetCoordinate(QPointF coordinate); - virtual QPointF convertWidgetCoordinateToShapeCoordinate(QPoint coordinate); - - singelDTypes m_type; - int m_barWidth; - virtual QRegion getMaskMap(); - virtual void drawCursor(); -}; - -class KisVisualEllipticalSelectorShape : public KisVisualColorSelectorShape -{ - Q_OBJECT -public: - enum singelDTypes{border, borderMirrored}; - explicit KisVisualEllipticalSelectorShape(QWidget *parent, - Dimensions dimension, - ColorModel model, - const KoColorSpace *cs, - int channel1, int channel2, - const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance(), int borwidth=20, - KisVisualEllipticalSelectorShape::singelDTypes d = KisVisualEllipticalSelectorShape::border - ); - ~KisVisualEllipticalSelectorShape(); - - void setBorderWidth(int width); - - /** - * @brief getSpaceForSquare - * @param geom the full widget rectangle - * @return rectangle with enough space for second widget - */ - virtual QRect getSpaceForSquare(QRect geom); - virtual QRect getSpaceForCircle(QRect geom); - virtual QRect getSpaceForTriangle(QRect geom); -protected: - void resizeEvent(QResizeEvent *); -private: - virtual QPointF convertShapeCoordinateToWidgetCoordinate(QPointF coordinate); - virtual QPointF convertWidgetCoordinateToShapeCoordinate(QPoint coordinate); - - - singelDTypes m_type; - int m_barWidth; - virtual QRegion getMaskMap(); - virtual void drawCursor(); - QSize sizeHint() const; -}; - -class KisVisualTriangleSelectorShape : public KisVisualColorSelectorShape -{ - Q_OBJECT -public: - enum singelDTypes{border, borderMirrored}; - explicit KisVisualTriangleSelectorShape(QWidget *parent, - Dimensions dimension, - ColorModel model, - const KoColorSpace *cs, - int channel1, int channel2, - const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance(), - int borwidth=20 - ); - ~KisVisualTriangleSelectorShape(); - - void setBorderWidth(int width); - void setTriangle(); - - /** - * @brief getSpaceForSquare - * @param geom the full widget rectangle - * @return rectangle with enough space for second widget - */ - virtual QRect getSpaceForSquare(QRect geom); - virtual QRect getSpaceForCircle(QRect geom); - virtual QRect getSpaceForTriangle(QRect geom); - -protected: - void resizeEvent(QResizeEvent *); - -private: - - virtual QPointF convertShapeCoordinateToWidgetCoordinate(QPointF coordinate); - virtual QPointF convertWidgetCoordinateToShapeCoordinate(QPoint coordinate); - - singelDTypes m_type; - int m_barWidth; - QPolygon m_triangle; - QPointF m_center; - qreal m_radius; - virtual QRegion getMaskMap(); - virtual void drawCursor(); -}; -#endif // KISVISUALCOLORSELECTOR_H +#endif diff --git a/libs/ui/widgets/KisVisualEllipticalSelectorShape.cpp b/libs/ui/widgets/KisVisualEllipticalSelectorShape.cpp new file mode 100644 index 0000000000..c70f6d2480 --- /dev/null +++ b/libs/ui/widgets/KisVisualEllipticalSelectorShape.cpp @@ -0,0 +1,240 @@ +/* + * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 + * + * 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 "KisVisualEllipticalSelectorShape.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "KoColorConversions.h" +#include "KoColorDisplayRendererInterface.h" +#include "KoChannelInfo.h" +#include +#include +#include "kis_signal_compressor.h" +#include "kis_debug.h" + +KisVisualEllipticalSelectorShape::KisVisualEllipticalSelectorShape(QWidget *parent, + Dimensions dimension, + ColorModel model, + const KoColorSpace *cs, + int channel1, int channel2, + const KoColorDisplayRendererInterface *displayRenderer, + int barWidth, + singelDTypes d) + : KisVisualColorSelectorShape(parent, dimension, model, cs, channel1, channel2, displayRenderer) +{ + //qDebug() << "creating KisVisualEllipticalSelectorShape" << this; + m_type = d; + m_barWidth = barWidth; +} + +KisVisualEllipticalSelectorShape::~KisVisualEllipticalSelectorShape() +{ + //qDebug() << "deleting KisVisualEllipticalSelectorShape" << this; +} + +QSize KisVisualEllipticalSelectorShape::sizeHint() const +{ + return QSize(180,180); +} +void KisVisualEllipticalSelectorShape::setBorderWidth(int width) +{ + m_barWidth = width; +} + +QRect KisVisualEllipticalSelectorShape::getSpaceForSquare(QRect geom) +{ + int sizeValue = qMin(width(),height()); + QRect b(geom.left(), geom.top(), sizeValue, sizeValue); + QLineF radius(b.center(), QPointF(b.left()+m_barWidth, b.center().y()) ); + radius.setAngle(135); + QPointF tl = radius.p2(); + radius.setAngle(315); + QPointF br = radius.p2(); + QRect r(tl.toPoint(), br.toPoint()); + return r; +} + +QRect KisVisualEllipticalSelectorShape::getSpaceForCircle(QRect geom) +{ + int sizeValue = qMin(width(),height()); + QRect b(geom.left(), geom.top(), sizeValue, sizeValue); + QPointF tl = QPointF (b.topLeft().x()+m_barWidth, b.topLeft().y()+m_barWidth); + QPointF br = QPointF (b.bottomRight().x()-m_barWidth, b.bottomRight().y()-m_barWidth); + QRect r(tl.toPoint(), br.toPoint()); + return r; +} + +QRect KisVisualEllipticalSelectorShape::getSpaceForTriangle(QRect geom) +{ + int sizeValue = qMin(width(),height()); + QRect b(geom.left(), geom.top(), sizeValue, sizeValue); + QLineF radius(b.center(), QPointF(b.left()+m_barWidth, b.center().y()) ); + radius.setAngle(90);//point at yellowgreen :) + QPointF t = radius.p2(); + radius.setAngle(330);//point to purple :) + QPointF br = radius.p2(); + radius.setAngle(210);//point to cerulean :) + QPointF bl = radius.p2(); + QPointF tl = QPoint(bl.x(),t.y()); + QRect r(tl.toPoint(), br.toPoint()); + return r; +} + +QPointF KisVisualEllipticalSelectorShape::convertShapeCoordinateToWidgetCoordinate(QPointF coordinate) +{ + qreal x; + qreal y; + qreal offset=7.0; + qreal a = (qreal)width()*0.5; + QPointF center(a, a); + QLineF line(center, QPoint((m_barWidth*0.5),a)); + qreal angle = coordinate.x()*360.0; + angle = fmod(angle+180.0,360.0); + angle = 180.0-angle; + angle = angle+180.0; + if (m_type==KisVisualEllipticalSelectorShape::borderMirrored) { + angle = (coordinate.x()/2)*360.0; + angle = fmod((angle+90.0), 360.0); + } + line.setAngle(angle); + if (getDimensions()!=KisVisualColorSelectorShape::onedimensional) { + line.setLength(qMin(coordinate.y()*(a-offset), a-offset)); + } + x = qRound(line.p2().x()); + y = qRound(line.p2().y()); + return QPointF(x,y); +} + +QPointF KisVisualEllipticalSelectorShape::convertWidgetCoordinateToShapeCoordinate(QPoint coordinate) +{ + //default implementation: + qreal x = 0.5; + qreal y = 1.0; + qreal offset = 7.0; + QRect total(0, 0, width(), height()); + QLineF line(total.center(), coordinate); + qreal a = (total.width()/2); + qreal angle; + + if (m_type!=KisVisualEllipticalSelectorShape::borderMirrored){ + angle = fmod((line.angle()+180.0), 360.0); + angle = 180.0-angle; + angle = angle+180.0; + x = angle/360.0; + if (getDimensions()==KisVisualColorSelectorShape::twodimensional) { + y = qBound(0.0,line.length()/(a-offset), 1.0); + } + + } else { + angle = fmod((line.angle()+270.0), 360.0); + if (angle>180.0) { + angle = 180.0-angle; + angle = angle+180; + } + x = (angle/360.0)*2; + if (getDimensions()==KisVisualColorSelectorShape::twodimensional) { + y = qBound(0.0,(line.length()+offset)/a, 1.0); + } + } + + return QPointF(x, y); +} + +QRegion KisVisualEllipticalSelectorShape::getMaskMap() +{ + QRegion mask = QRegion(0,0,width(),height(), QRegion::Ellipse); + if (getDimensions()==KisVisualColorSelectorShape::onedimensional) { + mask = mask.subtracted(QRegion(m_barWidth, m_barWidth, width()-(m_barWidth*2), height()-(m_barWidth*2), QRegion::Ellipse)); + } + return mask; +} + +void KisVisualEllipticalSelectorShape::resizeEvent(QResizeEvent *) +{ + //qDebug() << this << "KisVisualEllipticalSelectorShape::resizeEvent"; + forceImageUpdate(); +} + +void KisVisualEllipticalSelectorShape::drawCursor() +{ + //qDebug() << this << "KisVisualEllipticalSelectorShape::drawCursor: image needs update" << imagesNeedUpdate(); + QPointF cursorPoint = convertShapeCoordinateToWidgetCoordinate(getCursorPosition()); + QImage fullSelector = getImageMap(); + QColor col = getColorFromConverter(getCurrentColor()); + QPainter painter; + painter.begin(&fullSelector); + painter.setRenderHint(QPainter::Antialiasing); + QRect innerRect(m_barWidth, m_barWidth, width()-(m_barWidth*2), height()-(m_barWidth*2)); + + painter.save(); + painter.setCompositionMode(QPainter::CompositionMode_Clear); + QPen pen; + pen.setWidth(5); + painter.setPen(pen); + painter.drawEllipse(QRect(0,0,width(),height())); + + if (getDimensions()==KisVisualColorSelectorShape::onedimensional) { + painter.setBrush(Qt::SolidPattern); + painter.drawEllipse(innerRect); + } + painter.restore(); + + QBrush fill; + fill.setStyle(Qt::SolidPattern); + + int cursorwidth = 5; + + if (m_type==KisVisualEllipticalSelectorShape::borderMirrored) { + painter.setPen(Qt::white); + fill.setColor(Qt::white); + painter.setBrush(fill); + painter.drawEllipse(cursorPoint, cursorwidth, cursorwidth); + QPoint mirror(innerRect.center().x()+(innerRect.center().x()-cursorPoint.x()),cursorPoint.y()); + painter.drawEllipse(mirror, cursorwidth, cursorwidth); + fill.setColor(col); + painter.setPen(Qt::black); + painter.setBrush(fill); + painter.drawEllipse(cursorPoint, cursorwidth-1, cursorwidth-1); + painter.drawEllipse(mirror, cursorwidth-1, cursorwidth-1); + + } else { + painter.setPen(Qt::white); + fill.setColor(Qt::white); + painter.setBrush(fill); + painter.drawEllipse(cursorPoint, cursorwidth, cursorwidth); + fill.setColor(col); + painter.setPen(Qt::black); + painter.setBrush(fill); + painter.drawEllipse(cursorPoint, cursorwidth-1.0, cursorwidth-1.0); + } + painter.end(); + setFullImage(fullSelector); +} diff --git a/libs/ui/widgets/KisVisualEllipticalSelectorShape.h b/libs/ui/widgets/KisVisualEllipticalSelectorShape.h new file mode 100644 index 0000000000..05ad55d9e0 --- /dev/null +++ b/libs/ui/widgets/KisVisualEllipticalSelectorShape.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 + * + * 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 KISVISUALCOLORSELECTOR_H +#define KISVISUALCOLORSELECTOR_H + +#include +#include +#include +#include +#include + +#include +#include +#include "KoColorDisplayRendererInterface.h" + +#include "KisColorSelectorConfiguration.h" +#include "KisVisualColorSelectorShape.h" + +#include "kritaui_export.h" + +class KisVisualEllipticalSelectorShape : public KisVisualColorSelectorShape +{ + Q_OBJECT +public: + enum singelDTypes{border, borderMirrored}; + explicit KisVisualEllipticalSelectorShape(QWidget *parent, + Dimensions dimension, + ColorModel model, + const KoColorSpace *cs, + int channel1, int channel2, + const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance(), int barWidth=20, + KisVisualEllipticalSelectorShape::singelDTypes d = KisVisualEllipticalSelectorShape::border + ); + ~KisVisualEllipticalSelectorShape(); + + void setBorderWidth(int width); + + /** + * @brief getSpaceForSquare + * @param geom the full widget rectangle + * @return rectangle with enough space for second widget + */ + virtual QRect getSpaceForSquare(QRect geom); + virtual QRect getSpaceForCircle(QRect geom); + virtual QRect getSpaceForTriangle(QRect geom); +protected: + void resizeEvent(QResizeEvent *); +private: + virtual QPointF convertShapeCoordinateToWidgetCoordinate(QPointF coordinate); + virtual QPointF convertWidgetCoordinateToShapeCoordinate(QPoint coordinate); + + + singelDTypes m_type; + int m_barWidth; + virtual QRegion getMaskMap(); + virtual void drawCursor(); + QSize sizeHint() const; +}; + +#endif // KISVISUALCOLORSELECTOR_H diff --git a/libs/ui/widgets/KisVisualRectangleSelectorShape.cpp b/libs/ui/widgets/KisVisualRectangleSelectorShape.cpp new file mode 100644 index 0000000000..f1767c5c51 --- /dev/null +++ b/libs/ui/widgets/KisVisualRectangleSelectorShape.cpp @@ -0,0 +1,373 @@ +/* + * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 + * + * 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 "KisVisualRectangleSelectorShape.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "KoColorConversions.h" +#include "KoColorDisplayRendererInterface.h" +#include "KoChannelInfo.h" +#include +#include +#include "kis_signal_compressor.h" +#include "kis_debug.h" + +KisVisualRectangleSelectorShape::KisVisualRectangleSelectorShape(QWidget *parent, + Dimensions dimension, + ColorModel model, + const KoColorSpace *cs, + int channel1, int channel2, + const KoColorDisplayRendererInterface *displayRenderer, + int width, + singelDTypes d) + : KisVisualColorSelectorShape(parent, dimension, model, cs, channel1, channel2, displayRenderer) +{ + //qDebug() << "creating KisVisualRectangleSelectorShape" << this; + m_type = d; + m_barWidth = width; +} + +KisVisualRectangleSelectorShape::~KisVisualRectangleSelectorShape() +{ + //qDebug() << "deleting KisVisualRectangleSelectorShape" << this; +} + +void KisVisualRectangleSelectorShape::setBorderWidth(int width) +{ + m_barWidth = width; +} + +QRect KisVisualRectangleSelectorShape::getSpaceForSquare(QRect geom) +{ + QPointF tl; + QPointF br; + + if (m_type==KisVisualRectangleSelectorShape::vertical) { + br = geom.bottomRight(); + tl = QPoint(geom.topLeft().x()+m_barWidth, geom.topLeft().y()); + } else if (m_type==KisVisualRectangleSelectorShape::horizontal) { + br = geom.bottomRight(); + tl = QPoint(geom.topLeft().x(), geom.topLeft().y()+m_barWidth); + } else { + tl = QPointF (geom.topLeft().x()+m_barWidth, geom.topLeft().y()+m_barWidth); + br = QPointF (geom.bottomRight().x()-m_barWidth, geom.bottomRight().y()-m_barWidth); + + } + QRect a(tl.toPoint(), br.toPoint()); + QRect r(a.left(), a.top(), qMin(a.height(), a.width()), qMin(a.height(), a.width())); + return r; +} + +QRect KisVisualRectangleSelectorShape::getSpaceForCircle(QRect geom) +{ + return getSpaceForSquare(geom); +} + +QRect KisVisualRectangleSelectorShape::getSpaceForTriangle(QRect geom) +{ + return getSpaceForSquare(geom); +} + +QPointF KisVisualRectangleSelectorShape::convertShapeCoordinateToWidgetCoordinate(QPointF coordinate) +{ + qreal x = m_barWidth/2; + qreal y = m_barWidth/2; + qreal offset = 5.0; + KisVisualColorSelectorShape::Dimensions dimension = getDimensions(); + if (dimension == KisVisualColorSelectorShape::onedimensional) { + if ( m_type == KisVisualRectangleSelectorShape::vertical) { + y = qMin(coordinate.x()*(height()-offset*2)+offset, (qreal)height()); + } else if (m_type == KisVisualRectangleSelectorShape::horizontal) { + x = qMin(coordinate.x()*(width()-offset*2)+offset, (qreal)width()); + } else if (m_type == KisVisualRectangleSelectorShape::border) { + + QRectF innerRect(m_barWidth/2, m_barWidth/2, width()-m_barWidth, height()-m_barWidth); + QPointF left (innerRect.left(),innerRect.center().y()); + QList polygonLines; + polygonLines.append(QLineF(left, innerRect.topLeft())); + polygonLines.append(QLineF(innerRect.topLeft(), innerRect.topRight())); + polygonLines.append(QLineF(innerRect.topRight(), innerRect.bottomRight())); + polygonLines.append(QLineF(innerRect.bottomRight(), innerRect.bottomLeft())); + polygonLines.append(QLineF(innerRect.bottomLeft(), left)); + + qreal totalLength =0.0; + Q_FOREACH(QLineF line, polygonLines) { + totalLength += line.length(); + } + + qreal length = coordinate.x()*totalLength; + QPointF intersect(x,y); + Q_FOREACH(QLineF line, polygonLines) { + if (line.length()>length && length>0){ + intersect = line.pointAt(length/line.length()); + + } + length-=line.length(); + } + x = qRound(intersect.x()); + y = qRound(intersect.y()); + + } + else /*if (m_type == KisVisualRectangleSelectorShape::borderMirrored)*/ { + + QRectF innerRect(m_barWidth/2, m_barWidth/2, width()-m_barWidth, height()-m_barWidth); + QPointF bottom (innerRect.center().x(), innerRect.bottom()); + QList polygonLines; + polygonLines.append(QLineF(bottom, innerRect.bottomLeft())); + polygonLines.append(QLineF(innerRect.bottomLeft(), innerRect.topLeft())); + polygonLines.append(QLineF(innerRect.topLeft(), innerRect.topRight())); + polygonLines.append(QLineF(innerRect.topRight(), innerRect.bottomRight())); + polygonLines.append(QLineF(innerRect.bottomRight(), bottom)); + + qreal totalLength =0.0; + Q_FOREACH(QLineF line, polygonLines) { + totalLength += line.length(); + } + + qreal length = coordinate.x()*(totalLength/2); + QPointF intersect(x,y); + if (coordinate.y()==1) { + for (int i = polygonLines.size()-1; i==0; i--) { + QLineF line = polygonLines.at(i); + if (line.length()>length && length>0){ + intersect = line.pointAt(length/line.length()); + + } + length-=line.length(); + } + } else { + Q_FOREACH(QLineF line, polygonLines) { + if (line.length()>length && length>0){ + intersect = line.pointAt(length/line.length()); + + } + length-=line.length(); + } + } + x = qRound(intersect.x()); + y = qRound(intersect.y()); + + } + } else { + x = qMin(coordinate.x()*(height()-offset*2)+offset, (qreal)height()); + y = qMin(coordinate.y()*(width()-offset*2)+offset, (qreal)width()); + } + return QPointF(x,y); +} + +QPointF KisVisualRectangleSelectorShape::convertWidgetCoordinateToShapeCoordinate(QPoint coordinate) +{ + //default implementation: + qreal x = 0.5; + qreal y = 0.5; + qreal offset = 5.0; + KisVisualColorSelectorShape::Dimensions dimension = getDimensions(); + if (getMaskMap().contains(coordinate)) { + if (dimension == KisVisualColorSelectorShape::onedimensional ) { + if (m_type == KisVisualRectangleSelectorShape::vertical) { + x = qMax(((qreal)coordinate.y()-offset)/((qreal)height()-offset*2), 0.0); + } else if (m_type == KisVisualRectangleSelectorShape::horizontal) { + x = qMax(((qreal)coordinate.x()-offset)/((qreal)width()-offset*2),0.0); + } else if (m_type == KisVisualRectangleSelectorShape::border) { + //border + + QRectF innerRect(m_barWidth, m_barWidth, width()-(m_barWidth*2), height()-(m_barWidth*2)); + QPointF left (innerRect.left(),innerRect.center().y()); + QList polygonLines; + polygonLines.append(QLineF(left, innerRect.topLeft())); + polygonLines.append(QLineF(innerRect.topLeft(), innerRect.topRight())); + polygonLines.append(QLineF(innerRect.topRight(), innerRect.bottomRight())); + polygonLines.append(QLineF(innerRect.bottomRight(), innerRect.bottomLeft())); + polygonLines.append(QLineF(innerRect.bottomLeft(), left)); + + QLineF radius(coordinate, this->geometry().center()); + QPointF intersect(0.5,0.5); + qreal length = 0.0; + qreal totalLength = 0.0; + bool foundIntersect = false; + Q_FOREACH(QLineF line, polygonLines) { + if (line.intersect(radius,&intersect)==QLineF::BoundedIntersection && foundIntersect==false) + { + foundIntersect = true; + length+=QLineF(line.p1(), intersect).length(); + + } + if (foundIntersect==false) { + length+=line.length(); + } + totalLength+=line.length(); + } + + x = length/totalLength; + + } else /*if (m_type == KisVisualRectangleSelectorShape::borderMirrored)*/ { + //border + + QRectF innerRect(m_barWidth, m_barWidth, width()-(m_barWidth*2), height()-(m_barWidth*2)); + QPointF bottom (innerRect.center().x(), innerRect.bottom()); + QList polygonLines; + polygonLines.append(QLineF(bottom, innerRect.bottomLeft())); + polygonLines.append(QLineF(innerRect.bottomLeft(), innerRect.topLeft())); + polygonLines.append(QLineF(innerRect.topLeft(), innerRect.topRight())); + polygonLines.append(QLineF(innerRect.topRight(), innerRect.bottomRight())); + polygonLines.append(QLineF(innerRect.bottomRight(), bottom)); + + QLineF radius(coordinate, this->geometry().center()); + QPointF intersect(0.5,0.5); + qreal length = 0.0; + qreal totalLength = 0.0; + bool foundIntersect = false; + Q_FOREACH(QLineF line, polygonLines) { + if (line.intersect(radius,&intersect)==QLineF::BoundedIntersection && foundIntersect==false) + { + foundIntersect = true; + length+=QLineF(line.p1(), intersect).length(); + + } + if (foundIntersect==false) { + length+=line.length(); + } + totalLength+=line.length(); + } + int halflength = totalLength/2; + + if (length>halflength) { + x = (halflength - (length-halflength))/halflength; + y = 1.0; + } else { + x = length/halflength; + y = 0.0; + } + } + } + else { + x = qMax(((qreal)coordinate.x()-offset)/((qreal)width()-offset*2), 0.0); + y = qMax(((qreal)coordinate.y()-offset)/((qreal)height()-offset*2), 0.0);; + } + } + return QPointF(x, y); +} + +QRegion KisVisualRectangleSelectorShape::getMaskMap() +{ + QRegion mask = QRegion(0,0,width(),height()); + if (m_type==KisVisualRectangleSelectorShape::border || m_type==KisVisualRectangleSelectorShape::borderMirrored) { + mask = mask.subtracted(QRegion(m_barWidth, m_barWidth, width()-(m_barWidth*2), height()-(m_barWidth*2))); + } + return mask; +} +void KisVisualRectangleSelectorShape::resizeEvent(QResizeEvent *) +{ + //qDebug() << this << "KisVisualRectangleSelectorShape::resizeEvent"; + forceImageUpdate(); +} + +void KisVisualRectangleSelectorShape::drawCursor() +{ + //qDebug() << this << "KisVisualRectangleSelectorShape::drawCursor: image needs update" << imagesNeedUpdate(); + QPointF cursorPoint = convertShapeCoordinateToWidgetCoordinate(getCursorPosition()); + QImage fullSelector = getImageMap(); + QColor col = getColorFromConverter(getCurrentColor()); + QPainter painter; + painter.begin(&fullSelector); + painter.setRenderHint(QPainter::Antialiasing); + //QPainterPath path; + QBrush fill; + fill.setStyle(Qt::SolidPattern); + + int cursorwidth = 5; + QRect rect(cursorPoint.toPoint().x()-cursorwidth,cursorPoint.toPoint().y()-cursorwidth, + cursorwidth*2,cursorwidth*2); + if (m_type==KisVisualRectangleSelectorShape::vertical){ + int x = ( cursorPoint.x()-(width()/2)+1 ); + int y = ( cursorPoint.y()-cursorwidth ); + rect.setCoords(x, y, x+width()-2, y+(cursorwidth*2)); + painter.save(); + painter.setCompositionMode(QPainter::CompositionMode_Clear); + QPen pen; + pen.setWidth(5); + painter.setPen(pen); + painter.drawLine(QLine(QPoint(0.0,0.0), QPoint(0.0,height()))); + painter.drawLine(QLine(QPoint(width(),0.0), QPoint(width(),height()))); + painter.restore(); + } else { + int x = cursorPoint.x()-cursorwidth; + int y = cursorPoint.y()-(height()/2)+1; + rect.setCoords(x, y, x+(cursorwidth*2), y+cursorwidth-2); + } + QRectF innerRect(m_barWidth, m_barWidth, width()-(m_barWidth*2), height()-(m_barWidth*2)); + if (getDimensions() == KisVisualColorSelectorShape::onedimensional && m_type!=KisVisualRectangleSelectorShape::border && m_type!=KisVisualRectangleSelectorShape::borderMirrored) { + painter.setPen(Qt::white); + fill.setColor(Qt::white); + painter.setBrush(fill); + painter.drawRect(rect); + //set filter conversion! + fill.setColor(col); + painter.setPen(Qt::black); + painter.setBrush(fill); + rect.setCoords(rect.topLeft().x()+1, rect.topLeft().y()+1, + rect.topLeft().x()+rect.width()-2, rect.topLeft().y()+rect.height()-2); + painter.drawRect(rect); + + }else if(m_type==KisVisualRectangleSelectorShape::borderMirrored){ + painter.setPen(Qt::white); + fill.setColor(Qt::white); + painter.setBrush(fill); + painter.drawEllipse(cursorPoint, cursorwidth, cursorwidth); + QPoint mirror(innerRect.center().x()+(innerRect.center().x()-cursorPoint.x()),cursorPoint.y()); + painter.drawEllipse(mirror, cursorwidth, cursorwidth); + fill.setColor(col); + painter.setPen(Qt::black); + painter.setBrush(fill); + painter.drawEllipse(cursorPoint, cursorwidth-1, cursorwidth-1); + painter.drawEllipse(mirror, cursorwidth-1, cursorwidth-1); + + } else { + painter.save(); + painter.setCompositionMode(QPainter::CompositionMode_Clear); + QPen pen; + pen.setWidth(5); + painter.setPen(pen); + painter.drawRect(QRect(0,0,width(),height())); + painter.restore(); + + painter.setPen(Qt::white); + fill.setColor(Qt::white); + painter.setBrush(fill); + painter.drawEllipse(cursorPoint, cursorwidth, cursorwidth); + fill.setColor(col); + painter.setPen(Qt::black); + painter.setBrush(fill); + painter.drawEllipse(cursorPoint, cursorwidth-1.0, cursorwidth-1.0); + } + painter.end(); + setFullImage(fullSelector); +} diff --git a/libs/ui/widgets/KisVisualRectangleSelectorShape.h b/libs/ui/widgets/KisVisualRectangleSelectorShape.h new file mode 100644 index 0000000000..ffc15b35f2 --- /dev/null +++ b/libs/ui/widgets/KisVisualRectangleSelectorShape.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 + * + * 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_VISUAL_RECTANGLE_SELECTOR_SHAPE_H +#define KIS_VISUAL_RECTANGLE_SELECTOR_SHAPE_H + +#include +#include +#include +#include +#include + +#include +#include +#include "KoColorDisplayRendererInterface.h" + +#include "KisColorSelectorConfiguration.h" +#include "KisVisualColorSelectorShape.h" + +#include "kritaui_export.h" + +class KisVisualRectangleSelectorShape : public KisVisualColorSelectorShape +{ + Q_OBJECT +public: + enum singelDTypes{vertical, horizontal, border, borderMirrored}; + explicit KisVisualRectangleSelectorShape(QWidget *parent, + Dimensions dimension, + ColorModel model, + const KoColorSpace *cs, + int channel1, int channel2, + const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance(), int width=20, + KisVisualRectangleSelectorShape::singelDTypes d = KisVisualRectangleSelectorShape::vertical + ); + ~KisVisualRectangleSelectorShape(); + + void setBorderWidth(int width); + + /** + * @brief getSpaceForSquare + * @param geom the full widget rectangle + * @return rectangle with enough space for second widget + */ + virtual QRect getSpaceForSquare(QRect geom); + virtual QRect getSpaceForCircle(QRect geom); + virtual QRect getSpaceForTriangle(QRect geom); +protected: + void resizeEvent(QResizeEvent *); +private: + virtual QPointF convertShapeCoordinateToWidgetCoordinate(QPointF coordinate); + virtual QPointF convertWidgetCoordinateToShapeCoordinate(QPoint coordinate); + + singelDTypes m_type; + int m_barWidth; + virtual QRegion getMaskMap(); + virtual void drawCursor(); +}; + +#endif diff --git a/libs/ui/widgets/KisVisualTriangleSelectorShape.cpp b/libs/ui/widgets/KisVisualTriangleSelectorShape.cpp new file mode 100644 index 0000000000..a47d068b60 --- /dev/null +++ b/libs/ui/widgets/KisVisualTriangleSelectorShape.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 + * + * 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 "KisVisualTriangleSelectorShape.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "KoColorConversions.h" +#include "KoColorDisplayRendererInterface.h" +#include "KoChannelInfo.h" +#include +#include +#include "kis_signal_compressor.h" +#include "kis_debug.h" + +KisVisualTriangleSelectorShape::KisVisualTriangleSelectorShape(QWidget *parent, + Dimensions dimension, + ColorModel model, + const KoColorSpace *cs, + int channel1, int channel2, + const KoColorDisplayRendererInterface *displayRenderer, + int barwidth) + : KisVisualColorSelectorShape(parent, dimension, model, cs, channel1, channel2, displayRenderer) +{ + //qDebug() << "creating KisVisualTriangleSelectorShape" << this; + m_barWidth = barwidth; + setTriangle(); +} + +KisVisualTriangleSelectorShape::~KisVisualTriangleSelectorShape() +{ + //qDebug() << "deleting KisVisualTriangleSelectorShape" << this; +} + +void KisVisualTriangleSelectorShape::setBorderWidth(int width) +{ + m_barWidth = width; +} + +QRect KisVisualTriangleSelectorShape::getSpaceForSquare(QRect geom) +{ + return geom; +} + +QRect KisVisualTriangleSelectorShape::getSpaceForCircle(QRect geom) +{ + return geom; +} + +QRect KisVisualTriangleSelectorShape::getSpaceForTriangle(QRect geom) +{ + return geom; +} +void KisVisualTriangleSelectorShape::setTriangle() +{ + QPoint apex = QPoint (width()*0.5,0); + QPolygon triangle; + triangle<< QPoint(0,height()) << apex << QPoint(width(),height()) << QPoint(0,height()); + m_triangle = triangle; + QLineF a(triangle.at(0),triangle.at(1)); + QLineF b(triangle.at(0),triangle.at(2)); + QLineF ap(triangle.at(2), a.pointAt(0.5)); + QLineF bp(triangle.at(1), b.pointAt(0.5)); + QPointF intersect; + ap.intersect(bp,&intersect); + m_center = intersect; + QLineF r(triangle.at(0), intersect); + m_radius = r.length(); +} + +QPointF KisVisualTriangleSelectorShape::convertShapeCoordinateToWidgetCoordinate(QPointF coordinate) +{ + qreal offset=7.0;//the offset is so we get a nice little border that allows selecting extreme colors better. + qreal y = qMin(coordinate.y()*(height()-offset*2-5.0)+offset+5.0, (qreal)height()-offset); + + qreal triWidth = width(); + qreal horizontalLineLength = y*(2./sqrt(3.)); + qreal horizontalLineStart = triWidth/2.-horizontalLineLength/2.; + qreal relativeX = coordinate.x()*(horizontalLineLength-offset*2); + qreal x = qMin(relativeX + horizontalLineStart + offset, (qreal)width()-offset*2); + if (y, (C) 2016 + * + * 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_VISUAL_TRIANGLE_SELECTOR_SHAPE_H +#define KIS_VISUAL_TRIANGLE_SELECTOR_SHAPE_H + +#include +#include +#include +#include +#include + +#include +#include +#include "KoColorDisplayRendererInterface.h" + +#include "KisColorSelectorConfiguration.h" +#include "KisVisualColorSelectorShape.h" + +#include "kritaui_export.h" + +class KisVisualTriangleSelectorShape : public KisVisualColorSelectorShape +{ + Q_OBJECT +public: + enum singelDTypes{border, borderMirrored}; + explicit KisVisualTriangleSelectorShape(QWidget *parent, + Dimensions dimension, + ColorModel model, + const KoColorSpace *cs, + int channel1, int channel2, + const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance(), + int barwidth=20 + ); + ~KisVisualTriangleSelectorShape(); + + void setBorderWidth(int width); + void setTriangle(); + + /** + * @brief getSpaceForSquare + * @param geom the full widget rectangle + * @return rectangle with enough space for second widget + */ + virtual QRect getSpaceForSquare(QRect geom); + virtual QRect getSpaceForCircle(QRect geom); + virtual QRect getSpaceForTriangle(QRect geom); + +protected: + void resizeEvent(QResizeEvent *); + +private: + + virtual QPointF convertShapeCoordinateToWidgetCoordinate(QPointF coordinate); + virtual QPointF convertWidgetCoordinateToShapeCoordinate(QPoint coordinate); + + singelDTypes m_type; + int m_barWidth; + QPolygon m_triangle; + QPointF m_center; + qreal m_radius; + virtual QRegion getMaskMap(); + virtual void drawCursor(); +}; +#endif diff --git a/libs/ui/widgets/kis_visual_color_selector.cpp b/libs/ui/widgets/kis_visual_color_selector.cpp deleted file mode 100644 index 92d04b9420..0000000000 --- a/libs/ui/widgets/kis_visual_color_selector.cpp +++ /dev/null @@ -1,1644 +0,0 @@ -/* - * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 - * - * 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_visual_color_selector.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "KoColorConversions.h" -#include "KoColorDisplayRendererInterface.h" -#include "KoChannelInfo.h" -#include -#include -#include "kis_signal_compressor.h" -#include "kis_debug.h" - -struct KisVisualColorSelector::Private -{ - KoColor currentcolor; - const KoColorSpace *currentCS {0}; - QList widgetlist; - bool updateSelf {false}; - bool updateLonesome {false}; //for Modal dialogs. - bool circular {false}; - const KoColorDisplayRendererInterface *displayRenderer {0}; - KisColorSelectorConfiguration acs_config; - //Current coordinates. - KisSignalCompressor *updateTimer {0}; - QVector currentCoordinates; -}; - -KisVisualColorSelector::KisVisualColorSelector(QWidget *parent) - : QWidget(parent) - , m_d(new Private) -{ - this->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); - QVBoxLayout *layout = new QVBoxLayout; - this->setLayout(layout); - - KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); - m_d->acs_config = KisColorSelectorConfiguration::fromString(cfg.readEntry("colorSelectorConfiguration", KisColorSelectorConfiguration().toString())); - -} - -KisVisualColorSelector::~KisVisualColorSelector() -{ - -} - -void KisVisualColorSelector::slotSetColor(KoColor c) -{ - if (m_d->updateSelf == false) { - m_d->currentcolor = c; - if (m_d->currentCS != c.colorSpace()) { - slotsetColorSpace(c.colorSpace()); - } - } - updateSelectorElements(QObject::sender()); -} - -void KisVisualColorSelector::slotsetColorSpace(const KoColorSpace *cs) -{ - if (m_d->currentCS != cs) - { - m_d->currentCS = cs; - slotRebuildSelectors(); - } - -} - -void KisVisualColorSelector::setConfig(bool forceCircular, bool forceSelfUpdate) -{ - m_d->updateLonesome = forceSelfUpdate; - m_d->circular = forceCircular; -} - -KoColor KisVisualColorSelector::getCurrentColor() -{ - return m_d->currentcolor; -} - -void KisVisualColorSelector::ConfigurationChanged() -{ - m_d->updateTimer->start(); -} - -void KisVisualColorSelector::slotRebuildSelectors() -{ - KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); - m_d->acs_config = KisColorSelectorConfiguration::fromString(cfg.readEntry("colorSelectorConfiguration", KisColorSelectorConfiguration().toString())); - - qDeleteAll(children()); - m_d->widgetlist.clear(); - QLayout *layout = new QHBoxLayout; - //redraw all the widgets. - int sizeValue = qMin(width(), height()); - int borderWidth = qMax(sizeValue*0.1, 20.0); - - if (m_d->currentCS->colorChannelCount() == 1) { - KisVisualColorSelectorShape *bar; - if (m_d->circular==false) { - bar = new KisVisualRectangleSelectorShape(this, KisVisualColorSelectorShape::onedimensional,KisVisualColorSelectorShape::Channel, m_d->currentCS, 0, 0,m_d->displayRenderer, borderWidth); - bar->setMaximumWidth(width()*0.1); - bar->setMaximumHeight(height()); - } else { - bar = new KisVisualEllipticalSelectorShape(this, KisVisualColorSelectorShape::onedimensional,KisVisualColorSelectorShape::Channel, m_d->currentCS, 0, 0,m_d->displayRenderer, borderWidth, KisVisualEllipticalSelectorShape::borderMirrored); - layout->setMargin(0); - } - connect (bar, SIGNAL(sigNewColor(KoColor)), this, SLOT(updateFromWidgets(KoColor))); - layout->addWidget(bar); - m_d->widgetlist.append(bar); - } else if (m_d->currentCS->colorChannelCount() == 3) { - QRect newrect(0,0, this->geometry().width(), this->geometry().height()); - - KisVisualColorSelectorShape::ColorModel modelS = KisVisualColorSelectorShape::HSV; - int channel1 = 0; - int channel2 = 1; - int channel3 = 2; - - switch(m_d->acs_config.subTypeParameter) - { - case KisColorSelectorConfiguration::H: - channel1 = 0; - break; - case KisColorSelectorConfiguration::hsyS: - case KisColorSelectorConfiguration::hsiS: - case KisColorSelectorConfiguration::hslS: - case KisColorSelectorConfiguration::hsvS: - channel1 = 1; - break; - case KisColorSelectorConfiguration::V: - case KisColorSelectorConfiguration::L: - case KisColorSelectorConfiguration::I: - case KisColorSelectorConfiguration::Y: - channel1 = 2; - break; - default: - Q_ASSERT_X(false, "", "Invalid acs_config.subTypeParameter"); - } - - switch(m_d->acs_config.mainTypeParameter) - { - case KisColorSelectorConfiguration::hsySH: - modelS = KisVisualColorSelectorShape::HSY; - channel2 = 0; - channel3 = 1; - break; - case KisColorSelectorConfiguration::hsiSH: - modelS = KisVisualColorSelectorShape::HSI; - channel2 = 0; - channel3 = 1; - break; - case KisColorSelectorConfiguration::hslSH: - modelS = KisVisualColorSelectorShape::HSL; - channel2 = 0; - channel3 = 1; - break; - case KisColorSelectorConfiguration::hsvSH: - modelS = KisVisualColorSelectorShape::HSV; - channel2 = 0; - channel3 = 1; - break; - case KisColorSelectorConfiguration::YH: - modelS = KisVisualColorSelectorShape::HSY; - channel2 = 0; - channel3 = 2; - break; - case KisColorSelectorConfiguration::LH: - modelS = KisVisualColorSelectorShape::HSL; - channel2 = 0; - channel3 = 2; - break; - case KisColorSelectorConfiguration::IH: - modelS = KisVisualColorSelectorShape::HSL; - channel2 = 0; - channel3 = 2; - break; - case KisColorSelectorConfiguration::VH: - modelS = KisVisualColorSelectorShape::HSV; - channel2 = 0; - channel3 = 2; - break; - case KisColorSelectorConfiguration::SY: - modelS = KisVisualColorSelectorShape::HSY; - channel2 = 1; - channel3 = 2; - break; - case KisColorSelectorConfiguration::SI: - modelS = KisVisualColorSelectorShape::HSI; - channel2 = 1; - channel3 = 2; - break; - case KisColorSelectorConfiguration::SL: - modelS = KisVisualColorSelectorShape::HSL; - channel2 = 1; - channel3 = 2; - break; - case KisColorSelectorConfiguration::SV: - case KisColorSelectorConfiguration::SV2: - modelS = KisVisualColorSelectorShape::HSV; - channel2 = 1; - channel3 = 2; - break; - default: - Q_ASSERT_X(false, "", "Invalid acs_config.mainTypeParameter"); - } - if (m_d->acs_config.mainType == KisColorSelectorConfiguration::Triangle) { - modelS = KisVisualColorSelectorShape::HSV; - //Triangle only really works in HSV mode. - } - KisVisualColorSelectorShape *bar; - if (m_d->acs_config.subType == KisColorSelectorConfiguration::Ring) { - bar = new KisVisualEllipticalSelectorShape(this, - KisVisualColorSelectorShape::onedimensional, - modelS, - m_d->currentCS, channel1, channel1, - m_d->displayRenderer, borderWidth,KisVisualEllipticalSelectorShape::border); - bar->resize(sizeValue, sizeValue); - } - else if (m_d->acs_config.subType == KisColorSelectorConfiguration::Slider && m_d->circular==false) { - bar = new KisVisualRectangleSelectorShape(this, - KisVisualColorSelectorShape::onedimensional, - modelS, - m_d->currentCS, channel1, channel1, - m_d->displayRenderer, borderWidth); - bar->setMaximumWidth(borderWidth); - bar->setMinimumWidth(borderWidth); - bar->setMinimumHeight(sizeValue); - } - else if (m_d->acs_config.subType == KisColorSelectorConfiguration::Slider && m_d->circular==true) { - bar = new KisVisualEllipticalSelectorShape(this, - KisVisualColorSelectorShape::onedimensional, - modelS, - m_d->currentCS, channel1, channel1, - m_d->displayRenderer, borderWidth, KisVisualEllipticalSelectorShape::borderMirrored); - bar->resize(sizeValue, sizeValue); - } else { - // Accessing bar below would crash since it's not initialized. - // Hopefully this can never happen. - warnUI << "Invalid subType, cannot initialize KisVisualColorSelectorShape"; - Q_ASSERT_X(false, "", "Invalid subType, cannot initialize KisVisualColorSelectorShape"); - return; - } - - bar->setColor(m_d->currentcolor); - m_d->widgetlist.append(bar); - - KisVisualColorSelectorShape *block; - if (m_d->acs_config.mainType == KisColorSelectorConfiguration::Triangle) { - block = new KisVisualTriangleSelectorShape(this, KisVisualColorSelectorShape::twodimensional, - modelS, - m_d->currentCS, channel2, channel3, - m_d->displayRenderer); - block->setGeometry(bar->getSpaceForTriangle(newrect)); - } else if (m_d->acs_config.mainType == KisColorSelectorConfiguration::Square) { - block = new KisVisualRectangleSelectorShape(this, KisVisualColorSelectorShape::twodimensional, - modelS, - m_d->currentCS, channel2, channel3, - m_d->displayRenderer); - block->setGeometry(bar->getSpaceForSquare(newrect)); - } else { - block = new KisVisualEllipticalSelectorShape(this, KisVisualColorSelectorShape::twodimensional, - modelS, - m_d->currentCS, channel2, channel3, - m_d->displayRenderer); - block->setGeometry(bar->getSpaceForCircle(newrect)); - - } - - block->setColor(m_d->currentcolor); - connect (bar, SIGNAL(sigNewColor(KoColor)), block, SLOT(setColorFromSibling(KoColor))); - connect (block, SIGNAL(sigNewColor(KoColor)), SLOT(updateFromWidgets(KoColor))); - connect (bar, SIGNAL(sigHSXchange()), SLOT(HSXwrangler())); - connect (block, SIGNAL(sigHSXchange()), SLOT(HSXwrangler())); - m_d->widgetlist.append(block); - - - } - else if (m_d->currentCS->colorChannelCount() == 4) { - KisVisualRectangleSelectorShape *block = new KisVisualRectangleSelectorShape(this, KisVisualRectangleSelectorShape::twodimensional,KisVisualColorSelectorShape::Channel, m_d->currentCS, 0, 1); - KisVisualRectangleSelectorShape *block2 = new KisVisualRectangleSelectorShape(this, KisVisualRectangleSelectorShape::twodimensional,KisVisualColorSelectorShape::Channel, m_d->currentCS, 2, 3); - block->setMaximumWidth(width()*0.5); - block->setMaximumHeight(height()); - block2->setMaximumWidth(width()*0.5); - block2->setMaximumHeight(height()); - block->setColor(m_d->currentcolor); - block2->setColor(m_d->currentcolor); - connect (block, SIGNAL(sigNewColor(KoColor)), block2, SLOT(setColorFromSibling(KoColor))); - connect (block2, SIGNAL(sigNewColor(KoColor)), SLOT(updateFromWidgets(KoColor))); - layout->addWidget(block); - layout->addWidget(block2); - m_d->widgetlist.append(block); - m_d->widgetlist.append(block2); - } - this->setLayout(layout); -} - -void KisVisualColorSelector::setDisplayRenderer (const KoColorDisplayRendererInterface *displayRenderer) { - m_d->displayRenderer = displayRenderer; - if (m_d->widgetlist.size()>0) { - Q_FOREACH (KisVisualColorSelectorShape *shape, m_d->widgetlist) { - shape->setDisplayRenderer(displayRenderer); - } - } -} - -void KisVisualColorSelector::updateSelectorElements(QObject *source) -{ - //first lock all elements from sending updates, then update all elements. - Q_FOREACH (KisVisualColorSelectorShape *shape, m_d->widgetlist) { - shape->blockSignals(true); - } - - Q_FOREACH (KisVisualColorSelectorShape *shape, m_d->widgetlist) { - if (shape!=source) { - if (m_d->updateSelf) { - shape->setColorFromSibling(m_d->currentcolor); - } else { - shape->setColor(m_d->currentcolor); - } - } - } - Q_FOREACH (KisVisualColorSelectorShape *shape, m_d->widgetlist) { - shape->blockSignals(false); - } - -} - -void KisVisualColorSelector::updateFromWidgets(KoColor c) -{ - m_d->currentcolor = c; - m_d->updateSelf = true; - if (m_d->updateLonesome) { - slotSetColor(c); - Q_EMIT sigNewColor(c); - - } else { - Q_EMIT sigNewColor(c); - } -} - -void KisVisualColorSelector::leaveEvent(QEvent *) -{ - m_d->updateSelf = false; -} - -void KisVisualColorSelector::resizeEvent(QResizeEvent *) { - int sizeValue = qMin(width(), height()); - int borderWidth = qMax(sizeValue*0.1, 20.0); - QRect newrect(0,0, this->geometry().width(), this->geometry().height()); - if (!m_d->currentCS) { - slotsetColorSpace(m_d->currentcolor.colorSpace()); - } - if (m_d->currentCS->colorChannelCount()==3) { - - if (m_d->acs_config.subType == KisColorSelectorConfiguration::Ring) { - m_d->widgetlist.at(0)->resize(sizeValue,sizeValue); - } - else if (m_d->acs_config.subType == KisColorSelectorConfiguration::Slider && m_d->circular==false) { - m_d->widgetlist.at(0)->setMaximumWidth(borderWidth); - m_d->widgetlist.at(0)->setMinimumWidth(borderWidth); - m_d->widgetlist.at(0)->setMinimumHeight(sizeValue); - m_d->widgetlist.at(0)->setMaximumHeight(sizeValue); - } - else if (m_d->acs_config.subType == KisColorSelectorConfiguration::Slider && m_d->circular==true) { - m_d->widgetlist.at(0)->resize(sizeValue,sizeValue); - } - m_d->widgetlist.at(0)->setBorderWidth(borderWidth); - - if (m_d->acs_config.mainType == KisColorSelectorConfiguration::Triangle) { - m_d->widgetlist.at(1)->setGeometry(m_d->widgetlist.at(0)->getSpaceForTriangle(newrect)); - } - else if (m_d->acs_config.mainType == KisColorSelectorConfiguration::Square) { - m_d->widgetlist.at(1)->setGeometry(m_d->widgetlist.at(0)->getSpaceForSquare(newrect)); - } - else if (m_d->acs_config.mainType == KisColorSelectorConfiguration::Wheel) { - m_d->widgetlist.at(1)->setGeometry(m_d->widgetlist.at(0)->getSpaceForCircle(newrect)); - } - } - Q_FOREACH (KisVisualColorSelectorShape *shape, m_d->widgetlist) { - shape->update(); - } -} - -void KisVisualColorSelector::HSXwrangler() -{ - m_d->currentCoordinates = QVector (3); - - QVector w1 = m_d->widgetlist.at(0)->getHSX(m_d->currentCoordinates, true); - QVector w2 = m_d->widgetlist.at(1)->getHSX(m_d->currentCoordinates, true); - QVector ch(3); - - ch[0] = m_d->widgetlist.at(0)->getChannels().at(0); - ch[1] = m_d->widgetlist.at(1)->getChannels().at(0); - ch[2] = m_d->widgetlist.at(1)->getChannels().at(1); - - m_d->currentCoordinates[ch[0]] = w1[ch[0]]; - m_d->currentCoordinates[ch[1]] = w2[ch[1]]; - m_d->currentCoordinates[ch[2]] = w2[ch[2]]; - - m_d->widgetlist.at(0)->setHSX(m_d->currentCoordinates, true); - m_d->widgetlist.at(1)->setHSX(m_d->currentCoordinates, true); -} - -/*------------Selector shape------------*/ -struct KisVisualColorSelectorShape::Private -{ - QImage gradient; - QImage fullSelector; - bool imagesNeedUpdate {true}; - QPointF currentCoordinates; - Dimensions dimension; - ColorModel model; - const KoColorSpace *cs; - KoColor currentColor; - int channel1; - int channel2; - KisSignalCompressor *updateTimer {0}; - bool mousePressActive = false; - const KoColorDisplayRendererInterface *displayRenderer = 0; - qreal hue = 0.0; - qreal sat = 0.0; - qreal tone = 0.0; - -}; - -KisVisualColorSelectorShape::KisVisualColorSelectorShape(QWidget *parent, - KisVisualColorSelectorShape::Dimensions dimension, - KisVisualColorSelectorShape::ColorModel model, - const KoColorSpace *cs, - int channel1, - int channel2, - const KoColorDisplayRendererInterface *displayRenderer): QWidget(parent), m_d(new Private) -{ - m_d->dimension = dimension; - m_d->model = model; - m_d->cs = cs; - m_d->currentColor = KoColor(); - m_d->currentColor.setOpacity(1.0); - m_d->currentColor.convertTo(cs); - int maxchannel = m_d->cs->colorChannelCount()-1; - m_d->channel1 = qBound(0, channel1, maxchannel); - m_d->channel2 = qBound(0, channel2, maxchannel); - this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - m_d->updateTimer = new KisSignalCompressor(100 /* ms */, KisSignalCompressor::POSTPONE, this); - connect(m_d->updateTimer, SIGNAL(timeout()), SLOT(slotRebuildSelectors()), Qt::UniqueConnection); - setDisplayRenderer(displayRenderer); - show(); - -} - -KisVisualColorSelectorShape::~KisVisualColorSelectorShape() -{ -} - -void KisVisualColorSelectorShape::updateCursor() -{ - QPointF point1 = convertKoColorToShapeCoordinate(m_d->currentColor); - if (point1 != m_d->currentCoordinates) { - m_d->currentCoordinates = point1; - } -} - -QPointF KisVisualColorSelectorShape::getCursorPosition() { - return m_d->currentCoordinates; -} - -void KisVisualColorSelectorShape::setColor(KoColor c) -{ - //qDebug()() << "KisVisualColorSelectorShape::setColor"; - if (c.colorSpace() != m_d->cs) { - c.convertTo(m_d->cs); - } - m_d->currentColor = c; - updateCursor(); - - m_d->imagesNeedUpdate = true; - update(); -} - -void KisVisualColorSelectorShape::setColorFromSibling(KoColor c) -{ - //qDebug()() << "setColorFromSibling"; - if (c.colorSpace() != m_d->cs) { - c.convertTo(m_d->cs); - } - m_d->currentColor = c; - Q_EMIT sigNewColor(c); - m_d->imagesNeedUpdate = true; - update(); -} - -void KisVisualColorSelectorShape::setDisplayRenderer (const KoColorDisplayRendererInterface *displayRenderer) -{ - if (displayRenderer) { - if (m_d->displayRenderer) { - m_d->displayRenderer->disconnect(this); - } - m_d->displayRenderer = displayRenderer; - } else { - m_d->displayRenderer = KoDumbColorDisplayRenderer::instance(); - } - connect(m_d->displayRenderer, SIGNAL(displayConfigurationChanged()), - SLOT(updateFromChangedDisplayRenderer()), Qt::UniqueConnection); - -} - -void KisVisualColorSelectorShape::updateFromChangedDisplayRenderer() -{ - //qDebug()() << "updateFromChangedDisplayRenderer();"; - m_d->imagesNeedUpdate = true; - updateCursor(); - //m_d->currentColor = convertShapeCoordinateToKoColor(getCursorPosition()); - update(); -} - -void KisVisualColorSelectorShape::forceImageUpdate() -{ - //qDebug()() << "forceImageUpdate"; - m_d->imagesNeedUpdate = true; -} - -QColor KisVisualColorSelectorShape::getColorFromConverter(KoColor c){ - QColor col; - KoColor color = c; - if (m_d->displayRenderer) { - color.convertTo(m_d->displayRenderer->getPaintingColorSpace()); - col = m_d->displayRenderer->toQColor(c); - } else { - col = c.toQColor(); - } - return col; -} - -void KisVisualColorSelectorShape::slotSetActiveChannels(int channel1, int channel2) -{ - //qDebug()() << "slotSetActiveChannels"; - int maxchannel = m_d->cs->colorChannelCount()-1; - m_d->channel1 = qBound(0, channel1, maxchannel); - m_d->channel2 = qBound(0, channel2, maxchannel); - m_d->imagesNeedUpdate = true; - update(); -} - -bool KisVisualColorSelectorShape::imagesNeedUpdate() const { - return m_d->imagesNeedUpdate; -} - -QImage KisVisualColorSelectorShape::getImageMap() -{ - //qDebug()() << ">>>>>>>>> getImageMap()" << m_d->imagesNeedUpdate; - - if (m_d->imagesNeedUpdate == true) { - m_d->gradient = QImage(width(), height(), QImage::Format_ARGB32); - m_d->gradient.fill(Qt::transparent); - QImage img(width(), height(), QImage::Format_ARGB32); - img.fill(Qt::transparent); - for (int y = 0; y(img.scanLine(y)); - for (int x=0; ximagesNeedUpdate = false; - m_d->gradient = img; - } - return m_d->gradient; -} - -KoColor KisVisualColorSelectorShape::convertShapeCoordinateToKoColor(QPointF coordinates, bool cursor) -{ - KoColor c = m_d->currentColor; - QVector channelValues (c.colorSpace()->channelCount()); - channelValues.fill(1.0); - c.colorSpace()->normalisedChannelsValue(c.data(), channelValues); - QVector channelValuesDisplay = channelValues; - QVector maxvalue(c.colorSpace()->channelCount()); - maxvalue.fill(1.0); - if (m_d->displayRenderer - && (m_d->cs->colorDepthId() == Float16BitsColorDepthID - || m_d->cs->colorDepthId() == Float32BitsColorDepthID - || m_d->cs->colorDepthId() == Float64BitsColorDepthID) - && m_d->cs->colorModelId() != LABAColorModelID - && m_d->cs->colorModelId() != CMYKAColorModelID) { - for (int ch = 0; chcs->channels()[ch]; - maxvalue[ch] = m_d->displayRenderer->maxVisibleFloatValue(channel); - channelValues[ch] = channelValues[ch]/(maxvalue[ch]); - channelValuesDisplay[KoChannelInfo::displayPositionToChannelIndex(ch, m_d->cs->channels())] = channelValues[ch]; - } - } else { - for (int i =0; ics->channels())] = qBound((float)0.0,channelValues[i], (float)1.0); - } - } - qreal huedivider = 1.0; - qreal huedivider2 = 1.0; - - if (m_d->channel1==0) { - huedivider = 360.0; - } - if (m_d->channel2==0) { - huedivider2 = 360.0; - } - if (m_d->model != ColorModel::Channel && c.colorSpace()->colorModelId().id() == "RGBA") { - if (c.colorSpace()->colorModelId().id() == "RGBA") { - if (m_d->model == ColorModel::HSV){ - /* - * RGBToHSV has a undefined hue possibility. This means that hue will be -1. - * This can be annoying for dealing with a selector, but I understand it is being - * used for the KoColorSelector... For now implement a qMax here. - */ - QVector inbetween(3); - RGBToHSV(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); - inbetween = convertvectorqrealTofloat(getHSX(convertvectorfloatToqreal(inbetween))); - inbetween[m_d->channel1] = coordinates.x()*huedivider; - if (m_d->dimension == Dimensions::twodimensional) { - inbetween[m_d->channel2] = coordinates.y()*huedivider2; - } - if (cursor==true){setHSX(convertvectorfloatToqreal(inbetween));Q_EMIT sigHSXchange();} - HSVToRGB(qMax(inbetween[0],(float)0.0), inbetween[1], inbetween[2], &channelValuesDisplay[0], &channelValuesDisplay[1], &channelValuesDisplay[2]); - } else if (m_d->model == ColorModel::HSL) { - /* - * HSLToRGB can give negative values on the grey. I fixed the fromNormalisedChannel function to clamp, - * but you might want to manually clamp for floating point values. - */ - QVector inbetween(3); - RGBToHSL(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); - inbetween = convertvectorqrealTofloat(getHSX(convertvectorfloatToqreal(inbetween))); - inbetween[m_d->channel1] = fmod(coordinates.x()*huedivider, 360.0); - if (m_d->dimension == Dimensions::twodimensional) { - inbetween[m_d->channel2] = coordinates.y()*huedivider2; - } - if (cursor==true){setHSX(convertvectorfloatToqreal(inbetween));Q_EMIT sigHSXchange();} - HSLToRGB(qMax(inbetween[0],(float)0.0), inbetween[1], inbetween[2],&channelValuesDisplay[0],&channelValuesDisplay[1], &channelValuesDisplay[2]); - } else if (m_d->model == ColorModel::HSI) { - /* - * HSI is a modified HSY function. - */ - QVector chan2 = convertvectorfloatToqreal(channelValuesDisplay); - QVector inbetween(3); - RGBToHSI(chan2[0],chan2[1], chan2[2], &inbetween[0], &inbetween[1], &inbetween[2]); - inbetween = getHSX(inbetween); - inbetween[m_d->channel1] = coordinates.x(); - if (m_d->dimension == Dimensions::twodimensional) { - inbetween[m_d->channel2] = coordinates.y(); - } - if (cursor==true){setHSX(inbetween);Q_EMIT sigHSXchange();} - HSIToRGB(inbetween[0], inbetween[1], inbetween[2],&chan2[0],&chan2[1], &chan2[2]); - channelValuesDisplay = convertvectorqrealTofloat(chan2); - } else /*if (m_d->model == ColorModel::HSY)*/ { - /* - * HSY is pretty slow to render due being a pretty over-the-top function. - * Might be worth investigating whether HCY can be used instead, but I have had - * some weird results with that. - */ - QVector luma= m_d->cs->lumaCoefficients(); - QVector chan2 = convertvectorfloatToqreal(channelValuesDisplay); - QVector inbetween(3); - RGBToHSY(chan2[0],chan2[1], chan2[2], &inbetween[0], &inbetween[1], &inbetween[2], - luma[0], luma[1], luma[2]); - inbetween = getHSX(inbetween); - inbetween[m_d->channel1] = coordinates.x(); - if (m_d->dimension == Dimensions::twodimensional) { - inbetween[m_d->channel2] = coordinates.y(); - } - if (cursor==true){setHSX(inbetween);Q_EMIT sigHSXchange();} - HSYToRGB(inbetween[0], inbetween[1], inbetween[2],&chan2[0],&chan2[1], &chan2[2], - luma[0], luma[1], luma[2]); - channelValuesDisplay = convertvectorqrealTofloat(chan2); - } - } - } else { - channelValuesDisplay[m_d->channel1] = coordinates.x(); - if (m_d->dimension == Dimensions::twodimensional) { - channelValuesDisplay[m_d->channel2] = coordinates.y(); - } - } - for (int i=0; ics->channels())]*(maxvalue[i]); - } - c.colorSpace()->fromNormalisedChannelsValue(c.data(), channelValues); - return c; -} - -QPointF KisVisualColorSelectorShape::convertKoColorToShapeCoordinate(KoColor c) -{ - if (c.colorSpace() != m_d->cs) { - c.convertTo(m_d->cs); - } - QVector channelValues (m_d->currentColor.colorSpace()->channelCount()); - channelValues.fill(1.0); - m_d->cs->normalisedChannelsValue(c.data(), channelValues); - QVector channelValuesDisplay = channelValues; - QVector maxvalue(c.colorSpace()->channelCount()); - maxvalue.fill(1.0); - if (m_d->displayRenderer - && (m_d->cs->colorDepthId() == Float16BitsColorDepthID - || m_d->cs->colorDepthId() == Float32BitsColorDepthID - || m_d->cs->colorDepthId() == Float64BitsColorDepthID) - && m_d->cs->colorModelId() != LABAColorModelID - && m_d->cs->colorModelId() != CMYKAColorModelID) { - for (int ch = 0; chcs->channels()[ch]; - maxvalue[ch] = m_d->displayRenderer->maxVisibleFloatValue(channel); - channelValues[ch] = channelValues[ch]/(maxvalue[ch]); - channelValuesDisplay[KoChannelInfo::displayPositionToChannelIndex(ch, m_d->cs->channels())] = channelValues[ch]; - } - } else { - for (int i =0; ics->channels())] = qBound((float)0.0,channelValues[i], (float)1.0); - } - } - QPointF coordinates(0.0,0.0); - qreal huedivider = 1.0; - qreal huedivider2 = 1.0; - if (m_d->channel1==0) { - huedivider = 360.0; - } - if (m_d->channel2==0) { - huedivider2 = 360.0; - } - if (m_d->model != ColorModel::Channel && c.colorSpace()->colorModelId().id() == "RGBA") { - if (c.colorSpace()->colorModelId().id() == "RGBA") { - if (m_d->model == ColorModel::HSV){ - QVector inbetween(3); - RGBToHSV(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); - inbetween = convertvectorqrealTofloat(getHSX(convertvectorfloatToqreal(inbetween))); - coordinates.setX(inbetween[m_d->channel1]/huedivider); - if (m_d->dimension == Dimensions::twodimensional) { - coordinates.setY(inbetween[m_d->channel2]/huedivider2); - } - } else if (m_d->model == ColorModel::HSL) { - QVector inbetween(3); - RGBToHSL(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); - inbetween = convertvectorqrealTofloat(getHSX(convertvectorfloatToqreal(inbetween))); - coordinates.setX(inbetween[m_d->channel1]/huedivider); - if (m_d->dimension == Dimensions::twodimensional) { - coordinates.setY(inbetween[m_d->channel2]/huedivider2); - } - } else if (m_d->model == ColorModel::HSI) { - QVector chan2 = convertvectorfloatToqreal(channelValuesDisplay); - QVector inbetween(3); - RGBToHSI(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); - inbetween = getHSX(inbetween); - coordinates.setX(inbetween[m_d->channel1]); - if (m_d->dimension == Dimensions::twodimensional) { - coordinates.setY(inbetween[m_d->channel2]); - } - } else if (m_d->model == ColorModel::HSY) { - QVector luma = m_d->cs->lumaCoefficients(); - QVector chan2 = convertvectorfloatToqreal(channelValuesDisplay); - QVector inbetween(3); - RGBToHSY(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2], luma[0], luma[1], luma[2]); - inbetween = getHSX(inbetween); - coordinates.setX(inbetween[m_d->channel1]); - if (m_d->dimension == Dimensions::twodimensional) { - coordinates.setY(inbetween[m_d->channel2]); - } - } - } - } else { - coordinates.setX(qBound((float)0.0, channelValuesDisplay[m_d->channel1], (float)1.0)); - if (m_d->dimension == Dimensions::twodimensional) { - coordinates.setY(qBound((float)0.0, channelValuesDisplay[m_d->channel2], (float)1.0)); - } - } - return coordinates; -} - -QVector KisVisualColorSelectorShape::convertvectorqrealTofloat(QVector real) -{ - QVector vloat(real.size()); - for (int i=0; i KisVisualColorSelectorShape::convertvectorfloatToqreal(QVector vloat) -{ - QVector real(vloat.size()); - for (int i=0; ibutton()==Qt::LeftButton) { - m_d->mousePressActive = true; - QPointF coordinates = convertWidgetCoordinateToShapeCoordinate(e->pos()); - KoColor col = convertShapeCoordinateToKoColor(coordinates, true); - setColor(col); - Q_EMIT sigNewColor(col); - m_d->updateTimer->start(); - } -} - -void KisVisualColorSelectorShape::mouseMoveEvent(QMouseEvent *e) -{ - if (m_d->mousePressActive==true && this->mask().contains(e->pos())) { - QPointF coordinates = convertWidgetCoordinateToShapeCoordinate(e->pos()); - quint8* oldData = m_d->currentColor.data(); - KoColor col = convertShapeCoordinateToKoColor(coordinates, true); - QRect offsetrect(this->geometry().topLeft()+QPoint(7.0,7.0), this->geometry().bottomRight()-QPoint(7.0,7.0)); - if (offsetrect.contains(e->pos()) || (m_d->cs->difference(col.data(), oldData)>5)) { - setColor(col); - if (!m_d->updateTimer->isActive()) { - Q_EMIT sigNewColor(col); - m_d->updateTimer->start(); - } - } - - } else { - e->ignore(); - } -} - -void KisVisualColorSelectorShape::mouseReleaseEvent(QMouseEvent *) -{ - m_d->mousePressActive = false; -} -void KisVisualColorSelectorShape::paintEvent(QPaintEvent*) -{ - QPainter painter(this); - - //check if old and new colors differ. - - if (m_d->imagesNeedUpdate) { - setMask(getMaskMap()); - } - drawCursor(); - painter.drawImage(0,0,m_d->fullSelector); -} - -KisVisualColorSelectorShape::Dimensions KisVisualColorSelectorShape::getDimensions() -{ - return m_d->dimension; -} - -KisVisualColorSelectorShape::ColorModel KisVisualColorSelectorShape::getColorModel() -{ - return m_d->model; -} - -void KisVisualColorSelectorShape::setFullImage(QImage full) -{ - m_d->fullSelector = full; -} -KoColor KisVisualColorSelectorShape::getCurrentColor() -{ - return m_d->currentColor; -} - -QVector KisVisualColorSelectorShape::getHSX(QVector hsx, bool wrangler) -{ - QVector ihsx = hsx; - if (!wrangler){ - //Ok, so this docker will not update luminosity if there's not at the least 3% more variation. - //This is necessary for 8bit. - if (m_d->cs->colorDepthId()==Integer8BitsColorDepthID){ - if (hsx[2]>m_d->tone-0.03 && hsx[2]tone+0.03) { - ihsx[2] = m_d->tone; - } - } else { - if (hsx[2]>m_d->tone-0.005 && hsx[2]tone+0.005) { - ihsx[2] = m_d->tone; - } - } - if (m_d->model==HSV){ - if (hsx[2]<=0.0) { - ihsx[1] = m_d->sat; - } - } else { - if ((hsx[2]<=0.0 || hsx[2]>=1.0)) { - ihsx[1] = m_d->sat; - } - } - if ((hsx[1]<=0.0 || hsx[0]<0.0)){ - ihsx[0]=m_d->hue; - } - } else { - ihsx[0]=m_d->hue; - ihsx[1]=m_d->sat; - ihsx[2]=m_d->tone; - } - return ihsx; -} - -void KisVisualColorSelectorShape::setHSX(QVector hsx, bool wrangler) -{ - if (wrangler){ - m_d->tone = hsx[2]; - m_d->sat = hsx[1]; - m_d->hue = hsx[0]; - } else { - if (m_d->channel1==2 || m_d->channel2==2){ - m_d->tone=hsx[2]; - } - if (m_d->model==HSV){ - if (hsx[2]>0.0) { - m_d->sat = hsx[1]; - } - } else { - if ((hsx[2]>0.0 || hsx[2]<1.0)) { - m_d->sat = hsx[1]; - } - } - if ((hsx[1]>0.0 && hsx[0]>=0.0)){ - m_d->hue = hsx[0]; - } - } -} - -QVector KisVisualColorSelectorShape::getChannels() -{ - QVector channels(2); - channels[0] = m_d->channel1; - channels[1] = m_d->channel2; - return channels; -} - -/*-----------Rectangle Shape------------*/ - -KisVisualRectangleSelectorShape::KisVisualRectangleSelectorShape(QWidget *parent, - Dimensions dimension, - ColorModel model, - const KoColorSpace *cs, - int channel1, int channel2, - const KoColorDisplayRendererInterface *displayRenderer, - int width, - singelDTypes d) - : KisVisualColorSelectorShape(parent, dimension, model, cs, channel1, channel2, displayRenderer) -{ - m_type = d; - m_barWidth = width; -} - -KisVisualRectangleSelectorShape::~KisVisualRectangleSelectorShape() -{ - -} - -void KisVisualRectangleSelectorShape::setBorderWidth(int width) -{ - m_barWidth = width; -} - -QRect KisVisualRectangleSelectorShape::getSpaceForSquare(QRect geom) -{ - QPointF tl; - QPointF br; - - if (m_type==KisVisualRectangleSelectorShape::vertical) { - br = geom.bottomRight(); - tl = QPoint(geom.topLeft().x()+m_barWidth, geom.topLeft().y()); - } else if (m_type==KisVisualRectangleSelectorShape::horizontal) { - br = geom.bottomRight(); - tl = QPoint(geom.topLeft().x(), geom.topLeft().y()+m_barWidth); - } else { - tl = QPointF (geom.topLeft().x()+m_barWidth, geom.topLeft().y()+m_barWidth); - br = QPointF (geom.bottomRight().x()-m_barWidth, geom.bottomRight().y()-m_barWidth); - - } - QRect a(tl.toPoint(), br.toPoint()); - QRect r(a.left(), a.top(), qMin(a.height(), a.width()), qMin(a.height(), a.width())); - return r; -} - -QRect KisVisualRectangleSelectorShape::getSpaceForCircle(QRect geom) -{ - return getSpaceForSquare(geom); -} - -QRect KisVisualRectangleSelectorShape::getSpaceForTriangle(QRect geom) -{ - return getSpaceForSquare(geom); -} - -QPointF KisVisualRectangleSelectorShape::convertShapeCoordinateToWidgetCoordinate(QPointF coordinate) -{ - qreal x = m_barWidth/2; - qreal y = m_barWidth/2; - qreal offset = 5.0; - KisVisualColorSelectorShape::Dimensions dimension = getDimensions(); - if (dimension == KisVisualColorSelectorShape::onedimensional) { - if ( m_type == KisVisualRectangleSelectorShape::vertical) { - y = qMin(coordinate.x()*(height()-offset*2)+offset, (qreal)height()); - } else if (m_type == KisVisualRectangleSelectorShape::horizontal) { - x = qMin(coordinate.x()*(width()-offset*2)+offset, (qreal)width()); - } else if (m_type == KisVisualRectangleSelectorShape::border) { - - QRectF innerRect(m_barWidth/2, m_barWidth/2, width()-m_barWidth, height()-m_barWidth); - QPointF left (innerRect.left(),innerRect.center().y()); - QList polygonLines; - polygonLines.append(QLineF(left, innerRect.topLeft())); - polygonLines.append(QLineF(innerRect.topLeft(), innerRect.topRight())); - polygonLines.append(QLineF(innerRect.topRight(), innerRect.bottomRight())); - polygonLines.append(QLineF(innerRect.bottomRight(), innerRect.bottomLeft())); - polygonLines.append(QLineF(innerRect.bottomLeft(), left)); - - qreal totalLength =0.0; - Q_FOREACH(QLineF line, polygonLines) { - totalLength += line.length(); - } - - qreal length = coordinate.x()*totalLength; - QPointF intersect(x,y); - Q_FOREACH(QLineF line, polygonLines) { - if (line.length()>length && length>0){ - intersect = line.pointAt(length/line.length()); - - } - length-=line.length(); - } - x = qRound(intersect.x()); - y = qRound(intersect.y()); - - } else /*if (m_type == KisVisualRectangleSelectorShape::borderMirrored)*/ { - - QRectF innerRect(m_barWidth/2, m_barWidth/2, width()-m_barWidth, height()-m_barWidth); - QPointF bottom (innerRect.center().x(), innerRect.bottom()); - QList polygonLines; - polygonLines.append(QLineF(bottom, innerRect.bottomLeft())); - polygonLines.append(QLineF(innerRect.bottomLeft(), innerRect.topLeft())); - polygonLines.append(QLineF(innerRect.topLeft(), innerRect.topRight())); - polygonLines.append(QLineF(innerRect.topRight(), innerRect.bottomRight())); - polygonLines.append(QLineF(innerRect.bottomRight(), bottom)); - - qreal totalLength =0.0; - Q_FOREACH(QLineF line, polygonLines) { - totalLength += line.length(); - } - - qreal length = coordinate.x()*(totalLength/2); - QPointF intersect(x,y); - if (coordinate.y()==1) { - for (int i = polygonLines.size()-1; i==0; i--) { - QLineF line = polygonLines.at(i); - if (line.length()>length && length>0){ - intersect = line.pointAt(length/line.length()); - - } - length-=line.length(); - } - } else { - Q_FOREACH(QLineF line, polygonLines) { - if (line.length()>length && length>0){ - intersect = line.pointAt(length/line.length()); - - } - length-=line.length(); - } - } - x = qRound(intersect.x()); - y = qRound(intersect.y()); - - } - } else { - x = qMin(coordinate.x()*(height()-offset*2)+offset, (qreal)height()); - y = qMin(coordinate.y()*(width()-offset*2)+offset, (qreal)width()); - } - return QPointF(x,y); -} - -QPointF KisVisualRectangleSelectorShape::convertWidgetCoordinateToShapeCoordinate(QPoint coordinate) -{ - //default implementation: - qreal x = 0.5; - qreal y = 0.5; - qreal offset = 5.0; - KisVisualColorSelectorShape::Dimensions dimension = getDimensions(); - if (getMaskMap().contains(coordinate)) { - if (dimension == KisVisualColorSelectorShape::onedimensional ) { - if (m_type == KisVisualRectangleSelectorShape::vertical) { - x = qMax(((qreal)coordinate.y()-offset)/((qreal)height()-offset*2), 0.0); - } else if (m_type == KisVisualRectangleSelectorShape::horizontal) { - x = qMax(((qreal)coordinate.x()-offset)/((qreal)width()-offset*2),0.0); - } else if (m_type == KisVisualRectangleSelectorShape::border) { - //border - - QRectF innerRect(m_barWidth, m_barWidth, width()-(m_barWidth*2), height()-(m_barWidth*2)); - QPointF left (innerRect.left(),innerRect.center().y()); - QList polygonLines; - polygonLines.append(QLineF(left, innerRect.topLeft())); - polygonLines.append(QLineF(innerRect.topLeft(), innerRect.topRight())); - polygonLines.append(QLineF(innerRect.topRight(), innerRect.bottomRight())); - polygonLines.append(QLineF(innerRect.bottomRight(), innerRect.bottomLeft())); - polygonLines.append(QLineF(innerRect.bottomLeft(), left)); - - QLineF radius(coordinate, this->geometry().center()); - QPointF intersect(0.5,0.5); - qreal length = 0.0; - qreal totalLength = 0.0; - bool foundIntersect = false; - Q_FOREACH(QLineF line, polygonLines) { - if (line.intersect(radius,&intersect)==QLineF::BoundedIntersection && foundIntersect==false) - { - foundIntersect = true; - length+=QLineF(line.p1(), intersect).length(); - - } - if (foundIntersect==false) { - length+=line.length(); - } - totalLength+=line.length(); - } - - x = length/totalLength; - - } else /*if (m_type == KisVisualRectangleSelectorShape::borderMirrored)*/ { - //border - - QRectF innerRect(m_barWidth, m_barWidth, width()-(m_barWidth*2), height()-(m_barWidth*2)); - QPointF bottom (innerRect.center().x(), innerRect.bottom()); - QList polygonLines; - polygonLines.append(QLineF(bottom, innerRect.bottomLeft())); - polygonLines.append(QLineF(innerRect.bottomLeft(), innerRect.topLeft())); - polygonLines.append(QLineF(innerRect.topLeft(), innerRect.topRight())); - polygonLines.append(QLineF(innerRect.topRight(), innerRect.bottomRight())); - polygonLines.append(QLineF(innerRect.bottomRight(), bottom)); - - QLineF radius(coordinate, this->geometry().center()); - QPointF intersect(0.5,0.5); - qreal length = 0.0; - qreal totalLength = 0.0; - bool foundIntersect = false; - Q_FOREACH(QLineF line, polygonLines) { - if (line.intersect(radius,&intersect)==QLineF::BoundedIntersection && foundIntersect==false) - { - foundIntersect = true; - length+=QLineF(line.p1(), intersect).length(); - - } - if (foundIntersect==false) { - length+=line.length(); - } - totalLength+=line.length(); - } - int halflength = totalLength/2; - - if (length>halflength) { - x = (halflength - (length-halflength))/halflength; - y = 1.0; - } else { - x = length/halflength; - y = 0.0; - } - } - } - else { - x = qMax(((qreal)coordinate.x()-offset)/((qreal)width()-offset*2), 0.0); - y = qMax(((qreal)coordinate.y()-offset)/((qreal)height()-offset*2), 0.0);; - } - } - return QPointF(x, y); -} - -QRegion KisVisualRectangleSelectorShape::getMaskMap() -{ - QRegion mask = QRegion(0,0,width(),height()); - if (m_type==KisVisualRectangleSelectorShape::border || m_type==KisVisualRectangleSelectorShape::borderMirrored) { - mask = mask.subtracted(QRegion(m_barWidth, m_barWidth, width()-(m_barWidth*2), height()-(m_barWidth*2))); - } - return mask; -} -void KisVisualRectangleSelectorShape::resizeEvent(QResizeEvent *) -{ - //qDebug()() << "KisVisualRectangleSelectorShape::resizeEvent"; - forceImageUpdate(); -} - -void KisVisualRectangleSelectorShape::drawCursor() -{ - //qDebug()() << "KisVisualRectangleSelectorShape::drawCursor: image needs update" << imagesNeedUpdate(); - QPointF cursorPoint = convertShapeCoordinateToWidgetCoordinate(getCursorPosition()); - QImage fullSelector = getImageMap(); - QColor col = getColorFromConverter(getCurrentColor()); - QPainter painter; - painter.begin(&fullSelector); - painter.setRenderHint(QPainter::Antialiasing); - //QPainterPath path; - QBrush fill; - fill.setStyle(Qt::SolidPattern); - - int cursorwidth = 5; - QRect rect(cursorPoint.toPoint().x()-cursorwidth,cursorPoint.toPoint().y()-cursorwidth, - cursorwidth*2,cursorwidth*2); - if (m_type==KisVisualRectangleSelectorShape::vertical){ - int x = ( cursorPoint.x()-(width()/2)+1 ); - int y = ( cursorPoint.y()-cursorwidth ); - rect.setCoords(x, y, x+width()-2, y+(cursorwidth*2)); - painter.save(); - painter.setCompositionMode(QPainter::CompositionMode_Clear); - QPen pen; - pen.setWidth(5); - painter.setPen(pen); - painter.drawLine(QLine(QPoint(0.0,0.0), QPoint(0.0,height()))); - painter.drawLine(QLine(QPoint(width(),0.0), QPoint(width(),height()))); - painter.restore(); - } else { - int x = cursorPoint.x()-cursorwidth; - int y = cursorPoint.y()-(height()/2)+1; - rect.setCoords(x, y, x+(cursorwidth*2), y+cursorwidth-2); - } - QRectF innerRect(m_barWidth, m_barWidth, width()-(m_barWidth*2), height()-(m_barWidth*2)); - if (getDimensions() == KisVisualColorSelectorShape::onedimensional && m_type!=KisVisualRectangleSelectorShape::border && m_type!=KisVisualRectangleSelectorShape::borderMirrored) { - painter.setPen(Qt::white); - fill.setColor(Qt::white); - painter.setBrush(fill); - painter.drawRect(rect); - //set filter conversion! - fill.setColor(col); - painter.setPen(Qt::black); - painter.setBrush(fill); - rect.setCoords(rect.topLeft().x()+1, rect.topLeft().y()+1, - rect.topLeft().x()+rect.width()-2, rect.topLeft().y()+rect.height()-2); - painter.drawRect(rect); - - }else if(m_type==KisVisualRectangleSelectorShape::borderMirrored){ - painter.setPen(Qt::white); - fill.setColor(Qt::white); - painter.setBrush(fill); - painter.drawEllipse(cursorPoint, cursorwidth, cursorwidth); - QPoint mirror(innerRect.center().x()+(innerRect.center().x()-cursorPoint.x()),cursorPoint.y()); - painter.drawEllipse(mirror, cursorwidth, cursorwidth); - fill.setColor(col); - painter.setPen(Qt::black); - painter.setBrush(fill); - painter.drawEllipse(cursorPoint, cursorwidth-1, cursorwidth-1); - painter.drawEllipse(mirror, cursorwidth-1, cursorwidth-1); - - } else { - painter.save(); - painter.setCompositionMode(QPainter::CompositionMode_Clear); - QPen pen; - pen.setWidth(5); - painter.setPen(pen); - painter.drawRect(QRect(0,0,width(),height())); - painter.restore(); - - painter.setPen(Qt::white); - fill.setColor(Qt::white); - painter.setBrush(fill); - painter.drawEllipse(cursorPoint, cursorwidth, cursorwidth); - fill.setColor(col); - painter.setPen(Qt::black); - painter.setBrush(fill); - painter.drawEllipse(cursorPoint, cursorwidth-1.0, cursorwidth-1.0); - } - painter.end(); - setFullImage(fullSelector); -} - -//----------------Elliptical--------------------------// -KisVisualEllipticalSelectorShape::KisVisualEllipticalSelectorShape(QWidget *parent, - Dimensions dimension, - ColorModel model, - const KoColorSpace *cs, - int channel1, int channel2, - const KoColorDisplayRendererInterface *displayRenderer, - int borwidth, - singelDTypes d) - : KisVisualColorSelectorShape(parent, dimension, model, cs, channel1, channel2, displayRenderer) -{ - m_type = d; - m_barWidth = borwidth; -} - -KisVisualEllipticalSelectorShape::~KisVisualEllipticalSelectorShape() -{ - -} - -QSize KisVisualEllipticalSelectorShape::sizeHint() const -{ - return QSize(180,180); -} -void KisVisualEllipticalSelectorShape::setBorderWidth(int width) -{ - m_barWidth = width; -} - -QRect KisVisualEllipticalSelectorShape::getSpaceForSquare(QRect geom) -{ - int sizeValue = qMin(width(),height()); - QRect b(geom.left(), geom.top(), sizeValue, sizeValue); - QLineF radius(b.center(), QPointF(b.left()+m_barWidth, b.center().y()) ); - radius.setAngle(135); - QPointF tl = radius.p2(); - radius.setAngle(315); - QPointF br = radius.p2(); - QRect r(tl.toPoint(), br.toPoint()); - return r; -} - -QRect KisVisualEllipticalSelectorShape::getSpaceForCircle(QRect geom) -{ - int sizeValue = qMin(width(),height()); - QRect b(geom.left(), geom.top(), sizeValue, sizeValue); - QPointF tl = QPointF (b.topLeft().x()+m_barWidth, b.topLeft().y()+m_barWidth); - QPointF br = QPointF (b.bottomRight().x()-m_barWidth, b.bottomRight().y()-m_barWidth); - QRect r(tl.toPoint(), br.toPoint()); - return r; -} - -QRect KisVisualEllipticalSelectorShape::getSpaceForTriangle(QRect geom) -{ - int sizeValue = qMin(width(),height()); - QRect b(geom.left(), geom.top(), sizeValue, sizeValue); - QLineF radius(b.center(), QPointF(b.left()+m_barWidth, b.center().y()) ); - radius.setAngle(90);//point at yellowgreen :) - QPointF t = radius.p2(); - radius.setAngle(330);//point to purple :) - QPointF br = radius.p2(); - radius.setAngle(210);//point to cerulean :) - QPointF bl = radius.p2(); - QPointF tl = QPoint(bl.x(),t.y()); - QRect r(tl.toPoint(), br.toPoint()); - return r; -} - -QPointF KisVisualEllipticalSelectorShape::convertShapeCoordinateToWidgetCoordinate(QPointF coordinate) -{ - qreal x; - qreal y; - qreal offset=7.0; - qreal a = (qreal)width()*0.5; - QPointF center(a, a); - QLineF line(center, QPoint((m_barWidth*0.5),a)); - qreal angle = coordinate.x()*360.0; - angle = fmod(angle+180.0,360.0); - angle = 180.0-angle; - angle = angle+180.0; - if (m_type==KisVisualEllipticalSelectorShape::borderMirrored) { - angle = (coordinate.x()/2)*360.0; - angle = fmod((angle+90.0), 360.0); - } - line.setAngle(angle); - if (getDimensions()!=KisVisualColorSelectorShape::onedimensional) { - line.setLength(qMin(coordinate.y()*(a-offset), a-offset)); - } - x = qRound(line.p2().x()); - y = qRound(line.p2().y()); - return QPointF(x,y); -} - -QPointF KisVisualEllipticalSelectorShape::convertWidgetCoordinateToShapeCoordinate(QPoint coordinate) -{ - //default implementation: - qreal x = 0.5; - qreal y = 1.0; - qreal offset = 7.0; - QRect total(0, 0, width(), height()); - QLineF line(total.center(), coordinate); - qreal a = (total.width()/2); - qreal angle; - - if (m_type!=KisVisualEllipticalSelectorShape::borderMirrored){ - angle = fmod((line.angle()+180.0), 360.0); - angle = 180.0-angle; - angle = angle+180.0; - x = angle/360.0; - if (getDimensions()==KisVisualColorSelectorShape::twodimensional) { - y = qBound(0.0,line.length()/(a-offset), 1.0); - } - - } else { - angle = fmod((line.angle()+270.0), 360.0); - if (angle>180.0) { - angle = 180.0-angle; - angle = angle+180; - } - x = (angle/360.0)*2; - if (getDimensions()==KisVisualColorSelectorShape::twodimensional) { - y = qBound(0.0,(line.length()+offset)/a, 1.0); - } - } - - return QPointF(x, y); -} - -QRegion KisVisualEllipticalSelectorShape::getMaskMap() -{ - QRegion mask = QRegion(0,0,width(),height(), QRegion::Ellipse); - if (getDimensions()==KisVisualColorSelectorShape::onedimensional) { - mask = mask.subtracted(QRegion(m_barWidth, m_barWidth, width()-(m_barWidth*2), height()-(m_barWidth*2), QRegion::Ellipse)); - } - return mask; -} - -void KisVisualEllipticalSelectorShape::resizeEvent(QResizeEvent *) -{ - //qDebug()() << "KisVisualEllipticalSelectorShape::resizeEvent"; - forceImageUpdate(); -} - -void KisVisualEllipticalSelectorShape::drawCursor() -{ - //qDebug()() << "KisVisualEllipticalSelectorShape::drawCursor: image needs update" << imagesNeedUpdate(); - QPointF cursorPoint = convertShapeCoordinateToWidgetCoordinate(getCursorPosition()); - QImage fullSelector = getImageMap(); - QColor col = getColorFromConverter(getCurrentColor()); - QPainter painter; - painter.begin(&fullSelector); - painter.setRenderHint(QPainter::Antialiasing); - QRect innerRect(m_barWidth, m_barWidth, width()-(m_barWidth*2), height()-(m_barWidth*2)); - - painter.save(); - painter.setCompositionMode(QPainter::CompositionMode_Clear); - QPen pen; - pen.setWidth(5); - painter.setPen(pen); - painter.drawEllipse(QRect(0,0,width(),height())); - if (getDimensions()==KisVisualColorSelectorShape::onedimensional) { - painter.setBrush(Qt::SolidPattern); - painter.drawEllipse(innerRect); - } - painter.restore(); - - QBrush fill; - fill.setStyle(Qt::SolidPattern); - - int cursorwidth = 5; - if(m_type==KisVisualEllipticalSelectorShape::borderMirrored){ - painter.setPen(Qt::white); - fill.setColor(Qt::white); - painter.setBrush(fill); - painter.drawEllipse(cursorPoint, cursorwidth, cursorwidth); - QPoint mirror(innerRect.center().x()+(innerRect.center().x()-cursorPoint.x()),cursorPoint.y()); - painter.drawEllipse(mirror, cursorwidth, cursorwidth); - fill.setColor(col); - painter.setPen(Qt::black); - painter.setBrush(fill); - painter.drawEllipse(cursorPoint, cursorwidth-1, cursorwidth-1); - painter.drawEllipse(mirror, cursorwidth-1, cursorwidth-1); - - } else { - painter.setPen(Qt::white); - fill.setColor(Qt::white); - painter.setBrush(fill); - painter.drawEllipse(cursorPoint, cursorwidth, cursorwidth); - fill.setColor(col); - painter.setPen(Qt::black); - painter.setBrush(fill); - painter.drawEllipse(cursorPoint, cursorwidth-1.0, cursorwidth-1.0); - } - painter.end(); - setFullImage(fullSelector); -} - -//----------------Triangle--------------------------// -KisVisualTriangleSelectorShape::KisVisualTriangleSelectorShape(QWidget *parent, - Dimensions dimension, - ColorModel model, - const KoColorSpace *cs, - int channel1, int channel2, - const KoColorDisplayRendererInterface *displayRenderer, - int borwidth) - : KisVisualColorSelectorShape(parent, dimension, model, cs, channel1, channel2, displayRenderer) -{ - m_barWidth = borwidth; - QRect total(0,0,width()*0.9,width()*0.9); - setTriangle(); -} - -KisVisualTriangleSelectorShape::~KisVisualTriangleSelectorShape() -{ - -} - -void KisVisualTriangleSelectorShape::setBorderWidth(int width) -{ - m_barWidth = width; -} - -QRect KisVisualTriangleSelectorShape::getSpaceForSquare(QRect geom) -{ - return geom; -} - -QRect KisVisualTriangleSelectorShape::getSpaceForCircle(QRect geom) -{ - return geom; -} - -QRect KisVisualTriangleSelectorShape::getSpaceForTriangle(QRect geom) -{ - return geom; -} -void KisVisualTriangleSelectorShape::setTriangle() -{ - QPoint apex = QPoint (width()*0.5,0); - QPolygon triangle; - triangle<< QPoint(0,height()) << apex << QPoint(width(),height()) << QPoint(0,height()); - m_triangle = triangle; - QLineF a(triangle.at(0),triangle.at(1)); - QLineF b(triangle.at(0),triangle.at(2)); - QLineF ap(triangle.at(2), a.pointAt(0.5)); - QLineF bp(triangle.at(1), b.pointAt(0.5)); - QPointF intersect; - ap.intersect(bp,&intersect); - m_center = intersect; - QLineF r(triangle.at(0), intersect); - m_radius = r.length(); -} - -QPointF KisVisualTriangleSelectorShape::convertShapeCoordinateToWidgetCoordinate(QPointF coordinate) -{ - qreal offset=7.0;//the offset is so we get a nice little border that allows selecting extreme colors better. - qreal y = qMin(coordinate.y()*(height()-offset*2-5.0)+offset+5.0, (qreal)height()-offset); - - qreal triWidth = width(); - qreal horizontalLineLength = y*(2./sqrt(3.)); - qreal horizontalLineStart = triWidth/2.-horizontalLineLength/2.; - qreal relativeX = coordinate.x()*(horizontalLineLength-offset*2); - qreal x = qMin(relativeX + horizontalLineStart + offset, (qreal)width()-offset*2); - if (y * * 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 KIS_COLOR_SELECTOR_H #define KIS_COLOR_SELECTOR_H #include "kis_color_selector_base.h" -#include +#include + class KisColorSelectorRing; class KisColorSelectorComponent; class KisColorSelectorSimple; class KisColorSelectorWheel; class QPushButton; class KisSignalCompressor; class KisColorSelector : public KisColorSelectorBase { Q_OBJECT public: KisColorSelector(KisColorSelectorConfiguration conf, QWidget* parent = 0); KisColorSelector(QWidget* parent=0); KisColorSelectorBase* createPopup() const; void setConfiguration(KisColorSelectorConfiguration conf); KisColorSelectorConfiguration configuration() const; void setColor(const KoColor &color); public Q_SLOTS: void reset(); void updateSettings(); Q_SIGNALS: void settingsButtonClicked(); protected: void paintEvent(QPaintEvent*); void resizeEvent(QResizeEvent*); void mousePressEvent(QMouseEvent*); void mouseMoveEvent(QMouseEvent*); void mouseReleaseEvent(QMouseEvent*); bool displaySettingsButton(); private: void mouseEvent(QMouseEvent* e); void init(); KisColorSelectorRing* m_ring; KisColorSelectorComponent* m_triangle; KisColorSelectorSimple* m_slider; KisColorSelectorSimple* m_square; KisColorSelectorWheel* m_wheel; QPushButton* m_button; KisColorSelectorComponent* m_mainComponent; KisColorSelectorComponent* m_subComponent; KisColorSelectorComponent* m_grabbingComponent; KisSignalCompressor *m_signalCompressor; KisColorSelectorConfiguration m_configuration; KoColor m_lastRealColor; KoColor m_currentRealColor; bool m_blipDisplay; Acs::ColorRole m_lastColorRole; public: void setDisplayBlip(bool disp) {m_blipDisplay = disp;} bool displayBlip() const {return m_blipDisplay;} }; #endif // KIS_COLSELNG_COLOR_SELECTOR_H diff --git a/plugins/filters/colors/wdgcolortoalphabase.ui b/plugins/filters/colors/wdgcolortoalphabase.ui index 961c7726db..070138601a 100644 --- a/plugins/filters/colors/wdgcolortoalphabase.ui +++ b/plugins/filters/colors/wdgcolortoalphabase.ui @@ -1,217 +1,217 @@ WdgColorToAlphaBase 0 0 335 362 0 0 6 0 0 0 0 Color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false Qt::Horizontal 20 0 0 0 180 180 0 0 0 0 0 Qt::Horizontal 40 20 15 0 0 0 Threshold: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter false 0 0 0 0 Color Picker: 0 0 16777215 16777215 false false false KisVisualColorSelector QWidget -
kis_visual_color_selector.h
+
KisVisualColorSelector.h
1
KisColorButton QPushButton
kis_color_button.h
KisDoubleSliderSpinBox QWidget
kis_slider_spin_box.h
1
kcolorbutton.h