diff --git a/krita/krita.rc b/krita/krita.rc index 6f4433ddf5f..10504850b9d 100644 --- a/krita/krita.rc +++ b/krita/krita.rc @@ -1,197 +1,198 @@ - + &File &Edit &Resources + &View Grid Spacing &Image &Layer New &Select Filte&r &Tools Settings Brushes and Stuff diff --git a/krita/plugins/paintops/libbrush/kis_brush_server.cpp b/krita/plugins/paintops/libbrush/kis_brush_server.cpp index bf8adfeabb6..559df2d1db3 100644 --- a/krita/plugins/paintops/libbrush/kis_brush_server.cpp +++ b/krita/plugins/paintops/libbrush/kis_brush_server.cpp @@ -1,169 +1,178 @@ /* * Copyright (c) 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. */ #include "kis_brush_server.h" #include #include #include #include #include #include #include #include #include "kis_abr_brush.h" #include "kis_abr_brush_collection.h" #include "kis_gbr_brush.h" #include "kis_imagepipe_brush.h" #include "kis_png_brush.h" #include "kis_svg_brush.h" +#include class BrushResourceServer : public KoResourceServer, public KoResourceServerObserver { public: BrushResourceServer() : KoResourceServer("kis_brushes", "*.gbr:*.gih:*.abr:*.png:*.svg", false) { addObserver(this, true); } ~BrushResourceServer() { foreach(KisBrush* brush, m_brushes) { removeResourceFromServer(brush); } } virtual void resourceAdded(KisBrush* brush) { // Hack: This prevents the deletion of brushes in the resource server // Brushes outside the server use shared pointer, but not inside the server brush->ref(); m_brushes.append(brush); } ///Reimplemented virtual void removingResource(KisBrush* brush) { if(!brush->deref()) { delete brush; } m_brushes.removeAll(brush); } virtual void resourceChanged(KisBrush* resource) { Q_UNUSED(resource); } ///Reimplemented virtual void importResourceFile(const QString& filename, bool fileCreation = true) { QFileInfo fi( filename ); if( fi.exists() == false ) return; if( fi.suffix().toLower() == "abr") { if(fileCreation) { QFile::copy(filename, saveLocation() + fi.fileName()); } QList collectionResources = createResources( filename ); foreach(KisBrush* brush, collectionResources) { addResource(brush); } } else { KoResourceServer::importResourceFile(filename, fileCreation); } } private: ///Reimplemented virtual QList createResources( const QString & filename ) { QList brushes; QString fileExtension = QFileInfo(filename).suffix().toLower(); if(fileExtension == "abr") { KisAbrBrushCollection collection(filename); collection.load(); foreach(KisAbrBrush* abrBrush, collection.brushes()) { brushes.append(abrBrush); } } else { brushes.append(createResource(filename)); } return brushes; } ///Reimplemented virtual KisBrush* createResource(const QString & filename) { QString fileExtension = QFileInfo(filename).suffix().toLower(); KisBrush* brush = 0; if (fileExtension == "gbr") { brush = new KisGbrBrush(filename); } else if (fileExtension == "gih") { brush = new KisImagePipeBrush(filename); } else if (fileExtension == "png") { brush = new KisPngBrush(filename); } else if (fileExtension == "svg") { brush = new KisSvgBrush(filename); } return brush; } QList m_brushes; }; KisBrushServer::KisBrushServer() { KGlobal::mainComponent().dirs()->addResourceType("kis_brushes", "data", "krita/brushes/"); KGlobal::mainComponent().dirs()->addResourceDir("kis_brushes", "/usr/share/create/brushes/gimp"); KGlobal::mainComponent().dirs()->addResourceDir("kis_brushes", QDir::homePath() + QString("/.create/brushes/gimp")); m_brushServer = new BrushResourceServer(); m_brushThread = new KoResourceLoaderThread(m_brushServer); m_brushThread->start(); + + connect(KisResourceServerProvider::instance(), SIGNAL(notifyBrushBlacklistCleanup()), + this, SLOT(slotRemoveBlacklistedResources())); } KisBrushServer::~KisBrushServer() { dbgRegistry << "deleting KisBrushServer"; delete m_brushThread; delete m_brushServer; } KisBrushServer* KisBrushServer::instance() { K_GLOBAL_STATIC(KisBrushServer, s_instance); return s_instance; } KoResourceServer* KisBrushServer::brushServer() { m_brushThread->barrier(); return m_brushServer; } +void KisBrushServer::slotRemoveBlacklistedResources() +{ + m_brushServer->removeBlackListedFiles(); +} + #include "kis_brush_server.moc" diff --git a/krita/plugins/paintops/libbrush/kis_brush_server.h b/krita/plugins/paintops/libbrush/kis_brush_server.h index 48c013c2c3c..59eb6303573 100644 --- a/krita/plugins/paintops/libbrush/kis_brush_server.h +++ b/krita/plugins/paintops/libbrush/kis_brush_server.h @@ -1,60 +1,63 @@ /* * Copyright (c) 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_BRUSH_SERVER_H #define KIS_BRUSH_SERVER_H #include #include #include #include #include "krita_export.h" #include "kis_brush.h" class KoResource; class KoResourceLoaderThread; /** * */ class BRUSH_EXPORT KisBrushServer : public QObject { Q_OBJECT public: virtual ~KisBrushServer(); KoResourceServer* brushServer(); static KisBrushServer* instance(); +private slots: + void slotRemoveBlacklistedResources(); + private: KisBrushServer(); KisBrushServer(const KisBrushServer&); KisBrushServer operator=(const KisBrushServer&); KoResourceServer* m_brushServer; private: KoResourceLoaderThread *m_brushThread; }; #endif diff --git a/krita/ui/CMakeLists.txt b/krita/ui/CMakeLists.txt index 2bf86daff42..cc2efc8968b 100644 --- a/krita/ui/CMakeLists.txt +++ b/krita/ui/CMakeLists.txt @@ -1,330 +1,332 @@ include_directories( ${KOTEXT_INCLUDES} ${TEXTLAYOUT_INCLUDES} ${CMAKE_SOURCE_DIR}/libs/pigment/colorprofiles ${CMAKE_CURRENT_SOURCE_DIR}/flake ${CMAKE_CURRENT_SOURCE_DIR}/pigment/resources ${CMAKE_CURRENT_SOURCE_DIR}/widgets/resources ${CMAKE_CURRENT_SOURCE_DIR}/openrastertk ${CMAKE_SOURCE_DIR}/krita/image/metadata ${EXIV2_INCLUDE_DIR} ) add_subdirectory( tests ) configure_file(config-processor.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-processor.h ) include(kdefx.cmake) set(kritaui_LIB_SRCS canvas/kis_canvas_widget_base.cpp canvas/kis_canvas2.cpp canvas/kis_canvas_controller.cpp canvas/kis_display_filter.cpp canvas/kis_tool_proxy.cpp canvas/kis_canvas_decoration.cc canvas/kis_coordinates_converter.cpp canvas/kis_grid_manager.cpp canvas/kis_grid_painter_configuration.cpp canvas/kis_perspective_grid_manager.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 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_image_properties.cc dialogs/kis_dlg_layer_properties.cc dialogs/kis_dlg_preferences.cc + dialogs/kis_dlg_blacklist_cleanup.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 kis_autogradient.cc kis_autogradient_resource.cc kis_bookmarked_configurations_editor.cc kis_bookmarked_configurations_model.cc kis_bookmarked_filter_configurations_model.cc kis_canvas_resource_provider.cpp kis_categorized_item_delegate.cpp kis_clipboard.cc kis_config.cc kis_config_notifier.cpp kis_color_data_list.cpp kis_control_frame.cpp kis_composite_ops_model.cc kis_paint_ops_model.cpp kis_cursor.cc kis_custom_palette.cc kis_custom_pattern.cc kis_doc2.cc kis_part2.cpp kis_factory2.cc kis_filter_handler.cc 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_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_manager.cc kis_paintop_box.cc kis_palette_manager.cpp kis_popup_palette.cpp kis_png_converter.cpp kis_preference_set_registry.cpp kis_print_job.cpp kis_resource_server_provider.cpp kis_selection_decoration.cc kis_selection_manager.cc kis_statusbar.cc kis_view2.cpp kis_zoom_manager.cc ko_favorite_resource_manager.cpp kis_workspace_resource.cpp kis_mirror_visitor.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_image_textures.cpp opengl/kis_texture_tile.cpp openrastertk/kis_open_raster_stack_load_visitor.cpp openrastertk/kis_open_raster_stack_save_visitor.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_shape_tool_helper.cpp tool/kis_tool.cc tool/kis_tool_freehand.cc tool/kis_painting_information_builder.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_select_base.cpp tool/kis_tool_ellipse_base.cpp tool/kis_tool_rectangle_base.cpp tool/kis_tool_polyline_base.cpp tool/kis_color_picker_utils.cpp tool/kis_resources_snapshot.cpp tool/strokes/freehand_stroke.cpp tool/strokes/kis_painter_based_stroke_strategy.cpp widgets/kis_channelflags_widget.cpp widgets/kis_cmb_composite.cc widgets/kis_paintop_list_widget.cpp widgets/kis_cmb_idlist.cc widgets/kis_color_space_selector.cc widgets/kis_curve_widget.cpp widgets/kis_custom_image_widget.cc 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_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_tree_view_popup.cc widgets/kis_slider_spin_box.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_light_source.cpp # widgets/kis_light_stage.cpp input/kis_input_manager.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_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 kis_ui_action_factory.cpp kis_ui_action_factory_registry.cpp actions/kis_selection_action_factories.cpp ) if(HAVE_OPENGL) if(HAVE_GLEW) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} opengl/kis_opengl_shader.cpp opengl/kis_opengl_fragment_shader.cpp opengl/kis_opengl_vertex_shader.cpp opengl/kis_opengl_program.cpp opengl/kis_opengl_gradient_program.cpp ) endif(HAVE_GLEW) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} kis_3d_object_model.cpp ) endif(HAVE_OPENGL) add_definitions(${KDE4_ENABLE_EXCEPTIONS}) kde4_add_ui_files(kritaui_LIB_SRCS forms/wdgfullscreensettings.ui forms/wdgautogradient.ui forms/wdggeneralsettings.ui forms/wdgperformancesettings.ui forms/wdggridsettings.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/wdgdisplaysettings.ui forms/kis_previewwidgetbase.ui forms/kis_matrix_widget.ui forms/wdgselectionoptions.ui forms/wdgshapeoptions.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/wdgfilterselector.ui forms/wdgfilternodecreation.ui forms/wdgpaintactioneditor.ui forms/wdgmultipliersdoublesliderspinbox.ui forms/wdgnodequerypatheditor.ui forms/wdgpresetselectorstrip.ui + forms/wdgdlgblacklistcleanup.ui ) kde4_add_library(kritaui SHARED ${kritaui_LIB_SRCS} ) target_link_libraries(kritaui ${X11_X11_LIB}) if(GHNS) target_link_libraries(kritaui ${KDE4_THREADWEAVER_LIBRARIES} ${KDE4_KFILE_LIBRARY} kritaimage komain kowidgets ${PNG_LIBRARIES} ${EXIV2_LIBRARIES} ${KDE4_KNEWSTUFF3_LIBS}) else(GHNS) target_link_libraries(kritaui ${KDE4_THREADWEAVER_LIBRARIES} ${KDE4_KFILE_LIBRARY} kritaimage komain kowidgets ${PNG_LIBRARIES} ${EXIV2_LIBRARIES}) endif (GHNS) if(HAVE_OPENGL) target_link_libraries(kritaui ${OPENGL_LIBRARIES} ${QT_QTOPENGL_LIBRARY} ${OPENEXR_LIBRARIES}) set (GL_INTERFACE_LIBRARIES ";${OPENGL_LIBRARIES};${QT_QTOPENGL_LIBRARY}") if(HAVE_GLEW) target_link_libraries(kritaui ${GLEW_LIBRARIES}) endif(HAVE_GLEW) endif(HAVE_OPENGL) target_link_libraries(kritaui LINK_INTERFACE_LIBRARIES kritaimage komain ${GL_INTERFACE_LIBRARIES} ) set_target_properties(kritaui PROPERTIES VERSION ${GENERIC_CALLIGRA_LIB_VERSION} SOVERSION ${GENERIC_CALLIGRA_LIB_SOVERSION} ) install(TARGETS kritaui ${INSTALL_TARGETS_DEFAULT_ARGS}) ########### install files ############### install( FILES canvas/kis_canvas2.h canvas/kis_canvas_decoration.h canvas/kis_coordinates_converter.h tool/kis_tool.h kis_cursor.h kis_view2.h kis_ui_types.h # kis_cmb_composite.h # kis_cmb_idlist.h # kis_color_cup.h # kis_config.h # kis_double_click_event.h # kis_double_widget.h # kis_filter_manager.h # kis_gradient_chooser.h # kis_gradient_slider_widget.h # kis_histogram_view.h # kis_icon_item.h # kis_iconwidget.h # kis_itemchooser.h # kis_label_zoom.h # kis_move_event.h widgets/kis_multi_bool_filter_widget.h widgets/kis_multi_double_filter_widget.h widgets/kis_multi_integer_filter_widget.h # kis_paintop_box.h # kis_previewwidget.h # kis_tool_non_paint.h # kis_tool_paint.h # kis_tool_freehand.h # kis_tool_dummy.h # kis_tool_manager.h # kis_tool_types.h # KoInputDevice.h # canvas/kis_perspective_grid_manager.h DESTINATION ${INCLUDE_INSTALL_DIR}) diff --git a/krita/ui/dialogs/kis_dlg_blacklist_cleanup.cpp b/krita/ui/dialogs/kis_dlg_blacklist_cleanup.cpp new file mode 100644 index 00000000000..e4e4693683d --- /dev/null +++ b/krita/ui/dialogs/kis_dlg_blacklist_cleanup.cpp @@ -0,0 +1,60 @@ +/* + * + * Copyright (c) 2012 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_dlg_blacklist_cleanup.h" +#include + +#include +#include + +KisDlgBlacklistCleanup::KisDlgBlacklistCleanup() +{ + setCaption(i18n("Cleanup resource files")); + setButtons(Ok | Cancel); + setDefaultButton(Ok); + + QWidget* page = new QWidget(this); + setupUi(page); + setMainWidget(page); + labelWarning->setPixmap(koIcon("dialog-warning").pixmap(32, 32)); +} + +void KisDlgBlacklistCleanup::accept() +{ + QDialog::accept(); + if (cbRemovePresets->isChecked()) { + KisResourceServerProvider::instance()->paintOpPresetServer()->removeBlackListedFiles(); + } + if (cbRemoveBrushes->isChecked()) { + KisResourceServerProvider::instance()->brushBlacklistCleanup(); + } + if (cbRemoveWorkspaces->isChecked()) { + KisResourceServerProvider::instance()->workspaceServer()->removeBlackListedFiles(); + } + if (cbRemoveColorsets->isChecked()) { + KoResourceServerProvider::instance()->paletteServer()->removeBlackListedFiles(); + } + if (cbRemoveGradients->isChecked()) { + KoResourceServerProvider::instance()->gradientServer()->removeBlackListedFiles(); + } + if (cbRemovePattern->isChecked()) { + KoResourceServerProvider::instance()->patternServer()->removeBlackListedFiles(); + } +} + diff --git a/krita/plugins/paintops/libbrush/kis_brush_server.h b/krita/ui/dialogs/kis_dlg_blacklist_cleanup.h similarity index 51% copy from krita/plugins/paintops/libbrush/kis_brush_server.h copy to krita/ui/dialogs/kis_dlg_blacklist_cleanup.h index 48c013c2c3c..b2f5b428191 100644 --- a/krita/plugins/paintops/libbrush/kis_brush_server.h +++ b/krita/ui/dialogs/kis_dlg_blacklist_cleanup.h @@ -1,60 +1,34 @@ /* - * Copyright (c) 2008 Boudewijn Rempt + * + * Copyright (c) 2012 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef KIS_BRUSH_SERVER_H -#define KIS_BRUSH_SERVER_H - -#include -#include -#include - -#include -#include "krita_export.h" -#include "kis_brush.h" +#ifndef KIS_DLG_BLACKLIST_CLEANUP_H +#define KIS_DLG_BLACKLIST_CLEANUP_H -class KoResource; -class KoResourceLoaderThread; +#include +#include -/** - * - */ -class BRUSH_EXPORT KisBrushServer : public QObject +class KisDlgBlacklistCleanup : public KDialog, public Ui_WdgDisplayBlacklist { - Q_OBJECT - public: - - virtual ~KisBrushServer(); - KoResourceServer* brushServer(); - - static KisBrushServer* instance(); - -private: - - KisBrushServer(); - KisBrushServer(const KisBrushServer&); - KisBrushServer operator=(const KisBrushServer&); - - KoResourceServer* m_brushServer; - -private: - KoResourceLoaderThread *m_brushThread; + KisDlgBlacklistCleanup(); + virtual void accept(); }; -#endif +#endif // KIS_DLG_BLACKLIST_CLEANUP_H diff --git a/krita/ui/forms/wdgdlgblacklistcleanup.ui b/krita/ui/forms/wdgdlgblacklistcleanup.ui new file mode 100644 index 00000000000..4f9e0a0dba6 --- /dev/null +++ b/krita/ui/forms/wdgdlgblacklistcleanup.ui @@ -0,0 +1,125 @@ + + + WdgDisplayBlacklist + + + + 0 + 0 + 457 + 200 + + + + + 0 + 0 + + + + Display + + + + + + Workspaces + + + true + + + + + + + + + + + + + + + + + 400 + 0 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Ubuntu'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Warning</span>: Cleanup will remove resouce files permantently.</p></body></html> + + + Qt::RichText + + + true + + + + + + + + + Use trilinear filtering when zooming. Disabling this may improve painting performance. + + + Gradients + + + true + + + + + + + Pattern + + + true + + + + + + + Presets + + + true + + + + + + + Colorsets + + + true + + + + + + + Brushes + + + true + + + + + + + + + diff --git a/krita/ui/kis_resource_server_provider.cpp b/krita/ui/kis_resource_server_provider.cpp index cdfed90f42d..61896f7c2b8 100644 --- a/krita/ui/kis_resource_server_provider.cpp +++ b/krita/ui/kis_resource_server_provider.cpp @@ -1,103 +1,108 @@ /* * 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 KisResourceServerProvider::KisResourceServerProvider() { KGlobal::mainComponent().dirs()->addResourceType("kis_patterns", "data", "krita/patterns/"); KGlobal::mainComponent().dirs()->addResourceDir("kis_patterns", "/usr/share/create/patterns/gimp"); KGlobal::mainComponent().dirs()->addResourceDir("kis_patterns", QDir::homePath() + QString("/.create/patterns/gimp")); KGlobal::mainComponent().dirs()->addResourceType("kis_paintoppresets", "data", "krita/paintoppresets/"); KGlobal::mainComponent().dirs()->addResourceDir("kis_paintoppresets", QDir::homePath() + QString("/.create/paintoppresets/krita")); KGlobal::mainComponent().dirs()->addResourceType("kis_workspaces", "data", "krita/workspaces/"); m_patternServer = new KoResourceServer("kis_patterns", "*.jpg:*.gif:*.png:*.tif:*.xpm:*.bmp:*.pat"); patternThread = new KoResourceLoaderThread(m_patternServer); patternThread->start(); m_paintOpPresetServer = new KoResourceServer("kis_paintoppresets", "*.kpp"); paintOpPresetThread = new KoResourceLoaderThread(m_paintOpPresetServer); paintOpPresetThread->start(); m_workspaceServer = new KoResourceServer("kis_workspaces", "*.kws"); workspaceThread = new KoResourceLoaderThread(m_workspaceServer); workspaceThread->start(); } KisResourceServerProvider::~KisResourceServerProvider() { dbgRegistry << "deleting KisResourceServerProvider"; delete patternThread; delete paintOpPresetThread; delete workspaceThread; delete m_patternServer; delete m_paintOpPresetServer; delete m_workspaceServer; } KisResourceServerProvider* KisResourceServerProvider::instance() { K_GLOBAL_STATIC(KisResourceServerProvider, s_instance); return s_instance; } KoResourceServer* KisResourceServerProvider::patternServer() { patternThread->barrier(); return m_patternServer; } KoResourceServer* KisResourceServerProvider::paintOpPresetServer() { paintOpPresetThread->barrier(); return m_paintOpPresetServer; } KoResourceServer< KisWorkspaceResource >* KisResourceServerProvider::workspaceServer() { workspaceThread->barrier(); return m_workspaceServer; } +void KisResourceServerProvider::brushBlacklistCleanup() +{ + emit notifyBrushBlacklistCleanup(); +} + #include "kis_resource_server_provider.moc" diff --git a/krita/ui/kis_resource_server_provider.h b/krita/ui/kis_resource_server_provider.h index 508419bb8fb..0c60d96b45e 100644 --- a/krita/ui/kis_resource_server_provider.h +++ b/krita/ui/kis_resource_server_provider.h @@ -1,70 +1,74 @@ /* * 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 #include class KoResource; class KoResourceLoaderThread; class KisPattern; class KisPaintOpPreset; class KisWorkspaceResource; class KRITAUI_EXPORT KisResourceServerProvider : public QObject { Q_OBJECT public: virtual ~KisResourceServerProvider(); static KisResourceServerProvider* instance(); KoResourceServer* patternServer(); KoResourceServer* paintOpPresetServer(); KoResourceServer* workspaceServer(); + void brushBlacklistCleanup(); +signals: + void notifyBrushBlacklistCleanup(); + private: KisResourceServerProvider(); KisResourceServerProvider(const KisResourceServerProvider&); KisResourceServerProvider operator=(const KisResourceServerProvider&); KoResourceServer* m_patternServer; KoResourceServer* m_paintOpPresetServer; KoResourceServer* m_workspaceServer; private: KoResourceLoaderThread *patternThread; KoResourceLoaderThread *paintOpPresetThread; KoResourceLoaderThread *workspaceThread; }; #endif // KIS_RESOURCESERVERPROVIDER_H_ diff --git a/krita/ui/kis_view2.cpp b/krita/ui/kis_view2.cpp index 151ff4276fb..193a4666c92 100644 --- a/krita/ui/kis_view2.cpp +++ b/krita/ui/kis_view2.cpp @@ -1,1291 +1,1303 @@ /* * This file is part of KimageShop^WKrayon^WKrita * * Copyright (c) 1999 Matthias Elter * 1999 Michael Koch * 1999 Carsten Pfeiffer * 2002 Patrick Julien * 2003-2011 Boudewijn Rempt * 2004 Clarence Dang * 2011 José Luis Vergara * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "kis_view2.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KoColorSpaceRegistry.h" #include #include #include #include #include #include #include #include #include #include #include "kis_composite_progress_proxy.h" #include #include "canvas/kis_canvas2.h" #include "canvas/kis_canvas_controller.h" #include "canvas/kis_grid_manager.h" #include "canvas/kis_perspective_grid_manager.h" #include "dialogs/kis_dlg_preferences.h" +#include "dialogs/kis_dlg_blacklist_cleanup.h" #include "kis_canvas_resource_provider.h" #include "kis_config.h" #include "kis_config_notifier.h" #include "kis_control_frame.h" #include "kis_coordinates_converter.h" #include "kis_custom_palette.h" #include "kis_doc2.h" #include "kis_factory2.h" #include "kis_filter_manager.h" #include "kis_group_layer.h" #include "kis_image_manager.h" #include "kis_mask_manager.h" #include "kis_node.h" #include "kis_node_manager.h" #include "kis_painting_assistants_manager.h" #include #include "kis_paintop_box.h" #include "kis_part2.h" #include "kis_print_job.h" #include "kis_progress_widget.h" #include "kis_resource_server_provider.h" #include "kis_selection.h" #include "kis_selection_manager.h" #include "kis_shape_layer.h" #include "kis_statusbar.h" #include "kis_zoom_manager.h" #include "kra/kis_kra_loader.h" #include "widgets/kis_floating_message.h" #include #include #include "kis_paintop_box.h" #include "kis_node_commands_adapter.h" #include #include "ko_favorite_resource_manager.h" #include "kis_paintop_box.h" class BlockingUserInputEventFilter : public QObject { bool eventFilter(QObject *watched, QEvent *event) { Q_UNUSED(watched); if(dynamic_cast(event) || dynamic_cast(event) || dynamic_cast(event)) { return true; } else { return false; } } }; struct KisView2::KisView2Private { public: KisView2Private() : canvas(0) , doc(0) , part(0) , viewConverter(0) , canvasController(0) , resourceProvider(0) , filterManager(0) , statusBar(0) , selectionManager(0) , controlFrame(0) , nodeManager(0) , zoomManager(0) , imageManager(0) , gridManager(0) , perspectiveGridManager(0) , paintingAssistantManager(0) { } ~KisView2Private() { if (canvasController) { KoToolManager::instance()->removeCanvasController(canvasController); } delete canvasController; delete canvas; delete filterManager; delete selectionManager; delete nodeManager; delete zoomManager; delete imageManager; delete gridManager; delete perspectiveGridManager; delete paintingAssistantManager; delete viewConverter; delete statusBar; } public: KisCanvas2 *canvas; KisDoc2 *doc; KisPart2 *part; KisCoordinatesConverter * viewConverter; KisCanvasController * canvasController; KisCanvasResourceProvider * resourceProvider; KisFilterManager * filterManager; KisStatusBar * statusBar; KAction * totalRefresh; KAction* mirrorCanvas; KAction* createTemplate; KAction *saveIncremental; KAction *saveIncrementalBackup; KisSelectionManager *selectionManager; KisControlFrame * controlFrame; KisNodeManager * nodeManager; KisZoomManager * zoomManager; KisImageManager * imageManager; KisGridManager * gridManager; KisPerspectiveGridManager * perspectiveGridManager; KisPaintingAssistantsManager* paintingAssistantManager; BlockingUserInputEventFilter blockingEventFilter; }; KisView2::KisView2(KisPart2 *part, KisDoc2 * doc, QWidget * parent) : KoView(part, doc, parent), m_d(new KisView2Private()) { setXMLFile("krita.rc"); setFocusPolicy(Qt::NoFocus); if (mainWindow()) { actionCollection()->addAction(KStandardAction::KeyBindings, "keybindings", mainWindow()->guiFactory(), SLOT(configureShortcuts())); } m_d->doc = doc; m_d->part = part; m_d->viewConverter = new KisCoordinatesConverter(); KisCanvasController *canvasController = new KisCanvasController(this, actionCollection()); canvasController->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); canvasController->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); canvasController->setDrawShadow(false); canvasController->setCanvasMode(KoCanvasController::Infinite); KisConfig cfg; canvasController->setZoomWithWheel(cfg.zoomWithWheel()); canvasController->setVastScrolling(cfg.vastScrolling()); m_d->canvasController = canvasController; m_d->resourceProvider = new KisCanvasResourceProvider(this); m_d->resourceProvider->resetDisplayProfile(QApplication::desktop()->screenNumber(this)); m_d->canvas = new KisCanvas2(m_d->viewConverter, this, doc->shapeController()); connect(m_d->resourceProvider, SIGNAL(sigDisplayProfileChanged(const KoColorProfile *)), m_d->canvas, SLOT(slotSetDisplayProfile(const KoColorProfile *))); m_d->canvasController->setCanvas(m_d->canvas); m_d->resourceProvider->setResourceManager(m_d->canvas->resourceManager()); createManagers(); createActions(); m_d->controlFrame = new KisControlFrame(this); Q_ASSERT(m_d->canvasController); KoToolManager::instance()->addController(m_d->canvasController); KoToolManager::instance()->registerTools(actionCollection(), m_d->canvasController); // krita/krita.rc must also be modified to add actions to the menu entries m_d->saveIncremental = new KAction(i18n("Save Incremental &Version"), this); m_d->saveIncremental->setShortcut(Qt::Key_F2); actionCollection()->addAction("save_incremental_version", m_d->saveIncremental); connect(m_d->saveIncremental, SIGNAL(triggered()), this, SLOT(slotSaveIncremental())); m_d->saveIncrementalBackup = new KAction(i18n("Save Incremental Backup"), this); m_d->saveIncrementalBackup->setShortcut(Qt::Key_F4); actionCollection()->addAction("save_incremental_backup", m_d->saveIncrementalBackup); connect(m_d->saveIncrementalBackup, SIGNAL(triggered()), this, SLOT(slotSaveIncrementalBackup())); connect(shell(), SIGNAL(documentSaved()), this, SLOT(slotDocumentSaved())); if (koDocument()->localFilePath().isNull()) { m_d->saveIncremental->setEnabled(false); m_d->saveIncrementalBackup->setEnabled(false); } m_d->totalRefresh = new KAction(i18n("Total Refresh"), this); actionCollection()->addAction("total_refresh", m_d->totalRefresh); m_d->totalRefresh->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_R)); connect(m_d->totalRefresh, SIGNAL(triggered()), this, SLOT(slotTotalRefresh())); m_d->createTemplate = new KAction( i18n( "&Create Template From Image..." ), this); actionCollection()->addAction("createTemplate", m_d->createTemplate); connect(m_d->createTemplate, SIGNAL(triggered()), this, SLOT(slotCreateTemplate())); m_d->mirrorCanvas = new KToggleAction(i18n("Mirror View"), this); m_d->mirrorCanvas->setChecked(false); actionCollection()->addAction("mirror_canvas", m_d->mirrorCanvas); m_d->mirrorCanvas->setShortcut(QKeySequence(Qt::Key_M)); connect(m_d->mirrorCanvas, SIGNAL(toggled(bool)),m_d->canvasController, SLOT(mirrorCanvas(bool))); KAction *rotateCanvasRight = new KAction(i18n("Rotate Canvas Right"), this); actionCollection()->addAction("rotate_canvas_right", rotateCanvasRight); rotateCanvasRight->setShortcut(QKeySequence("Ctrl+]")); connect(rotateCanvasRight, SIGNAL(triggered()),m_d->canvasController, SLOT(rotateCanvasRight15())); KAction *rotateCanvasLeft = new KAction(i18n("Rotate Canvas Left"), this); actionCollection()->addAction("rotate_canvas_left", rotateCanvasLeft); rotateCanvasLeft->setShortcut(QKeySequence("Ctrl+[")); connect(rotateCanvasLeft, SIGNAL(triggered()),m_d->canvasController, SLOT(rotateCanvasLeft15())); KAction *resetCanvasTransformations = new KAction(i18n("Reset Canvas Transformations"), this); actionCollection()->addAction("reset_canvas_transformations", resetCanvasTransformations); resetCanvasTransformations->setShortcut(QKeySequence("Ctrl+'")); connect(resetCanvasTransformations, SIGNAL(triggered()),m_d->canvasController, SLOT(resetCanvasTransformations())); KToggleAction *tAction = new KToggleAction(i18n("Show Status Bar"), this); tAction->setCheckedState(KGuiItem(i18n("Hide Status Bar"))); tAction->setChecked(true); tAction->setToolTip(i18n("Shows or hides the status bar")); actionCollection()->addAction("showStatusBar", tAction); connect(tAction, SIGNAL(toggled(bool)), this, SLOT(showStatusBar(bool))); tAction = new KToggleAction(i18n("Show Canvas Only"), this); tAction->setCheckedState(KGuiItem(i18n("Return to Window"))); tAction->setToolTip(i18n("Shows just the canvas or the whole window")); QList shortcuts; shortcuts << QKeySequence(Qt::Key_Tab); tAction->setShortcuts(shortcuts); tAction->setChecked(false); actionCollection()->addAction("view_show_just_the_canvas", tAction); connect(tAction, SIGNAL(toggled(bool)), this, SLOT(showJustTheCanvas(bool))); //Workaround, by default has the same shortcut as mirrorCanvas KAction* action = dynamic_cast(actionCollection()->action("format_italic")); if (action) { action->setShortcut(QKeySequence(), KAction::DefaultShortcut); action->setShortcut(QKeySequence(), KAction::ActiveShortcut); } //Workaround, by default has the same shortcut as hide/show dockers action = dynamic_cast(shell()->actionCollection()->action("view_toggledockers")); if (action) { action->setShortcut(QKeySequence(), KAction::DefaultShortcut); action->setShortcut(QKeySequence(), KAction::ActiveShortcut); } if (shell()) { KoToolBoxFactory toolBoxFactory(m_d->canvasController); shell()->createDockWidget(&toolBoxFactory); connect(canvasController, SIGNAL(toolOptionWidgetsChanged(const QList &)), shell()->dockerManager(), SLOT(newOptionWidgets(const QList &))); shell()->dockerManager()->setIcons(false); } m_d->statusBar = new KisStatusBar(this); connect(m_d->canvasController->proxyObject, SIGNAL(documentMousePositionChanged(const QPointF &)), m_d->statusBar, SLOT(documentMousePositionChanged(const QPointF &))); connect(m_d->nodeManager, SIGNAL(sigNodeActivated(KisNodeSP)), m_d->resourceProvider, SLOT(slotNodeActivated(KisNodeSP))); connect(m_d->nodeManager, SIGNAL(sigNodeActivated(KisNodeSP)), m_d->controlFrame->paintopBox(), SLOT(slotCurrentNodeChanged(KisNodeSP))); connect(m_d->nodeManager, SIGNAL(sigNodeActivated(KisNodeSP)), m_d->doc->image(), SLOT(requestStrokeEnd())); connect(KoToolManager::instance(), SIGNAL(inputDeviceChanged(const KoInputDevice &)), m_d->controlFrame->paintopBox(), SLOT(slotInputDeviceChanged(const KoInputDevice &))); connect(KoToolManager::instance(), SIGNAL(changedTool(KoCanvasController*,int)), m_d->controlFrame->paintopBox(), SLOT(slotToolChanged(KoCanvasController*,int))); // 25 px is a distance that works well for Tablet and Mouse events qApp->setStartDragDistance(25); show(); loadPlugins(); // Wait for the async image to have loaded connect(m_d->doc, SIGNAL(sigLoadingFinished()), this, SLOT(slotLoadingFinished())); if (!m_d->doc->isLoading() || m_d->doc->image()) { slotLoadingFinished(); } connect(m_d->canvasController, SIGNAL(documentSizeChanged()), m_d->zoomManager, SLOT(slotScrollAreaSizeChanged())); setAcceptDrops(true); KConfigGroup group(KGlobal::config(), "krita/shortcuts"); foreach(KActionCollection *collection, KActionCollection::allCollections()) { collection->setConfigGroup("krita/shortcuts"); collection->readSettings(&group); } #if 0 //check for colliding shortcuts QSet existingShortcuts; foreach(QAction* action, actionCollection()->actions()) { if(action->shortcut() == QKeySequence(0)) { continue; } dbgUI << "shortcut " << action->text() << " " << action->shortcut(); Q_ASSERT(!existingShortcuts.contains(action->shortcut())); existingShortcuts.insert(action->shortcut()); } #endif } KisView2::~KisView2() { { KConfigGroup group(KGlobal::config(), "krita/shortcuts"); foreach(KActionCollection *collection, KActionCollection::allCollections()) { collection->setConfigGroup("krita/shortcuts"); collection->writeSettings(&group); } } delete m_d; } void KisView2::dragEnterEvent(QDragEnterEvent *event) { dbgUI << "KisView2::dragEnterEvent"; // Only accept drag if we're not busy, particularly as we may // be showing a progress bar and calling qApp->processEvents(). if (event->mimeData()->hasImage() || event->mimeData()->hasUrls() || event->mimeData()->hasFormat("application/x-krita-node")) { event->accept(); } else { event->ignore(); } } void KisView2::dropEvent(QDropEvent *event) { KisImageSP kisimage = image(); QPointF pos = canvasBase()->coordinatesConverter()->widgetToImage(event->pos()); if (event->mimeData()->hasFormat("application/x-krita-node") || event->mimeData()->hasImage()) { KisNodeSP node; if (event->mimeData()->hasFormat("application/x-krita-node")) { QByteArray ba = event->mimeData()->data("application/x-krita-node"); KisPart2 part; KisDoc2 tempDoc(&part); part.setDocument(&tempDoc); tempDoc.loadNativeFormatFromStore(ba); KisImageWSP tempImage = tempDoc.image(); node = tempImage->rootLayer()->firstChild(); tempImage->removeNode(node); // layers store a link to the image, so update it KisLayer *layer = dynamic_cast(node.data()); if (layer) { layer->setImage(kisimage); } KisShapeLayer *shapeLayer = dynamic_cast(node.data()); if (shapeLayer) { KoShapeContainer * parentContainer = dynamic_cast(m_d->doc->shapeForNode(kisimage->rootLayer())); KisShapeLayer *shapeLayer2 = new KisShapeLayer(parentContainer, m_d->doc->shapeController(), kisimage, node->name(), node->opacity()); QList shapes = shapeLayer->shapes(); shapeLayer->removeAllShapes(); foreach(KoShape *shape, shapes) { shapeLayer2->addShape(shape); } node = shapeLayer2; } } else if (event->mimeData()->hasImage()) { QImage qimage = qvariant_cast(event->mimeData()->imageData()); if (kisimage) { KisPaintDeviceSP device = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb8()); device->convertFromQImage(qimage, 0); node = new KisPaintLayer(kisimage.data(), kisimage->nextLayerName(), OPACITY_OPAQUE_U8, device); } } if (node) { node->setX(pos.x() - node->projection()->exactBounds().width()); node->setY(pos.y() - node->projection()->exactBounds().height()); KisNodeCommandsAdapter adapter(this); if (!m_d->nodeManager->activeLayer()) { adapter.addNode(node, kisimage->rootLayer() , 0); } else { adapter.addNode(node, m_d->nodeManager->activeLayer()->parent(), m_d->nodeManager->activeLayer()); } } return; } if (event->mimeData()->hasUrls()) { QList urls = event->mimeData()->urls(); if (urls.length() > 0) { KMenu popup; popup.setObjectName("drop_popup"); QAction *insertAsNewLayer = new KAction(i18n("Insert as New Layer"), &popup); QAction *insertAsNewLayers = new KAction(i18n("Insert as New Layers"), &popup); QAction *openInNewDocument = new KAction(i18n("Open in New Document"), &popup); QAction *openInNewDocuments = new KAction(i18n("Open in New Documents"), &popup); QAction *replaceCurrentDocument = new KAction(i18n("Replace Current Document"), &popup); QAction *cancel = new KAction(i18n("Cancel"), &popup); if (urls.count() == 1) { if (!image().isNull()) { popup.addAction(insertAsNewLayer); } popup.addAction(openInNewDocument); popup.addAction(replaceCurrentDocument); } else { if (!image().isNull()) { popup.addAction(insertAsNewLayers); } popup.addAction(openInNewDocuments); } popup.addSeparator(); popup.addAction(cancel); QAction *action = popup.exec(QCursor::pos()); if (action != 0 && action != cancel) { foreach(QUrl url, urls) { if (action == insertAsNewLayer || action == insertAsNewLayers) { m_d->imageManager->importImage(KUrl(url)); } else if (action == replaceCurrentDocument) { if (m_d->part->isModified()) { m_d->part->save(); } if (shell() != 0) { shell()->openDocument(url); } shell()->close(); } else { Q_ASSERT(action == openInNewDocument || action == openInNewDocuments); if (shell() != 0) { shell()->openDocument(url); } } } } } } } KoZoomController *KisView2::zoomController() const { return m_d->zoomManager->zoomController(); } KisImageWSP KisView2::image() { if (m_d && m_d->doc) { return m_d->doc->image(); } return 0; } KisCanvasResourceProvider * KisView2::resourceProvider() { return m_d->resourceProvider; } KisCanvas2 * KisView2::canvasBase() const { return m_d->canvas; } QWidget* KisView2::canvas() const { return m_d->canvas->canvasWidget(); } KisStatusBar * KisView2::statusBar() const { return m_d->statusBar; } KisPaintopBox* KisView2::paintOpBox() const { return m_d->controlFrame->paintopBox(); } KoProgressUpdater* KisView2::createProgressUpdater(KoProgressUpdater::Mode mode) { return m_d->statusBar->progress()->createUpdater(mode); } KisSelectionManager * KisView2::selectionManager() { return m_d->selectionManager; } KoCanvasController * KisView2::canvasController() { return m_d->canvasController; } KisNodeSP KisView2::activeNode() { if (m_d->nodeManager) return m_d->nodeManager->activeNode(); else return 0; } KisLayerSP KisView2::activeLayer() { if (m_d->nodeManager) return m_d->nodeManager->activeLayer(); else return 0; } KisPaintDeviceSP KisView2::activeDevice() { if (m_d->nodeManager) return m_d->nodeManager->activePaintDevice(); else return 0; } KisZoomManager * KisView2::zoomManager() { return m_d->zoomManager; } KisFilterManager * KisView2::filterManager() { return m_d->filterManager; } KisImageManager * KisView2::imageManager() { return m_d->imageManager; } KisSelectionSP KisView2::selection() { KisLayerSP layer = activeLayer(); if (layer) return layer->selection(); // falls through to the global // selection, or 0 in the end return image()->globalSelection(); } bool KisView2::selectionEditable() { KisLayerSP layer = activeLayer(); if (layer) { KoProperties properties; QList masks = layer->childNodes(QStringList("KisSelectionMask"), properties); if (masks.size() == 1) { return masks[0]->isEditable(); } } // global selection is always editable return true; } KisUndoAdapter * KisView2::undoAdapter() { KisImageWSP image = m_d->doc->image(); Q_ASSERT(image); return image->undoAdapter(); } void KisView2::slotLoadingFinished() { /** * Cold-start of image-size signals */ slotImageSizeChanged(); if (m_d->statusBar) { m_d->statusBar->imageSizeChanged(image()->width(), image()->height()); } if (m_d->resourceProvider) { m_d->resourceProvider->slotImageSizeChanged(); } if (m_d->nodeManager) { m_d->nodeManager->nodesUpdated(); } connectCurrentImage(); if (image()->locked()) { // If this is the first view on the image, the image will have been locked // so unlock it. image()->blockSignals(false); image()->unlock(); } KisNodeSP activeNode = m_d->doc->preActivatedNode(); m_d->doc->setPreActivatedNode(0); // to make sure that we don't keep a reference to a layer the user can later delete. if (!activeNode) { activeNode = image()->rootLayer()->firstChild(); } while (activeNode && !activeNode->inherits("KisLayer")) { activeNode = activeNode->nextSibling(); } if (activeNode) { m_d->nodeManager->slotNonUiActivatedNode(activeNode); } // get the assistants and push them to the manager QList paintingAssistants = m_d->doc->preLoadedAssistants(); foreach (KisPaintingAssistant* assistant, paintingAssistants) { m_d->paintingAssistantManager->addAssistant(assistant); } /** * Dirty hack alert */ if (m_d->zoomManager && m_d->zoomManager->zoomController()) m_d->zoomManager->zoomController()->setAspectMode(true); if (m_d->viewConverter) m_d->viewConverter->setZoomMode(KoZoomMode::ZOOM_PAGE); if (m_d->paintingAssistantManager){ foreach(KisPaintingAssistant* assist, m_d->doc->preLoadedAssistants()){ m_d->paintingAssistantManager->addAssistant(assist); } m_d->paintingAssistantManager->setVisible(true); } updateGUI(); emit sigLoadingFinished(); } void KisView2::createActions() { actionCollection()->addAction(KStandardAction::Preferences, "preferences", this, SLOT(slotPreferences())); KAction* action = new KAction(i18n("Edit Palette..."), this); actionCollection()->addAction("edit_palette", action); connect(action, SIGNAL(triggered()), this, SLOT(slotEditPalette())); + + action = new KAction(i18n("Cleanup removed files..."), this); + actionCollection()->addAction("edit_blacklist_cleanup", action); + connect(action, SIGNAL(triggered()), this, SLOT(slotBlacklistCleanup())); } void KisView2::createManagers() { // Create the managers for filters, selections, layers etc. // XXX: When the currentlayer changes, call updateGUI on all // managers m_d->filterManager = new KisFilterManager(this, m_d->doc); m_d->filterManager->setup(actionCollection()); m_d->selectionManager = new KisSelectionManager(this, m_d->doc); m_d->selectionManager->setup(actionCollection()); m_d->nodeManager = new KisNodeManager(this, m_d->doc); m_d->nodeManager->setup(actionCollection()); // the following cast is not really safe, but better here than in the zoomManager // best place would be outside kisview too m_d->zoomManager = new KisZoomManager(this, m_d->viewConverter, m_d->canvasController); m_d->zoomManager->setup(actionCollection()); m_d->imageManager = new KisImageManager(this); m_d->imageManager->setup(actionCollection()); m_d->gridManager = new KisGridManager(this); m_d->gridManager->setup(actionCollection()); m_d->canvas->addDecoration(m_d->gridManager); m_d->perspectiveGridManager = new KisPerspectiveGridManager(this); m_d->perspectiveGridManager->setup(actionCollection()); m_d->canvas->addDecoration(m_d->perspectiveGridManager); m_d->paintingAssistantManager = new KisPaintingAssistantsManager(this); m_d->paintingAssistantManager->setup(actionCollection()); m_d->canvas->addDecoration(m_d->paintingAssistantManager); } void KisView2::updateGUI() { m_d->nodeManager->updateGUI(); m_d->selectionManager->updateGUI(); m_d->filterManager->updateGUI(); m_d->zoomManager->updateGUI(); m_d->imageManager->updateGUI(); m_d->gridManager->updateGUI(); m_d->perspectiveGridManager->updateGUI(); } void KisView2::connectCurrentImage() { if (image()) { if (m_d->statusBar) { connect(image(), SIGNAL(sigColorSpaceChanged(const KoColorSpace *)), m_d->statusBar, SLOT(updateStatusBarProfileLabel())); connect(image(), SIGNAL(sigProfileChanged(const KoColorProfile *)), m_d->statusBar, SLOT(updateStatusBarProfileLabel())); connect(image(), SIGNAL(sigSizeChanged(qint32, qint32)), m_d->statusBar, SLOT(imageSizeChanged(qint32, qint32))); } connect(image(), SIGNAL(sigSizeChanged(qint32, qint32)), m_d->resourceProvider, SLOT(slotImageSizeChanged())); connect(image(), SIGNAL(sigResolutionChanged(double, double)), m_d->resourceProvider, SLOT(slotOnScreenResolutionChanged())); connect(zoomManager()->zoomController(), SIGNAL(zoomChanged(KoZoomMode::Mode, qreal)), m_d->resourceProvider, SLOT(slotOnScreenResolutionChanged())); connect(image(), SIGNAL(sigSizeChanged(qint32, qint32)), this, SLOT(slotImageSizeChanged())); connect(image(), SIGNAL(sigResolutionChanged(double, double)), this, SLOT(slotImageSizeChanged())); connect(image(), SIGNAL(sigNodeChanged(KisNodeSP)), this, SLOT(slotNodeChanged())); connect(image()->undoAdapter(), SIGNAL(selectionChanged()), selectionManager(), SLOT(selectionChanged())); /** * WARNING: Currently we access the global progress bar in two ways: * connecting to composite progress proxy (strokes) and creating * progress updaters. The latter way should be depracated in favour * of displaying the status of the global strokes queue */ //image()->compositeProgressProxy()->addProxy(m_d->statusBar->progress()->progressProxy()); } m_d->canvas->connectCurrentImage(); if (m_d->controlFrame) { connect(image(), SIGNAL(sigColorSpaceChanged(const KoColorSpace *)), m_d->controlFrame->paintopBox(), SLOT(slotColorSpaceChanged(const KoColorSpace*))); } } void KisView2::disconnectCurrentImage() { if (image()) { image()->disconnect(this); image()->disconnect(m_d->nodeManager); image()->disconnect(m_d->selectionManager); if (m_d->statusBar) image()->disconnect(m_d->statusBar); m_d->canvas->disconnectCurrentImage(); } } void KisView2::slotPreferences() { if (KisDlgPreferences::editPreferences()) { KisConfigNotifier::instance()->notifyConfigChanged(); m_d->resourceProvider->resetDisplayProfile(QApplication::desktop()->screenNumber(this)); KisConfig cfg; static_cast(m_d->canvasController)->setZoomWithWheel(cfg.zoomWithWheel()); // Update the settings for all nodes -- they don't query // KisConfig directly because they need the settings during // compositing, and they don't connect to the confignotifier // because nodes are not QObjects (because only one base class // can be a QObject). KisNode* node = dynamic_cast(image()->rootLayer().data()); node->updateSettings(); } } void KisView2::slotEditPalette() { QList palettes = KoResourceServerProvider::instance()->paletteServer()->resources(); KDialog* base = new KDialog(this); base->setCaption(i18n("Edit Palette")); base->setButtons(KDialog::Ok); base->setDefaultButton(KDialog::Ok); KisCustomPalette* cp = new KisCustomPalette(palettes, base, "edit palette", i18n("Edit Palette"), this); base->setMainWidget(cp); base->show(); } +void KisView2::slotBlacklistCleanup() +{ + KisDlgBlacklistCleanup dialog; + dialog.exec(); +} + + void KisView2::slotImageSizeChanged() { QSizeF size(image()->width() / image()->xRes(), image()->height() / image()->yRes()); m_d->zoomManager->zoomController()->setPageSize(size); m_d->zoomManager->zoomController()->setDocumentSize(size); canvasBase()->notifyZoomChanged(); QSize widgetSize = canvasBase()->coordinatesConverter()->imageRectInWidgetPixels().toAlignedRect().size(); m_d->canvasController->updateDocumentSize(widgetSize, true); m_d->zoomManager->updateGUI(); //update view canvas()->update(); } void KisView2::slotNodeChanged() { updateGUI(); } void KisView2::loadPlugins() { // Load all plugins KService::List offers = KServiceTypeTrader::self()->query(QString::fromLatin1("Krita/ViewPlugin"), QString::fromLatin1("(Type == 'Service') and " "([X-Krita-Version] == 5)")); KService::List::ConstIterator iter; for (iter = offers.constBegin(); iter != offers.constEnd(); ++iter) { KService::Ptr service = *iter; dbgUI << "Load plugin " << service->name(); QString error; KParts::Plugin* plugin = dynamic_cast(service->createInstance(this, QVariantList(), &error)); if (plugin) { insertChildClient(plugin); } else { errKrita << "Fail to create an instance for " << service->name() << " " << error; } } } KisDoc2 * KisView2::document() const { return m_d->doc; } KoPrintJob * KisView2::createPrintJob() { return new KisPrintJob(image()); } KisNodeManager * KisView2::nodeManager() { return m_d->nodeManager; } KisPerspectiveGridManager* KisView2::perspectiveGridManager() { return m_d->perspectiveGridManager; } KisGridManager * KisView2::gridManager() { return m_d->gridManager; } KisPaintingAssistantsManager* KisView2::paintingAssistantManager() { return m_d->paintingAssistantManager; } void KisView2::slotTotalRefresh() { KisConfig cfg; m_d->canvas->resetCanvas(cfg.useOpenGL()); } void KisView2::slotCreateTemplate() { KoTemplateCreateDia::createTemplate("krita_template", ".kra", KisFactory2::componentData(), m_d->doc, this); } void KisView2::slotDocumentSaved() { m_d->saveIncremental->setEnabled(true); m_d->saveIncrementalBackup->setEnabled(true); } void KisView2::slotSaveIncremental() { KoDocument* pDoc = koDocument(); if (!pDoc) return; bool foundVersion; bool fileAlreadyExists; bool isBackup; QString version = "000"; QString newVersion; QString letter; QString fileName = pDoc->localFilePath(); // Find current version filenames // v v Regexp to find incremental versions in the filename, taking our backup scheme into account as well // Considering our incremental version and backup scheme, format is filename_001~001.ext QRegExp regex("_\\d{1,4}[.]|_\\d{1,4}[a-z][.]|_\\d{1,4}[~]|_\\d{1,4}[a-z][~]"); regex.indexIn(fileName); // Perform the search QStringList matches = regex.capturedTexts(); foundVersion = matches.at(0).isEmpty() ? false : true; // Ensure compatibility with Save Incremental Backup // If this regex is not kept separate, the entire algorithm needs modification; // It's simpler to just add this. QRegExp regexAux("_\\d{1,4}[~]|_\\d{1,4}[a-z][~]"); regexAux.indexIn(fileName); // Perform the search QStringList matchesAux = regexAux.capturedTexts(); isBackup = matchesAux.at(0).isEmpty() ? false : true; // If the filename has a version, prepare it for incrementation if (foundVersion) { version = matches.at(matches.count() - 1); // Look at the last index, we don't care about other matches if (version.contains(QRegExp("[a-z]"))) { version.chop(1); // Trim "." letter = version.right(1); // Save letter version.chop(1); // Trim letter } else { version.chop(1); // Trim "." } version.remove(0, 1); // Trim "_" } else { // ...else, simply add a version to it so the next loop works QRegExp regex2("[.][a-z]{2,4}$"); // Heuristic to find file extension regex2.indexIn(fileName); QStringList matches2 = regex2.capturedTexts(); QString extensionPlusVersion = matches2.at(0); extensionPlusVersion.prepend(version); extensionPlusVersion.prepend("_"); fileName.replace(regex2, extensionPlusVersion); } // Prepare the base for new version filename int intVersion = version.toInt(0); ++intVersion; QString baseNewVersion = QString::number(intVersion); while (baseNewVersion.length() < version.length()) { baseNewVersion.prepend("0"); } // Check if the file exists under the new name and search until options are exhausted (test appending a to z) do { newVersion = baseNewVersion; newVersion.prepend("_"); if (!letter.isNull()) newVersion.append(letter); if (isBackup) { newVersion.append("~"); } else { newVersion.append("."); } fileName.replace(regex, newVersion); fileAlreadyExists = KIO::NetAccess::exists(fileName, KIO::NetAccess::DestinationSide, this); if (fileAlreadyExists) { if (!letter.isNull()) { char letterCh = letter.at(0).toLatin1(); ++letterCh; letter = QString(QChar(letterCh)); } else { letter = "a"; } } } while (fileAlreadyExists && letter != "{"); // x, y, z, {... if (letter == "{") { KMessageBox::error(this, "Alternative names exhausted, try manually saving with a higher number", "Couldn't save incremental version"); return; } pDoc->setSaveInBatchMode(true); m_d->part->saveAs(fileName); pDoc->setSaveInBatchMode(false); shell()->updateCaption(); } void KisView2::slotSaveIncrementalBackup() { KoDocument* pDoc = koDocument(); if (!pDoc) return; bool workingOnBackup; bool fileAlreadyExists; QString version = "000"; QString newVersion; QString letter; QString fileName = pDoc->localFilePath(); // First, discover if working on a backup file, or a normal file QRegExp regex("~\\d{1,4}[.]|~\\d{1,4}[a-z][.]"); regex.indexIn(fileName); // Perform the search QStringList matches = regex.capturedTexts(); workingOnBackup = matches.at(0).isEmpty() ? false : true; if (workingOnBackup) { // Try to save incremental version (of backup), use letter for alt versions version = matches.at(matches.count() - 1); // Look at the last index, we don't care about other matches if (version.contains(QRegExp("[a-z]"))) { version.chop(1); // Trim "." letter = version.right(1); // Save letter version.chop(1); // Trim letter } else { version.chop(1); // Trim "." } version.remove(0, 1); // Trim "~" // Prepare the base for new version filename int intVersion = version.toInt(0); ++intVersion; QString baseNewVersion = QString::number(intVersion); while (baseNewVersion.length() < version.length()) { baseNewVersion.prepend("0"); } // Check if the file exists under the new name and search until options are exhausted (test appending a to z) do { newVersion = baseNewVersion; newVersion.prepend("~"); if (!letter.isNull()) newVersion.append(letter); newVersion.append("."); fileName.replace(regex, newVersion); fileAlreadyExists = KIO::NetAccess::exists(fileName, KIO::NetAccess::DestinationSide, this); if (fileAlreadyExists) { if (!letter.isNull()) { char letterCh = letter.at(0).toLatin1(); ++letterCh; letter = QString(QChar(letterCh)); } else { letter = "a"; } } } while (fileAlreadyExists && letter != "{"); // x, y, z, {... if (letter == "{") { KMessageBox::error(this, "Alternative names exhausted, try manually saving with a higher number", "Couldn't save incremental backup"); return; } m_d->part->saveAs(fileName); shell()->updateCaption(); } else { // if NOT working on a backup... // Navigate directory searching for latest backup version, ignore letters const quint8 HARDCODED_DIGIT_COUNT = 3; QString baseNewVersion = "000"; QString backupFileName = pDoc->localFilePath(); QRegExp regex2("[.][a-z]{2,4}$"); // Heuristic to find file extension regex2.indexIn(backupFileName); QStringList matches2 = regex2.capturedTexts(); QString extensionPlusVersion = matches2.at(0); extensionPlusVersion.prepend(baseNewVersion); extensionPlusVersion.prepend("~"); backupFileName.replace(regex2, extensionPlusVersion); // Save version with 1 number higher than the highest version found ignoring letters do { newVersion = baseNewVersion; newVersion.prepend("~"); newVersion.append("."); backupFileName.replace(regex, newVersion); fileAlreadyExists = KIO::NetAccess::exists(backupFileName, KIO::NetAccess::DestinationSide, this); if (fileAlreadyExists) { // Prepare the base for new version filename, increment by 1 int intVersion = baseNewVersion.toInt(0); ++intVersion; baseNewVersion = QString::number(intVersion); while (baseNewVersion.length() < HARDCODED_DIGIT_COUNT) { baseNewVersion.prepend("0"); } } } while (fileAlreadyExists); // Save both as backup and on current file for interapplication workflow pDoc->setSaveInBatchMode(true); m_d->part->saveAs(backupFileName); m_d->part->saveAs(fileName); pDoc->setSaveInBatchMode(false); shell()->updateCaption(); } } void KisView2::disableControls() { // prevents possible crashes, if somebody changes the paintop during dragging by using the mousewheel // this is for Bug 250944 // the solution blocks all wheel, mouse and key event, while dragging with the freehand tool // see KisToolFreehand::initPaint() and endPaint() m_d->controlFrame->paintopBox()->installEventFilter(&m_d->blockingEventFilter); foreach(QObject* child, m_d->controlFrame->paintopBox()->children()) { child->installEventFilter(&m_d->blockingEventFilter); } } void KisView2::enableControls() { m_d->controlFrame->paintopBox()->removeEventFilter(&m_d->blockingEventFilter); foreach(QObject* child, m_d->controlFrame->paintopBox()->children()) { child->removeEventFilter(&m_d->blockingEventFilter); } } void KisView2::showStatusBar(bool toggled) { if (KoView::statusBar()) { KoView::statusBar()->setVisible(toggled); } } void KisView2::showJustTheCanvas(bool toggled) { KisConfig cfg; KToggleAction *action; if (cfg.hideStatusbarFullscreen()) { action = dynamic_cast(actionCollection()->action("showStatusBar")); if (action && action->isChecked() == toggled) { action->setChecked(!toggled); } } if (cfg.hideDockersFullscreen()) { action = dynamic_cast(shell()->actionCollection()->action("view_toggledockers")); if (action && action->isChecked() == toggled) { action->setChecked(!toggled); } } if (cfg.hideTitlebarFullscreen()) { action = dynamic_cast(shell()->actionCollection()->action("view_fullscreen")); if (action && action->isChecked() != toggled) { action->setChecked(toggled); } } if (cfg.hideMenuFullscreen()) { if (shell()->menuBar()->isVisible() == toggled) { shell()->menuBar()->setVisible(!toggled); } } if (cfg.hideToolbarFullscreen()) { foreach(KToolBar* toolbar, shell()->toolBars()) { if (toolbar->isVisible() == toggled) { toolbar->setVisible(!toggled); } } } if (cfg.hideScrollbarsFullscreen()) { if (toggled) { dynamic_cast(canvasController())->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); dynamic_cast(canvasController())->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); } else { dynamic_cast(canvasController())->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); dynamic_cast(canvasController())->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); } } if (toggled) { // show a fading heads-up display about the shortcut to go back KisFloatingMessage *floatingMessage = new KisFloatingMessage(i18n("Going into Canvas-Only mode.\nPress %1 to go back.", actionCollection()->action("view_show_just_the_canvas")->shortcut().toString()), this); floatingMessage->showMessage(); } } void KisView2::showFloatingMessage(const QString message, const QIcon& icon) { KisFloatingMessage *floatingMessage = new KisFloatingMessage(message, mainWindow()->centralWidget()); floatingMessage->setShowOverParent(true); floatingMessage->setIcon(icon); floatingMessage->showMessage(); } #include "kis_view2.moc" diff --git a/krita/ui/kis_view2.h b/krita/ui/kis_view2.h index 5425b54ff56..a1899e2934c 100644 --- a/krita/ui/kis_view2.h +++ b/krita/ui/kis_view2.h @@ -1,218 +1,219 @@ /* * Copyright (c) 2006 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_VIEW_2 #define KIS_VIEW_2 #include #include #include #include #include #include #include class QDragEnterEvent; class QDropEvent; class QPoint; class KisPaintOpPreset; class KoCanvasController; class KisCanvas2; class KisCanvasResourceProvider; class KisDoc2; class KisFilterManager; class KisGridManager; class KisImage; class KisImageManager; class KisNodeManager; class KisPaintingAssistantsManager; class KisPaintopBox; class KisPart2; class KisPerspectiveGridManager; class KisSelectionManager; class KisStatusBar; class KisUndoAdapter; class KisZoomManager; /** * Krita view class * * Following the broad model-view-controller idea this class shows you one view on the document. * There can be multiple views of the same document each in with independent settings for viewMode and zoom etc. */ class KRITAUI_EXPORT KisView2 : public KoView { Q_OBJECT public: /** * Construct a new view on the krita document. * @param document the document we show. * @param parent a parent widget we show ourselves in. */ KisView2(KisPart2 *part, KisDoc2 *document, QWidget *parent); virtual ~KisView2(); public: // QWidget overrides virtual void dragEnterEvent(QDragEnterEvent * event); virtual void dropEvent(QDropEvent * event); // KoView implementation virtual void updateReadWrite(bool readwrite) { Q_UNUSED(readwrite); } // KoView implementation virtual KoZoomController *zoomController() const; public: // Krita specific interfaces /// Return the image this view is displaying KisImageWSP image(); /// The resource provider contains all per-view settings, such as /// current color, current paint op etc. KisCanvasResourceProvider * resourceProvider(); /// Return the canvasbase class KisCanvas2 * canvasBase() const; /// Return the actual widget that is displaying the current image QWidget* canvas() const; /// Return the wrapper class around the statusbar KisStatusBar * statusBar() const; KisPaintopBox* paintOpBox() const; /// create a new progress updater KoProgressUpdater* createProgressUpdater(KoProgressUpdater::Mode mode = KoProgressUpdater::Threaded); /// The selection manager handles everything action related to /// selections. KisSelectionManager * selectionManager(); /// The CanvasController decorates the canvas with scrollbars /// and knows where to start painting on the canvas widget, i.e., /// the document offset. KoCanvasController * canvasController(); /// The node manager handles everything about nodes KisNodeManager * nodeManager(); /** * Convenience method to get at the active node, which may be * a layer or a mask or a selection */ KisNodeSP activeNode(); /// Convenience method to get at the active layer KisLayerSP activeLayer(); /// Convenience method to get at the active paint device KisPaintDeviceSP activeDevice(); /// The zoommanager handles everything action-related to zooming KisZoomManager * zoomManager(); /// The filtermanager handles everything action-related to filters KisFilterManager * filterManager(); /// The image manager handles everything action-related to the /// current image KisImageManager * imageManager(); /// Convenience method to get at the active selection (the /// selection of the current layer, or, if that does not exist, /// the global selection. KisSelectionSP selection(); /// Checks if the current global or local selection is editable bool selectionEditable(); /// The undo adapter is used to add commands to the undo stack KisUndoAdapter * undoAdapter(); /// Go to all managers and enable or disable all actions and other /// gui elements void updateGUI(); KisDoc2* document() const; /// Connects the signals from the current image to the various /// slots of the various managers void connectCurrentImage(); /// Disconnect the current image (for instance, before connecting /// another image) from the slots in the various managers void disconnectCurrentImage(); virtual KoPrintJob * createPrintJob(); KisGridManager * gridManager(); KisPerspectiveGridManager* perspectiveGridManager(); KisPaintingAssistantsManager* paintingAssistantManager(); /// disable and enable toolbar controls. used for disabling them during painting. void enableControls(); void disableControls(); /// shows a floating message in the top right corner of the canvas void showFloatingMessage(const QString message, const QIcon& icon); signals: void sigLoadingFinished(); private slots: void slotLoadingFinished(); void slotPreferences(); void slotEditPalette(); + void slotBlacklistCleanup(); void slotImageSizeChanged(); void slotNodeChanged(); void slotTotalRefresh(); void slotCreateTemplate(); void slotDocumentSaved(); void slotSaveIncremental(); void slotSaveIncrementalBackup(); void showStatusBar(bool toggled); void showJustTheCanvas(bool toggled); private: void createGUI(); void createActions(); void createManagers(); void loadPlugins(); private: class KisView2Private; KisView2Private * const m_d; }; #endif diff --git a/libs/widgets/KoResourceServer.h b/libs/widgets/KoResourceServer.h index 2e07dbfd347..c3ac731f273 100644 --- a/libs/widgets/KoResourceServer.h +++ b/libs/widgets/KoResourceServer.h @@ -1,568 +1,565 @@ /* This file is part of the KDE project Copyright (c) 1999 Matthias Elter Copyright (c) 2003 Patrick Julien Copyright (c) 2005 Sven Langkamp Copyright (c) 2007 Jan Hambrecht Copyright (C) 2011 Srikanth Tiyyagura This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef KORESOURCESERVER_H #define KORESOURCESERVER_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KoResource.h" #include "KoResourceServerObserver.h" #include "KoResourceTagging.h" #include "kowidgets_export.h" #include class KoResource; /** * KoResourceServerBase is the base class of all resource servers */ class KOWIDGETS_EXPORT KoResourceServerBase { public: /** * Constructs a KoResourceServerBase * @param resource type, has to be the same as used by KStandardDirs * @param extensions the file extensions separate by ':', e.g. "*.kgr:*.svg:*.ggr" */ KoResourceServerBase(const QString& type, const QString& extensions) : m_type(type) , m_extensions(extensions) , m_cancelled(false) { } virtual ~KoResourceServerBase() {} virtual void loadResources(QStringList filenames) = 0; virtual QStringList blackListedFiles() = 0; QString type() { return m_type; } /** * File extensions for resources of the server * @returns the file extensions separated by ':', e.g. "*.kgr:*.svg:*.ggr" */ QString extensions() { return m_extensions; } void cancel() { m_cancelled = true; } private: QString m_type; QString m_extensions; protected: bool m_cancelled; QMutex m_loadLock; }; /** * KoResourceServer manages the resources of one type. It stores, loads and saves the resources. * To keep track of changes the server can be observed with a KoResourceServerObserver */ template class KoResourceServer : public KoResourceServerBase { public: KoResourceServer(const QString& type, const QString& extensions, bool deleteResource = true) : KoResourceServerBase(type, extensions) , m_deleteResource(deleteResource) { - blackListFile = KStandardDirs::locateLocal("data", "krita/" + type + ".blacklist"); + m_blackListFile = KStandardDirs::locateLocal("data", "krita/" + type + ".blacklist"); + m_blackListFileNames = readBlackListFile(); m_tagObject = new KoResourceTagging(extensions); } virtual ~KoResourceServer() { qDeleteAll(m_resources); delete m_tagObject; } /** * Loads a set of resources and adds them to the resource server. * If a filename appears twice the resource will only be added once. Resources that can't * be loaded or and invalid aren't added to the server. * @param filenames list of filenames to be loaded */ void loadResources(QStringList filenames) { kDebug(30009) << "loading resources for type " << type(); QStringList uniqueFiles; while (!filenames.empty() && !m_cancelled) { QString front = filenames.first(); filenames.pop_front(); QString fname = QFileInfo(front).fileName(); // XXX: Don't load resources with the same filename. Actually, we should look inside // the resource to find out whether they are really the same, but for now this // will prevent the same brush etc. showing up twice. if (uniqueFiles.empty() || uniqueFiles.indexOf(fname) == -1) { m_loadLock.lock(); uniqueFiles.append(fname); QList resources = createResources(front); foreach(T* resource, resources) { Q_CHECK_PTR(resource); if (resource->load() && resource->valid()) { m_resourcesByFilename[resource->shortFilename()] = resource; if ( resource->name().isEmpty() ) { resource->setName( fname ); } if (m_resourcesByName.contains(resource->name())) { resource->setName(resource->name() + "(" + resource->shortFilename() + ")"); } m_resourcesByName[resource->name()] = resource; notifyResourceAdded(resource); } else { delete resource; } } m_loadLock.unlock(); } } m_resources = sortedResources(); kDebug(30009) << "done loading resources for type " << type(); } /// Adds an already loaded resource to the server bool addResource(T* resource, bool save = true, bool infront = false) { if (!resource->valid()) { kWarning(30009) << "Tried to add an invalid resource!"; return false; } QFileInfo fileInfo(resource->filename()); if (fileInfo.exists()) { QString filename = fileInfo.path() + "/" + fileInfo.baseName() + "XXXXXX" + "." + fileInfo.suffix(); kDebug() << "fileName is " << filename; QTemporaryFile file(filename); if (file.open()) { kDebug() << "now " << file.fileName(); resource->setFilename(file.fileName()); } } if( save && ! resource->save()) { kWarning(30009) << "Could not save resource!"; return false; } Q_ASSERT( !resource->filename().isEmpty() || !resource->name().isEmpty() ); if ( resource->filename().isEmpty() ) { resource->setFilename( resource->name() ); } else if ( resource->name().isEmpty() ) { resource->setName( resource->filename() ); } m_resourcesByFilename[resource->shortFilename()] = resource; m_resourcesByName[resource->name()] = resource; if (infront) { m_resources.insert(0, resource); } else { m_resources.append(resource); } notifyResourceAdded(resource); return true; } /// Remove a resource from Resource Server but not from a file bool removeResourceFromServer(T* resource){ if ( !m_resourcesByFilename.contains( resource->shortFilename() ) ) { return false; } m_resourcesByName.remove(resource->name()); m_resourcesByFilename.remove(resource->shortFilename()); m_resources.removeAt(m_resources.indexOf(resource)); notifyRemovingResource(resource); if (m_deleteResource) { delete resource; } return true; } /// Remove a resource from resourceserver and hard disk bool removeResource(T* resource) { if ( !m_resourcesByFilename.contains( resource->shortFilename() ) ) { return false; } m_resourcesByName.remove(resource->name()); m_resourcesByFilename.remove(resource->shortFilename()); m_resources.removeAt(m_resources.indexOf(resource)); notifyRemovingResource(resource); - writeBlackListFile(resource->filename()); + + m_blackListFileNames.append(resource->filename()); + writeBlackListFile(); if (m_deleteResource && resource) { delete resource; } return true; } QList resources() { m_loadLock.lock(); QList resourceList = m_resources; foreach(T* r, m_resourceBlackList) { resourceList.removeOne(r); } m_loadLock.unlock(); return resourceList; } /// Returns path where to save user defined and imported resources to virtual QString saveLocation() { return KGlobal::mainComponent().dirs()->saveLocation(type().toAscii()); } /** * Creates a new resource from a given file and adds them to the resource server * The base implementation does only load one resource per file, override to implement collections * @param filename file name of the resource file to be imported * @param fileCreation decides whether to create the file in the saveLocation() directory */ virtual void importResourceFile(const QString & filename , bool fileCreation=true) { QFileInfo fi( filename ); if( fi.exists() == false ) return; T* resource = createResource( filename ); resource->load(); if(!resource->valid()){ kWarning(30009) << "Import failed! Resource is not valid"; delete resource; return; } if(fileCreation) { Q_ASSERT(!resource->defaultFileExtension().isEmpty()); Q_ASSERT(!saveLocation().isEmpty()); QString newFilename = saveLocation() + fi.baseName() + resource->defaultFileExtension(); QFileInfo fileInfo(newFilename); int i = 1; while (fileInfo.exists()) { fileInfo.setFile(saveLocation() + fi.baseName() + QString("%1").arg(i) + resource->defaultFileExtension()); i++; } resource->setFilename(fileInfo.filePath()); } if(!addResource(resource)) { delete resource; } } /// Removes the resource file from the resource server virtual void removeResourceFile(const QString & filename) { QFileInfo fi(filename); T* resource = getResourceByFilename(fi.fileName()); if (!resource) { kWarning(30009) << "Resource file do not exist "; return; } if (!removeResourceFromServer(resource)) return; } /** * Addes an observer to the server * @param observer the observer to be added * @param notifyLoadedResources determines if the observer should be notified about the already loaded resources */ void addObserver(KoResourceServerObserver* observer, bool notifyLoadedResources = true) { m_loadLock.lock(); if(observer && !m_observers.contains(observer)) { m_observers.append(observer); if(notifyLoadedResources) { foreach(T* resource, m_resourcesByFilename) { observer->resourceAdded(resource); } } } m_loadLock.unlock(); } /** * Removes an observer from the server * @param observer the observer to be removed */ void removeObserver(KoResourceServerObserver* observer) { int index = m_observers.indexOf( observer ); if( index < 0 ) return; m_observers.removeAt( index ); } T* getResourceByFilename( const QString& filename ) { if ( !m_resourcesByFilename.contains( filename ) ) { return 0; } return m_resourcesByFilename[filename]; } T* getResourceByName( const QString& name ) { if ( !m_resourcesByName.contains( name ) ) { return 0; } return m_resourcesByName[name]; } /** * Call after changing the content of a resource; * Notifies the connected views. */ void updateResource( T* resource ) { notifyResourceChanged(resource); } QStringList blackListedFiles() { - blackListFileNames = readBlackListFile(); - return blackListFileNames; + return m_blackListFileNames; + } + + void removeBlackListedFiles() { + QStringList remainingFiles; // Files that can't be removed e.g. no rights will stay blacklisted + foreach(QString filename, m_blackListFileNames) { + QFile file( filename ); + if( ! file.remove() ) { + remainingFiles.append(filename); + } + } + m_blackListFileNames = remainingFiles; + writeBlackListFile(); } /// the below functions helps to access tagObject functions QStringList getAssignedTagsList( KoResource* resource ) { return m_tagObject->getAssignedTagsList(resource); } QStringList getTagNamesList() { return m_tagObject->getTagNamesList(); } void addTag( KoResource* resource,const QString& tag) { m_tagObject->addTag(resource,tag); } void delTag( KoResource* resource,const QString& tag) { m_tagObject->delTag(resource,tag); } QStringList searchTag(const QString& lineEditText) { return m_tagObject->searchTag(lineEditText); } #ifdef NEPOMUK void updateNepomukXML(bool nepomukOn) { KoResourceTagging* tagObject = new KoResourceTagging(extensions()); tagObject->setNepomukBool(nepomukOn); tagObject->updateNepomukXML(nepomukOn); delete tagObject; m_tagObject->setNepomukBool(nepomukOn); } #endif protected: /** * Create one or more resources from a single file. By default one resource is created. * Overide to create more resources from the file. * @param filename the filename of the resource or resource collection */ virtual QList createResources( const QString & filename ) { QList createdResources; createdResources.append(createResource(filename)); return createdResources; } virtual T* createResource( const QString & filename ) { return new T(filename); } /// Return the currently stored resources in alphabetical order, overwrite for customized sorting virtual QList sortedResources() { QMap sortedNames; foreach(QString name, m_resourcesByName.keys()) { sortedNames.insert(name.toLower(), m_resourcesByName[name]); } return sortedNames.values(); } void notifyResourceAdded(T* resource) { foreach(KoResourceServerObserver* observer, m_observers) { observer->resourceAdded(resource); } } void notifyRemovingResource(T* resource) { foreach(KoResourceServerObserver* observer, m_observers) { observer->removingResource(resource); } } void notifyResourceChanged(T* resource) { foreach(KoResourceServerObserver* observer, m_observers) { observer->resourceChanged(resource); } } /// Reads the xml file and returns the filenames as a list QStringList readBlackListFile() { QStringList filenameList; - QFile f(blackListFile); + QFile f(m_blackListFile); if (!f.open(QIODevice::ReadOnly)) { return filenameList; } QDomDocument doc; if (!doc.setContent(&f)) { kWarning() << "The file could not be parsed."; return filenameList; } QDomElement root = doc.documentElement(); if (root.tagName() != "resourceFilesList") { kWarning() << "The file doesn't seem to be of interest."; return filenameList; } QDomElement file = root.firstChildElement("file"); while (!file.isNull()) { QDomNode n = file.firstChild(); QDomElement e = n.toElement(); if (e.tagName() == "name") { filenameList.append((e.text()).replace(QString("~"),QDir::homePath())); } file = file.nextSiblingElement("file"); } return filenameList; } /// write the blacklist file entries to an xml file - void writeBlackListFile(QString fileName) + void writeBlackListFile() { - QFile f(blackListFile); - bool fileExists = f.exists(); + QFile f(m_blackListFile); - if (!f.open(QIODevice::ReadWrite | QIODevice::Text)) { - kWarning() << "Cannot write meta information to '" << blackListFile << "'." << endl; + if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) { + kWarning() << "Cannot write meta information to '" << m_blackListFile << "'." << endl; return; - } - - QDomDocument doc; - QDomElement root; - - if (!fileExists) { - QDomDocument docTemp("blackListFile"); - doc = docTemp; - doc.appendChild(doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"")); - root = doc.createElement("resourceFilesList"); - doc.appendChild(root); - } - else { - if (!doc.setContent(&f)) { - kWarning() << "The file could not be parsed."; - return; - } - - root = doc.documentElement(); - if (root.tagName() != "resourceFilesList") { - kWarning() << "The file doesn't seem to be of interest."; - return; - } - } - - QDomElement fileEl = doc.createElement("file"); - QDomElement nameEl = doc.createElement("name"); - QDomText nameText = doc.createTextNode(fileName.replace(QDir::homePath(),QString("~"))); - nameEl.appendChild(nameText); - fileEl.appendChild(nameEl); - root.appendChild(fileEl); + } - f.remove(); - if(!f.open(QIODevice::WriteOnly | QIODevice::Text)) { - kWarning() << "Cannot write meta information to '" << blackListFile << "'." << endl; - } - QTextStream metastream(&f); - metastream << doc.toByteArray(); - f.close(); + QDomDocument doc; + QDomElement root; + + QDomDocument docTemp("m_blackListFile"); + doc = docTemp; + doc.appendChild(doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"")); + root = doc.createElement("resourceFilesList"); + doc.appendChild(root); + + foreach(QString filename, m_blackListFileNames) { + QDomElement fileEl = doc.createElement("file"); + QDomElement nameEl = doc.createElement("name"); + QDomText nameText = doc.createTextNode(filename.replace(QDir::homePath(),QString("~"))); + nameEl.appendChild(nameText); + fileEl.appendChild(nameEl); + root.appendChild(fileEl); + } + + QTextStream metastream(&f); + metastream << doc.toByteArray(); + f.close(); } private: QHash m_resourcesByName; QHash m_resourcesByFilename; QList m_resourceBlackList; QList m_resources; ///< list of resources in order of addition QList*> m_observers; bool m_deleteResource; - QString blackListFile; - QStringList blackListFileNames; + QString m_blackListFile; + QStringList m_blackListFileNames; KoResourceTagging* m_tagObject; }; #endif // KORESOURCESERVER_H