diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt index 6044a960d6..6386b2375b 100644 --- a/libs/ui/CMakeLists.txt +++ b/libs/ui/CMakeLists.txt @@ -1,583 +1,585 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/qtlockedfile ${EXIV2_INCLUDE_DIR} ) include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR} ${OCIO_INCLUDE_DIR} ) add_subdirectory( tests ) if (APPLE) find_library(FOUNDATION_LIBRARY Foundation) find_library(APPKIT_LIBRARY AppKit) endif () set(kritaui_LIB_SRCS canvas/kis_canvas_widget_base.cpp canvas/kis_canvas2.cpp canvas/kis_canvas_updates_compressor.cpp canvas/kis_canvas_controller.cpp canvas/kis_paintop_transformation_connector.cpp canvas/kis_display_color_converter.cpp canvas/kis_display_filter.cpp canvas/kis_exposure_gamma_correction_interface.cpp canvas/kis_tool_proxy.cpp canvas/kis_canvas_decoration.cc canvas/kis_coordinates_converter.cpp canvas/kis_grid_manager.cpp canvas/kis_grid_decoration.cpp canvas/kis_grid_config.cpp canvas/kis_prescaled_projection.cpp canvas/kis_qpainter_canvas.cpp canvas/kis_projection_backend.cpp canvas/kis_update_info.cpp canvas/kis_image_patch.cpp canvas/kis_image_pyramid.cpp canvas/kis_infinity_manager.cpp canvas/kis_change_guides_command.cpp canvas/kis_guides_decoration.cpp canvas/kis_guides_manager.cpp canvas/kis_guides_config.cpp canvas/kis_snap_config.cpp canvas/kis_snap_line_strategy.cpp canvas/KisSnapPointStrategy.cpp 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_change_file_layer_command.h kis_safe_document_loader.cpp kis_splash_screen.cpp kis_filter_manager.cc kis_filters_model.cc kis_histogram_view.cc KisImageBarrierLockerWithFeedback.cpp kis_image_manager.cc kis_image_view_converter.cpp kis_import_catcher.cc kis_layer_manager.cc kis_mask_manager.cc kis_mimedata.cpp kis_node_commands_adapter.cpp kis_node_manager.cpp kis_node_juggler_compressed.cpp kis_node_selection_adapter.cpp kis_node_insertion_adapter.cpp 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_script_manager.cpp kis_resource_server_provider.cpp KisSelectedShapesProxy.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 opengl/kis_texture_tile_info_pool.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/KisStrokeSpeedMonitor.cpp tool/strokes/freehand_stroke.cpp tool/strokes/KisStrokeEfficiencyMeasurer.cpp tool/strokes/kis_painter_based_stroke_strategy.cpp tool/strokes/kis_filter_stroke_strategy.cpp tool/strokes/kis_color_picker_stroke_strategy.cpp tool/strokes/KisFreehandStrokeInfo.cpp tool/strokes/KisMaskedFreehandStrokePainter.cpp tool/strokes/KisMaskingBrushRenderer.cpp tool/strokes/KisMaskingBrushCompositeOpFactory.cpp 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_paintop_presets_save.cpp widgets/kis_paintop_preset_icon_library.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/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_preset_live_preview_view.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 widgets/KoStrokeConfigWidget.cpp widgets/KoFillConfigWidget.cpp widgets/KoShapeFillWrapper.cpp utils/kis_document_aware_spin_box_unit_manager.cpp input/kis_input_manager.cpp input/kis_input_manager_p.cpp input/kis_extended_modifiers_mapper.cpp input/kis_abstract_input_action.cpp input/kis_tool_invocation_action.cpp input/kis_pan_action.cpp input/kis_alternate_invocation_action.cpp input/kis_rotate_canvas_action.cpp input/kis_zoom_action.cpp input/kis_change_frame_action.cpp input/kis_gamma_exposure_action.cpp input/kis_show_palette_action.cpp input/kis_change_primary_setting_action.cpp input/kis_abstract_shortcut.cpp input/kis_native_gesture_shortcut.cpp input/kis_single_action_shortcut.cpp input/kis_stroke_shortcut.cpp input/kis_shortcut_matcher.cpp input/kis_select_layer_action.cpp input/KisQtWidgetsTweaker.cpp input/KisInputActionGroup.cpp operations/kis_operation.cpp operations/kis_operation_configuration.cpp operations/kis_operation_registry.cpp operations/kis_operation_ui_factory.cpp operations/kis_operation_ui_widget.cpp operations/kis_filter_selection_operation.cpp actions/kis_selection_action_factories.cpp actions/KisPasteActionFactory.cpp 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 KisImportExportUtils.cpp kis_async_action_feedback.cpp KisMainWindow.cpp KisOpenPane.cpp KisPart.cpp KisPrintJob.cpp KisTemplate.cpp KisTemplateCreateDia.cpp KisTemplateGroup.cpp KisTemplates.cpp KisTemplatesPane.cpp KisTemplateTree.cpp 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 + KisWindowLayoutResource.cpp + KisWindowLayoutResource.h ) 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 input/wintab/kis_tablet_support_win8.cpp opengl/kis_opengl_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 KisAsyncAnimationRendererBase.cpp KisAsyncAnimationCacheRenderer.cpp KisAsyncAnimationFramesSavingRenderer.cpp dialogs/KisAsyncAnimationRenderDialogBase.cpp dialogs/KisAsyncAnimationCacheRenderDialog.cpp dialogs/KisAsyncAnimationFramesSaveDialog.cpp canvas/kis_animation_player.cpp kis_animation_importer.cpp KisSyncedAudioPlayback.cpp ) 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(APPLE) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} osx.mm ) endif() ki18n_wrap_ui(kritaui_LIB_SRCS widgets/KoFillConfigWidget.ui widgets/KoStrokeConfigWidget.ui forms/wdgdlgpngimport.ui forms/wdgfullscreensettings.ui forms/wdgautogradient.ui forms/wdggeneralsettings.ui forms/wdgperformancesettings.ui forms/wdggenerators.ui forms/wdgbookmarkedconfigurationseditor.ui forms/wdgapplyprofile.ui forms/wdgcustompattern.ui forms/wdglayerproperties.ui forms/wdgcolorsettings.ui forms/wdgtabletsettings.ui forms/wdgcolorspaceselector.ui forms/wdgcolorspaceselectoradvanced.ui forms/wdgdisplaysettings.ui forms/kis_previewwidgetbase.ui forms/kis_matrix_widget.ui forms/wdgselectionoptions.ui forms/wdggeometryoptions.ui forms/wdgnewimage.ui forms/wdgimageproperties.ui forms/wdgmaskfromselection.ui forms/wdgmasksource.ui forms/wdgfilterdialog.ui forms/wdgmetadatamergestrategychooser.ui forms/wdgpaintoppresets.ui forms/wdgpaintopsettings.ui forms/wdgdlggeneratorlayer.ui forms/wdgdlgfilelayer.ui forms/wdgfilterselector.ui forms/wdgfilternodecreation.ui forms/wdgpaintactioneditor.ui forms/wdgmultipliersdoublesliderspinbox.ui forms/wdgnodequerypatheditor.ui forms/wdgpresetselectorstrip.ui forms/wdgsavebrushpreset.ui forms/wdgpreseticonlibrary.ui forms/wdgdlgblacklistcleanup.ui forms/wdgrectangleconstraints.ui forms/wdgimportimagesequence.ui forms/wdgstrokeselectionproperties.ui forms/KisDetailsPaneBase.ui forms/KisOpenPaneBase.ui forms/wdgstopgradienteditor.ui 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_QT_MULTIMEDIA) target_link_libraries(kritaui Qt5::Multimedia) endif() 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}) target_link_libraries(kritaui ${APPKIT_LIBRARY}) endif () target_link_libraries(kritaui ${OPENEXR_LIBRARIES}) # Add VSync disable workaround if(NOT WIN32 AND NOT APPLE) target_link_libraries(kritaui ${CMAKE_DL_LIBS} Qt5::X11Extras) endif() if(X11_FOUND) target_link_libraries(kritaui Qt5::X11Extras ${X11_LIBRARIES}) endif() target_include_directories(kritaui PUBLIC $ $ $ $ $ $ $ ) set_target_properties(kritaui PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritaui ${INSTALL_TARGETS_DEFAULT_ARGS}) if (APPLE) install(FILES osx.stylesheet DESTINATION ${DATA_INSTALL_DIR}/krita) endif () diff --git a/libs/ui/KisApplication.cpp b/libs/ui/KisApplication.cpp index 6cf0e6bb16..013e322a0d 100644 --- a/libs/ui/KisApplication.cpp +++ b/libs/ui/KisApplication.cpp @@ -1,812 +1,813 @@ /* * Copyright (C) 1998, 1999 Torben Weis * Copyright (C) 2012 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KisApplication.h" #include #ifdef Q_OS_WIN #include #include #endif #ifdef Q_OS_OSX #include "osx.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KoGlobal.h" #include "KoConfig.h" #include #include #include #include "thememanager.h" #include "KisPrintJob.h" #include "KisDocument.h" #include "KisMainWindow.h" #include "KisAutoSaveRecoveryDialog.h" #include "KisPart.h" #include #include "kis_md5_generator.h" #include "kis_splash_screen.h" #include "kis_config.h" #include "flake/kis_shape_selection.h" #include #include #include #include #include #include #include #include "kisexiv2/kis_exiv2.h" #include "KisApplicationArguments.h" #include #include "kis_action_registry.h" #include #include #include #include "kis_image_barrier_locker.h" #include "opengl/kis_opengl.h" #include "kis_spin_box_unit_manager.h" #include "kis_document_aware_spin_box_unit_manager.h" #include "KisViewManager.h" #include "kis_workspace_resource.h" #include namespace { const QTime appStartTime(QTime::currentTime()); } class KisApplicationPrivate { public: KisApplicationPrivate() : splashScreen(0) {} QPointer splashScreen; }; class KisApplication::ResetStarting { public: ResetStarting(KisSplashScreen *splash, int fileCount) : m_splash(splash) , m_fileCount(fileCount) { } ~ResetStarting() { if (m_splash) { KConfigGroup cfg( KSharedConfig::openConfig(), "SplashScreen"); bool hideSplash = cfg.readEntry("HideSplashAfterStartup", false); if (m_fileCount > 0 || hideSplash) { m_splash->hide(); } else { m_splash->setWindowFlags(Qt::Dialog); QRect r(QPoint(), m_splash->size()); m_splash->move(QApplication::desktop()->availableGeometry().center() - r.center()); m_splash->setWindowTitle(qAppName()); m_splash->setParent(0); Q_FOREACH (QObject *o, m_splash->children()) { QWidget *w = qobject_cast(o); if (w && w->isHidden()) { w->setVisible(true); } } m_splash->show(); m_splash->activateWindow(); } } } QPointer m_splash; int m_fileCount; }; KisApplication::KisApplication(const QString &key, int &argc, char **argv) : QtSingleApplication(key, argc, argv) , d(new KisApplicationPrivate) , m_autosaveDialog(0) , m_mainWindow(0) , m_batchRun(false) { #ifdef Q_OS_OSX setMouseCoalescingEnabled(false); #endif QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath()); setApplicationDisplayName("Krita"); setApplicationName("krita"); // Note: Qt docs suggest we set this, but if we do, we get resource paths of the form of krita/krita, which is weird. // setOrganizationName("krita"); setOrganizationDomain("krita.org"); QString version = KritaVersionWrapper::versionString(true); setApplicationVersion(version); setWindowIcon(KisIconUtils::loadIcon("calligrakrita")); if (qgetenv("KRITA_NO_STYLE_OVERRIDE").isEmpty()) { QStringList styles = QStringList() << "breeze" << "fusion" << "plastique"; if (!styles.contains(style()->objectName().toLower())) { Q_FOREACH (const QString & style, styles) { if (!setStyle(style)) { qDebug() << "No" << style << "available."; } else { qDebug() << "Set style" << style; break; } } } } else { qDebug() << "Style override disabled, using" << style()->objectName(); } KisOpenGL::initialize(); qDebug() << "krita has opengl" << KisOpenGL::hasOpenGL(); } #if defined(Q_OS_WIN) && defined(ENV32BIT) typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); LPFN_ISWOW64PROCESS fnIsWow64Process; BOOL isWow64() { BOOL bIsWow64 = FALSE; //IsWow64Process is not available on all supported versions of Windows. //Use GetModuleHandle to get a handle to the DLL that contains the function //and GetProcAddress to get a pointer to the function if available. fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress( GetModuleHandle(TEXT("kernel32")),"IsWow64Process"); if(0 != fnIsWow64Process) { if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64)) { //handle error } } return bIsWow64; } #endif void KisApplication::initializeGlobals(const KisApplicationArguments &args) { int dpiX = args.dpiX(); int dpiY = args.dpiY(); if (dpiX > 0 && dpiY > 0) { KoDpi::setDPI(dpiX, dpiY); } } void KisApplication::addResourceTypes() { // All Krita's resource types KoResourcePaths::addResourceType("kis_pics", "data", "/pics/"); KoResourcePaths::addResourceType("kis_images", "data", "/images/"); KoResourcePaths::addResourceType("icc_profiles", "data", "/profiles/"); KoResourcePaths::addResourceType("metadata_schema", "data", "/metadata/schemas/"); KoResourcePaths::addResourceType("kis_brushes", "data", "/brushes/"); KoResourcePaths::addResourceType("kis_taskset", "data", "/taskset/"); KoResourcePaths::addResourceType("kis_taskset", "data", "/taskset/"); KoResourcePaths::addResourceType("gmic_definitions", "data", "/gmic/"); KoResourcePaths::addResourceType("kis_resourcebundles", "data", "/bundles/"); KoResourcePaths::addResourceType("kis_defaultpresets", "data", "/defaultpresets/"); KoResourcePaths::addResourceType("kis_paintoppresets", "data", "/paintoppresets/"); KoResourcePaths::addResourceType("kis_workspaces", "data", "/workspaces/"); + KoResourcePaths::addResourceType("kis_windowlayouts", "data", "/windowlayouts/"); KoResourcePaths::addResourceType("psd_layer_style_collections", "data", "/asl"); KoResourcePaths::addResourceType("ko_patterns", "data", "/patterns/", true); KoResourcePaths::addResourceType("ko_gradients", "data", "/gradients/"); KoResourcePaths::addResourceType("ko_gradients", "data", "/gradients/", true); KoResourcePaths::addResourceType("ko_palettes", "data", "/palettes/", true); KoResourcePaths::addResourceType("kis_shortcuts", "data", "/shortcuts/"); KoResourcePaths::addResourceType("kis_actions", "data", "/actions"); KoResourcePaths::addResourceType("icc_profiles", "data", "/color/icc"); KoResourcePaths::addResourceType("ko_effects", "data", "/effects/"); KoResourcePaths::addResourceType("tags", "data", "/tags/"); KoResourcePaths::addResourceType("templates", "data", "/templates"); KoResourcePaths::addResourceType("pythonscripts", "data", "/pykrita"); KoResourcePaths::addResourceType("symbols", "data", "/symbols"); KoResourcePaths::addResourceType("preset_icons", "data", "/preset_icons"); // // Extra directories to look for create resources. (Does anyone actually use that anymore?) // KoResourcePaths::addResourceDir("ko_gradients", "/usr/share/create/gradients/gimp"); // KoResourcePaths::addResourceDir("ko_gradients", QDir::homePath() + QString("/.create/gradients/gimp")); // KoResourcePaths::addResourceDir("ko_patterns", "/usr/share/create/patterns/gimp"); // KoResourcePaths::addResourceDir("ko_patterns", QDir::homePath() + QString("/.create/patterns/gimp")); // KoResourcePaths::addResourceDir("kis_brushes", "/usr/share/create/brushes/gimp"); // KoResourcePaths::addResourceDir("kis_brushes", QDir::homePath() + QString("/.create/brushes/gimp")); // KoResourcePaths::addResourceDir("ko_palettes", "/usr/share/create/swatches"); // KoResourcePaths::addResourceDir("ko_palettes", QDir::homePath() + QString("/.create/swatches")); // Make directories for all resources we can save, and tags QDir d; d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/tags/"); d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/asl/"); d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/bundles/"); d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/gradients/"); d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/paintoppresets/"); d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/palettes/"); d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/patterns/"); d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/taskset/"); d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/workspaces/"); d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/input/"); d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/pykrita/"); d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/symbols/"); d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/preset_icons/"); d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/preset_icons/tool_icons/"); d.mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/preset_icons/emblem_icons/"); // Indicate that it is now safe for users of KoResourcePaths to load resources KoResourcePaths::setReady(); } void KisApplication::loadResources() { setSplashScreenLoadingText(i18n("Loading Gradients...")); processEvents(); KoResourceServerProvider::instance()->gradientServer(true); // Load base resources setSplashScreenLoadingText(i18n("Loading Patterns...")); processEvents(); KoResourceServerProvider::instance()->patternServer(true); setSplashScreenLoadingText(i18n("Loading Palettes...")); processEvents(); KoResourceServerProvider::instance()->paletteServer(false); setSplashScreenLoadingText(i18n("Loading Brushes...")); processEvents(); KisBrushServer::instance()->brushServer(true); // load paintop presets setSplashScreenLoadingText(i18n("Loading Paint Operations...")); processEvents(); KisResourceServerProvider::instance()->paintOpPresetServer(true); // load symbols setSplashScreenLoadingText(i18n("Loading SVG Symbol Collections...")); processEvents(); KoResourceServerProvider::instance()->svgSymbolCollectionServer(true); setSplashScreenLoadingText(i18n("Loading Resource Bundles...")); processEvents(); KisResourceServerProvider::instance()->resourceBundleServer(); } void KisApplication::loadPlugins() { KoShapeRegistry* r = KoShapeRegistry::instance(); r->add(new KisShapeSelectionFactory()); KisActionRegistry::instance(); KisFilterRegistry::instance(); KisGeneratorRegistry::instance(); KisPaintOpRegistry::instance(); KoColorSpaceRegistry::instance(); // Load the krita-specific tools setSplashScreenLoadingText(i18n("Loading Plugins for Krita/Tool...")); processEvents(); KoPluginLoader::instance()->load(QString::fromLatin1("Krita/Tool"), QString::fromLatin1("[X-Krita-Version] == 28")); // Load dockers setSplashScreenLoadingText(i18n("Loading Plugins for Krita/Dock...")); processEvents(); KoPluginLoader::instance()->load(QString::fromLatin1("Krita/Dock"), QString::fromLatin1("[X-Krita-Version] == 28")); // XXX_EXIV: make the exiv io backends real plugins setSplashScreenLoadingText(i18n("Loading Plugins Exiv/IO...")); processEvents(); KisExiv2::initialize(); } bool KisApplication::start(const KisApplicationArguments &args) { KisConfig cfg; #if defined(Q_OS_WIN) #ifdef ENV32BIT if (isWow64() && !cfg.readEntry("WarnedAbout32Bits", false)) { QMessageBox::information(0, i18nc("@title:window", "Krita: Warning"), i18n("You are running a 32 bits build on a 64 bits Windows.\n" "This is not recommended.\n" "Please download and install the x64 build instead.")); cfg.writeEntry("WarnedAbout32Bits", true); } #endif #endif QString opengl = cfg.canvasState(); if (opengl == "OPENGL_NOT_TRIED" ) { cfg.setCanvasState("TRY_OPENGL"); } else if (opengl != "OPENGL_SUCCESS") { cfg.setCanvasState("OPENGL_FAILED"); } setSplashScreenLoadingText(i18n("Initializing Globals")); processEvents(); initializeGlobals(args); const bool doNewImage = args.doNewImage(); const bool doTemplate = args.doTemplate(); const bool print = args.print(); const bool exportAs = args.exportAs(); const bool exportAsPdf = args.exportAsPdf(); const QString exportFileName = args.exportFileName(); m_batchRun = (print || exportAs || exportAsPdf || !exportFileName.isEmpty()); // print & exportAsPdf do user interaction ATM const bool needsMainWindow = !exportAs; // only show the mainWindow when no command-line mode option is passed // TODO: fix print & exportAsPdf to work without mainwindow shown const bool showmainWindow = !exportAs; // would be !batchRun; const bool showSplashScreen = !m_batchRun && qEnvironmentVariableIsEmpty("NOSPLASH"); if (showSplashScreen && d->splashScreen) { d->splashScreen->show(); d->splashScreen->repaint(); processEvents(); } KoHashGeneratorProvider::instance()->setGenerator("MD5", new KisMD5Generator()); // Initialize all Krita directories etc. KoGlobal::initialize(); KConfigGroup group(KSharedConfig::openConfig(), "theme"); Digikam::ThemeManager themeManager; themeManager.setCurrentTheme(group.readEntry("Theme", "Krita dark")); ResetStarting resetStarting(d->splashScreen, args.filenames().count()); // remove the splash when done Q_UNUSED(resetStarting); // Make sure we can save resources and tags setSplashScreenLoadingText(i18n("Adding resource types")); processEvents(); addResourceTypes(); // Load all resources and tags before the plugins do that loadResources(); // Load the plugins loadPlugins(); if (needsMainWindow) { // show a mainWindow asap, if we want that setSplashScreenLoadingText(i18n("Loading Main Window...")); processEvents(); if (showmainWindow) { KisPart::instance()->restoreSession(); m_mainWindow = KisPart::instance()->currentMainwindow(); if (!args.workspace().isEmpty()) { KoResourceServer * rserver = KisResourceServerProvider::instance()->workspaceServer(); KisWorkspaceResource* workspace = rserver->resourceByName(args.workspace()); if (workspace) { m_mainWindow->restoreWorkspace(workspace->dockerState()); } } if (args.canvasOnly()) { m_mainWindow->viewManager()->switchCanvasOnly(true); } if (args.fullScreen()) { m_mainWindow->showFullScreen(); } } else { m_mainWindow = KisPart::instance()->createMainWindow(); } } short int numberOfOpenDocuments = 0; // number of documents open // Check for autosave files that can be restored, if we're not running a batchrun (test, print, export to pdf) if (!m_batchRun) { checkAutosaveFiles(); } setSplashScreenLoadingText(QString()); // done loading, so clear out label processEvents(); //configure the unit manager KisSpinBoxUnitManagerFactory::setDefaultUnitManagerBuilder(new KisDocumentAwareSpinBoxUnitManagerBuilder()); connect(this, &KisApplication::aboutToQuit, &KisSpinBoxUnitManagerFactory::clearUnitManagerBuilder); //ensure the builder is destroyed when the application leave. //the new syntax slot syntax allow to connect to a non q_object static method. // Create a new image, if needed if (doNewImage) { KisDocument *doc = args.image(); if (doc) { KisPart::instance()->addDocument(doc); m_mainWindow->addViewAndNotifyLoadingCompleted(doc); } } // Get the command line arguments which we have to parse int argsCount = args.filenames().count(); if (argsCount > 0) { // Loop through arguments short int nPrinted = 0; for (int argNumber = 0; argNumber < argsCount; argNumber++) { QString fileName = args.filenames().at(argNumber); // are we just trying to open a template? if (doTemplate) { // called in mix with batch options? ignore and silently skip if (m_batchRun) { continue; } if (createNewDocFromTemplate(fileName, m_mainWindow)) { ++numberOfOpenDocuments; } // now try to load } else { if (exportAs) { QString outputMimetype = KisMimeDatabase::mimeTypeForFile(exportFileName, false); if (outputMimetype == "application/octetstream") { dbgKrita << i18n("Mimetype not found, try using the -mimetype option") << endl; return 1; } KisDocument *doc = KisPart::instance()->createDocument(); doc->setFileBatchMode(m_batchRun); doc->openUrl(QUrl::fromLocalFile(fileName)); qApp->processEvents(); // For vector layers to be updated doc->setFileBatchMode(true); if (!doc->exportDocumentSync(QUrl::fromLocalFile(exportFileName), outputMimetype.toLatin1())) { dbgKrita << "Could not export " << fileName << "to" << exportFileName << ":" << doc->errorMessage(); } nPrinted++; QTimer::singleShot(0, this, SLOT(quit())); } else if (m_mainWindow) { KisMainWindow::OpenFlags flags = m_batchRun ? KisMainWindow::BatchMode : KisMainWindow::None; if (m_mainWindow->openDocument(QUrl::fromLocalFile(fileName), flags)) { if (print) { m_mainWindow->slotFilePrint(); nPrinted++; // TODO: trigger closing of app once printing is done } else if (exportAsPdf) { KisPrintJob *job = m_mainWindow->exportToPdf(exportFileName); if (job) connect (job, SIGNAL(destroyed(QObject*)), m_mainWindow, SLOT(slotFileQuit()), Qt::QueuedConnection); nPrinted++; } else { // Normal case, success numberOfOpenDocuments++; } } else { // .... if failed // delete doc; done by openDocument } } } } if (m_batchRun) { return nPrinted > 0; } } // fixes BUG:369308 - Krita crashing on splash screen when loading. // trying to open a file before Krita has loaded can cause it to hang and crash if (d->splashScreen) { d->splashScreen->displayLinks(true); d->splashScreen->displayRecentFiles(true); } // not calling this before since the program will quit there. return true; } KisApplication::~KisApplication() { delete d; } void KisApplication::setSplashScreen(QWidget *splashScreen) { d->splashScreen = qobject_cast(splashScreen); } void KisApplication::setSplashScreenLoadingText(QString textToLoad) { if (d->splashScreen) { //d->splashScreen->loadingLabel->setText(textToLoad); d->splashScreen->setLoadingText(textToLoad); d->splashScreen->repaint(); } } void KisApplication::hideSplashScreen() { if (d->splashScreen) { // hide the splashscreen to see the dialog d->splashScreen->hide(); } } bool KisApplication::notify(QObject *receiver, QEvent *event) { try { return QApplication::notify(receiver, event); } catch (std::exception &e) { qWarning("Error %s sending event %i to object %s", e.what(), event->type(), qPrintable(receiver->objectName())); } catch (...) { qWarning("Error sending event %i to object %s", event->type(), qPrintable(receiver->objectName())); } return false; } void KisApplication::remoteArguments(QByteArray message, QObject *socket) { Q_UNUSED(socket); // check if we have any mainwindow KisMainWindow *mw = qobject_cast(qApp->activeWindow()); if (!mw) { mw = KisPart::instance()->mainWindows().first(); } if (!mw) { return; } KisApplicationArguments args = KisApplicationArguments::deserialize(message); const bool doTemplate = args.doTemplate(); const int argsCount = args.filenames().count(); if (argsCount > 0) { // Loop through arguments for (int argNumber = 0; argNumber < argsCount; ++argNumber) { QString filename = args.filenames().at(argNumber); // are we just trying to open a template? if (doTemplate) { createNewDocFromTemplate(filename, mw); } else if (QFile(filename).exists()) { KisMainWindow::OpenFlags flags = m_batchRun ? KisMainWindow::BatchMode : KisMainWindow::None; mw->openDocument(QUrl::fromLocalFile(filename), flags); } } } } void KisApplication::fileOpenRequested(const QString &url) { KisMainWindow *mainWindow = KisPart::instance()->mainWindows().first(); if (mainWindow) { KisMainWindow::OpenFlags flags = m_batchRun ? KisMainWindow::BatchMode : KisMainWindow::None; mainWindow->openDocument(QUrl::fromLocalFile(url), flags); } } void KisApplication::checkAutosaveFiles() { if (m_batchRun) return; // Check for autosave files from a previous run. There can be several, and // we want to offer a restore for every one. Including a nice thumbnail! QStringList filters; filters << QString(".krita-*-*-autosave.kra"); #ifdef Q_OS_WIN QDir dir = QDir::temp(); #else QDir dir = QDir::home(); #endif // all autosave files for our application QStringList autosaveFiles = dir.entryList(filters, QDir::Files | QDir::Hidden); // Allow the user to make their selection if (autosaveFiles.size() > 0) { if (d->splashScreen) { // hide the splashscreen to see the dialog d->splashScreen->hide(); } m_autosaveDialog = new KisAutoSaveRecoveryDialog(autosaveFiles, activeWindow()); QDialog::DialogCode result = (QDialog::DialogCode) m_autosaveDialog->exec(); if (result == QDialog::Accepted) { QStringList filesToRecover = m_autosaveDialog->recoverableFiles(); Q_FOREACH (const QString &autosaveFile, autosaveFiles) { if (!filesToRecover.contains(autosaveFile)) { QFile::remove(dir.absolutePath() + "/" + autosaveFile); } } autosaveFiles = filesToRecover; } else { autosaveFiles.clear(); } if (autosaveFiles.size() > 0) { QList autosaveUrls; Q_FOREACH (const QString &autoSaveFile, autosaveFiles) { const QUrl url = QUrl::fromLocalFile(dir.absolutePath() + QLatin1Char('/') + autoSaveFile); autosaveUrls << url; } if (m_mainWindow) { Q_FOREACH (const QUrl &url, autosaveUrls) { KisMainWindow::OpenFlags flags = m_batchRun ? KisMainWindow::BatchMode : KisMainWindow::None; m_mainWindow->openDocument(url, flags | KisMainWindow::RecoveryFile); } } } // cleanup delete m_autosaveDialog; m_autosaveDialog = nullptr; } } bool KisApplication::createNewDocFromTemplate(const QString &fileName, KisMainWindow *mainWindow) { QString templatePath; const QUrl templateUrl = QUrl::fromLocalFile(fileName); if (QFile::exists(fileName)) { templatePath = templateUrl.toLocalFile(); dbgUI << "using full path..."; } else { QString desktopName(fileName); const QString templatesResourcePath = QStringLiteral("templates/"); QStringList paths = KoResourcePaths::findAllResources("data", templatesResourcePath + "*/" + desktopName); if (paths.isEmpty()) { paths = KoResourcePaths::findAllResources("data", templatesResourcePath + desktopName); } if (paths.isEmpty()) { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("No template found for: %1", desktopName)); } else if (paths.count() > 1) { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Too many templates found for: %1", desktopName)); } else { templatePath = paths.at(0); } } if (!templatePath.isEmpty()) { QUrl templateBase; templateBase.setPath(templatePath); KDesktopFile templateInfo(templatePath); QString templateName = templateInfo.readUrl(); QUrl templateURL; templateURL.setPath(templateBase.adjusted(QUrl::RemoveFilename|QUrl::StripTrailingSlash).path() + '/' + templateName); KisMainWindow::OpenFlags batchFlags = m_batchRun ? KisMainWindow::BatchMode : KisMainWindow::None; if (mainWindow->openDocument(templateURL, KisMainWindow::Import | batchFlags)) { dbgUI << "Template loaded..."; return true; } else { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Template %1 failed to load.", templateURL.toDisplayString())); } } return false; } void KisApplication::clearConfig() { KIS_ASSERT_RECOVER_RETURN(qApp->thread() == QThread::currentThread()); KSharedConfigPtr config = KSharedConfig::openConfig(); // find user settings file bool createDir = false; QString kritarcPath = KoResourcePaths::locateLocal("config", "kritarc", createDir); QFile configFile(kritarcPath); if (configFile.exists()) { // clear file if (configFile.open(QFile::WriteOnly)) { configFile.close(); } else { QMessageBox::warning(0, i18nc("@title:window", "Krita"), i18n("Failed to clear %1\n\n" "Please make sure no other program is using the file and try again.", kritarcPath), QMessageBox::Ok, QMessageBox::Ok); } } // reload from disk; with the user file settings cleared, // this should load any default configuration files shipping with the program config->reparseConfiguration(); config->sync(); } void KisApplication::askClearConfig() { Qt::KeyboardModifiers mods = QApplication::queryKeyboardModifiers(); bool askClearConfig = (mods & Qt::ControlModifier) && (mods & Qt::ShiftModifier) && (mods & Qt::AltModifier); if (askClearConfig) { bool ok = QMessageBox::question(0, i18nc("@title:window", "Krita"), i18n("Do you want to clear the settings file?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes; if (ok) { clearConfig(); } } } diff --git a/libs/ui/KisWindowLayoutResource.cpp b/libs/ui/KisWindowLayoutResource.cpp new file mode 100644 index 0000000000..8e84e90556 --- /dev/null +++ b/libs/ui/KisWindowLayoutResource.cpp @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018 Jouni Pentikäinen + * + * 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 "KisWindowLayoutResource.h" + +#include +#include +#include + +#include +#include + +static const int WINDOW_LAYOUT_VERSION = 1; + +struct KisWindowLayoutResource::Private +{ + struct Window { + QByteArray geometry; + QByteArray windowState; + }; + + QVector windows; + + Private() = default; + + explicit Private(QVector windows) + : windows(std::move(windows)) + {} + + void openNecessaryWindows(QList> ¤tWindows) { + auto *kisPart = KisPart::instance(); + + while (currentWindows.length() < windows.length()) { + KisMainWindow *window = kisPart->createMainWindow(); + currentWindows.append(window); + window->show(); + } + } + + void closeUnneededWindows(QList> ¤tWindows) { + if (currentWindows.length() <= windows.length()) return; + + migrateViewsFromClosingWindows(currentWindows); + + while (currentWindows.length() > windows.length()) { + KisMainWindow *window = currentWindows.takeLast(); + window->close(); + } + } + + void migrateViewsFromClosingWindows(QList> ¤tWindows) const + { + auto *kisPart = KisPart::instance(); + + QVector visibleDocuments; + Q_FOREACH(KisView *view, kisPart->views()) { + KisMainWindow *window = view->mainWindow(); + int index = currentWindows.indexOf(window); + + if (index >= 0 && index < windows.length()) { + visibleDocuments.append(view->document()); + } + } + + Q_FOREACH(KisDocument *document, kisPart->documents()) { + if (!visibleDocuments.contains(document)) { + visibleDocuments.append(document); + currentWindows.first()->newView(document); + } + } + } +}; + +KisWindowLayoutResource::KisWindowLayoutResource(const QString &filename) + : KoResource(filename) + , d(new Private) +{} + +KisWindowLayoutResource::KisWindowLayoutResource(const QString &filename, KisWindowLayoutResource::Private *d) + : KoResource(filename) + , d(d) +{} + +KisWindowLayoutResource::~KisWindowLayoutResource() +{} + +KisWindowLayoutResource * KisWindowLayoutResource::fromCurrentWindows(const QString &filename, const QList> &mainWindows) +{ + QVector windows; + + Q_FOREACH(auto window, mainWindows) { + Private::Window state; + state.geometry = window->saveGeometry(); + state.windowState = window->saveState(); + + windows.append(state); + } + + return new KisWindowLayoutResource(filename, new Private(windows)); +} + +void KisWindowLayoutResource::applyLayout() +{ + KisPart *kisPart = KisPart::instance(); + QList> currentWindows = kisPart->mainWindows(); + + // TODO? map the open windows to ones saved... somehow + + d->openNecessaryWindows(currentWindows); + + int index = 0; + Q_FOREACH(const auto &window, d->windows) { + currentWindows.at(index)->restoreGeometry(window.geometry); + currentWindows.at(index)->restoreWorkspace(window.windowState); + index++; + } + + d->closeUnneededWindows(currentWindows); +} + +bool KisWindowLayoutResource::save() +{ + if (filename().isEmpty()) + return false; + + QFile file(filename()); + file.open(QIODevice::WriteOnly); + bool res = saveToDevice(&file); + file.close(); + return res; +} + +bool KisWindowLayoutResource::load() +{ + if (filename().isEmpty()) + return false; + + QFile file(filename()); + if (file.size() == 0) return false; + if (!file.open(QIODevice::ReadOnly)) { + warnKrita << "Can't open file " << filename(); + return false; + } + + bool res = loadFromDevice(&file); + file.close(); + return res; +} + +bool KisWindowLayoutResource::saveToDevice(QIODevice *dev) const +{ + QDomDocument doc; + QDomElement root = doc.createElement("WindowLayout"); + root.setAttribute("name", name()); + root.setAttribute("version", WINDOW_LAYOUT_VERSION); + + Q_FOREACH(const auto &window, d->windows) { + QDomElement elem = doc.createElement("window"); + + QDomElement geometry = doc.createElement("geometry"); + geometry.appendChild(doc.createCDATASection(window.geometry.toBase64())); + elem.appendChild(geometry); + + QDomElement state = doc.createElement("windowState"); + state.appendChild(doc.createCDATASection(window.windowState.toBase64())); + elem.appendChild(state); + root.appendChild(elem); + } + + doc.appendChild(root); + + QTextStream textStream(dev); + textStream.setCodec("UTF-8"); + doc.save(textStream, 4); + + KoResource::saveToDevice(dev); + + return true; +} + +bool KisWindowLayoutResource::loadFromDevice(QIODevice *dev) +{ + QDomDocument doc; + if (!doc.setContent(dev)) { + return false; + } + + QDomElement element = doc.documentElement(); + setName(element.attribute("name")); + + d->windows.clear(); + + for (auto windowElement = element.firstChildElement("window"); + !windowElement.isNull(); + windowElement = windowElement.nextSiblingElement()) { + + Private::Window window; + + QDomElement geometry = windowElement.firstChildElement("geometry"); + QDomElement state = windowElement.firstChildElement("windowState"); + + window.geometry = QByteArray::fromBase64(geometry.text().toLatin1()); + window.windowState = QByteArray::fromBase64(state.text().toLatin1()); + + d->windows.append(window); + } + + setValid(true); + return true; +} + +QString KisWindowLayoutResource::defaultFileExtension() const +{ + return QString(".kwl"); +} + + diff --git a/libs/ui/KisWindowLayoutResource.h b/libs/ui/KisWindowLayoutResource.h new file mode 100644 index 0000000000..7f41cc2984 --- /dev/null +++ b/libs/ui/KisWindowLayoutResource.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018 Jouni Pentikäinen + * + * 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 KISWINDOWLAYOUTRESOURCE_H +#define KISWINDOWLAYOUTRESOURCE_H + +#include +#include + +class KisWindowLayoutResource : public KoResource +{ +public: + explicit KisWindowLayoutResource(const QString &filename); + ~KisWindowLayoutResource() override; + + static KisWindowLayoutResource * fromCurrentWindows(const QString &filename, const QList> &mainWindows); + + void applyLayout(); + + bool save() override; + bool load() override; + + bool saveToDevice(QIODevice *dev) const override; + bool loadFromDevice(QIODevice *dev) override; + + QString defaultFileExtension() const override; + +private: + struct Private; + QScopedPointer d; + + KisWindowLayoutResource(const QString &filename, Private *d); +}; + +#endif \ No newline at end of file diff --git a/libs/ui/kis_resource_server_provider.cpp b/libs/ui/kis_resource_server_provider.cpp index ad7fe33831..98283ecfea 100644 --- a/libs/ui/kis_resource_server_provider.cpp +++ b/libs/ui/kis_resource_server_provider.cpp @@ -1,158 +1,175 @@ /* * kis_resourceserver.cc - part of KImageShop * * Copyright (c) 1999 Matthias Elter * Copyright (c) 2003 Patrick Julien * Copyright (c) 2005 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_resource_server_provider.h" #include #include #include #include #include #include #include #include #include #include #include #include #include +#include + #include #include Q_GLOBAL_STATIC(KisResourceServerProvider, s_instance) typedef KoResourceServerSimpleConstruction > KisPaintOpPresetResourceServer; typedef KoResourceServerAdapter > KisPaintOpPresetResourceServerAdapter; inline bool isRunningInKrita() { return qApp->applicationName().contains(QLatin1String("krita"), Qt::CaseInsensitive); } KisResourceServerProvider::KisResourceServerProvider() : m_resourceBundleServer(0) { KisBrushServer *brushServer = KisBrushServer::instance(); m_paintOpPresetServer = new KisPaintOpPresetResourceServer("kis_paintoppresets", "*.kpp"); if (!QFileInfo(m_paintOpPresetServer->saveLocation()).exists()) { QDir().mkpath(m_paintOpPresetServer->saveLocation()); } m_paintOpPresetThread = new KoResourceLoaderThread(m_paintOpPresetServer); m_paintOpPresetThread->loadSynchronously(); // if (!isRunningInKrita()) { // m_paintOpPresetThread->barrier(); // } m_workspaceServer = new KoResourceServerSimpleConstruction("kis_workspaces", "*.kws"); if (!QFileInfo(m_workspaceServer->saveLocation()).exists()) { QDir().mkpath(m_workspaceServer->saveLocation()); } m_workspaceThread = new KoResourceLoaderThread(m_workspaceServer); m_workspaceThread->loadSynchronously(); // if (!isRunningInKrita()) { // m_workspaceThread->barrier(); // } + m_windowLayoutServer= new KoResourceServerSimpleConstruction("kis_windowlayouts", "*.kwl"); + if (!QFileInfo(m_windowLayoutServer->saveLocation()).exists()) { + QDir().mkpath(m_windowLayoutServer->saveLocation()); + } + m_windowLayoutThread = new KoResourceLoaderThread(m_windowLayoutServer); + m_windowLayoutThread->loadSynchronously(); + + m_layerStyleCollectionServer = new KoResourceServerSimpleConstruction("psd_layer_style_collections", "*.asl"); if (!QFileInfo(m_layerStyleCollectionServer->saveLocation()).exists()) { QDir().mkpath(m_layerStyleCollectionServer->saveLocation()); } m_layerStyleCollectionThread = new KoResourceLoaderThread(m_layerStyleCollectionServer); m_layerStyleCollectionThread->loadSynchronously(); // if (!isRunningInKrita()) { // m_layerStyleCollectionThread->barrier(); // } connect(this, SIGNAL(notifyBrushBlacklistCleanup()), brushServer, SLOT(slotRemoveBlacklistedResources())); } KisResourceServerProvider::~KisResourceServerProvider() { delete m_paintOpPresetThread; delete m_workspaceThread; + delete m_windowLayoutThread; delete m_layerStyleCollectionThread; delete m_paintOpPresetServer; delete m_workspaceServer; + delete m_windowLayoutServer; delete m_layerStyleCollectionServer; } KisResourceServerProvider* KisResourceServerProvider::instance() { return s_instance; } KoResourceServer *KisResourceServerProvider::resourceBundleServer() { if (!m_resourceBundleServer) { m_resourceBundleServer = new KoResourceServerSimpleConstruction("kis_resourcebundles", "*.bundle"); KoResourceLoaderThread bundleLoader(m_resourceBundleServer); bundleLoader.loadSynchronously(); Q_FOREACH (KisResourceBundle *bundle, m_resourceBundleServer->resources()) { if (!bundle->install()) { warnKrita << "Could not install resources for bundle" << bundle->name(); } } } return m_resourceBundleServer; } KisPaintOpPresetResourceServer* KisResourceServerProvider::paintOpPresetServer(bool block) { if (block) m_paintOpPresetThread->barrier(); return m_paintOpPresetServer; } KoResourceServer< KisWorkspaceResource >* KisResourceServerProvider::workspaceServer(bool block) { - if (block) m_workspaceThread->barrier(); return m_workspaceServer; } +KoResourceServer< KisWindowLayoutResource >* KisResourceServerProvider::windowLayoutServer(bool block) +{ + if (block) m_windowLayoutThread->barrier(); + return m_windowLayoutServer; +} + KoResourceServer *KisResourceServerProvider::layerStyleCollectionServer(bool block) { if (block) m_layerStyleCollectionThread->barrier(); return m_layerStyleCollectionServer; } void KisResourceServerProvider::brushBlacklistCleanup() { emit notifyBrushBlacklistCleanup(); } diff --git a/libs/ui/kis_resource_server_provider.h b/libs/ui/kis_resource_server_provider.h index a8b168eab7..07df631830 100644 --- a/libs/ui/kis_resource_server_provider.h +++ b/libs/ui/kis_resource_server_provider.h @@ -1,79 +1,83 @@ /* * kis_resource_server_provider.h - part of KImageShop * * Copyright (c) 1999 Matthias Elter * Copyright (c) 2003 Patrick Julien * Copyright (c) 2005 Sven Langkamp * Copyright (c) 2003-2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_RESOURCESERVERPROVIDER_H_ #define KIS_RESOURCESERVERPROVIDER_H_ #include #include #include #include "KisResourceBundle.h" #include "kritaui_export.h" +#include "KisWindowLayoutResource.h" class KoResourceLoaderThread; class KisWorkspaceResource; class KisPSDLayerStyleCollectionResource; typedef KoResourceServerSimpleConstruction > KisPaintOpPresetResourceServer; typedef KoResourceServerAdapter > KisPaintOpPresetResourceServerAdapter; class KRITAUI_EXPORT KisResourceServerProvider : public QObject { Q_OBJECT public: KisResourceServerProvider(); ~KisResourceServerProvider() override; static KisResourceServerProvider* instance(); KoResourceServer *resourceBundleServer(); KisPaintOpPresetResourceServer* paintOpPresetServer(bool block = true); KoResourceServer* workspaceServer(bool block = true); + KoResourceServer* windowLayoutServer(bool block = true); KoResourceServer* layerStyleCollectionServer(bool block = true); void brushBlacklistCleanup(); Q_SIGNALS: void notifyBrushBlacklistCleanup(); private: KisResourceServerProvider(const KisResourceServerProvider&); KisResourceServerProvider operator=(const KisResourceServerProvider&); KisPaintOpPresetResourceServer *m_paintOpPresetServer; KoResourceServer *m_workspaceServer; + KoResourceServer *m_windowLayoutServer; KoResourceServer *m_layerStyleCollectionServer; KoResourceServer *m_resourceBundleServer; private: KoResourceLoaderThread *m_paintOpPresetThread; KoResourceLoaderThread *m_workspaceThread; + KoResourceLoaderThread *m_windowLayoutThread; KoResourceLoaderThread *m_layerStyleCollectionThread; }; #endif // KIS_RESOURCESERVERPROVIDER_H_ diff --git a/libs/ui/tests/kis_derived_resources_test.cpp b/libs/ui/tests/kis_derived_resources_test.cpp index 759b57b7c5..81381ae948 100644 --- a/libs/ui/tests/kis_derived_resources_test.cpp +++ b/libs/ui/tests/kis_derived_resources_test.cpp @@ -1,143 +1,144 @@ /* * Copyright (c) 2016 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_derived_resources_test.h" #include #include #include #include #include "kis_canvas_resource_provider.h" #include #include #include #include #include #include #include #include #include "testutil.h" void addResourceTypes() { // All Krita's resource types KoResourcePaths::addResourceType("kis_pics", "data", "/pics/"); KoResourcePaths::addResourceType("kis_images", "data", "/images/"); KoResourcePaths::addResourceType("icc_profiles", "data", "/profiles/"); KoResourcePaths::addResourceType("metadata_schema", "data", "/metadata/schemas/"); KoResourcePaths::addResourceType("kis_brushes", "data", "/brushes/"); KoResourcePaths::addResourceType("kis_taskset", "data", "/taskset/"); KoResourcePaths::addResourceType("kis_taskset", "data", "/taskset/"); KoResourcePaths::addResourceType("gmic_definitions", "data", "/gmic/"); KoResourcePaths::addResourceType("kis_resourcebundles", "data", "/bundles/"); KoResourcePaths::addResourceType("kis_defaultpresets", "data", "/defaultpresets/"); KoResourcePaths::addResourceType("kis_paintoppresets", "data", "/paintoppresets/"); KoResourcePaths::addResourceType("kis_workspaces", "data", "/workspaces/"); + KoResourcePaths::addResourceType("kis_windowlayouts", "data", "/windowlayouts/"); KoResourcePaths::addResourceType("psd_layer_style_collections", "data", "/asl"); KoResourcePaths::addResourceType("ko_patterns", "data", "/patterns/", true); KoResourcePaths::addResourceType("ko_gradients", "data", "/gradients/"); KoResourcePaths::addResourceType("ko_gradients", "data", "/gradients/", true); KoResourcePaths::addResourceType("ko_palettes", "data", "/palettes/", true); KoResourcePaths::addResourceType("kis_shortcuts", "data", "/shortcuts/"); KoResourcePaths::addResourceType("kis_actions", "data", "/actions"); KoResourcePaths::addResourceType("icc_profiles", "data", "/color/icc"); KoResourcePaths::addResourceType("ko_effects", "data", "/effects/"); KoResourcePaths::addResourceType("tags", "data", "/tags/"); } void KisDerivedResourcesTest::test() { KisDocument* doc = createEmptyDocument(); addResourceTypes(); KisMainWindow* mainWindow = KisPart::instance()->createMainWindow(); QPointer view = new KisView(doc, mainWindow->resourceManager(), mainWindow->actionCollection(), mainWindow); KisViewManager *viewManager = new KisViewManager(mainWindow, mainWindow->actionCollection()); KoCanvasResourceManager *manager = viewManager->resourceProvider()->resourceManager(); QApplication::processEvents(); QString presetFileName = "autobrush_300px.kpp"; QVariant i; KisPaintOpPresetSP preset; if (!presetFileName.isEmpty()) { QString fullFileName = TestUtil::fetchDataFileLazy(presetFileName); preset = new KisPaintOpPreset(fullFileName); bool presetValid = preset->load(); Q_ASSERT(presetValid); Q_UNUSED(presetValid); i.setValue(preset); } QVERIFY(i.isValid()); QSignalSpy spy(manager, SIGNAL(canvasResourceChanged(int, const QVariant &))); manager->setResource(KisCanvasResourceProvider::CurrentPaintOpPreset, i); QCOMPARE(spy[0][0].toInt(), (int)KisCanvasResourceProvider::CurrentPaintOpPreset); QCOMPARE(spy[0][1].value(), preset); QCOMPARE(spy[1][0].toInt(), (int)KisCanvasResourceProvider::EraserMode); QCOMPARE(spy[1][1].toBool(), false); QCOMPARE(spy[2][0].toInt(), (int)KisCanvasResourceProvider::LodAvailability); QCOMPARE(spy[2][1].toBool(), true); QCOMPARE(spy[3][0].toInt(), (int)KisCanvasResourceProvider::Size); QCOMPARE(spy[3][1].toDouble(), 1.0); QCOMPARE(spy[4][0].toInt(), (int)KisCanvasResourceProvider::Flow); QCOMPARE(spy[4][1].toDouble(), 1.0); QCOMPARE(spy[5][0].toInt(), (int)KisCanvasResourceProvider::Opacity); QCOMPARE(spy[5][1].toDouble(), 1.0); QCOMPARE(spy[6][0].toInt(), (int)KisCanvasResourceProvider::CurrentEffectiveCompositeOp); QCOMPARE(spy[6][1].toString(), COMPOSITE_OVER); spy.clear(); preset->settings()->setPaintOpOpacity(0.8); QCOMPARE(spy.size(), 1); QCOMPARE(spy[0][0].toInt(), (int)KisCanvasResourceProvider::Opacity); QCOMPARE(spy[0][1].toDouble(), 0.8); spy.clear(); mainWindow->hide(); QApplication::processEvents(); delete view; delete doc; delete mainWindow; } QTEST_MAIN(KisDerivedResourcesTest) diff --git a/libs/ui/widgets/kis_workspace_chooser.cpp b/libs/ui/widgets/kis_workspace_chooser.cpp index 9144af8f0a..318194aa04 100644 --- a/libs/ui/widgets/kis_workspace_chooser.cpp +++ b/libs/ui/widgets/kis_workspace_chooser.cpp @@ -1,173 +1,239 @@ /* This file is part of the KDE project * Copyright (C) 2011 Sven Langkamp * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_workspace_chooser.h" #include #include #include #include #include +#include +#include +#include #include #include #include #include -#include #include -#include #include "kis_resource_server_provider.h" #include "kis_workspace_resource.h" #include "KisViewManager.h" -#include -#include #include +#include +#include class KisWorkspaceDelegate : public QAbstractItemDelegate { public: KisWorkspaceDelegate(QObject * parent = 0) : QAbstractItemDelegate(parent) {} ~KisWorkspaceDelegate() override {} /// reimplemented void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const override; /// reimplemented QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex &) const override { return option.decorationSize; } }; void KisWorkspaceDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { if (!index.isValid()) return; - KisWorkspaceResource* workspace = static_cast(index.internalPointer()); + KoResource* workspace = static_cast(index.internalPointer()); QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled) ? QPalette::Active : QPalette::Disabled; QPalette::ColorRole cr = (option.state & QStyle::State_Selected) ? QPalette::HighlightedText : QPalette::Text; painter->setPen(option.palette.color(cg, cr)); if (option.state & QStyle::State_Selected) { painter->fillRect(option.rect, option.palette.highlight()); } else { painter->fillRect(option.rect, option.palette.base()); } painter->drawText(option.rect.x() + 5, option.rect.y() + painter->fontMetrics().ascent() + 5, workspace->name()); } KisWorkspaceChooser::KisWorkspaceChooser(KisViewManager * view, QWidget* parent): QWidget(parent), m_view(view) { - KoResourceServer * rserver = KisResourceServerProvider::instance()->workspaceServer(false); - QSharedPointer adapter(new KoResourceServerAdapter(rserver)); - m_itemChooser = new KoResourceItemChooser(adapter, this); - m_itemChooser->setItemDelegate(new KisWorkspaceDelegate(this)); - m_itemChooser->setFixedSize(250, 250); - m_itemChooser->setRowHeight(30); - m_itemChooser->setColumnCount(1); - m_itemChooser->showTaggingBar(false); - connect(m_itemChooser, SIGNAL(resourceSelected(KoResource*)), - this, SLOT(resourceSelected(KoResource*))); - - QPushButton* saveButton = new QPushButton(i18n("Save")); - connect(saveButton, SIGNAL(clicked(bool)), this, SLOT(slotSave())); - - m_nameEdit = new QLineEdit(this); - m_nameEdit->setPlaceholderText(i18n("Insert name")); - m_nameEdit->setClearButtonEnabled(true); - - QGridLayout* layout = new QGridLayout(this); - layout->addWidget(m_itemChooser, 0, 0, 1, 2); - layout->addWidget(m_nameEdit, 1, 0, 1, 1); - layout->addWidget(saveButton, 1, 1, 1, 1); + KoResourceServer * workspaceServer = KisResourceServerProvider::instance()->workspaceServer(false); + QSharedPointer workspaceAdapter(new KoResourceServerAdapter(workspaceServer)); + + KoResourceServer * windowLayoutServer = KisResourceServerProvider::instance()->windowLayoutServer(false); + QSharedPointer windowLayoutAdapter(new KoResourceServerAdapter(windowLayoutServer)); + + m_layout = new QGridLayout(this); + + m_workspaceWidgets = createChooserWidgets(workspaceAdapter, i18n("Workspaces")); + m_windowLayoutWidgets = createChooserWidgets(windowLayoutAdapter, i18n("Window layouts")); + + connect(m_workspaceWidgets.itemChooser, SIGNAL(resourceSelected(KoResource*)), + this, SLOT(workspaceSelected(KoResource*))); + connect(m_workspaceWidgets.saveButton, SIGNAL(clicked(bool)), this, SLOT(slotSaveWorkspace())); + + connect(m_windowLayoutWidgets.itemChooser, SIGNAL(resourceSelected(KoResource*)), + this, SLOT(windowLayoutSelected(KoResource*))); + connect(m_windowLayoutWidgets.saveButton, SIGNAL(clicked(bool)), this, SLOT(slotSaveWindowLayout())); +} + +KisWorkspaceChooser::ChooserWidgets KisWorkspaceChooser::createChooserWidgets(QSharedPointer adapter, const QString &title) +{ + ChooserWidgets widgets; + + QLabel *titleLabel = new QLabel(this); + QFont titleFont; + titleFont.setBold(true); + titleLabel->setFont(titleFont); + titleLabel->setText(title); + + widgets.itemChooser = new KoResourceItemChooser(adapter, this); + widgets.itemChooser->setItemDelegate(new KisWorkspaceDelegate(this)); + widgets.itemChooser->setFixedSize(250, 250); + widgets.itemChooser->setRowHeight(30); + widgets.itemChooser->setColumnCount(1); + widgets.itemChooser->showTaggingBar(false); + widgets.saveButton = new QPushButton(i18n("Save")); + + widgets.nameEdit = new QLineEdit(this); + widgets.nameEdit->setPlaceholderText(i18n("Insert name")); + widgets.nameEdit->setClearButtonEnabled(true); + + int firstRow = m_layout->rowCount(); + m_layout->addWidget(titleLabel, firstRow, 0, 1, 2); + m_layout->addWidget(widgets.itemChooser, firstRow + 1, 0, 1, 2); + m_layout->addWidget(widgets.nameEdit, firstRow + 2, 0, 1, 1); + m_layout->addWidget(widgets.saveButton, firstRow + 2, 1, 1, 1); + + return widgets; } KisWorkspaceChooser::~KisWorkspaceChooser() { } -void KisWorkspaceChooser::slotSave() +void KisWorkspaceChooser::slotSaveWorkspace() { if (!m_view->qtMainWindow()) { return; } + KoResourceServer * rserver = KisResourceServerProvider::instance()->workspaceServer(); KisWorkspaceResource* workspace = new KisWorkspaceResource(QString()); workspace->setDockerState(m_view->qtMainWindow()->saveState()); m_view->resourceProvider()->notifySavingWorkspace(workspace); workspace->setValid(true); QString saveLocation = rserver->saveLocation(); - QString name = m_nameEdit->text(); + QString name = m_workspaceWidgets.nameEdit->text(); bool newName = false; if(name.isEmpty()) { newName = true; name = i18n("Workspace"); } QFileInfo fileInfo(saveLocation + name + workspace->defaultFileExtension()); int i = 1; while (fileInfo.exists()) { fileInfo.setFile(saveLocation + name + QString("%1").arg(i) + workspace->defaultFileExtension()); i++; } workspace->setFilename(fileInfo.filePath()); if(newName) { name = i18n("Workspace %1", i); } workspace->setName(name); rserver->addResource(workspace); } -void KisWorkspaceChooser::resourceSelected(KoResource* resource) +void KisWorkspaceChooser::workspaceSelected(KoResource *resource) { if (!m_view->qtMainWindow()) { return; } KisWorkspaceResource* workspace = static_cast(resource); QMap dockWidgetMap; Q_FOREACH (QDockWidget *docker, m_view->mainWindow()->dockWidgets()) { dockWidgetMap[docker] = docker->property("Locked").toBool(); } KisMainWindow *mainWindow = qobject_cast(m_view->qtMainWindow()); mainWindow->restoreWorkspace(workspace->dockerState()); m_view->resourceProvider()->notifyLoadingWorkspace(workspace); Q_FOREACH (QDockWidget *docker, dockWidgetMap.keys()) { if (docker->isVisible()) { docker->setProperty("Locked", dockWidgetMap[docker]); docker->updateGeometry(); } else { docker->setProperty("Locked", false); // Unlock invisible dockers docker->toggleViewAction()->setEnabled(true); } } } + +void KisWorkspaceChooser::slotSaveWindowLayout() +{ + QString name = m_windowLayoutWidgets.nameEdit->text(); + auto *layout = KisWindowLayoutResource::fromCurrentWindows(name, KisPart::instance()->mainWindows()); + + layout->setValid(true); + + KoResourceServer * rserver = KisResourceServerProvider::instance()->windowLayoutServer(); + QString saveLocation = rserver->saveLocation(); + + bool newName = false; + if (name.isEmpty()) { + newName = true; + name = i18n("Window Layout"); + } + QFileInfo fileInfo(saveLocation + name + layout->defaultFileExtension()); + + int i = 1; + while (fileInfo.exists()) { + fileInfo.setFile(saveLocation + name + QString("%1").arg(i) + layout->defaultFileExtension()); + i++; + } + layout->setFilename(fileInfo.filePath()); + + if (newName) { + name = i18n("Window Layout %1", i); + } + layout->setName(name); + rserver->addResource(layout); +} + +void KisWorkspaceChooser::windowLayoutSelected(KoResource * resource) +{ + auto *layout = static_cast(resource); + layout->applyLayout(); +} diff --git a/libs/ui/widgets/kis_workspace_chooser.h b/libs/ui/widgets/kis_workspace_chooser.h index 3582b13d2a..645b5001cc 100644 --- a/libs/ui/widgets/kis_workspace_chooser.h +++ b/libs/ui/widgets/kis_workspace_chooser.h @@ -1,48 +1,65 @@ /* This file is part of the KDE project * Copyright (C) 2011 Sven Langkamp * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KIS_WORKSPACE_CHOOSER_H #define KIS_WORKSPACE_CHOOSER_H #include class QLineEdit; +class QPushButton; +class QGridLayout; class KoResourceItemChooser; class KisViewManager; class KoResource; +class KoAbstractResourceServerAdapter; class KisWorkspaceChooser : public QWidget { Q_OBJECT public: KisWorkspaceChooser(KisViewManager * view, QWidget* parent = 0); ~KisWorkspaceChooser() override; private Q_SLOTS: - void slotSave(); - void resourceSelected( KoResource * resource ); - + void slotSaveWorkspace(); + void workspaceSelected( KoResource * resource ); + + void slotSaveWindowLayout(); + void windowLayoutSelected( KoResource * resource ); + private: - KoResourceItemChooser * m_itemChooser; - KisViewManager* m_view; - QLineEdit* m_nameEdit; + struct ChooserWidgets + { + KoResourceItemChooser *itemChooser; + QLineEdit *nameEdit; + QPushButton *saveButton; + }; + + KisViewManager *m_view; + + QGridLayout* m_layout; + ChooserWidgets m_workspaceWidgets; + ChooserWidgets m_windowLayoutWidgets; + + ChooserWidgets createChooserWidgets(QSharedPointer adapter, const QString &title); }; #endif // KIS_WORKSPACE_CHOOSER_H