diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt index 21dfc97bf0..958d7e20b5 100644 --- a/libs/ui/CMakeLists.txt +++ b/libs/ui/CMakeLists.txt @@ -1,532 +1,535 @@ # Disable -Wswitch because of the extra definitions we here: # kis_input_manager.cpp: In member function ‘virtual bool KisInputManager::eventFilter(QObject*, QEvent*)’: # warning: case value ‘1001’ not in enumerated type ‘QEvent::Type’ [-Wswitch] # warning: case value ‘1002’ not in enumerated type ‘QEvent::Type’ [-Wswitch] if (CMAKE_COMPILER_IS_GNUCXX) add_definitions(${KDE4_ENABLE_EXCEPTIONS} -Wno-switch) endif () 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_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_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 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_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_async_action_feedback.cpp kisexiv2/kis_exif_io.cpp kisexiv2/kis_exiv2.cpp kisexiv2/kis_iptc_io.cpp kisexiv2/kis_xmp_io.cpp kra/kis_kra_utils.cpp kra/kis_kra_load_visitor.cpp kra/kis_kra_loader.cpp kra/kis_kra_save_visitor.cpp kra/kis_kra_saver.cpp kra/kis_kra_savexml_visitor.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 kis_fps_decoration.cpp ora/kis_open_raster_stack_load_visitor.cpp ora/kis_open_raster_stack_save_visitor.cpp ora/ora_load_context.cc ora/ora_save_context.cc 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/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_spinbox_color_selector.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 KisFilterChain.cpp KisFilterChainLink.cpp KisFilterChainLinkList.cpp KisImportExportFilter.cpp KisFilterEdge.cpp KisFilterEntry.cpp KisFilterGraph.cpp KisImportExportManager.cpp KisFilterVertex.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 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() if(WIN32) #ki18n_wrap_ui( # input/wintab/kis_screen_size_choice_dialog.ui #) 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/wdgcustompalette.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/KisDetailsPaneBase.ui forms/KisOpenPaneBase.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 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_link_libraries(kritaui LINK_INTERFACE_LIBRARIES kritaimage kritalibbrush kritapigment KF5::Completion KF5::I18n ${GL_INTERFACE_LIBRARIES}) 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_internal_color_selector.cpp b/libs/ui/dialogs/kis_internal_color_selector.cpp new file mode 100644 index 0000000000..1148a465ed --- /dev/null +++ b/libs/ui/dialogs/kis_internal_color_selector.cpp @@ -0,0 +1,140 @@ +/* + * 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 "KoColorSpaceRegistry.h" + +#include "kis_signal_compressor.h" +#include "kis_canvas_resource_provider.h" +#include "KoColorDisplayRendererInterface.h" +#include "kis_display_color_converter.h" +#include "kis_spinbox_color_selector.h" + +#include "kis_internal_color_selector.h" + +struct KisInternalColorSelector::Private +{ + bool allowUpdates = true; + KoColor currentColor; + const KoColorSpace *currentColorSpace; + + KisCanvas2 *canvas; + + KisSpinboxColorSelector *spinBoxSelector; + KisSignalCompressor *compressColorChanges; +}; + +KisInternalColorSelector::KisInternalColorSelector(QWidget *parent, const QString &caption) + : QDialog(parent) + ,m_d(new Private) +{ + setModal(false); + setWindowTitle(caption); + + m_d->currentColor = KoColor(); + m_d->currentColorSpace = m_d->currentColor.colorSpace(); + m_d->spinBoxSelector = new KisSpinboxColorSelector; + m_d->spinBoxSelector->slotSetColorSpace(m_d->currentColorSpace); + ui->base->addWidget(m_d->spinBoxSelector); + connect(m_d->spinBoxSelector, SIGNAL(sigNewColor(KoColor)), this, SLOT(slotColorUpdated(KoColor))); + + connect(this, SIGNAL(signalForegroundColorChosen(KoColor)), this, SLOT(slotLockSelector())); + m_d->compressColorChanges = new KisSignalCompressor(500 /* ms */, KisSignalCompressor::POSTPONE, this); + connect(m_d->compressColorChanges, SIGNAL(timeout()), this, SLOT(sentUpdateWithNewColor())); +} + +KisInternalColorSelector::~KisInternalColorSelector() +{ + delete ui; + //TODO: Does the scoped pointer also need to be deleted??? +} + +void KisInternalColorSelector::setCanvas(KisCanvas2 *canvas) +{ + if (m_d->canvas) { + m_d->canvas->disconnectCanvasObserver(this); + } + m_d->canvas = canvas; + + if (m_d->canvas) { + //basics// + connect(m_d->canvas->imageView()->resourceProvider(), SIGNAL(sigFGColorChanged(KoColor)), this, SLOT(slotColorUpdated(KoColor))); + connect(this, SIGNAL(signalForegroundColorChosen(KoColor)), m_d->canvas->imageView()->resourceProvider(), SLOT(slotSetFGColor(KoColor))); + //display color converter// + connect(m_d->canvas->displayColorConverter(), SIGNAL(displayConfigurationChanged()), this, SLOT(slotConfigurationChanged())); + } +} + +void KisInternalColorSelector::unsetCanvas() +{ + setEnabled(false); + m_d->canvas = 0; +} + +void KisInternalColorSelector::slotColorUpdated(KoColor newColor) +{ + //if the update did not come from this selector... + if (m_d->allowUpdates) { + m_d->currentColor = newColor; + updateAllElements(); + } else { + emit(signalForegroundColorChosen(m_d->currentColor)); + m_d->compressColorChanges->start(); + } +} + +void KisInternalColorSelector::slotColorSpaceChanged(const KoColorSpace *cs) +{ + if (cs == m_d->currentColorSpace) { + return; + } + + m_d->currentColorSpace = KoColorSpaceRegistry::instance()->colorSpace(cs->colorModelId().id(), cs->colorDepthId().id(), cs->profile()); + //Empty the layout. + m_d->spinBoxSelector->slotSetColorSpace(m_d->currentColorSpace); + +} + +void KisInternalColorSelector::slotConfigurationChanged() +{ + if (!m_d->canvas) { + return; + } + //m_d->canvas->displayColorConverter()-> + //slotColorSpaceChanged(m_d->canvas->image()->colorSpace()); +} + +void KisInternalColorSelector::slotLockSelector() +{ + m_d->allowUpdates = false; +} + +void KisInternalColorSelector::updateAllElements() +{ + //update everything!!! + m_d->spinBoxSelector->slotSetColor(m_d->currentColor); +} + +void KisInternalColorSelector::endUpdateWithNewColor() +{ + m_d->allowUpdates = true; +} diff --git a/libs/ui/dialogs/kis_internal_color_selector.h b/libs/ui/dialogs/kis_internal_color_selector.h new file mode 100644 index 0000000000..8bf3428a04 --- /dev/null +++ b/libs/ui/dialogs/kis_internal_color_selector.h @@ -0,0 +1,108 @@ +/* + * 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 KISINTERNALCOLORSELECTOR_H +#define KISINTERNALCOLORSELECTOR_H + +#include "kritaui_export.h" +#include "kis_mainwindow_observer.h" +#include "kis_canvas2.h" +#include "KoColor.h" +#include "KoColorSpace.h" +#include + +#include "ui_wdgdlginternalcolorselector.h" + +/** + * @brief The KisInternalColorSelector class + * + * A non-modal color selector dialog that is not a plugin and can thus be used for filters. + */ +class KRITAUI_EXPORT KisInternalColorSelector : public QDialog, public KisMainwindowObserver +{ + Q_OBJECT +public: + KisInternalColorSelector(QWidget* parent, const QString &caption); + ~KisInternalColorSelector(); + /** + * @brief setCanvas + * reimplemented from the canvasobserver class. + * @param canvas + */ + virtual void setCanvas(KisCanvas2 *canvas); + /** + * @brief unsetCanvas + * reimplemented from the canvas observer class. + */ + virtual void unsetCanvas(); + +Q_SIGNALS: + /** + * @brief signalForegroundColorChosen + * The most important signal. This will sent out when a color has been picked from the selector. + * There will be a small delay to make sure that the selector causes too many updates. + * + * Do not connect this to slotColorUpdated. + * @param color The new color chosen + */ + + void signalForegroundColorChosen(KoColor color); +public Q_SLOTS: + /** + * @brief slotColorUpdated + * Very important slot. Is connected to krita's resources to make sure it has + * the currently active color. It's very important that this function is able to understand + * when the signal came from itself. + * @param newColor This is the new color. + */ + void slotColorUpdated(KoColor newColor); +private Q_SLOTS: + + /** + * @brief slotLockSelector + * This slot will prevent the color from being updated. + */ + void slotLockSelector(); + + /** + * @brief slotColorSpaceChanged + * Color space has changed. + */ + void slotColorSpaceChanged(const KoColorSpace *cs); + /** + * @brief slotConfigurationChanged + * Wrapper slot for changes to the colorspace. + */ + void slotConfigurationChanged(); + + void endUpdateWithNewColor(); + +private: + Ui::WdgDlgInternalColorSelector *ui; //the UI + struct Private; //The private struct + const QScopedPointer m_d; //the private pointer + + /** + * @brief updateAllElements + * Updates each widget with the new element, and if it's responsible for the update sents + * a signal out that there's a new color. + */ + void updateAllElements(); +}; + +#endif // KISINTERNALCOLORSELECTOR_H diff --git a/libs/ui/forms/wdgdlginternalcolorselector.ui b/libs/ui/forms/wdgdlginternalcolorselector.ui new file mode 100644 index 0000000000..2df3e7e167 --- /dev/null +++ b/libs/ui/forms/wdgdlginternalcolorselector.ui @@ -0,0 +1,67 @@ + + + WdgDlgInternalColorSelector + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + WdgDlgInternalColorSelector + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + WdgDlgInternalColorSelector + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/libs/ui/opengl/kis_opengl_image_textures.cpp b/libs/ui/opengl/kis_opengl_image_textures.cpp index 2c8e6df73c..3e30856fe3 100644 --- a/libs/ui/opengl/kis_opengl_image_textures.cpp +++ b/libs/ui/opengl/kis_opengl_image_textures.cpp @@ -1,643 +1,642 @@ /* * Copyright (c) 2005-2007 Adrian Page * * 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 "opengl/kis_opengl_image_textures.h" #include #include #include #include #include #include #include #include #include "kis_image.h" #include "kis_config.h" #include "KisPart.h" #ifdef HAVE_OPENEXR #include #endif #ifndef GL_CLAMP_TO_EDGE #define GL_CLAMP_TO_EDGE 0x812F #endif #ifndef GL_BGRA #define GL_BGRA 0x80E1 #endif KisOpenGLImageTextures::ImageTexturesMap KisOpenGLImageTextures::imageTexturesMap; KisOpenGLImageTextures::KisOpenGLImageTextures() : m_image(0) , m_monitorProfile(0) , m_proofingConfig(0) , m_proofingTransform(0) , m_createNewProofingTransform(true) , m_tilesDestinationColorSpace(0) , m_internalColorManagementActive(true) , m_checkerTexture(0) , m_glFuncs(0) , m_allChannelsSelected(true) , m_useOcio(false) , m_initialized(false) { KisConfig cfg; m_renderingIntent = (KoColorConversionTransformation::Intent)cfg.monitorRenderIntent(); m_conversionFlags = KoColorConversionTransformation::HighQuality; if (cfg.useBlackPointCompensation()) m_conversionFlags |= KoColorConversionTransformation::BlackpointCompensation; if (!cfg.allowLCMSOptimization()) m_conversionFlags |= KoColorConversionTransformation::NoOptimization; m_useOcio = cfg.useOcio(); } KisOpenGLImageTextures::KisOpenGLImageTextures(KisImageWSP image, const KoColorProfile *monitorProfile, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) : m_image(image) , m_monitorProfile(monitorProfile) , m_renderingIntent(renderingIntent) , m_conversionFlags(conversionFlags) , m_proofingConfig(0) , m_proofingTransform(0) , m_createNewProofingTransform(true) , m_tilesDestinationColorSpace(0) - , m_createNewProofingTransform(true) , m_internalColorManagementActive(true) , m_checkerTexture(0) , m_glFuncs(0) , m_allChannelsSelected(true) , m_useOcio(false) , m_initialized(false) { Q_ASSERT(renderingIntent < 4); } void KisOpenGLImageTextures::initGL(QOpenGLFunctions *f) { if (f) { m_glFuncs = f; } else { errUI << "Tried to create OpenGLImageTextures with uninitialized QOpenGLFunctions"; } getTextureSize(&m_texturesInfo); // we use local static object for creating pools shared among // different images static KisTextureTileInfoPoolRegistry s_poolRegistry; m_infoChunksPool = s_poolRegistry.getPool(m_texturesInfo.width, m_texturesInfo.height); m_glFuncs->glGenTextures(1, &m_checkerTexture); createImageTextureTiles(); KisOpenGLUpdateInfoSP info = updateCache(m_image->bounds()); recalculateCache(info); } KisOpenGLImageTextures::~KisOpenGLImageTextures() { ImageTexturesMap::iterator it = imageTexturesMap.find(m_image); if (it != imageTexturesMap.end()) { KisOpenGLImageTextures *textures = it.value(); if (textures == this) { dbgUI << "Removing shared image context from map"; imageTexturesMap.erase(it); } } destroyImageTextureTiles(); m_glFuncs->glDeleteTextures(1, &m_checkerTexture); } KisImageSP KisOpenGLImageTextures::image() const { return m_image; } bool KisOpenGLImageTextures::imageCanShareTextures() { KisConfig cfg; if (cfg.useOcio()) return false; if (KisPart::instance()->mainwindowCount() == 1) return true; if (qApp->desktop()->screenCount() == 1) return true; for (int i = 1; i < qApp->desktop()->screenCount(); i++) { if (cfg.displayProfile(i) != cfg.displayProfile(i - 1)) { return false; } } return true; } KisOpenGLImageTexturesSP KisOpenGLImageTextures::getImageTextures(KisImageWSP image, const KoColorProfile *monitorProfile, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) { // Disabled until we figure out why we're deleting the shared textures on closing the second view on a single image if (false && imageCanShareTextures()) { ImageTexturesMap::iterator it = imageTexturesMap.find(image); if (it != imageTexturesMap.end()) { KisOpenGLImageTexturesSP textures = it.value(); textures->setMonitorProfile(monitorProfile, renderingIntent, conversionFlags); return textures; } else { KisOpenGLImageTextures *imageTextures = new KisOpenGLImageTextures(image, monitorProfile, renderingIntent, conversionFlags); imageTexturesMap[image] = imageTextures; dbgUI << "Added shareable textures to map"; return imageTextures; } } else { return new KisOpenGLImageTextures(image, monitorProfile, renderingIntent, conversionFlags); } } QRect KisOpenGLImageTextures::calculateTileRect(int col, int row) const { return m_image->bounds() & QRect(col * m_texturesInfo.effectiveWidth, row * m_texturesInfo.effectiveHeight, m_texturesInfo.effectiveWidth, m_texturesInfo.effectiveHeight); } void KisOpenGLImageTextures::createImageTextureTiles() { destroyImageTextureTiles(); updateTextureFormat(); if (!m_tilesDestinationColorSpace) { qDebug() << "No destination colorspace!!!!"; return; } m_storedImageBounds = m_image->bounds(); const int lastCol = xToCol(m_image->width()); const int lastRow = yToRow(m_image->height()); m_numCols = lastCol + 1; // Default color is transparent black const int pixelSize = m_tilesDestinationColorSpace->pixelSize(); QByteArray emptyTileData((m_texturesInfo.width) * (m_texturesInfo.height) * pixelSize, 0); KisConfig config; KisOpenGL::FilterMode mode = (KisOpenGL::FilterMode)config.openGLFilteringMode(); QOpenGLContext *ctx = QOpenGLContext::currentContext(); if (ctx) { QOpenGLFunctions *f = ctx->functions(); m_initialized = true; dbgUI << "OpenGL: creating texture tiles of size" << m_texturesInfo.height << "x" << m_texturesInfo.width; m_textureTiles.reserve((lastRow+1)*m_numCols); for (int row = 0; row <= lastRow; row++) { for (int col = 0; col <= lastCol; col++) { QRect tileRect = calculateTileRect(col, row); KisTextureTile *tile = new KisTextureTile(tileRect, &m_texturesInfo, emptyTileData, mode, config.useOpenGLTextureBuffer(), config.numMipmapLevels(), f); m_textureTiles.append(tile); } } } else { dbgUI << "Tried to init texture tiles without a current OpenGL Context."; } } void KisOpenGLImageTextures::destroyImageTextureTiles() { if (m_textureTiles.isEmpty()) return; Q_FOREACH (KisTextureTile *tile, m_textureTiles) { delete tile; } m_textureTiles.clear(); m_storedImageBounds = QRect(); } KisOpenGLUpdateInfoSP KisOpenGLImageTextures::updateCache(const QRect& rect) { return updateCacheImpl(rect, true); } KisOpenGLUpdateInfoSP KisOpenGLImageTextures::updateCacheNoConversion(const QRect& rect) { return updateCacheImpl(rect, false); } KisOpenGLUpdateInfoSP KisOpenGLImageTextures::updateCacheImpl(const QRect& rect, bool convertColorSpace) { const KoColorSpace *dstCS = m_tilesDestinationColorSpace; ConversionOptions options; if (convertColorSpace) { options = ConversionOptions(dstCS, m_renderingIntent, m_conversionFlags); } KisOpenGLUpdateInfoSP info = new KisOpenGLUpdateInfo(options); QRect updateRect = rect & m_image->bounds(); if (updateRect.isEmpty() || !(m_initialized)) return info; /** * Why the rect is artificial? That's easy! * It does not represent any real piece of the image. It is * intentionally stretched to get through the overlappping * stripes of neutrality and poke neighbouring tiles. * Thanks to the rect we get the coordinates of all the tiles * involved into update process */ QRect artificialRect = stretchRect(updateRect, m_texturesInfo.border); artificialRect &= m_image->bounds(); int firstColumn = xToCol(artificialRect.left()); int lastColumn = xToCol(artificialRect.right()); int firstRow = yToRow(artificialRect.top()); int lastRow = yToRow(artificialRect.bottom()); QBitArray channelFlags; // empty by default if (m_channelFlags.size() != m_image->projection()->colorSpace()->channels().size()) { setChannelFlags(QBitArray()); } if (!m_useOcio) { // Ocio does its own channel flipping if (!m_allChannelsSelected) { // and we do it only if necessary channelFlags = m_channelFlags; } } qint32 numItems = (lastColumn - firstColumn + 1) * (lastRow - firstRow + 1); info->tileList.reserve(numItems); const QRect bounds = m_image->bounds(); const int levelOfDetail = m_image->currentLevelOfDetail(); QRect alignedUpdateRect = updateRect; QRect alignedBounds = bounds; if (levelOfDetail) { alignedUpdateRect = KisLodTransform::alignedRect(alignedUpdateRect, levelOfDetail); alignedBounds = KisLodTransform::alignedRect(alignedBounds, levelOfDetail); } for (int col = firstColumn; col <= lastColumn; col++) { for (int row = firstRow; row <= lastRow; row++) { const QRect tileRect = calculateTileRect(col, row); const QRect tileTextureRect = stretchRect(tileRect, m_texturesInfo.border); QRect alignedTileTextureRect = levelOfDetail ? KisLodTransform::alignedRect(tileTextureRect, levelOfDetail) : tileTextureRect; KisTextureTileUpdateInfoSP tileInfo( new KisTextureTileUpdateInfo(col, row, alignedTileTextureRect, alignedUpdateRect, alignedBounds, levelOfDetail, m_infoChunksPool)); // Don't update empty tiles if (tileInfo->valid()) { tileInfo->retrieveData(m_image, channelFlags, m_onlyOneChannelSelected, m_selectedChannelIndex); //create transform if (m_createNewProofingTransform) { const KoColorSpace *proofingSpace = KoColorSpaceRegistry::instance()->colorSpace(m_proofingConfig->proofingModel,m_proofingConfig->proofingDepth,m_proofingConfig->proofingProfile); m_proofingTransform = tileInfo->generateProofingTransform(dstCS, proofingSpace, m_renderingIntent, m_proofingConfig->intent, m_proofingConfig->conversionFlags, m_proofingConfig->warningColor, m_proofingConfig->adaptationState); m_createNewProofingTransform = false; } if (convertColorSpace) { if (m_proofingConfig && m_proofingTransform && m_proofingConfig->conversionFlags.testFlag(KoColorConversionTransformation::SoftProofing)) { tileInfo->proofTo(dstCS, m_proofingConfig->conversionFlags, m_proofingTransform); } else { tileInfo->convertTo(dstCS, m_renderingIntent, m_conversionFlags); } } info->tileList.append(tileInfo); } else { dbgUI << "Trying to create an empty tileinfo record" << col << row << tileTextureRect << updateRect << m_image->bounds(); } } } info->assignDirtyImageRect(rect); info->assignLevelOfDetail(levelOfDetail); return info; } void KisOpenGLImageTextures::recalculateCache(KisUpdateInfoSP info) { if (!m_initialized) { dbgUI << "OpenGL: Tried to edit image texture cache before it was initialized."; return; } KisOpenGLUpdateInfoSP glInfo = dynamic_cast(info.data()); if(!glInfo) return; KisTextureTileUpdateInfoSP tileInfo; Q_FOREACH (tileInfo, glInfo->tileList) { KisTextureTile *tile = getTextureTileCR(tileInfo->tileCol(), tileInfo->tileRow()); KIS_ASSERT_RECOVER_RETURN(tile); tile->update(*tileInfo); } } void KisOpenGLImageTextures::generateCheckerTexture(const QImage &checkImage) { QOpenGLContext *ctx = QOpenGLContext::currentContext(); if (ctx) { QOpenGLFunctions *f = ctx->functions(); dbgUI << "Attaching checker texture" << checkerTexture(); f->glBindTexture(GL_TEXTURE_2D, checkerTexture()); f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); f->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); QImage img = checkImage; if (checkImage.width() != BACKGROUND_TEXTURE_SIZE || checkImage.height() != BACKGROUND_TEXTURE_SIZE) { img = checkImage.scaled(BACKGROUND_TEXTURE_SIZE, BACKGROUND_TEXTURE_SIZE); } f->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, BACKGROUND_TEXTURE_SIZE, BACKGROUND_TEXTURE_SIZE, 0, GL_BGRA, GL_UNSIGNED_BYTE, img.constBits()); } else { dbgUI << "OpenGL: Tried to generate checker texture before OpenGL was initialized."; } } GLuint KisOpenGLImageTextures::checkerTexture() { if (m_glFuncs) { if (m_checkerTexture == 0) { m_glFuncs->glGenTextures(1, &m_checkerTexture); } return m_checkerTexture; } else { dbgUI << "Tried to access checker texture before OpenGL was initialized"; return 0; } } void KisOpenGLImageTextures::updateConfig(bool useBuffer, int NumMipmapLevels) { if(m_textureTiles.isEmpty()) return; Q_FOREACH (KisTextureTile *tile, m_textureTiles) { tile->setUseBuffer(useBuffer); tile->setNumMipmapLevels(NumMipmapLevels); } } void KisOpenGLImageTextures::slotImageSizeChanged(qint32 /*w*/, qint32 /*h*/) { createImageTextureTiles(); } void KisOpenGLImageTextures::setMonitorProfile(const KoColorProfile *monitorProfile, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) { //dbgUI << "Setting monitor profile to" << monitorProfile->name() << renderingIntent << conversionFlags; m_monitorProfile = monitorProfile; m_renderingIntent = renderingIntent; m_conversionFlags = conversionFlags; createImageTextureTiles(); } void KisOpenGLImageTextures::setChannelFlags(const QBitArray &channelFlags) { m_channelFlags = channelFlags; int selectedChannels = 0; const KoColorSpace *projectionCs = m_image->projection()->colorSpace(); QList channelInfo = projectionCs->channels(); if (m_channelFlags.size() != channelInfo.size()) { m_channelFlags = QBitArray(); } for (int i = 0; i < m_channelFlags.size(); ++i) { if (m_channelFlags.testBit(i) && channelInfo[i]->channelType() == KoChannelInfo::COLOR) { selectedChannels++; m_selectedChannelIndex = i; } } m_allChannelsSelected = (selectedChannels == m_channelFlags.size()); m_onlyOneChannelSelected = (selectedChannels == 1); } void KisOpenGLImageTextures::setProofingConfig(KisProofingConfiguration *proofingConfig) { m_proofingConfig = proofingConfig; m_createNewProofingTransform = true; } void KisOpenGLImageTextures::getTextureSize(KisGLTexturesInfo *texturesInfo) { KisConfig cfg; const GLint preferredTextureSize = cfg.openGLTextureSize(); GLint maxTextureSize; if (m_glFuncs) { m_glFuncs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); } else { dbgUI << "OpenGL: Tried to read texture size before OpenGL was initialized."; maxTextureSize = GL_MAX_TEXTURE_SIZE; } texturesInfo->width = qMin(preferredTextureSize, maxTextureSize); texturesInfo->height = qMin(preferredTextureSize, maxTextureSize); texturesInfo->border = cfg.textureOverlapBorder(); texturesInfo->effectiveWidth = texturesInfo->width - 2 * texturesInfo->border; texturesInfo->effectiveHeight = texturesInfo->height - 2 * texturesInfo->border; } bool KisOpenGLImageTextures::internalColorManagementActive() const { return m_internalColorManagementActive; } bool KisOpenGLImageTextures::setInternalColorManagementActive(bool value) { bool needsFinalRegeneration = m_internalColorManagementActive != value; if (needsFinalRegeneration) { m_internalColorManagementActive = value; createImageTextureTiles(); // at this point the value of m_internalColorManagementActive might // have been forcely reverted to 'false' in case of some problems } return needsFinalRegeneration; } void KisOpenGLImageTextures::updateTextureFormat() { QOpenGLContext *ctx = QOpenGLContext::currentContext(); if (!(m_image && ctx)) return; m_texturesInfo.internalFormat = GL_RGBA8; m_texturesInfo.type = GL_UNSIGNED_BYTE; m_texturesInfo.format = GL_BGRA; KoID colorModelId = m_image->colorSpace()->colorModelId(); KoID colorDepthId = m_image->colorSpace()->colorDepthId(); KoID destinationColorModelId = RGBAColorModelID; KoID destinationColorDepthId = Integer8BitsColorDepthID; dbgUI << "Choosing texture format:"; if (colorModelId == RGBAColorModelID) { if (colorDepthId == Float16BitsColorDepthID) { if (ctx->hasExtension("GL_ARB_texture_float")) { m_texturesInfo.internalFormat = GL_RGBA16F_ARB; dbgUI << "Using ARB half"; } else if (ctx->hasExtension("GL_ATI_texture_float")) { m_texturesInfo.internalFormat = GL_RGBA_FLOAT16_ATI; dbgUI << "Using ATI half"; } bool haveBuiltInOpenExr = false; #ifdef HAVE_OPENEXR haveBuiltInOpenExr = true; #endif if (haveBuiltInOpenExr && ctx->hasExtension("GL_ARB_half_float_pixel")) { m_texturesInfo.type = GL_HALF_FLOAT_ARB; destinationColorDepthId = Float16BitsColorDepthID; dbgUI << "Pixel type half"; } else { m_texturesInfo.type = GL_FLOAT; destinationColorDepthId = Float32BitsColorDepthID; dbgUI << "Pixel type float"; } m_texturesInfo.format = GL_RGBA; } else if (colorDepthId == Float32BitsColorDepthID) { if (ctx->hasExtension("GL_ARB_texture_float")) { m_texturesInfo.internalFormat = GL_RGBA32F_ARB; dbgUI << "Using ARB float"; } else if (ctx->hasExtension("GL_ATI_texture_float")) { m_texturesInfo.internalFormat = GL_RGBA_FLOAT32_ATI; dbgUI << "Using ATI float"; } m_texturesInfo.type = GL_FLOAT; m_texturesInfo.format = GL_RGBA; destinationColorDepthId = Float32BitsColorDepthID; } else if (colorDepthId == Integer16BitsColorDepthID) { m_texturesInfo.internalFormat = GL_RGBA16; m_texturesInfo.type = GL_UNSIGNED_SHORT; m_texturesInfo.format = GL_BGRA; destinationColorDepthId = Integer16BitsColorDepthID; dbgUI << "Using 16 bits rgba"; } } else { // We will convert the colorspace to 16 bits rgba, instead of 8 bits if (colorDepthId == Integer16BitsColorDepthID) { m_texturesInfo.internalFormat = GL_RGBA16; m_texturesInfo.type = GL_UNSIGNED_SHORT; m_texturesInfo.format = GL_BGRA; destinationColorDepthId = Integer16BitsColorDepthID; dbgUI << "Using conversion to 16 bits rgba"; } } if (!m_internalColorManagementActive && colorModelId != destinationColorModelId) { KisConfig cfg; KisConfig::OcioColorManagementMode cm = cfg.ocioColorManagementMode(); if (cm != KisConfig::INTERNAL) { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("You enabled OpenColorIO based color management, but your image is not an RGB image.\n" "OpenColorIO-based color management only works with RGB images.\n" "Please check the settings in the LUT docker.\n" "OpenColorIO will now be deactivated.")); } warnUI << "WARNING: Internal color management was forcely enabled"; warnUI << "Color Management Mode: " << cm; warnUI << ppVar(m_image->colorSpace()); warnUI << ppVar(destinationColorModelId); warnUI << ppVar(destinationColorDepthId); cfg.setOcioColorManagementMode(KisConfig::INTERNAL); m_internalColorManagementActive = true; } const KoColorProfile *profile = m_internalColorManagementActive || colorModelId != destinationColorModelId ? m_monitorProfile : m_image->colorSpace()->profile(); /** * TODO: add an optimization so that the tile->convertTo() method * would not be called when not needed (DK) */ m_tilesDestinationColorSpace = KoColorSpaceRegistry::instance()->colorSpace(destinationColorModelId.id(), destinationColorDepthId.id(), profile); } diff --git a/libs/ui/widgets/kis_spinbox_color_selector.cpp b/libs/ui/widgets/kis_spinbox_color_selector.cpp new file mode 100644 index 0000000000..820c7704cf --- /dev/null +++ b/libs/ui/widgets/kis_spinbox_color_selector.cpp @@ -0,0 +1,198 @@ +/* + * 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_spinbox_color_selector.h" +#include +#include +#include +#include +#include "kis_signal_compressor.h" + +#include "KoChannelInfo.h" +#include "KoColorSpaceTraits.h" +#include "KoColorSpaceMaths.h" +#include "KoColorSpaceRegistry.h" + +struct KisSpinboxColorSelector::Private +{ + bool allowUpdates = false; + QList spinBoxList; + QList doubleSpinBoxList; + KoColor color; + const KoColorSpace *cs; + KisSignalCompressor *compressUpdates; +}; + +KisSpinboxColorSelector::KisSpinboxColorSelector(QWidget *parent) : QWidget(parent) , m_d(new Private) +{ + + QFormLayout *layout = new QFormLayout(); + this->setLayout(layout); + + m_d->compressUpdates = new KisSignalCompressor(500 /* ms */, KisSignalCompressor::POSTPONE, this); + connect(m_d->compressUpdates, SIGNAL(timeout()), this, SLOT(slotFinishUpdate())); +} +KisSpinboxColorSelector::~KisSpinboxColorSelector() +{ + +} + +void KisSpinboxColorSelector::slotSetColor(KoColor color) +{ + m_d->color = color; +} + +void KisSpinboxColorSelector::slotSetColorSpace(const KoColorSpace *cs) +{ + if (cs == m_d->cs) { + return; + } + + m_d->cs = KoColorSpaceRegistry::instance()->colorSpace(cs->colorModelId().id(), cs->colorDepthId().id(), cs->profile()); + + //remake spinboxes + Q_FOREACH (QSpinBox *input, m_d->spinBoxList) { + this->layout()->removeWidget(input); + delete input; + } + m_d->spinBoxList.clear(); + Q_FOREACH (QDoubleSpinBox *input, m_d->doubleSpinBoxList) { + this->layout()->removeWidget(input); + delete input; + } + m_d->doubleSpinBoxList.clear(); + + QList channels = KoChannelInfo::displayOrderSorted(m_d->cs->channels()); + Q_FOREACH (KoChannelInfo* channel, channels) { + if (channel->channelType() == KoChannelInfo::COLOR) { + switch (channel->channelValueType()) { + case KoChannelInfo::UINT8: { + QSpinBox *input = new QSpinBox(this); + input->setMinimum(0); + input->setMaximum(0xFF); + m_d->spinBoxList.append(input); + this->layout()->addWidget(input); + if (input) { + connect(input, SIGNAL(updated()), this, SLOT(updateFromSpinBoxes())); + } + } + break; + case KoChannelInfo::UINT16: { + QSpinBox *input = new QSpinBox(this); + input->setMinimum(0); + input->setMaximum(0xFFFF); + m_d->spinBoxList.append(input); + this->layout()->addWidget(input); + if (input) { + connect(input, SIGNAL(updated()), this, SLOT(updateFromSpinBoxes())); + } + } + break; + case KoChannelInfo::UINT32: { + QSpinBox *input = new QSpinBox(this); + input->setMinimum(0); + input->setMaximum(0xFFFFFFFF); + m_d->spinBoxList.append(input); + this->layout()->addWidget(input); + if (input) { + connect(input, SIGNAL(updated()), this, SLOT(updateFromSpinBoxes())); + } + } + break; + case KoChannelInfo::FLOAT16: + case KoChannelInfo::FLOAT32: { + QDoubleSpinBox *input = new QDoubleSpinBox(this); + input->setMinimum(0); + input->setMaximum(1.0); + m_d->doubleSpinBoxList.append(input); + this->layout()->addWidget(input); + if (input) { + connect(input, SIGNAL(updated()), this, SLOT(updateFromSpinBoxes())); + } + } + break; + default: + Q_ASSERT(false); + } + + } + } +} + +void KisSpinboxColorSelector::createColorFromSpinboxValues() +{ + KoColor newColor; + int channelcount = m_d->cs->channelCount(); + quint8 *data; + QVector channelValues(channelcount); + channelValues.fill(1.0); + QList channels = KoChannelInfo::displayOrderSorted(m_d->cs->channels()); + + for (int i=0; ispinBoxList.at(i)) { + if (channels.at(i)->channelValueType()==KoChannelInfo::UINT8){ + channelValues[i] = KoColorSpaceMaths::scaleToA(m_d->spinBoxList.at(i)->value()); + } else if (channels.at(i)->channelValueType()==KoChannelInfo::UINT16){ + channelValues[i] = KoColorSpaceMaths::scaleToA(m_d->spinBoxList.at(i)->value()); + } + } else if (m_d->doubleSpinBoxList.at(i)){ + channelValues[i] = m_d->doubleSpinBoxList.at(i)->value(); + } + } + + m_d->cs->fromNormalisedChannelsValue(data, channelValues); + newColor.setColor(data, m_d->cs); + newColor.setOpacity(m_d->color.opacityU8()); + + m_d->color = newColor; +} + +void KisSpinboxColorSelector::slotUpdateFromSpinBoxes() +{ + m_d->allowUpdates = false; + createColorFromSpinboxValues(); + emit sigNewColor(m_d->color); + m_d->compressUpdates->start(); +} + +void KisSpinboxColorSelector::slotFinishUpdate() +{ + m_d->allowUpdates = true; +} + +void KisSpinboxColorSelector::updateSpinboxesWithNewValues() +{ + int channelcount = m_d->cs->channelCount(); + QVector channelValues(channelcount); + channelValues.fill(1.0); + m_d->cs->normalisedChannelsValue(m_d->color.data(), channelValues); + QList channels = KoChannelInfo::displayOrderSorted(m_d->cs->channels()); + + for (int i=0; ispinBoxList.at(i)) { + if (channels.at(i)->channelValueType() == KoChannelInfo::UINT8) { + m_d->spinBoxList.at(i)->setValue(KoColorSpaceMaths::scaleToA(channelValues[i])); + } else if (channels.at(i)->channelValueType() == KoChannelInfo::UINT16) { + m_d->spinBoxList.at(i)->setValue(KoColorSpaceMaths::scaleToA(channelValues[i])); + } + } else if (m_d->doubleSpinBoxList.at(i)) { + m_d->doubleSpinBoxList.at(i)->setValue(channelValues[i]); + } + } +} + + diff --git a/libs/ui/widgets/kis_spinbox_color_selector.h b/libs/ui/widgets/kis_spinbox_color_selector.h new file mode 100644 index 0000000000..63409b0a02 --- /dev/null +++ b/libs/ui/widgets/kis_spinbox_color_selector.h @@ -0,0 +1,58 @@ +/* + * 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 KISSPINBOXCOLORSELECTOR_H +#define KISSPINBOXCOLORSELECTOR_H + +#include +#include "kritaui_export.h" +#include +#include "KoColor.h" +#include "KoColorSpace.h" + +/** + * @brief The KisSpinboxColorSelector class + * This will give a widget with spinboxes depending on the color space + * Take responsibility for changing the color space. + */ +class KRITAUI_EXPORT KisSpinboxColorSelector : public QWidget +{ + Q_OBJECT +public: + explicit KisSpinboxColorSelector(QWidget *parent = 0); + ~KisSpinboxColorSelector(); + +Q_SIGNALS: + + void sigNewColor(KoColor color); + +public Q_SLOTS: + + void slotSetColorSpace(const KoColorSpace *cs); + void slotSetColor(KoColor color); +private Q_SLOTS: + void slotUpdateFromSpinBoxes(); + void slotFinishUpdate(); +private: + struct Private; + const QScopedPointer m_d; + void createColorFromSpinboxValues(); + void updateSpinboxesWithNewValues(); +}; + +#endif // KISSPINBOXCOLORSELECTOR_H